緑のパイプラインから消えたファイルを追跡する
目標
業務の成功と、成果物の保持・片付けの成功を区別し、衝突のないキーと最小権限で検証します。
なぜ重要なのか
業務が成功しても、最終ファイルが消えたり、中間ファイルがたまり続けたりすることがあります。このラボは、VM内の実際のArgo Workflows 4.1.3とSeaweedFS 4.46を使います。画面の成功表示ではなく、実行UIDと実際のファイルのバイト、GCのエラーをあわせて確認します。デフォルトのクラスターとストレージは自動で準備され、受講者は、ポリシーを修正したり、比較シナリオを直接実行したりします。
ステップ
- argoネームスペースのartifact-repositoriesとService seaweedを読んでください。/root/capa-artifacts/inventory.jsonに、namespace=argo、endpoint=seaweed:8333、writer_bucket=artifacts、anonymous_allowed=falseを記録します。採点は、実際に許可されたアカウントのファイル読み取りと、匿名リクエスト、ほかのチームのバケットへのアクセスの拒否も照合します。
- 用意されている/root/capa-artifacts/isolated.yamlのproduceの出力2つで、s3.keyだけを直します。temporaryはruns/{{workflow.uid}}/temp.txt、finalはruns/{{workflow.uid}}/final.jsonです。残りのパイプラインと最終のNeverは維持して、実験ヘルパーでisolatedを実行してください。別々の2つのWorkflowのUIDと、最終ファイルの内容を比較します。
- isolatedの2つの実行の完了後に、ストレージを確認します。/root/capa-artifacts/retention.jsonに、business=Succeeded、temporary=deleted、final=retained、final_policy=Neverを記録します。2つの最終ファイルの生成UIDが違うことと、Aの片付けの時点でBの入力が生きていたかどうかも、実験記録で確認してください。
- 用意されているmissing-retain.yamlは、最終artifactのNeverをわざと外してあります。ヘルパーでmissing-retainを実行したあと、/root/capa-artifacts/missing.jsonに、business=Succeeded、final_present=false、fix=Neverを記録してください。この比較実行のYAMLを、正常なポリシーに変えないでください。エラーの原因と、直すフィールドを説明するステップです。
- 用意されているgc-denied.yamlは、Roleのないgc-deniedというGCアカウントを使います。ヘルパーでgc-deniedを実行して、/root/capa-artifacts/gc-error.jsonに、business=Succeeded、condition=ArtifactGCError、cause=RBAC、force_finalizer=falseを書きます。実際のforbiddenのログと、残った2つのファイルを読み、finalizerは消しません。
- /root/capa-artifacts/gc-binding.yamlに、RoleBinding capa-gc-repairを作成・適用してください。ネームスペースはargo、roleRefはapiGroup=rbac.authorization.k8s.io、kind=Role、name=artifact-gcで、subjectsはargoのServiceAccount gc-denied 1つです。既存のRoleを広げずに、gc-repaired.yamlで新しい実行を確認します。元の失敗したWorkflowの記録とfinalizerは保全します。
- collision.yamlのshared/{{workflow.parameters.batch}}キーを維持して、ヘルパーでcollisionを実行してください。Aの入力がBのUIDで上書きされてAが失敗したあと、AのGCがBの入力を消して、Bも失敗するかを確認します。2つのWorkflowのFailed/Errorは、この比較の期待される結果です。単にファイルを消して、失敗の真似をしないでください。
- on-deletion.yamlは、OnWorkflowDeletionと、最終のNeverを一緒に使います。ヘルパーでon-deletionを実行してください。ヘルパーは、成功の直後にファイルを観測し、正確なWorkflow UIDを確認して、そのWorkflowだけを削除したあと、再び観測します。業務の完了時には2つのファイルがあり、削除のあとには最終ファイルだけが残る必要があります。
- /root/capa-artifacts/report.jsonに、lost_result_uidはmissing-retainの実際のUID、gc_failure_uidはgc-deniedの実際のUIDを書きます。same_business_status=true、same_storage_result=false、status_is_retention_proof=falseを記録してください。2つのSucceededが、なぜ別の対処を求めるのかを、実際のファイルの状態とエラーの層を根拠に説明します。
参考
- 用意されているYAMLは、/root/capa-artifacts/にあります。ステップ2の2つのkey以外は、比較に必要な誤った設定を消さないでください。各ステップのカードに、正確な変更・観測の項目があります。
- 実行: python3 /opt/fixtures/capa-lifecycle/runtime.py run isolated /root/capa-artifacts/isolated.yaml(ほかのシナリオも同じ形式で、名前は、該当するYAMLのファイル名から.yamlを除いたものです)。
- 状態: python3 /opt/fixtures/capa-lifecycle/runtime.py status isolated
- statusが示すattemptの前後の観測の原文は、
/var/lib/labhub/capa-lifecycle/attempts/<attempt>.jsonにあります。beforeは生成後、afterは消費・片付け後、while_a_finishedはAが終わったときのBの状態です。受講者の答案ではなく、ヘルパーの観測記録なので、直接編集しないでください。 - 実際の実行の照会:
kubectl -n argo get workflow WORKFLOW_NAME -o yaml、実際のPodの照会:kubectl -n argo get pods -l workflows.argoproj.io/workflow=WORKFLOW_NAME、ログの照会:kubectl -n argo logs POD_NAME --all-containers=true。WORKFLOW_NAMEとPOD_NAMEは、前のコマンドで見つけた実際の名前に置き換えます。 - ストレージの一覧:
kubectl -n argo exec store-admin -- mc --config-dir /tmp/mc ls --recursive store/artifacts/、ファイルの読み取り:kubectl -n argo exec store-admin -- mc --config-dir /tmp/mc cat store/artifacts/runs/<UID>/final.json。store-adminは、このVM内の観測用の管理ツールです。業務のアップロードとGCは、別のartifact-writerアカウントを使い、ステップ1は、そのアカウントのバケット制限を検査します。 - 観測時間が終わっても、実行は続くことがあります。同じ作業を、wait isolatedで確認し、生きている作業を重複して作らないでください。同じYAMLの完了記録は再利用されます。終了した実験を、意図的に新しく比較するときだけ、runに--new-attemptを付けます。
- ヘルパーは、アップロード後の一時停止・観測・消費の再開を行います。実行ヘルパーの完了は、正解の合格ではありません。誤ったYAMLで終わった実行は、採点で拒否されます。
- kubectlにはKUBECONFIG=/etc/rancher/k3s/k3s.yamlを使います。argo CLIには--kubeconfig=/etc/rancher/k3s/k3s.yamlを明示すると、ホームディレクトリに依存しません。
- ストレージのHTTPとemptyDirは、破棄可能なラボ用です。セッションが終わると、ファイルとVMがすべて回収されます。Neverも、セッションの終了を超えて保持したり、バックアップしたりする機能ではありません。
正常な読み取りと拒否すべき読み取りを区別する
argoネームスペースのartifact-repositoriesとService seaweedを読んでください。/root/capa-artifacts/inventory.jsonに、namespace=argo、endpoint=seaweed:8333、writer_bucket=artifacts、anonymous_allowed=falseを記録します。採点は、実際に許可されたアカウントのファイル読み取りと、匿名リクエスト、ほかのチームのバケットへのアクセスの拒否も照合します。
ストレージ参照のendpointとbucketは、別のフィールドです。正常なリクエストが成功するかどうかも、あわせて確認します。
2つの実行の成果物キーを分離する
用意されている/root/capa-artifacts/isolated.yamlのproduceの出力2つで、s3.keyだけを直します。temporaryはruns/{{workflow.uid}}/temp.txt、finalはruns/{{workflow.uid}}/final.jsonです。残りのパイプラインと最終のNeverは維持して、実験ヘルパーでisolatedを実行してください。別々の2つのWorkflowのUIDと、最終ファイルの内容を比較します。
Kubernetesの名前が違っても、ストレージのkeyが同じなら衝突します。UIDは、ローカルのファイル名ではなく、S3のkeyに入れます。
中間ファイルを消して、最終結果は保持する
isolatedの2つの実行の完了後に、ストレージを確認します。/root/capa-artifacts/retention.jsonに、business=Succeeded、temporary=deleted、final=retained、final_policy=Neverを記録します。2つの最終ファイルの生成UIDが違うことと、Aの片付けの時点でBの入力が生きていたかどうかも、実験記録で確認してください。
OnWorkflowCompletionのデフォルトのポリシーと、個別のfinalのNeverをあわせて見ます。観測記録は、ヘルパーのstatusで実行名を見つけてから確認できます。
最終保持を忘れた成功の分析
用意されているmissing-retain.yamlは、最終artifactのNeverをわざと外してあります。ヘルパーでmissing-retainを実行したあと、/root/capa-artifacts/missing.jsonに、business=Succeeded、final_present=false、fix=Neverを記録してください。この比較実行のYAMLを、正常なポリシーに変えないでください。エラーの原因と、直すフィールドを説明するステップです。
間違った設定が、業務の失敗を作らないこともあります。正常なisolatedの結果と、この実行の最終ファイルを比べてください。
業務の成功とGCの権限失敗を分離する
用意されているgc-denied.yamlは、Roleのないgc-deniedというGCアカウントを使います。ヘルパーでgc-deniedを実行して、/root/capa-artifacts/gc-error.jsonに、business=Succeeded、condition=ArtifactGCError、cause=RBAC、force_finalizer=falseを書きます。実際のforbiddenのログと、残った2つのファイルを読み、finalizerは消しません。
このステップで失敗すべきものは、業務のコンテナではなく、GCです。権限を付ける作業は、次のステップで行います。
最小のGC権限で、新しい実行を検証する
/root/capa-artifacts/gc-binding.yamlに、RoleBinding capa-gc-repairを作成・適用してください。ネームスペースはargo、roleRefはapiGroup=rbac.authorization.k8s.io、kind=Role、name=artifact-gcで、subjectsはargoのServiceAccount gc-denied 1つです。既存のRoleを広げずに、gc-repaired.yamlで新しい実行を確認します。元の失敗したWorkflowの記録とfinalizerは保全します。
GCには、taskのlist/watchと、task statusのpatchだけが必要です。status権限は、--subresource=statusで確認します。
共有キーが作る2回の失敗
collision.yamlのshared/{{workflow.parameters.batch}}キーを維持して、ヘルパーでcollisionを実行してください。Aの入力がBのUIDで上書きされてAが失敗したあと、AのGCがBの入力を消して、Bも失敗するかを確認します。2つのWorkflowのFailed/Errorは、この比較の期待される結果です。単にファイルを消して、失敗の真似をしないでください。
ヘルパーは、同じ実験試行の2つの実行にだけ、同じbatchを渡します。statusに出た別々のUIDとログを比べてください。
完了の時点と削除の時点を比較する
on-deletion.yamlは、OnWorkflowDeletionと、最終のNeverを一緒に使います。ヘルパーでon-deletionを実行してください。ヘルパーは、成功の直後にファイルを観測し、正確なWorkflow UIDを確認して、そのWorkflowだけを削除したあと、再び観測します。業務の完了時には2つのファイルがあり、削除のあとには最終ファイルだけが残る必要があります。
Workflowの削除とPodの削除は、同じできごとではありません。finalizerの強制削除なしで、削除が終わった証拠を読みます。
同じ成功に隠れた、別の保存結果を報告する
/root/capa-artifacts/report.jsonに、lost_result_uidはmissing-retainの実際のUID、gc_failure_uidはgc-deniedの実際のUIDを書きます。same_business_status=true、same_storage_result=false、status_is_retention_proof=falseを記録してください。2つのSucceededが、なぜ別の対処を求めるのかを、実際のファイルの状態とエラーの層を根拠に説明します。
ヘルパーのstatusのUIDを読みますが、名前と混同しないでください。最終結果の消失と、一時ファイルの片付けの失敗は、同じ障害ではありません。