TT Lab
はじめる
学ぶ 学習パス コース

GitOpsとArgo CD

マニフェストリポジトリを作りドリフトを捕まえる

TT Labで続きを見る

目標

マニフェストを入れたgitリポジトリを作ってクラスターに適用し、手で作った変更(ドリフト)を検知して、リポジトリを基準に元に戻せるようになります。

なぜ重要なのか

GitOpsのルールは1文です。リポジトリが正しく、クラスターがそれに従う。このルールを守った瞬間から、「今プロダクションで何が動いているか」という質問がgit logで答えられる質問になり、ロールバックはgit revertという平凡な作業になります。反対に、クラスターを直接直す習慣が1つでも残っていると、リポジトリは現実を説明できない文書になり、その瞬間から再現が不可能になります。このラボでkubectl diffを繰り返し使う理由がここにあります。diffは、「宣言と実際がどれだけ離れたか」を終了コードで答えてくれるドリフト計測器であり、Argo CDが画面にOutOfSyncと表示するのとまったく同じ判断を、人の手で行うことです。この環境にはArgo CDコントローラーが動いていないので、そのコントローラーが代わりにやってくれることを、最後のステップで自分でスクリプトに書いてみます。

ステップ

  1. /root/gitops/repoディレクトリを作ってgit initし、そのリポジトリにuser.nameとuser.emailを設定してください。そのあと/root/gitops/repo/README.mdを作って、最初のコミットを残してください(コミットが最低1つ必要です)。
  2. /opt/lab/fixtures/gitops/seed/deployment.yamlとservice.yamlを/root/gitops/repo/apps/web/にコピーしてください。Deploymentはmetadata.labelsにapp.kubernetes.io/managed-by: gitopsを持ち、spec.selector.matchLabelsのapp.kubernetes.io/nameはwebであり、spec.replicasはデフォルト値に任せず明示する必要があります(ここでは2から始めます)。コンテナイメージはnginx:1.27のようにタグが固定された値でなければなりません(:latestは失敗扱いになります)。README.mdもそのまま残っている必要があります。
  3. apps/web/deployment.yaml、apps/web/service.yaml、README.mdの3つのファイルをすべてgit addして追跡させ、10文字以上の意味のあるメッセージでコミットしてください。終わったら、git status --porcelainの出力が空である必要があります。
  4. kubectl apply -n gitops-lab -f /root/gitops/repo/apps/web/で適用し、その出力全体を/root/gitops/out/apply.txtに保存してください。適用後、gitops-labネームスペースにDeploymentwebとServicewebがあり、Deploymentにapp.kubernetes.io/managed-by=gitopsラベルが付いている必要があります。
  5. リポジトリのapps/web/deployment.yamlでspec.replicasを3に直し、コミットメッセージにreplicasという単語を入れてコミットしたあとで、クラスターにもう一度適用してください。終わったら、コミットが2つ以上あり、リポジトリとクラスターのreplicasがどちらも3で、作業ツリーがきれいである必要があります。
  6. 今回はリポジトリに触れず、kubectl scale deploy web -n gitops-lab --replicas=5でドリフトを作ってください。その状態でkubectl diff -n gitops-lab -f /root/gitops/repo/apps/web/の出力を/root/gitops/out/drift-diff.txtに、そのコマンドの終了コードを/root/gitops/out/drift-exit.txtに保存してください。そして/root/gitops/out/drift-note.txtに、手で行った変更が次の適用で元に戻されて消えるという内容を、韓国語で2、3行書いてください。
  7. リポジトリを基準にもう一度適用して、ドリフトをなくしてください。そのあとkubectl diff -n gitops-lab -f /root/gitops/repo/apps/web/をもう一度実行し、そのときの終了コードを/root/gitops/out/clean-exit.txtに保存してください。手で作った5をリポジトリに反映してはいけません。リポジトリのreplicasは3で、作業ツリーはきれいである必要があります。
  8. /root/gitops/sync.shを作って、実行権限を与えてください。このスクリプトは、(a)kubectl diffで適用前の差を確認し、(b)kubectl applyで適用し、(c)git rev-parse HEADでどのコミットを適用したかを記録する必要があります。実行結果として、/root/gitops/out/sync-report.jsonにrepo_commit(現在のHEADの完全なハッシュ)、drift(ブール値のfalse)、applied(適用したオブジェクトの数、2以上)の3つのキーを入れてください。

参考

宣言を入れるリポジトリを初期化する

/root/gitops/repoディレクトリを作ってgit initし、そのリポジトリにuser.nameとuser.emailを設定してください。そのあと/root/gitops/repo/README.mdを作って、最初のコミットを残してください(コミットが最低1つ必要です)。

GitOpsでは、コミット履歴がそのまま監査記録です。リポジトリに誰が変えたかが残るには、user.nameとuser.emailがそのリポジトリに設定されている必要があり、コミットが最低1つ必要です。

アプリごとのマニフェストディレクトリを作る

/opt/lab/fixtures/gitops/seed/deployment.yamlとservice.yamlを/root/gitops/repo/apps/web/にコピーしてください。Deploymentはmetadata.labelsにapp.kubernetes.io/managed-by: gitopsを持ち、spec.selector.matchLabelsのapp.kubernetes.io/nameはwebであり、spec.replicasはデフォルト値に任せず明示する必要があります(ここでは2から始めます)。コンテナイメージはnginx:1.27のようにタグが固定された値でなければなりません(:latestは失敗扱いになります)。README.mdもそのまま残っている必要があります。

フィクスチャをコピーして使いますが、リポジトリは人も読みます。そして、デフォルト値に頼らず、個数とイメージのタグを明示してください。同じコミットが違う結果を生めば、そのリポジトリは状態を定義できません。セレクターがPodのラベルと合っているかも確認してください。

宣言をコミットで固定する

apps/web/deployment.yaml、apps/web/service.yaml、README.mdの3つのファイルをすべてgit addして追跡させ、10文字以上の意味のあるメッセージでコミットしてください。終わったら、git status --porcelainの出力が空である必要があります。

追跡されていないファイルが残っていると、リポジトリはクラスターを定義できません。コミットメッセージは、数か月後にこの1行だけを見て、元に戻すかどうかを判断することになる文章です。

リポジトリの宣言をクラスターに適用する

kubectl apply -n gitops-lab -f /root/gitops/repo/apps/web/で適用し、その出力全体を/root/gitops/out/apply.txtに保存してください。適用後、gitops-labネームスペースにDeploymentwebとServicewebがあり、Deploymentにapp.kubernetes.io/managed-by=gitopsラベルが付いている必要があります。

ディレクトリ全体を一度に適用できます。マニフェストにネームスペースが書かれていないので、コマンドで指定する必要があり、適用結果はファイルに残す必要があります。

変更をコミットを経由して反映する

リポジトリのapps/web/deployment.yamlでspec.replicasを3に直し、コミットメッセージにreplicasという単語を入れてコミットしたあとで、クラスターにもう一度適用してください。終わったら、コミットが2つ以上あり、リポジトリとクラスターのreplicasがどちらも3で、作業ツリーがきれいである必要があります。

順序が核心です。リポジトリを先に直してコミットし、そのあと適用します。クラスターを先に直せば、それは変更ではなくドリフトです。

手で変えてドリフトを作ってみる

今回はリポジトリに触れず、kubectl scale deploy web -n gitops-lab --replicas=5でドリフトを作ってください。その状態でkubectl diff -n gitops-lab -f /root/gitops/repo/apps/web/の出力を/root/gitops/out/drift-diff.txtに、そのコマンドの終了コードを/root/gitops/out/drift-exit.txtに保存してください。そして/root/gitops/out/drift-note.txtに、手で行った変更が次の適用で元に戻されて消えるという内容を、韓国語で2、3行書いてください。

今回はわざとリポジトリに触れず、クラスターだけを変えます。差を示すコマンドの終了コードが何かがこのステップの核心で、そのコードはコマンドの直後に読む必要があります。

リポジトリを基準に元に戻す

リポジトリを基準にもう一度適用して、ドリフトをなくしてください。そのあとkubectl diff -n gitops-lab -f /root/gitops/repo/apps/web/をもう一度実行し、そのときの終了コードを/root/gitops/out/clean-exit.txtに保存してください。手で作った5をリポジトリに反映してはいけません。リポジトリのreplicasは3で、作業ツリーはきれいである必要があります。

手で作った値をこっそりリポジトリに反映すれば、事故をコードに昇格させることになります。リポジトリが正しいと仮定してクラスターを合わせたあと、差がないときの終了コードを確認してください。

同期スクリプトとレポートを作る

/root/gitops/sync.shを作って、実行権限を与えてください。このスクリプトは、(a)kubectl diffで適用前の差を確認し、(b)kubectl applyで適用し、(c)git rev-parse HEADでどのコミットを適用したかを記録する必要があります。実行結果として、/root/gitops/out/sync-report.jsonにrepo_commit(現在のHEADの完全なハッシュ)、drift(ブール値のfalse)、applied(適用したオブジェクトの数、2以上)の3つのキーを入れてください。

コントローラーがやっていることを、シェルで真似ます。適用前に何が変わるかを見て、適用し、どのコミットを適用したかを残します。スクリプトをリポジトリの中に置くと、レポートに書いたハッシュがずれます。