目次
20 章

GitOps

マニフェストの source of truth を git に置き、クラスタ内のコントローラが git を watch して自動的に同期する運用モデルを扱います。push モデルと pull モデルの違い、GitOps の4原則、ArgoCD の Application CRD・App of Apps・Sync Wave、Flux の GitRepository・Kustomization・HelmRelease、ディレクトリ構造のパターン、そして秘密を git に置く3つの標準ツールまでを一連の流れで整理して3部を締めくくります。

3部の最後の章です。第15章 CNI 深掘り から 第19章 可観測性 までクラスタのデータプレーン・権限・ポリシー・拡張・観測を一層ずつ積み上げてきました。本章はそのすべてのマニフェストがクラスタに入る 方式自体 を扱います — GitOps です。kubectl apply を人が手で回す代わりに、マニフェストの source of truth を git に置き、クラスタ内のコントローラが git を watch して自動的に同期する運用モデルです。ArgoCD と Flux がこのモデルの2つの標準実装で、3部の最後の章として2つのツールのモデル・運用パターン・3部の振り返り・4部の案内までを一連の流れで整理します。

本章の終わりには 運用クラスタの変更が人の手ではなく git PR を経て自動的に流れる形 が手に入ります。第4章 Deployment と ReplicaSet §「replicas 調整」で押さえた「宣言型マニフェストが常に真実の出所」が本格的な運用モデルとして固まる段階です。

Push モデルと Pull モデル #

まず GitOps が登場する前の標準だったモデルと比較してみます。CI / CD パイプラインがクラスタにマニフェストを適用する方式は大きく2つの系統です。

モデル流れ
PushCI パイプラインがクラスタの API サーバーに直接 kubectl apply。CI システムがクラスタ資格情報を保有
Pull (GitOps)クラスタ内のコントローラが git を watch。マニフェストが変更されるとコントローラが自動的に同期

伝統的な CD パイプラインは push モデルでした。GitHub Actions や Jenkins がビルド後 kubectl apply -f manifests/ を回して終わりでした。このモデルの問題は3つです。

  • CI システムがクラスタの強い資格情報を持っている — CI システムが侵害されるとクラスタも侵害されます。
  • Drift が見えない — 誰かがクラスタに直接 kubectl edit を回すと git のマニフェストと実際のクラスタがずれますが、そのずれを検知する標準メカニズムがありません。
  • 複数のクラスタへの拡張が難しい — クラスタ N 個に同じマニフェストを適用するには N 回 kubectl apply を回さなければなりません。

GitOps モデルはこの3つを一度に解いた方式です。クラスタ内のコントローラが git を watch するので外部でクラスタ資格情報を持っている必要がなく、そのコントローラが同期状態をずっと見ているので drift を自動的に検知し、各クラスタが自分の git を watch するモデルなので N 個への拡張が自然です。

GitOps の4原則 #

OpenGitOps プロジェクトが整理した GitOps の4原則は次の通りです。

原則意味
Declarativeシステムの desired state が宣言的に表現される
Versioned and Immutabledesired state が git のような変更不可能な保存所に保管される
Pulled Automatically承認された変更が自動的にシステムに適用される
Continuously Reconciledコントローラが desired state と実際の state の差を継続的に狭める

K8s のマニフェストは declarative で、git は versioned + immutable です。ArgoCD と Flux がその上に pull + reconciliation を足して GitOps を完成させます。第1章 Kubernetes とは で見た reconcile loop モデルがクラスタ内のコントローラ段を越えてクラスタ・git 間の同期にまで拡張された形です。

ArgoCD — Application CRD 中心のモデル #

ArgoCD は Intuit が作って CNCF に寄贈した GitOps ツールです。最大の特徴は 豊富なウェブ UI です。クラスタのすべての Application の同期状態、drift、マニフェストの変更履歴を1つの画面で見られるので運用チームの参入障壁が低いです。

Application CRD — ArgoCD の単位 #

ArgoCD が git からマニフェストを取ってきてクラスタに同期する単位が Application CRD です。第18章 CRD と Operator パターン のモデルが GitOps ツールにもそのまま適用された例です。

application-my-app.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-app
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/myorg/manifests.git
    targetRevision: main
    path: apps/my-app/overlays/prod
  destination:
    server: https://kubernetes.default.svc
    namespace: my-app
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
      - CreateNamespace=true

このマニフェストが ArgoCD に適用されると次のことが自動的に起こります。

  1. ArgoCD コントローラが repoURLpath ディレクトリを git から取ってくる
  2. Kustomize / Helm / 一般 YAML を自動認識してマニフェストをレンダリング
  3. クラスタの destination に同期 (automated.selfHeal: true なので drift を自動復旧)
  4. git のマニフェストが変更されると自動的に再同期 (automated)
  5. git から消えたオブジェクトはクラスタからも削除 (prune: true)

App of Apps — Application の束ね管理 #

複数の Application を1ヶ所で管理するパターンが App of Apps です。1つの Application の source が他の Application マニフェストたちが入っているディレクトリを指す構造です。

App of Apps ディレクトリ構造
manifests/
  apps/
    root.yaml              ← ルートApplication (ArgoCDにmanual適用)
    children/
      app-a.yaml           ← Application: app-a
      app-b.yaml           ← Application: app-b
      app-c.yaml           ← Application: app-c
  ...

ルート Application 1個だけを ArgoCD に最初に登録すると、その中で子 Application たちが順に作られ、各子 Application が再び自分のマニフェストを同期します。クラスタに新しいアプリを追加するには git に新しい子 Application 1枚を追加するだけで終わりです。

Sync Wave — 順序のある適用 #

マニフェスト適用に順序が必要な場合があります — Namespace を先に作り、その中に ConfigMap を作り、その次に Deployment を起動する順序。ArgoCD は annotation でこの順序を表現します。

順序表現 — argocd.argoproj.io/sync-wave
metadata:
  annotations:
    argocd.argoproj.io/sync-wave: "0"   # Namespace
---
metadata:
  annotations:
    argocd.argoproj.io/sync-wave: "1"   # ConfigMap, Secret
---
metadata:
  annotations:
    argocd.argoproj.io/sync-wave: "2"   # Deployment, StatefulSet

低い wave が先に適用され、その wave のオブジェクトがすべて healthy 状態になった後に次の wave が進行します。CRD を先に作ってその CRD のインスタンスを適用するパターンが最もよく出会う使いどころです。

Flux — 小さなコンポーネントの束 #

Flux は Weaveworks が作った GitOps ツールで ArgoCD と同じカテゴリのツールですがアプローチが違います。Flux v2 は1つの大きなコンポーネントではなく 複数の小さなコントローラの束 として設計されています。

Flux コントローラ役割
source-controllergit / Helm 保存所 / OCI イメージからマニフェストを fetching
kustomize-controllerKustomize マニフェストを適用
helm-controllerHelmRelease オブジェクトで Helm チャートを適用
notification-controllerSlack / Teams / GitHub などにイベントを通知
image-automation-controllerコンテナイメージの新バージョンを git に自動 commit

各コントローラが自分の CRD を持ち、その CRD のマニフェストですべての動作が表現されます。

GitRepository + Kustomization — Flux の基本の束 #

git 保存所の登録
apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
  name: manifests
  namespace: flux-system
spec:
  interval: 1m
  url: https://github.com/myorg/manifests.git
  ref:
    branch: main
---
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: my-app
  namespace: flux-system
spec:
  interval: 5m
  path: ./apps/my-app/overlays/prod
  prune: true
  sourceRef:
    kind: GitRepository
    name: manifests
  targetNamespace: my-app

GitRepository が git を watch し、Kustomization がその git の1つのディレクトリをクラスタに適用します。2つのオブジェクトの分離のおかげで同じ git を複数の Kustomization が異なる path で指せます。

HelmRelease — Helm チャートの GitOps 化 #

HelmRelease — Helm チャートもマニフェストで表現
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
  name: prometheus
  namespace: monitoring
spec:
  interval: 10m
  chart:
    spec:
      chart: kube-prometheus-stack
      version: "55.x"
      sourceRef:
        kind: HelmRepository
        name: prometheus-community
  values:
    prometheus:
      prometheusSpec:
        retention: 30d

helm install を手で回す代わりに HelmRelease マニフェストで表現すると Helm チャートのインストール・アップグレードも GitOps の流れの中に入ります。第19章 の kube-prometheus-stack も同じ形で GitOps の中に束ねられます。

ArgoCD vs Flux — 選択の肌合い #

次元ArgoCDFlux
モデル1つの大きなコンポーネント + 豊富な UI小さなコントローラの束 + CLI 中心
参入障壁低い (UI で開始)中間 (CRD マニフェストで開始)
マルチテナンシーAppProject で表現namespace 単位の分離
マルチクラスタ1つの ArgoCD が複数のクラスタを管理可能各クラスタに Flux 1個 (hub-spoke 可能)
Helm サポート1級HelmRelease CRD で1級
イメージ自動更新argocd-image-updater (別途)image-automation-controller (内蔵)

選択の肌合いは普通次を辿ります。

  • 運用チームが GUI を好み、1つの画面ですべてのクラスタを見たいなら ArgoCD が自然です。
  • すべての運用をマニフェストで表現したく、小さなコンポーネントの束を好むなら Flux がよく合います。

2つのツールとも CNCF 卒業プロジェクトで運用規模に固まっています。一方を誤って選んで大きな事故になる種類の決定ではありません。第24章 CI / CD パイプライン では GitHub Actions と ArgoCD の連携 — ビルド結果のイメージタグが git PR で入ってきて ArgoCD が自動同期する流れ — を本格的に扱います。

ディレクトリ構造のパターン #

GitOps repo のディレクトリ構造は運用チームのスタイルによって分かれますが、よく見るパターンが2つあります。

1. env-per-folder — 環境別の分岐 #

環境を最上位に
manifests/
  base/
    my-app/
      deployment.yaml
      service.yaml
  envs/
    dev/
      kustomization.yaml      ← base + dev patch
    staging/
      kustomization.yaml
    prod/
      kustomization.yaml

Kustomize の base + overlay パターンをそのまま活用した構造です。環境別の違い (replicas、image tag、resources) が overlay にパッチとして入ります。第7章 Namespace とラベル で押さえた環境別マニフェスト一式パターンがこのディレクトリ構造の上で本格的に回ります。

2. app-per-folder + branch-per-env #

アプリを最上位に、環境はブランチに
manifests/        (main branch = prod)
  apps/
    my-app/
      deployment.yaml
      service.yaml
    other-app/
      ...

manifests-dev/    (dev branch)
manifests-staging/ (staging branch)

ブランチを環境分岐として使うモデルです。環境の違いが commit で表現されて audit が自然ですが、ブランチ間の sync 負担が大きいです。

運用では env-per-folder がよく使われます。変更の流れが1つのブランチ (main) の中で起こるので PR レビューが単純です。

Secret を git にどう載せるか #

GitOps の大きな宿題の1つが秘密を git に置く道です。K8s Secret を平文で git に載せることはできません。標準ツールが3つあります。

ツールモデル
Sealed SecretsBitnami が作ったツール。秘密を SealedSecret に暗号化して git に載せる。クラスタ内のコントローラが自分の鍵でのみ復号可能
External Secrets Operatorgit には外部の秘密保存所 (AWS Secrets Manager、Vault など) の参照だけを置き、コントローラが K8s Secret へ同期
SOPS + age / PGPgit に暗号化された YAML を直接載せる。ArgoCD / Flux ともに SOPS 統合をサポート

External Secrets Operator が最もよく使われる道です。秘密の source of truth が外部の保存所にあり、K8s にはその参照だけが入ってくるので秘密の回転が外部の保存所で一度に終わります。第16章 RBAC / ServiceAccount 深掘り の IRSA と連携すれば秘密保存所へのアクセス資格情報すらクラスタの中に静的に置かずに済みます。3つのツールの本格的な運用比較は 第29章 シークレット運用 で扱います。

運用時に固めておく原則 #

1. auto-sync vs manual sync — 環境別の分岐 #

syncPolicy.automated をオンにしておくと git の変更が即座にクラスタに反映されます。dev / staging は自動、prod は手動 (または PR マージ後に自動) と系統を分けるのが一般的です。prod に自動 sync をかけるときは syncOptions: PruneLast=true で削除を最後に処理するなどの安全装置を一緒に固めます。

2. drift detection の意味 #

GitOps コントローラは git と実際のクラスタの差を継続的に比較します。誰かが kubectl edit で直接修正するとその変更は即座に drift として検知され、selfHeal: true なら git のマニフェストで再び上書きします。これが GitOps の強みですが、同時に罠でもあります — コントローラが自動生成するフィールド (status、自動ラベル) は drift のように見えてはいけません。 ArgoCD / Flux ともに ignoreDifferences 設定で無視するフィールドを書けます。第18章 §「status subresource」がこの drift 問題を CRD 次元で事前に分離しておくパターンです。

3. Helm value 変更の影響 #

HelmRelease の values を変えるとそのチャートが作ったすべてのオブジェクトが再デプロイされます。意図しない再デプロイが起こらないよう values 変更の影響範囲を PR 段階で dry-run で事前に確認するのがよいです。第17章 Admission Controller の dry-run 漸進的導入パターンが GitOps 同期とそのまま連動します — ポリシーの dry-run も GitOps の dry-run も同じ方向の安全装置です。

4. マルチクラスタの hub-spoke モデル #

クラスタ N 個を GitOps で管理するとき標準モデルが2つあります。

  • 各クラスタが自分の GitOps コントローラを持つ — クラスタが自己完結的、外部依存が少ない
  • 1つの hub クラスタの GitOps コントローラが spoke クラスタたちを管理 — 運用の単純化、hub の可用性が critical

ArgoCD は2つのモデルともよく合い、Flux は1つ目のモデルが自然です。

3部の振り返り — 深さ6章で手に入ったもの #

3部の最後の章なので一度押さえておきます。1部がマニフェスト1枚のモデルを、2部がそのマニフェストが運用クラスタで回る深さを、3部がその上にポリシーエンジン・拡張・観測・同期の深さを一層ずつ足しました。

  • 第15章CNI 深掘り。K8s ネットワークモデルの4条件、CNI インターフェース、iptables / IPVS / eBPF のデータプレーン、Calico と Cilium の比較。
  • 第16章RBAC / ServiceAccount 深掘り。Aggregated ClusterRole、Impersonation、projected token、IRSA / Workload Identity で K8s ServiceAccount をクラウド IAM と接続。
  • 第17章Admission Controller。API サーバーの5段階の流れ、mutating / validating webhook、OPA Gatekeeper と Kyverno のポリシーエンジン比較。
  • 第18章CRD と Operator パターン。K8s API 自体を拡張する道、controller-runtime ベースの Operator の骨格、ownerReference / finalizer / status subresource。
  • 第19章可観測性。メトリクス / ログ / トレースの3つの軸、Prometheus + kube-state-metrics、Loki、OpenTelemetry、Grafana、Alertmanager。
  • 第20章 (本章)GitOps。マニフェストの source of truth を git に置く運用モデル、ArgoCD と Flux、ディレクトリ構造と秘密管理。

この6章をすべて辿った時点なら K8s を導入して運用する人の視野 — 「どの CNI を導入するか、どのポリシーエンジンを導入するか、どの可観測性スタックを選ぶか、GitOps パイプラインをどう組むか」を決定する段階の視野が手に入ります。

練習問題 #

  1. ArgoCD をローカルクラスタにインストールし、自分のマニフェスト保存所を指す Application 1枚を作ってみます。automated.selfHeal: true にしておき、その後 kubectl edit でクラスタのオブジェクトを直接修正してみます。ArgoCD が drift を検知して git のマニフェストで自動復旧する流れを時間順に記録し、§「drift detection の意味」のモデルで一段落で整理します。
  2. 自分のマニフェスト保存所を env-per-folder 構造に再構成してみます。base/envs/dev/envs/staging/envs/prod/ に分けておき、dev と prod の replicas・image tag がどう overlay として表現されるかを整理します。第7章 のネームスペース分離とこのディレクトリ構造がどう対をなすかを一段落でメモします。
  3. Sealed Secrets、External Secrets Operator、SOPS の3つのツールのモデルを §「Secret を git にどう載せるか」の表で比較した後、自分のクラスタ環境 (EKS / GKE / オンプレミス、外部の秘密保存所の使用有無) に照らしてどのツールを選ぶかを一段落で決定します。第16章 の IRSA / Workload Identity と連携したときどのツールが「パスワード0」運用に最も滑らかに当てはまるかも一緒に推論します。

一行まとめ: GitOps はマニフェストの source of truth を git に置き、クラスタ内のコントローラが git を watch して pull・reconcile する運用モデルだ。ArgoCD は豊富な UI と Application CRD・App of Apps・Sync Wave が強み、Flux は小さなコントローラの束 (source・kustomize・helm・notification・image-automation) と CLI 中心が強みだ。秘密は Sealed Secrets・External Secrets・SOPS の3つのツールから環境に合わせて選び、IRSA と連携すれば秘密保存所へのアクセスまで静的資格情報なしに運用できる。運用の4ガードレールは環境別の auto-sync 分岐・drift detection の ignoreDifferences・Helm value 変更の影響点検・マルチクラスタの hub-spoke 決定だ。

次の章 #

3部が終わりました。1 ~ 3部が K8s のマニフェストとその運用モデルをマニフェスト次元で理解する道だったとすれば、4部はその上に本物のサービスを1つ載せて運用する一連の流れです。EKS の上にクラスタを最初からセットアップし、アプリ配備の骨格を固め、DB を接続し、CI / CD パイプラインを組み、モニタリング・アラートをかける流れを最初から最後まで辿ります。

4部全体のあらすじは次の通りです。

テーマ
第21章EKS クラスタセットアップ — Terraform・eksctl・IRSA・アドオン
第22章アプリ配備の骨格 — Deployment・Service・Ingress・Helm
第23章DB 連携 — RDS・Secrets Manager・External Secrets・コネクションプール
第24章CI / CD パイプライン — GitHub Actions・ECR・ArgoCD
第25章モニタリング・アラート — Prometheus・CloudWatch・Alertmanager
第26章運用チェックリスト — アップグレード・バックアップ・復旧・コスト・セキュリティ

第21章 EKS クラスタセットアップ からは抽象ではなく本物の導入事例です。Terraform で VPC・IAM・EKS クラスタを最初から作り、ノードグループとアドオンを固め、IRSA と ALB Controller を一緒にインストールする一連の流れを辿ります。

X