ApplicationとAppProjectを自分で書く
目標
Argo CDのApplicationとAppProjectを自分で書いて、「何をどこから読み、どこにどんな順序とポリシーで適用するか」を宣言として表現できるようになります。
なぜ重要なのか
デプロイをスクリプトではなくオブジェクトにすると、3つのことが付いてきます。クラスターに「今何をデプロイされているか」を尋ねられ、RBACと監査ログがただで付き、その宣言自体をまたgitにコミットできます。このラボで埋めるフィールドは、すべて実際の事故と対になっています。pruneは、リポジトリのパスの打ち間違い1回を大量削除に変えうるスイッチであり、retry.backoffがないと、失敗した同期がAPIサーバーを同じ間隔で叩く負荷装置になり、ignoreDifferencesがないと、HPAとArgo CDが互いにreplicasを元に戻し合う無限ループが生まれます。ただし、この環境ではArgo CDコントローラーが実行されません。CRDを登録してカスタムリソースを作ることはできますが、それがひとりでSynced/Healthyに変わることはありません。そのため、採点するのは状態ではなく宣言の正確さであり、その宣言が実際のコントローラーに何をさせるかは、前の読み物と最後のモジュールで扱います。
ステップ
/opt/crds/の下のオフラインCRDバンドルから、Argo CDのCRDが入ったファイルを探し(grep -l applications.argoproj.io /opt/crds/*.yaml)、kubectl apply -fで適用してください。applications.argoproj.ioとappprojects.argoproj.ioの2つのCRDができて、Established条件がTrueであり、ネームスペースargocdがある必要があります。登録された型の一覧を/root/gitops/app/out/crds.txtに保存してください(applicationsという文字列が入っている必要があります)。argocdネームスペースに、kind: Application、metadata.name: webのオブジェクトを作ってください。spec.source.repoURLはfile:///root/gitops/repo、spec.source.pathはapps/web、spec.source.targetRevisionはmain、spec.destination.serverはhttps://kubernetes.default.svc、spec.destination.namespaceはgitops-lab、spec.projectはplatformです。webのspec.syncPolicy.automatedを追加して、prune: true、selfHeal: trueにしてください。そして/root/gitops/app/out/prune-note.txtに、pruneを有効にしたときのリスク(パスを誤って指したコミット1つが、大量削除につながる)を、韓国語で2、3行書いてください。webのspec.syncPolicy.syncOptionsにCreateNamespace=trueとServerSideApply=trueを入れ、spec.syncPolicy.retryにlimit: 3、backoff.duration: 10s、backoff.factor: 2、backoff.maxDuration: 5mを入れてください。- リポジトリ
/root/gitops/repoがまだなければ、先に作ってください。/opt/lab/fixtures/gitops/seed/のdeployment.yamlとservice.yamlを/root/gitops/repo/apps/web/にコピーして、git initしたあとコミットすれば済みます。そのあと、リポジトリ/root/gitops/repo/apps/web/のservice.yamlにargocd.argoproj.io/sync-wave: "-1"アノテーションを、deployment.yamlにargocd.argoproj.io/sync-wave: "0"アノテーションを追加してください。値は必ず二重引用符で囲んだ文字列でなければなりません。そして/root/gitops/app/out/wave-note.txtに、同じウェーブの中ではリソースの種類(kind)ごとのデフォルトの順序で適用されるという点を書いてください。 /root/gitops/repo/apps/web/presync-job.yamlに、kind: Jobのフックリソースを作ってください。アノテーションとしてargocd.argoproj.io/hook: PreSyncとargocd.argoproj.io/hook-delete-policy: BeforeHookCreationを入れ、コンテナ名はmigrate、spec.backoffLimitは1、PodのrestartPolicyはNeverにしてください。このディレクトリで、フックのアノテーションが付いたファイルはこの1つだけである必要があります。argocdネームスペースに、kind: AppProject、metadata.name: platformを作ってください。spec.sourceReposにはfile:///root/gitops/repoだけを(*は禁止)、spec.destinations[0]にはserverhttps://kubernetes.default.svcとnamespacegitops-lab(*は禁止)、spec.clusterResourceWhitelistにはgroup""/kindNamespace、spec.namespaceResourceBlacklistにはgroup""/kindResourceQuotaとgroup""/kindLimitRangeを入れてください。Applicationwebのspec.projectはplatformである必要があります。webにspec.ignoreDifferencesを追加してください。groupapps、kindDeployment、jsonPointersに/spec/replicas(HPAが所有するフィールド)です。そしてspec.revisionHistoryLimitを5にしてください。最後に、/root/gitops/app/out/gitops-report.jsonを作ってください。applicationsは、argocdネームスペースのすべてのApplicationを{"name": "..."}の形で入れた配列で、projectは"platform"、self_healはtrueです。
参考
Applicationが指すリポジトリは、このPodの中のローカルパスです。前のラボを別のPodで行った場合は、/root/gitops/repoが空なので、ステップ5でフィクスチャ(/opt/lab/fixtures/gitops/seed/)からもう一度作る必要があります。宣言が指す対象が実際に存在するかを確認することも、GitOpsの仕事です。- この環境にはリモートのgitがないので、
repoURLがローカルパス(file://)です。実務ではhttps://やgit@のアドレスが来て、そのリポジトリの認証情報は、argocdネームスペースのSecret(argocd.argoproj.io/secret-type: repositoryラベル)で管理します。 - マニフェストは
kubectl apply -f 파일で作ればよいです(プレースホルダーはファイルです)。CRDが先に登録されていて初めて、Application型を認識します。 - ステップ8のレポートは、手で個数を合わせず、クラスターに尋ねた結果で作ってください。
kubectl get application -n argocd -o jsonをjqで加工すれば、アプリが増えても個数が自動で合います。 - よくあるミス1は、sync waveの値を
argocd.argoproj.io/sync-wave: -1のように引用符なしで書くことです。アノテーションの値は文字列でなければならず、引用符がないとYAMLパーサーが数値として読んで、適用そのものが拒否されます。 - よくあるミス2は、フックのアノテーションのキーを1つだと勘違いすることです。
argocd.argoproj.io/hookとargocd.argoproj.io/hook-delete-policyは別のキーで、両方が必要です。
Argo CDのAPI型を登録する
/opt/crds/の下のオフラインCRDバンドルから、Argo CDのCRDが入ったファイルを探し(grep -l applications.argoproj.io /opt/crds/*.yaml)、kubectl apply -fで適用してください。applications.argoproj.ioとappprojects.argoproj.ioの2つのCRDができて、Established条件がTrueであり、ネームスペースargocdがある必要があります。登録された型の一覧を/root/gitops/app/out/crds.txtに保存してください(applicationsという文字列が入っている必要があります)。
インターネットがないので、オフラインのCRDバンドルを使います。ファイル名を覚える代わりに、中身で探してください。どのファイルにapplications.argoproj.ioが入っているかは、grepで探せます。
Applicationのソースと対象を定義する
argocdネームスペースに、kind: Application、metadata.name: webのオブジェクトを作ってください。spec.source.repoURLはfile:///root/gitops/repo、spec.source.pathはapps/web、spec.source.targetRevisionはmain、spec.destination.serverはhttps://kubernetes.default.svc、spec.destination.namespaceはgitops-lab、spec.projectはplatformです。
Applicationオブジェクト自身がある場所と、デプロイ先のネームスペースは別です。sourceには、どこから・どこを・どのリビジョンで読むかの3つがすべて必要です。
自動同期・整理・自己修復を有効にする
webのspec.syncPolicy.automatedを追加して、prune: true、selfHeal: trueにしてください。そして/root/gitops/app/out/prune-note.txtに、pruneを有効にしたときのリスク(パスを誤って指したコミット1つが、大量削除につながる)を、韓国語で2、3行書いてください。
automatedの下のスイッチ2つは、別々の仕事をします。1つはリポジトリから消したものを処理し、もう1つはクラスターで変わったものを処理します。危険なほうが何かも書く必要があります。
同期オプションとリトライのバックオフを入れる
webのspec.syncPolicy.syncOptionsにCreateNamespace=trueとServerSideApply=trueを入れ、spec.syncPolicy.retryにlimit: 3、backoff.duration: 10s、backoff.factor: 2、backoff.maxDuration: 5mを入れてください。
syncOptionsは、키=값の形の文字列の配列です(プレースホルダーは、順にキーと値です)。リトライは回数だけでは足りず、間隔がだんだん開くようにする値が3つ必要です。
sync waveでデプロイの順序を作る
リポジトリ/root/gitops/repoがまだなければ、先に作ってください。/opt/lab/fixtures/gitops/seed/のdeployment.yamlとservice.yamlを/root/gitops/repo/apps/web/にコピーして、git initしたあとコミットすれば済みます。そのあと、リポジトリ/root/gitops/repo/apps/web/のservice.yamlにargocd.argoproj.io/sync-wave: "-1"アノテーションを、deployment.yamlにargocd.argoproj.io/sync-wave: "0"アノテーションを追加してください。値は必ず二重引用符で囲んだ文字列でなければなりません。そして/root/gitops/app/out/wave-note.txtに、同じウェーブの中ではリソースの種類(kind)ごとのデフォルトの順序で適用されるという点を書いてください。
ウェーブの値はアノテーションで、数値ではなく二重引用符で囲んだ文字列で書きます。先に作るべきものにより小さい値を、必要なら負の数を与えます。順序を作るには、ファイルが2つ以上必要です。
PreSyncフックのJobを書く
/root/gitops/repo/apps/web/presync-job.yamlに、kind: Jobのフックリソースを作ってください。アノテーションとしてargocd.argoproj.io/hook: PreSyncとargocd.argoproj.io/hook-delete-policy: BeforeHookCreationを入れ、コンテナ名はmigrate、spec.backoffLimitは1、PodのrestartPolicyはNeverにしてください。このディレクトリで、フックのアノテーションが付いたファイルはこの1つだけである必要があります。
フックは、たいていJobです。アノテーションが2つ必要で、1つはどの段階か、もう1つはいつ片付けるかを決めます。削除ポリシーを抜くと、フックのリソースが積み上がり続けます。
AppProjectで境界を引く
argocdネームスペースに、kind: AppProject、metadata.name: platformを作ってください。spec.sourceReposにはfile:///root/gitops/repoだけを(*は禁止)、spec.destinations[0]にはserverhttps://kubernetes.default.svcとnamespacegitops-lab(*は禁止)、spec.clusterResourceWhitelistにはgroup""/kindNamespace、spec.namespaceResourceBlacklistにはgroup""/kindResourceQuotaとgroup""/kindLimitRangeを入れてください。Applicationwebのspec.projectはplatformである必要があります。
許可リストは「書かれたものだけを許可」、拒否リストは「書かれたものだけを禁止」です。リポジトリとネームスペースに*を使うと、プロジェクトを分けた意味がなくなります。アプリをそのプロジェクトに所属させることも、忘れないでください。
無視するフィールドを指定して構成レポートを作る
webにspec.ignoreDifferencesを追加してください。groupapps、kindDeployment、jsonPointersに/spec/replicas(HPAが所有するフィールド)です。そしてspec.revisionHistoryLimitを5にしてください。最後に、/root/gitops/app/out/gitops-report.jsonを作ってください。applicationsは、argocdネームスペースのすべてのApplicationを{"name": "..."}の形で入れた配列で、projectは"platform"、self_healはtrueです。
ほかのコントローラーが所有するフィールドまで元に戻すと、無限同期になります。レポートのアプリの個数は、手で数えず、クラスターに尋ねた結果で作ってください。そうすれば、常に実際と一致します。