EKS本番運用 Vol3 GitOps ArgoCD Application 環境分離 Sync戦略 Helm Kustomize

目次

1. なぜGitOpsか — Vol1-2からの架橋と「動かす→見える→保つ」三段昇格

1-1. 「このクラスタ、明日も安全か?」— GitOps を必要とした理由

EKS クラスタを動かし、観測可能な状態にした。
次の課題は「状態を保つ」ことだ。

kubectl apply による手動デプロイを続けていると、こんなシーンに遭遇する。

シーン1: 本番と検証の設定ズレ

先週まで正常だった検証環境でのテストが通る。しかし本番にデプロイすると動かない。
調べると、1ヶ月前に本番の ConfigMap が直接 kubectl edit で変更されていた。
検証環境との差異が積み重なり、いつのまにか異なる設定で動き続けていた状態だ。
手動デプロイの怖さは「変更が記録されない」ことにある。

シーン2: デプロイ手順の属人化

本番デプロイ手順は担当者個人のメモに書いてある。担当者が不在の日にリリースが必要になった。
手順書を探すが最新版がどれか分からない。コマンド履歴を掘り起こして何とかデプロイするが、
本当に正しい状態かどうか確認する術がない。
チームが増えるほど「手順の正しさ」を保証することが難しくなる。

シーン3: 誰が何を変えたか分からない

夜中に本番のメトリクスが急変した。CloudWatch で Pod の CPU スパイクを確認するが、
いつ何がデプロイされたか分からない。kubectl で直接変更が加えられた形跡があるが
変更者を特定できない。原因調査が始まっても「何が変わったか」の起点が不明なまま時間が過ぎる。


3つのシーンに共通する根本原因は 「クラスタの状態が Git に記録されていない」 ことだ。

GitOps の着想は単純だ。
「全ての Kubernetes 設定を Git リポジトリに集約し、Git の変更だけがクラスタに反映される」
— これが実現できれば、3つのシーンはすべて防げる。

GitOps の定義:
Git をシステムの「真実の源泉 (Single source of truth)」として、
クラスタ状態を継続的に同期する運用手法。
変更はすべて Git コミットを経由し、エージェントがクラスタを desired state に自動収束させる。

ArgoCD はこの GitOps 原則を EKS 上で実現するツールだ。
Pull 型アーキテクチャで Git の変更を検知し、クラスタへの反映を自動化する。
本記事を通じて ArgoCD の設計と実装を体系的に習得できる。


1-2. Vol1-2 からの架橋 — 三段昇格の集大成

EKS 本番運用シリーズは「動かす → 見える → 保つ」の三段昇格で構成されている。
各 Vol の課題と解決手段を整理しておこう。

ステージ解くべき課題解決手段リンク
Vol1「動かす」クラスタ構築 / IRSA / ALB IngressTerraform + Helm + eksctlVol1 →
Vol2「見える」ログ / メトリクス / トレースFluentBit / ADOT / X-RayVol2 →
Vol3「保つ」継続的デプロイ / Drift 防止 / 環境分離GitOps × ArgoCD本記事

Vol1 でクラスタを動かし、Vol2 で状態を見えるようにした。
Vol3 では「状態を保つ」仕組みを構築する — GitOps がその中核技術だ。

Vol1 で習得した IRSA は Vol3 でも活きる。
ArgoCD の GitHub 認証・ECR イメージ取得・Secrets Manager アクセスに IRSA を使う設計を §3 で解説する。
Vol2 で構築した Container Insights / ADOT は ArgoCD のデプロイ状態の可視化と連携する。
3つの Vol は独立した教材ではなく、本番 EKS 運用の技術スタックの積み重ねだ。

この記事の構成

セクション内容
§1 (本章)GitOps の必要性 / Vol1-2架橋 / 解決できる3つの壁
§2GitOps 全体像 — Pull型 vs Push型 / ArgoCD vs FluxCD / 4原則
§3ArgoCD 設計 — Application/ApplicationSet/AppProject / Repository 構成3パターン
§4環境分離 — dev/staging/prod / Sync戦略 / Sync wave/hook
§5Helm × Kustomize 使い分け / ArgoCD Image Updater
§6IRSA × ArgoCD 権限設計
§7詰まりポイント7選 + 演習5問
§8まとめ / Vol4予告

1-3. GitOps で解決できる3つの壁

§1-1 で挙げた3つのシーンを、GitOps と ArgoCD がどう解決するかを整理する。

壁1: 誰が何をデプロイしたか分からない → Git 履歴で変更を可視化

問題シーン:
深夜に Pod の CPU が急増した。どのデプロイが原因かを調べようとするが、
手動 kubectl apply の履歴はターミナルのスクロールバックにしか残っていない。
変更者を特定できず、原因追跡が困難になる。

GitOps での解決:
全ての変更は Git のプルリクエストを経由する。
コミットメッセージ・レビュアー・マージ時刻がすべて Git 履歴として記録される。
ArgoCD の Activity Log と合わせると「いつ・誰が・何を・なぜ」デプロイしたかをトレースできる。

# ArgoCD CLI でデプロイ履歴を確認
argocd app history my-app

# Git コミット履歴で変更内容を確認
git log --oneline --graph origin/main -- k8s/

壁2: 本番と検証の設定ズレが分からない → ArgoCD Drift 検出

問題シーン:
本番環境で kubectl edit を使って緊急対応した。その後、検証環境に同じ変更を反映し忘れた。
3ヶ月後、本番と検証で全く異なる設定が走り続けていることに気づかず問題が発生する。
設定ズレが積み重なると、再現性のないテスト環境になる。

GitOps での解決:
ArgoCD は Git の desired state とクラスタの actual state を常時比較する (Drift 検出)。
設定ズレが発生すると UI で OutOfSync アラートが表示される。
selfHeal: true を設定すれば、直接変更を自動的に Git 状態へ戻す。

# ArgoCD Application: Auto-Sync + Self-Heal 設定例
spec:
  syncPolicy:
 automated:
selfHeal: true# Drift を自動修正
prune: true# Git 削除時にクラスタからも削除

kubectl edit による直接変更は次の同期サイクル (デフォルト 3分) で上書きされ、
変更の痕跡は ArgoCD の Diff 画面に記録される。


壁3: 設定変更後に正常状態に戻せない → Git を SOT にした切り戻し

問題シーン:
本番で Deployment の image タグを変更したら動作が不安定になった。
手動デプロイだと「直前の正常な設定」がどれか分からず、切り戻しに時間がかかる。
設定の誤りを素早く元に戻す仕組みがないと、問題の影響範囲が拡大する。

GitOps での解決:
Git のコミット履歴が正常状態の記録そのものだ。
ArgoCD では特定コミットへの Rollback を UI または CLI から実行できる。
git revert でコミットを元に戻して push するだけで、ArgoCD が自動的にクラスタを収束させる。

# ArgoCD CLI でロールバック
argocd app rollback my-app <HISTORY_ID>

# または Git revert → push → ArgoCD が自動同期
git revert HEAD~1
git push origin main
# → ArgoCD が変更を検知して自動 Sync

1-4. 本記事で到達できること

本記事を読み終えると、以下5つのゴールを達成できる。

(a) GitOps 原則の習得
Pull 型 vs Push 型の違い・Single source of truth の意味・Declarative/Continuous reconciliation の動作原理を、ArgoCD の実装を通じて理解できる。

(b) ArgoCD 設計の習得
Application / ApplicationSet / AppProject の3階層の役割を整理し、
Mono / Multi / App-of-Apps の Repository 構成3パターンから自分のチーム規模に合う選択基準を持てる。

(c) 環境分離の実装
dev / staging / prod の3環境分離を ArgoCD ApplicationSet と Kustomize overlays で実装し、
環境ごとの値の差異を Helm values / Kustomize patch で安全に管理できる。

(d) Helm × Kustomize の使い分け
Helm Chart のラッパーとして Kustomize を使うパターン・ArgoCD Image Updater による自動イメージ更新・
Sync wave と hook による依存関係制御を実装できる。

(e) 詰まりポイント7選の予防
ArgoCD 導入時に頻出する設定ミス (RBAC 設定不備 / Sync loop / Resource Health 誤検知など) を
事前に把握し、本番導入前に対策を打てる。


EKS本番運用シリーズ ナビゲーション

関連シリーズ: IAM入門 Vol4 (STS × Cross-Account) — Vol3 §3 ArgoCD IRSA 設計の前提知識


2. GitOps全体像 — Pull型 vs Push型 / ArgoCD vs FluxCD / 4原則

GitOps は「Git リポジトリを唯一の信頼源として、クラスタ内のエージェントが継続的に状態を同期する」運用モデルです。従来の CI/CD パイプラインが外部からクラスタへ直接書き込む Push型 に対し、GitOps は Pull型 を採用します。この章では、Push/Pull の構造的な違い・GitOps 4原則・ArgoCD と FluxCD の選定基準・ArgoCD のアーキテクチャを整理します。

fig01: GitOps全体アーキテクチャ (Pull型 / Single source of truth / Continuous reconciliation)

2-1. Push型 vs Pull型 — 構造的な差を理解する

Push型デプロイの仕組みと問題点

従来の CI/CD パイプラインは、ビルド完了後に外部システム (GitHub Actions / Jenkins) が直接 kubectl applyhelm upgrade を実行します。クラスタから見ると「外から書き込まれる」モデルです。

【Push型デプロイフロー】

Developer
  │ git push
  ▼
Git Repository
  │ webhook / polling
  ▼
CI/CD Pipeline (GitHub Actions / Jenkins)
  │ build → test → docker push
  ▼
Container Registry
  │
  ▼
CI/CD Pipeline ──kubectl apply──▶ Kubernetes API Server
  (クラスタ外部) │
 ▼
 クラスタ状態変更

Push型の主な問題点:

問題点詳細
認証情報の管理コストkubectl / helm 用の kubeconfig をCI/CDシステムに配布・ローテーションが必要
ネットワーク境界を越えるCI/CDシステムがクラスタのAPI Serverへ直接到達できる構成が必要
状態ドリフトを検知できないデプロイ後に手動変更があっても CI/CDは検知・修正しない
監査ログが分散Git履歴・CI/CDログ・kubectl audit log が別々に存在する
ロールバックが複雑「いつ・どの状態に戻すか」を手動で判断しコマンドを実行する必要がある

Push型で実際に起きやすい事故シナリオを示します。

【Push型 ドリフト事故シナリオ】

① CI/CDが my-app v1.2 をデプロイ → クラスタ状態 = v1.2
② 深夜の障害対応で担当者が手動で v1.1 に kubectl rollout undo
③ Git上は v1.2 のまま / クラスタ実態は v1.1 → ドリフト発生
④ 翌朝のデプロイで CI/CDが v1.2 を再デプロイ → 意図しない変更
⑤ ドリフト期間中のアクセスログと設定が不一致 → 監査で問題化

GitOps (Pull型) では、②の手動変更を ArgoCD が即座に検出し、Git の Desired State (v1.2) に自動収束させます。手動変更を永続させたい場合は必ず Git にコミットする運用フローを強制できます。

Pull型デプロイの仕組みと利点

GitOps (Pull型) では、クラスタ内部に常駐するエージェント (ArgoCD / Flux) が Git リポジトリを継続的にポーリングし、差分を検出すると自動的に同期します。クラスタ外部から書き込む権限は不要です。

【Pull型デプロイフロー (GitOps)】

Developer
  │ git push (マニフェスト変更)
  ▼
Git Repository (Single source of truth)
  ▲
  │ 定期ポーリング (3分間隔)
  │ Desired State 取得
  │
ArgoCD (クラスタ内部)
  │ Desired State vs Actual State 比較
  │ 差分検出 → kubectl apply
  ▼
Kubernetes API Server
  │
  ▼
クラスタ状態 (Actual State)
  └──比較フィードバック──▶ ArgoCD Application Controller

Pull型の主な利点:

利点詳細
認証情報の外部配布が不要ArgoCD はクラスタ内で動作し ServiceAccount IRSA で Git/ECR にアクセス
ネットワーク境界をまたがないArgoCD → Git (外向きのみ)。外部からAPIサーバへの経路が不要
ドリフトを即時検出・修正Reconciliation Loop が常にDesired/Actualを比較し自動修正
監査ログ = Git履歴git log が完全な変更履歴。git revert でロールバック
宣言的ロールバックGitの任意コミットへ revert するだけで自動適用

ArgoCD の Reconciliation Loop は以下のサイクルで動作します。

【ArgoCD Reconciliation Loop (デフォルト3分間隔)】

┌─────────────────────────────────────────────────────┐
│  ArgoCD Application Controller  │
│ │
│  1. Git リポジトリをポーリング (HTTPS / SSH) │
│  2. Desired State を計算│
│  (Helm template / Kustomize build / plain YAML)│
│  3. Kubernetes API から Actual State を取得  │
│  4. Desired ≠ Actual → OutOfSync 状態に遷移 │
│  5. 自動同期 ON の場合 → kubectl apply 相当を実行 │
│  6. 同期完了 → Synced / Healthy 状態に遷移  │
│  7. 3分後に Step 1 へ戻る │
└─────────────────────────────────────────────────────┘
ArgoCD 同期状態意味対応アクション
Synced / HealthyGit = クラスタ。正常なし
OutOfSyncGit ≠ クラスタ。差分あり自動または手動同期
DegradedPod障害・CrashLoopBackOff等アプリケーションの修正
UnknownAPI Server 到達不能クラスタ接続確認

2-2. GitOps 4原則

GitOps の国際標準化団体 OpenGitOps (CNCF) が定める4原則を理解することで、「なぜ Pull型なのか」の根拠が明確になります。

GitOps 4原則 (OpenGitOps v1.0)

  1. Declarative (宣言的): システムの望ましい状態を宣言的に定義する
    Kubernetes マニフェスト・Helm values・Kustomize overlay がすべて「あるべき姿」の宣言です。手続き的なスクリプト (kubectl set image 等) ではなく、YAML で状態を記述します。
  2. Versioned and Immutable (バージョン管理・不変): Git で全状態をバージョン管理し、過去の状態は書き換えない
    各コミットは特定時点のクラスタ状態のスナップショットです。タグ・ブランチ・コミットハッシュで任意の過去状態を参照でき、監査証跡が自然に生まれます。
  3. Pulled Automatically (自動 Pull): エージェントが自動的に Git から Desired State を取得する
    人間が手動でデプロイコマンドを実行する必要はありません。ArgoCD が定期的に Git をポーリングし、変更を検出すると自動的に同期を開始します。
  4. Continuously Reconciled (継続的収束): エージェントが継続的に Actual State を Desired State に収束させる
    手動変更・障害・スケール変動によってクラスタ状態がずれても、Reconciliation Loop が自動的に修正します。人的ミスによる「設定ドリフト」が構造的に防止されます。

4原則は相互補完的です。宣言的でなければバージョン管理できず、バージョン管理されなければ自動 Pull の基点がなく、自動 Pull なければ継続的収束は成立しません。この4原則をすべて満たすシステムのみが「真の GitOps」と呼べます。

従来の CI/CD パイプラインと GitOps の4原則への準拠状況を比較します。

原則従来 CI/CD (Push型)GitOps (Pull型)
Declarative△ (スクリプトと宣言が混在)✅ YAML のみ
Versioned and Immutable△ (マニフェストはGit管理でもスクリプトはそうでないことも)✅ 全状態を Git 管理
Pulled Automatically❌ 外部システムが Push✅ エージェントが Pull
Continuously Reconciled❌ デプロイ後は放置✅ 常に収束を試みる

この対比から、従来 CI/CD は「デプロイの自動化」にすぎず、GitOps は「クラスタ状態の継続的管理」であることが分かります。GitOps を導入することで、デプロイ後の状態維持・ドリフト修正・ロールバックまでを一貫した宣言的フローで実現できます。

2-3. ArgoCD vs FluxCD — 選定基準

CNCF Graduated プロジェクトとして成熟した ArgoCD と FluxCD を比較します。どちらも GitOps の4原則を満たしますが、運用スタイルと機能セットに明確な違いがあります。

比較軸ArgoCDFluxCD
Web UI✅ 充実 (同期状態・差分可視化・手動同期)❌ なし (CLI / Grafana 連携が前提)
マルチクラスタ✅ 組み込み (ApplicationSet Generator)✅ 組み込み (Kustomization target)
Helm サポート✅ ネイティブ (values override / OCI対応)✅ ネイティブ (HelmRelease CRD)
Kustomize サポート✅ ネイティブ✅ ネイティブ
Progressive DeliveryArgo Rollouts (別プロジェクト)Flagger (別プロジェクト)
CNCF ステータスGraduated (2022)Graduated (2022)
学習曲線中程度 (UI直感的 / CRD数は多い)中程度 (CLI習熟が必要)
GitOps Agent 方式Application Controller (Pod)source-controller / kustomize-controller
IRSA 対応 (EKS)✅ ServiceAccount アノテーションで対応✅ ServiceAccount アノテーションで対応

本記事で ArgoCD を選択する理由:

  1. Web UI による状態可視化: Desired State / Actual State の差分をグラフィカルに確認でき、運用チームの学習コストを下げられます。Vol2 で構築した観測可能性 (Metrics / Logs) と組み合わせると、ArgoCD の同期状態・アプリケーションの健全性・メトリクスを一画面で把握できます。
  2. Kubernetes エコシステムでの採用数 No.1: CNCF Survey 2024 において GitOps ツールとして最多採用。コミュニティ・周辺ツール (Argo Rollouts / Argo Workflows / Argo Events) のエコシステムが充実しています。
  3. ApplicationSet によるマルチクラスタ拡張: 単一の ApplicationSet 定義から dev/stg/prod クラスタへの横展開が宣言的に行えます。§4 で詳細を解説します。

どちらを選ぶべきかの判断基準を整理します。

状況推奨理由
運用チームに UI ベースで確認させたいArgoCDWeb UI が標準装備
GitOps エージェントを Helm で管理したいFluxCDflux-operator の bootstrap が簡潔
Argo Rollouts (Canary / Blue-Green) と組み合わせるArgoCD同一 Argo エコシステム
Notification Controller で Slack 通知を細かく制御FluxCDnotification-controller が標準
組織がセキュリティ審査で OSS ツールを評価中どちらも可両者 CNCF Graduated で同等
学習コストを最小化したい初期フェーズArgoCDドキュメント・日本語資料が豊富

本記事では ArgoCD を使った EKS 本番運用の実装例を §3 以降で詳解します。FluxCD との統合 (ArgoCD + Flux Notification) や移行パターンについては Vol4 で扱います。

2-4. ArgoCD アーキテクチャ概要

ArgoCD は複数の独立したコンポーネントで構成されます。各コンポーネントの役割を理解することで、障害発生時の原因特定と適切なスケーリング設計が可能になります。

【ArgoCD コンポーネント構成図】

  ┌──────────────────────────────────────────────────┐
  │  argocd namespace│
  │ │
  │  ┌─────────────┐ ┌──────────────────────────┐  │
  │  │  API Server │◄───│  Web UI / CLI / CI/CD │  │
  │  └──────┬──────┘ └──────────────────────────┘  │
  │││
  │  ┌──────▼──────────────────────┐│
  │  │  Application Controller  │◄──┐ Git Polling  │
  │  │  (Reconciliation Loop)││  │
  │  └──────┬──────────────────────┘│  │
  ││ kubectl apply  ┌───┴──────────┐│
  │▼ │  Repo Server ││
  │  Kubernetes API Server└──────────────┘│
  └──────────────────────────────────────────────────┘
コンポーネント役割スケーリング
API ServerREST / gRPC / WebSocket。Web UI・CLI・CI/CDからのリクエストを受け付けるHPA 可
Repository ServerGit クローン・マニフェスト生成 (Helm template / Kustomize build)。CPU集約HPA 可
Application ControllerReconciliation Loop の中枢。Desired vs Actual 比較・同期実行StatefulSet (シャード分散)
ApplicationSet ControllerApplicationSet CRD を監視し Application を自動生成単一 Pod
DexOIDC / SAML 認証プロバイダ連携 (GitHub SSO / Okta 等)単一 Pod
RedisApplication Controller のキャッシュ・状態保持HA構成推奨

Application Controller は大規模クラスタで最もリソースを消費するコンポーネントです。Application 数が 100 を超えたら StatefulSet のシャード (--sharding-algorithm オプション) を検討してください。

ArgoCD のインストールと初期セットアップ:

# ArgoCD CLI のインストール (macOS)
brew install argocd

# Linux の場合
curl -sSL -o argocd-linux-amd64https://github.com/argoproj/argo-cd/releases/latest/download/argocd-linux-amd64
sudo install -m 555 argocd-linux-amd64 /usr/local/bin/argocd

# EKS クラスタへ ArgoCD をインストール
kubectl create namespace argocd
kubectl apply -n argocd-f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

# インストール確認 (全 Pod が Running になるまで待機)
kubectl get pods -n argocd -w

# 初期 admin パスワード取得
kubectl -n argocd get secret argocd-initial-admin-secret-o jsonpath="{.data.password}" | base64 -d && echo

# ArgoCD API Server へのアクセス (ポートフォワード)
kubectl port-forward svc/argocd-server -n argocd 8080:443

# CLI ログイン
argocd login localhost:8080 --username admin --insecure

# クラスタ登録確認
argocd cluster list

インストール後、Web UI (https://localhost:8080) にブラウザでアクセスすると、Application の同期状態・Desired/Actual の差分・Resource Tree をグラフィカルに確認できます。§3 以降でこの UI を活用した Application 設計を実践します。


3. ArgoCD設計実践 (山場1) — Application/ApplicationSet/AppProject + Repository構成3パターン

3-1. ArgoCD 3階層リソース詳解

ArgoCD は Application / AppProject / ApplicationSet の3階層でデプロイを管理します。それぞれの役割を正しく理解することで、マルチ環境・マルチチームの GitOps 運用を安全に設計できます。

Application — デプロイの最小単位

Application は「どの Git リポジトリの・どのパスを・どのクラスタの・どの Namespace に同期するか」を定義するリソースです。

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-app
  namespace: argocd
spec:
  project: production
  source:
 repoURL: https://github.com/my-org/my-app-config
 targetRevision: main
 path: k8s/overlays/prod
  destination:
 server: https://kubernetes.default.svc
 namespace: my-app
  syncPolicy:
 automated:
prune: true
selfHeal: true
 syncOptions:
- CreateNamespace=true
フィールド説明
project所属する AppProject(権限境界)
source.repoURLマニフェストを取得する Git リポジトリ
source.targetRevisionブランチ / タグ / コミット SHA
source.pathリポジトリ内のマニフェストディレクトリ
destination.serverデプロイ先クラスタの API サーバ URL
syncPolicy.automated.pruneGit 削除に追随して K8s リソースも削除
syncPolicy.automated.selfHeal手動変更を自動で Git 状態に戻す

AppProject — 環境ごとの権限境界

AppProject は「どのリポジトリからマニフェストを取得できるか」「どの Namespace にデプロイできるか」を制限するリソースです。本番 / ステージング / 開発 の各環境ごとに作成し、権限を分離します。

apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
  name: production
  namespace: argocd
spec:
  description: Production environment — restricted access
  sourceRepos:
  - 'https://github.com/my-org/*'
  destinations:
  - namespace: 'prod-*'
 server: https://kubernetes.default.svc
  clusterResourceWhitelist:
  - group: ''
 kind: Namespace
  namespaceResourceWhitelist:
  - group: apps
 kind: Deployment
  - group: ''
 kind: Service
  roles:
  - name: read-only
 description: Read-only access for audit
 policies:
 - p, proj:production:read-only, applications, get, production/*, allow

sourceRepos でリポジトリを制限し、destinations で Namespace を prod-* パターンに絞ることで、開発チームが誤って本番クラスタにデプロイすることを防ぎます。

ApplicationSet — マルチクラスタ / マルチ環境の一括管理

ApplicationSet は Generator(list / cluster / git / matrix など)を使い、複数クラスタや複数環境に対して Application を動的に生成します。

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: my-app-set
  namespace: argocd
spec:
  generators:
  - list:
elements:
- cluster: dev
  url: https://dev-cluster.example.com
  env: dev
- cluster: staging
  url: https://staging-cluster.example.com
  env: staging
- cluster: prod
  url: https://prod-cluster.example.com
  env: prod
  template:
 metadata:
name: 'my-app-{{cluster}}'
 spec:
project: '{{env}}'
source:
  repoURL: https://github.com/my-org/my-app-config
  targetRevision: main
  path: 'k8s/overlays/{{env}}'
destination:
  server: '{{url}}'
  namespace: my-app
syncPolicy:
  automated:
 prune: true
 selfHeal: true

{{cluster}} / {{env}} / {{url}} のテンプレート変数が Generator の各要素で展開され、3クラスタ分の Application が自動生成されます。新しい環境を追加する際は Generator の elements に1行追加するだけです。

fig02: ArgoCD Application × ApplicationSet × AppProject 構造図

ArgoCD 3階層リソース 5鉄則

  1. AppProject は環境ごとに作成: prod / staging / dev を同一 AppProject で管理すると権限分離が崩れる。最低3 AppProject を作成する
  2. Application は1デプロイ単位: 1 Application = 1 Git path の原則を守り、複数マイクロサービスを1 Application に混在させない
  3. ApplicationSet はマルチ展開専用: 単一クラスタ・単一環境への展開に ApplicationSet は使わない(YAML が複雑化する)
  4. source.path は環境別 overlay を指定: Kustomize overlay(k8s/overlays/prod)を指定し、環境差分は overlay で管理する
  5. selfHeal は本番のみ有効化: 開発環境で selfHeal を有効にすると手動テストの変更が即時消える。本番の設定ドリフト検知に絞って使う

3-2. Repository 構成3パターン — Mono-repo / Multi-repo / App-of-Apps

GitOps における Repository 設計は運用コストとスケーラビリティに直結します。3つのパターンを5軸で比較します。

評価軸Mono-repoMulti-repoApp-of-Apps
リポジトリ数1マイクロサービス数2以上(管理用 + アプリ用)
権限管理ブランチ保護のみリポジトリ単位で細分化管理リポジトリで全体制御
スケール小〜中規模(〜20サービス)中〜大規模(20+サービス)大規模(50+サービス)
管理コスト高(リポジトリ数に比例)中(管理 repo の設計次第)
CI/CD連携シンプル(1パイプライン)複雑(サービスごとにパイプライン)中程度(管理 repo の CI で一元化可)

Mono-repo ディレクトリ構造例

my-app-config/
├── k8s/
│├── base/# 共通マニフェスト
││├── deployment.yaml
││└── service.yaml
│└── overlays/
│ ├── dev/# 開発環境差分
│ │└── kustomization.yaml
│ ├── staging/
│ └── prod/  # 本番環境差分
│  └── kustomization.yaml
└── apps/ # ArgoCD Application マニフェスト
 ├── app-a.yaml
 └── app-b.yaml

Multi-repo ディレクトリ構造例

# サービスごとにリポジトリを分割するパターン
service-a-config/# サービスAのマニフェストリポジトリ
├── k8s/
│├── base/
│└── overlays/
│ ├── dev/
│ └── prod/
└── .argocd-source-app.yaml

service-b-config/# サービスBのマニフェストリポジトリ
├── k8s/
│├── base/
│└── overlays/
│ ├── dev/
│ └── prod/
└── .argocd-source-app.yaml

各サービスが独自のリポジトリを持つことでアクセス権限をリポジトリ単位に設定できますが、リポジトリ数がマイクロサービス数に比例して増加するため、20 サービスを超えると管理が複雑になります。

App-of-Apps パターン構造例

argocd-apps/# 管理リポジトリ (ArgoCD Application の管理)
├── bootstrap/
│└── root-app.yaml# Root Application (argocd-apps 全体を管理)
├── apps/
│├── app-a.yaml# 個別アプリの Application マニフェスト
│├── app-b.yaml
│└── monitoring.yaml # Prometheus / Grafana なども Application 化
└── projects/
 ├── production.yaml # AppProject マニフェスト
 └── staging.yaml

App-of-Apps では「ArgoCD Application を管理する Application」を作ることで、すべてのアプリの同期状態を1つの Root Application から俯瞰できます。新しいマイクロサービスを追加する場合は apps/ ディレクトリに YAML を1ファイル追加するだけです。


3-3. Mermaid01: GitOps Sync フロー

sequenceDiagram
 participant Dev as 開発者
 participant Git as Git Repository
 participant ArgoCD as ArgoCD Controller
 participant K8s as Kubernetes API

 Dev->>Git: git push (マニフェスト更新)
 Git->>ArgoCD: Webhook 通知 (または 3分ポーリング)
 ArgoCD->>Git: マニフェスト取得 (source.path)
 ArgoCD->>K8s: 現在の状態取得 (Desired vs Actual)
 Note over ArgoCD: OutOfSync 検出
 ArgoCD->>K8s: kubectl apply (同期実行)
 K8s-->>ArgoCD: 同期完了通知
 ArgoCD->>ArgoCD: Sync ステータス → Synced / Healthy 更新

開発者が Git にプッシュすると ArgoCD は Webhook(または 3 分間隔のポーリング)で変更を検知します。Desired State(Git のマニフェスト)と Actual State(K8s クラスタの実態)を比較し、差分が検出されると自動で kubectl apply を実行します。syncPolicy.automated.selfHeal: true を設定した場合、手動で kubectl edit した変更も Git の状態に自動で戻ります。


3-4. Vol1 架橋 — ArgoCD IRSA 設定 + ALB Ingress による Web UI 公開

ArgoCD Application Controller への IRSA 付与

ArgoCD Application Controller が AWS リソース(ECR / S3 / Secrets Manager など)にアクセスする場合、EKS本番運用Vol1 §4 IRSA設計 で学んだ IRSA の仕組みを適用します。

ArgoCD Application Controller 用の IAM Role を Terraform で作成します。

data "aws_iam_policy_document" "argocd_trust" {
  statement {
 effect  = "Allow"
 actions = ["sts:AssumeRoleWithWebIdentity"]

 principals {
type  = "Federated"
identifiers = [aws_iam_openid_connect_provider.eks.arn]
 }

 condition {
test  = "StringEquals"
variable = "${replace(aws_iam_openid_connect_provider.eks.url, "https://", "")}:sub"
values= ["system:serviceaccount:argocd:argocd-application-controller"]
 }

 condition {
test  = "StringEquals"
variable = "${replace(aws_iam_openid_connect_provider.eks.url, "https://", "")}:aud"
values= ["sts.amazonaws.com"]
 }
  }
}

resource "aws_iam_role" "argocd_controller" {
  name= "${local.cluster_name}-argocd-controller-irsa"
  assume_role_policy = data.aws_iam_policy_document.argocd_trust.json
}

resource "aws_iam_role_policy" "argocd_ecr" {
  name = "argocd-ecr-read"
  role = aws_iam_role.argocd_controller.id

  policy = jsonencode({
 Version = "2012-10-17"
 Statement = [
{
  Effect= "Allow"
  Action= ["ecr:GetAuthorizationToken", "ecr:BatchGetImage", "ecr:GetDownloadUrlForLayer"]
  Resource = "*"
}
 ]
  })
}

IAM Role 作成後は kubectl annotate でアノテーションを設定します。

# ArgoCD Application Controller の ServiceAccount に IAM Role をアノテーション
kubectl annotate serviceaccount argocd-application-controller-n argocdeks.amazonaws.com/role-arn=arn:aws:iam::123456789012:role/ArgoCD-Controller-Role

# 設定確認
kubectl get serviceaccount argocd-application-controller -n argocd -o yaml| grep "role-arn"

# OIDC Provider URL 確認 (信頼ポリシー作成時に必要)
aws eks describe-cluster--name my-eks-cluster--query "cluster.identity.oidc.issuer"--output text

IAM Role の信頼ポリシーは system:serviceaccount:argocd:argocd-application-controllersub Condition で指定します。詳細な IRSA 設計・Terraform 実装は Vol1 §4 を参照してください。

ArgoCD Web UI を ALB Ingress で公開

ArgoCD の UI を社内ネットワークに公開する場合、ALB Ingress を使用します。EKS本番運用Vol1 §5 ALB Ingress Controller の設定が前提です。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: argocd-ingress
  namespace: argocd
  annotations:
 kubernetes.io/ingress.class: alb
 alb.ingress.kubernetes.io/scheme: internal
 alb.ingress.kubernetes.io/target-type: ip
 alb.ingress.kubernetes.io/backend-protocol: HTTPS
 alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS":443}]'
 alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:ap-northeast-1:123456789012:certificate/xxxx
spec:
  rules:
  - host: argocd.internal.example.com
 http:
paths:
- path: /
  pathType: Prefix
  backend:
 service:
name: argocd-server
port:
  number: 443

alb.ingress.kubernetes.io/scheme: internal を指定することで ALB をプライベートサブネットに配置し、社内 VPN 経由のアクセスのみに制限します。backend-protocol: HTTPS は ArgoCD Server が自己署名証明書を使用しているため必須です。ALB が TLS ターミネーションを行い、バックエンドの ArgoCD Server との通信は HTTPS で維持されます。


4. 環境分離 + Sync戦略 + Sync wave/hook (山場2)

EKS 本番環境では dev / staging / prod の3環境を ArgoCD の Application リソースで分離し、環境ごとに異なる Sync 戦略を適用することで「開発速度」と「本番安定性」を両立させる。本章では環境分離設計・Sync 戦略の選択・Sync wave/hook による依存関係制御を解説する。


4-1. 環境分離設計 — dev/staging/prod の役割と Sync 戦略マトリクス

3環境のコンセプトを明確にすることが設計の出発点だ。

環境目的Sync 戦略承認ゲート
dev開発者が自由にデプロイ・実験Automated + selfHeal + prune=trueなし (完全自動)
stagingリリース前の品質検証・E2E テストAutomated Sync + prune=trueデプロイ後に手動テスト確認
prod本番サービス提供Manual Sync onlyPR レビュー + 担当者による手動 Sync

Kustomize ディレクトリ構造例:

apps/
├── base/  # 共通マニフェスト (Deployment / Service / ConfigMap)
│├── deployment.yaml
│├── service.yaml
│└── kustomization.yaml
└── overlays/
 ├── dev/  # dev 環境オーバーレイ (レプリカ数少/リソース制限緩)
 │├── kustomization.yaml
 │└── patch-replicas.yaml
 ├── staging/ # staging 環境オーバーレイ (本番に近い設定)
 │├── kustomization.yaml
 │└── patch-resources.yaml
 └── prod/ # prod 環境オーバーレイ (HPA/PDB 付き)
  ├── kustomization.yaml
  └── patch-hpa.yaml

ArgoCD Application — dev 環境 (Automated Sync):

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-app-dev
  namespace: argocd
spec:
  project: dev-project
  source:
 repoURL: https://github.com/my-org/k8s-manifests.git
 targetRevision: HEAD
 path: apps/overlays/dev
  destination:
 server: https://kubernetes.default.svc
 namespace: development
  syncPolicy:
 automated:
prune: true  # Git から削除されたリソースを自動削除
selfHeal: true  # Drift 検出時に自動同期 (手動変更も上書き)
 syncOptions:
- CreateNamespace=true
- ServerSideApply=true

ArgoCD Application — prod 環境 (Manual Sync):

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-app-prod
  namespace: argocd
spec:
  project: prod-project
  source:
 repoURL: https://github.com/my-org/k8s-manifests.git
 targetRevision: HEAD
 path: apps/overlays/prod
  destination:
 server: https://kubernetes.default.svc
 namespace: production
  # syncPolicy を設定しない = Manual Sync のみ
  # prod 環境では自動 Sync を使わない

3環境の Application を ApplicationSet で一元管理する:

ApplicationSet を使うと、dev / staging / prod の Application を1つのリソース定義で管理できる。環境が増えても generators に追加するだけでよい。

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: my-app-environments
  namespace: argocd
spec:
  generators:
  - list:
elements:
- env: dev
  namespace: development
  syncPolicy: automated
- env: staging
  namespace: staging
  syncPolicy: automated
- env: prod
  namespace: production
  syncPolicy: manual
  template:
 metadata:
name: 'my-app-{{env}}'
 spec:
project: '{{env}}-project'
source:
  repoURL: https://github.com/my-org/k8s-manifests.git
  targetRevision: HEAD
  path: 'apps/overlays/{{env}}'
destination:
  server: https://kubernetes.default.svc
  namespace: '{{namespace}}'
環境分離 + Sync戦略 5鉄則

  1. dev 環境: Automated + selfHeal + prune=true — 開発者が最速で試行できるよう完全自動化する。dev は壊れてもいい環境と割り切ることが重要だ。
  2. staging 環境: Automated Sync だが手動確認ゲートを設ける — 自動デプロイ後に E2E テストを手動確認してから prod を更新する。
  3. prod 環境: Manual Sync only — ArgoCD の自動デプロイは禁止。変更は必ず PR ベースで行い、担当者が手動で argocd app sync を実行する。
  4. prod AppProject の clusterResourceBlacklist で危険操作を制限する — Namespace 削除や RBAC 変更を AppProject レベルでブロックする。
  5. Sync Window を設定し prod は業務時間内のみ Sync を許可する — 深夜の誤操作や予期しない自動 Sync を防ぐ。

4-2. Sync 戦略詳解 — Automated / Manual / Sync Window

Sync Window (本番デプロイ時間制限):

AppProject に syncWindows を設定することで、Sync が許可される時間帯を制限できる。

apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
  name: prod-project
  namespace: argocd
spec:
  syncWindows:
  - kind: allow
 schedule: '0 9-17 * * 1-5'# 平日 9:00-17:00 のみ許可
 duration: 8h
 applications:
 - 'my-app-prod'
 manualSync: true# 手動 Sync は常に許可 (緊急ホットフィックス用)
  sourceRepos:
  - 'https://github.com/my-org/k8s-manifests.git'
  destinations:
  - namespace: production
 server: https://kubernetes.default.svc

Manual Sync の手順 (prod 運用フロー):

# Step 1: Drift の確認 (Git の状態 vs クラスター実態)
argocd app diff my-app-prod --local ./apps/overlays/prod

# Step 2: 同期内容のドライラン (実際には適用しない)
argocd app sync my-app-prod --dry-run

# Step 3: 確認後に本番 Sync 実行
argocd app sync my-app-prod --prune

# Step 4: Sync 完了後にアプリの健全性を確認
argocd app wait my-app-prod --health --timeout 120

argocd app wait で Healthy になるまで待機し、デプロイ完了を確認してから次の作業に移る。


4-3. Sync Wave と Sync Hook — 依存関係制御

複数リソースを同時にデプロイする際、作成順序が重要なケースがある (例: Namespace → ConfigMap → Deployment の順)。Sync wave と Sync hook でこの依存関係を制御する。

Sync Wave — リソース適用順序の制御:

argocd.argoproj.io/sync-wave アノテーションで数値を指定し、小さい値から順に適用される。

# wave 1: Namespace を最初に作成
apiVersion: v1
kind: Namespace
metadata:
  name: production
  annotations:
 argocd.argoproj.io/sync-wave: "1"
---
# wave 2: ConfigMap は Namespace の後に作成
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
  namespace: production
  annotations:
 argocd.argoproj.io/sync-wave: "2"
---
# wave 5: Deployment は ConfigMap が揃ってから作成
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  namespace: production
  annotations:
 argocd.argoproj.io/sync-wave: "5"

Sync Hook — デプロイ前後のジョブ実行:

argocd.argoproj.io/hook アノテーションで Pre-Sync / Post-Sync ジョブを定義できる。

# Pre-Sync Hook: デプロイ前の DB マイグレーション
apiVersion: batch/v1
kind: Job
metadata:
  name: db-migration
  namespace: production
  annotations:
 argocd.argoproj.io/hook: PreSync
 argocd.argoproj.io/hook-delete-policy: HookSucceeded# 成功後にJob自動削除
spec:
  template:
 spec:
restartPolicy: Never
containers:
- name: migration
  image: my-app:latest
  command: ["./migrate.sh"]
  env:
  - name: DB_HOST
 valueFrom:
secretKeyRef:
  name: db-secret
  key: host
Hook タイプタイミング代表的な用途
PreSyncSync 開始前DB マイグレーション・事前検証
SyncSync 中 (wave と並行)カスタムリソース初期化
PostSyncSync 完了後スモークテスト・Slack 通知
SyncFailSync 失敗時アラート送信・ロールバック処理

4-4. Mermaid02: ArgoCD Reconcile Loop フロー

flowchart TD
 GitRepo["Git Repository<br/>(Desired State)"]
 ArgoCDCtrl["ArgoCD Application Controller<br/>(Reconciliation Loop)"]
 K8sAPI["Kubernetes API Server<br/>(Actual State)"]
 Decision{"Desired == Actual?"}
 Apply["kubectl apply<br/>(差分適用)"]
 Monitor["Health Check<br/>Degraded / Progressing / Healthy"]

 GitRepo -->|"マニフェスト取得<br/>(3分毎 or Webhook)"| ArgoCDCtrl
 K8sAPI -->|"実際の状態取得"| ArgoCDCtrl
 ArgoCDCtrl --> Decision
 Decision -->|"同期済み"| Monitor
 Decision -->|"Drift 検出"| Apply
 Apply --> K8sAPI
 K8sAPI --> Monitor

ArgoCD Application Controller は約3分間隔 (または Git Webhook 受信時) に Git の Desired State とクラスターの Actual State を比較する。Drift を検出した場合、Automated Sync 設定なら自動的に kubectl apply で差分を適用し、Manual Sync 設定なら OutOfSync 状態として管理者に通知する。


4-5. Vol2架橋 — ArgoCD Prometheus メトリクスを ADOT で収集

ArgoCD はデフォルトで Prometheus 形式のメトリクスを公開しており、ADOT Collector (Vol2 §4) と連携することでクラスター監視ダッシュボードに統合できる。

# ArgoCD metrics service の確認
kubectl get svc -n argocd | grep metrics
# 出力例:
# argocd-metrics ClusterIP  10.100.x.x  <none>  8082/TCP

# メトリクスの確認 (kubectl port-forward でローカルアクセス)
kubectl port-forward svc/argocd-metrics -n argocd 8082:8082 &
curl -s http://localhost:8082/metrics | grep argocd_app_info
# 出力例:
# argocd_app_info{dest_namespace="production",health_status="Healthy",name="my-app-prod",...} 1

ADOT Collector の Prometheus Receiver に ArgoCD メトリクスの scrape_config を追加する設定方法は EKS本番運用Vol2 §4 ADOTメトリクス収集 を参照されたい。

argocd_app_sync_total (Sync 実行回数) や argocd_app_health_status (アプリ健全性) を CloudWatch Metrics に転送することで、ArgoCD の運用状況を既存の EKS 監視ダッシュボードに統合できる。


fig04: 環境分離 dev/staging/prod × Sync戦略 マトリクス


5. Helm × Kustomize × Plain manifest 使い分け + ArgoCD Image Updater

fig05: Helm × Kustomize × Plain manifest 使い分け比較図

5-1. 三形式の使い分け早見表

ArgoCD は Plain manifest / Kustomize / Helm Chart の3形式をネイティブにサポートする。どれを選ぶかはチームの習熟度・アプリ規模・環境差分の複雑さによって決まる。まず各形式の特徴を比較し、選定基準を明確にする。

新規プロジェクトでは Plain manifest から始めて Kustomize に移行し、OSS コンポーネントの導入時に Helm を追加するという段階的な移行が現実的だ。一度に全てを Helm に統一しようとするとオーバーエンジニアリングになる。

比較軸Plain manifestKustomizeHelm
学習コスト
環境差分管理ファイルコピー&修正overlay で差分のみ管理values.yaml で管理
テンプレート機能なし限定的 (パッチ適用)フル機能 (Go テンプレート)
依存関係管理なしなしChart.yaml で依存管理
ArgoCD 統合ネイティブネイティブネイティブ
バージョン管理Git タグのみGit タグのみChart バージョンで管理
推奨ユースケース小規模/学習用途中規模/overlay 環境分離OSS Chart 活用/大規模

選定の判断基準

  • 自社アプリが1〜2環境 (dev / prod): Plain manifest か Kustomize で十分
  • 自社アプリが3環境以上 (dev / stg / prod / dr): Kustomize overlay で環境差分を管理
  • Prometheus / cert-manager 等の OSS を使う: 公式 Helm Chart を活用する
  • 複数チームが同一 Chart を異なる設定で使う: Helm + values.yaml を Git 管理
Helm vs Kustomize 選定フローチャート

  • Prometheus / Grafana / cert-manager 等の OSS を使う → Helm Chart を利用する
  • 自社アプリで環境ごとに image tag / replica 数だけ変えたい → Kustomize overlay
  • 単一環境でシンプルに始めたい → Plain manifest から始めて後で移行
  • Helm Chart のカスタマイズが複雑になってきた → Helm + Kustomize の組み合わせ

5-2. ArgoCD + Kustomize 設定例

Kustomize は base ディレクトリに共通マニフェストを置き、overlays/<env> ディレクトリで環境差分を管理するパターンが標準だ。ArgoCD Application の path に overlay ディレクトリを指定するだけで Kustomize が自動適用される。

ディレクトリ構成例

my-app/
├── base/
│├── deployment.yaml
│├── service.yaml
│└── kustomization.yaml
└── overlays/
 ├── dev/
 │├── kustomization.yaml
 │└── replica-patch.yaml
 └── prod/
  ├── kustomization.yaml
  └── replica-patch.yaml

ArgoCD Application — Kustomize overlay 参照

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-app-prod
  namespace: argocd
spec:
  project: default
  source:
 repoURL: https://github.com/my-org/my-app
 targetRevision: main
 path: overlays/prod
 kustomize:
namePrefix: prod-
images:
  - my-app=my-registry/my-app:v1.2.3
  destination:
 server: https://kubernetes.default.svc
 namespace: production
  syncPolicy:
 automated:
prune: true
selfHeal: true

overlays/prod/kustomization.yaml

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
bases:
  - ../../base
namePrefix: prod-
commonLabels:
  env: production
patchesStrategicMerge:
  - replica-patch.yaml
images:
  - name: my-app
 newTag: v1.2.3
resources:
  - hpa.yaml

kustomize.images を ArgoCD Application に指定すると、kustomization.yaml の images をオーバーライドできる。イメージタグを Application レベルで制御し、kustomization.yaml はコミット不要にする運用も可能だ。

Kustomize と ArgoCD の連携のポイント

  • ArgoCD は kustomize build を内部で実行し、生成されたマニフェストをクラスターに適用する
  • kustomize.commonAnnotationskustomize.commonLabels で全リソースに共通メタデータを付与できる
  • kustomize.version を指定すると特定バージョンの Kustomize バイナリを使う (デフォルトは ArgoCD 同梱版)
  • namePrefix / nameSuffix を使うと同一クラスター内でのリソース名衝突を防げる

5-3. ArgoCD + Helm 設定例

Helm Chart は OCI レジストリまたは Helm リポジトリから直接参照できる。ArgoCD Application の spec.source.helmvalues を埋め込む方法と、Git で管理した values.yaml を参照する方法がある。

シンプルな Helm Chart 参照 (values インライン)

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: prometheus-prod
  namespace: argocd
spec:
  project: default
  source:
 repoURL: https://prometheus-community.github.io/helm-charts
 chart: kube-prometheus-stack
 targetRevision: 55.5.0
 helm:
releaseName: prometheus
values: |
  grafana:
 enabled: true
  prometheus:
 prometheusSpec:
retention: 30d
storageSpec:
  volumeClaimTemplate:
 spec:
storageClassName: gp3
resources:
  requests:
 storage: 50Gi
  destination:
 server: https://kubernetes.default.svc
 namespace: monitoring
  syncPolicy:
 automated:
prune: true
selfHeal: true

values.yaml を Git 管理する構成 (Multi-Source)

複数の values ファイルを Git リポジトリで管理する場合は ArgoCD の Multi-Source 機能を使う。Chart リポジトリと設定リポジトリを分離することで、Chart のバージョンアップと設定変更を独立してレビューできる。

この構成では Chart の targetRevision を上げる PR と、prometheus-values-prod.yaml を修正する PR を別々に作成・レビューできる。Helm Chart のアップグレードは変更量が大きいため、設定変更と分離することでレビューの質が上がる。

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: prometheus-prod
  namespace: argocd
spec:
  project: default
  sources:
 - repoURL: https://prometheus-community.github.io/helm-charts
chart: kube-prometheus-stack
targetRevision: 55.5.0
 - repoURL: https://github.com/my-org/my-config
targetRevision: main
ref: myconfig
  helm:
 valueFiles:
- $myconfig/monitoring/prometheus-values-prod.yaml
  destination:
 server: https://kubernetes.default.svc
 namespace: monitoring

5-4. ArgoCD Image Updater — コンテナイメージ自動更新

ArgoCD Image Updater は、コンテナレジストリを監視して新しいイメージタグが公開されると ArgoCD Application を自動更新するツールだ。CI が Docker イメージを push すると、Image Updater が検知して GitOps フローで自動デプロイする。

インストール

# ArgoCD Image Updater のインストール
kubectl apply -n argocd-f https://raw.githubusercontent.com/argoproj-labs/argocd-image-updater/stable/manifests/install.yaml

# 起動確認
kubectl get pods -n argocd -l app.kubernetes.io/name=argocd-image-updater

# ArgoCD API アクセス用トークン生成 (Image Updater が ArgoCD API を呼ぶために必要)
argocd account generate-token --account image-updater --id image-updater
kubectl create secret generic argocd-image-updater-secret-n argocd--from-literal=argocd.token=<上記で生成したトークン>

Application に Annotation を追加

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-app-prod
  namespace: argocd
  annotations:
 # 監視するイメージと更新戦略
 argocd-image-updater.argoproj.io/image-list: my-app=my-registry/my-app
 argocd-image-updater.argoproj.io/my-app.update-strategy: semver
 argocd-image-updater.argoproj.io/my-app.allow-tags: regexp:^v[0-9]+\.[0-9]+\.[0-9]+$
 # 更新方法: git (kustomization.yaml を更新して commit)
 argocd-image-updater.argoproj.io/write-back-method: git
 argocd-image-updater.argoproj.io/git-branch: image-update
spec:
  source:
 repoURL: https://github.com/my-org/my-app
 targetRevision: main
 path: overlays/prod

update-strategy: semver にすると、セマンティックバージョンの最新版 (v1.2.4 など) が自動適用される。write-back-method: git を指定すると kustomization.yaml の newTag を自動コミットしてくれるため、完全な GitOps フローが実現する。

Image Updater が動作するには、ArgoCD がアクセスするコンテナレジストリへの認証が必要だ。ECR を使う場合は IRSA で Image Updater の ServiceAccount に ECR ReadOnly 権限を付与する。argocd-image-updater-secret に認証情報を設定する代わりに、IRSA による認証が ECR では推奨される。

更新戦略の選択肢

戦略動作推奨ケース
semver最新 semver タグを自動適用本番 (v1.x.x 形式)
latestlatest タグを常に追従開発環境のみ
digestイメージ Digest で固定セキュリティ重視
nameアルファベット順最新タグ日付タグ (2026-05-08 等)

ArgoCD Image Updater 公式ドキュメント


6. 詰まりポイント7選 図解

本番ArgoCD環境で実際に踏まれやすい7つの詰まりポイントを「なぜ詰まるか → どう解くか」の2段構成で図解します。§4・§5で設計を固めた後でも、運用フェーズに入ると必ず遭遇するパターンです。事前に把握しておくことで、障害発生時の復旧時間を大幅に短縮できます。


詰まり1: Drift検出が機能しない

なぜ詰まるか

ArgoCD の Drift 検出が動作しない原因の多くは、syncPolicy.automated.selfHealfalse(デフォルト)のままになっているケースです。さらに、ArgoCD の ServiceAccount に付与されている ClusterRole が read-only 相当の権限しかなく、実際のリソース状態を取得できない状態になっていることもあります。

kubectl apply で手動変更したリソースが ArgoCD の Desired State と乖離しているにもかかわらず、ArgoCD UI に「Synced」と表示され続ける場合、RBAC 権限不足が原因である可能性が高いです。

どう解くか

まず selfHeal: true を設定し、RBAC 権限を確認します。

# Application の現在の Sync 状態を確認
argocd app get my-app --show-operation

# 強制的に Sync を実行して差分を顕在化
argocd app sync my-app --force

# ArgoCD application-controller の権限確認
kubectl get clusterrolebinding argocd-application-controller -o yaml
# syncPolicy で selfHeal を有効化
syncPolicy:
  automated:
 prune: false# 本番では慎重に
 selfHeal: true # Drift 自動修復を有効化
詰まり1 解決策: syncPolicy.automated.selfHeal: true を設定し、ArgoCD application-controller の ClusterRole に get/list/watch/patch/update 権限が付与されているか確認する。RBAC 不足の場合は ClusterRole を修正して再デプロイ。

詰まり2: RBAC設計ミス — ArgoCD RBAC と Kubernetes RBAC の混同

なぜ詰まるか

ArgoCD には独自の RBAC システム(argocd-rbac-cm ConfigMap)があり、Kubernetes の RBAC(ClusterRole/RoleBinding)とは別軸で動作します。この2種類の RBAC を混同し、Kubernetes RBAC だけ設定しても ArgoCD UI のアクセス制御が機能しない、という事態が発生します。

また、AppProjectdestinations フィールドを "*" で許可してしまうと、本番クラスタへの誤デプロイが発生する可能性があります。

どう解くか

argocd-rbac-cm で ArgoCD 独自のロールとグループを定義し、AppProject で許可クラスタと Namespace を明示的に制限します。

# ConfigMap: argocd-rbac-cm
apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-rbac-cm
  namespace: argocd
data:
  policy.default: role:readonly# デフォルトは読み取り専用
  policy.csv: |
 # 本番デプロイロール: production/* への sync のみ許可
 p, role:deploy-prod, applications, sync, production/*, allow
 p, role:deploy-prod, applications, get, production/*, allow
 # ops-team グループをデプロイロールに紐付け
 g, ops-team, role:deploy-prod
# AppProject で本番クラスタへのデプロイ先を制限
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
  name: production
  namespace: argocd
spec:
  destinations:
  - namespace: production
 server: https://prod-cluster.example.com
  sourceRepos:
  - 'https://github.com/your-org/gitops-repo'
詰まり2 解決策: ArgoCD RBAC(argocd-rbac-cm)と AppProject destinations を組み合わせて最小権限を実現する。policy.default: role:readonly を設定したうえで、デプロイ権限を持つロールを明示的に定義する。

詰まり3: Secrets管理 — GitにKubernetes Secret plain YAMLが混入

なぜ詰まるか

GitOps では「Git = Single source of truth」であるため、すべての設定を Git に置きたくなります。しかし kubectl create secret で生成した YAML をそのまま Git にコミットすると、Base64エンコードされているだけで実質平文の機密情報が Git 履歴に残り続けます。ArgoCD は Git を正とするため、この設計ミスを自動的に検出できません。

どう解くか

Sealed Secrets または External Secrets Operator(ESO)を使い、Git に機密情報をそのまま置かない設計にします。

# Sealed Secrets: kubeseal で暗号化
kubeseal --format=yaml < my-secret.yaml > my-sealed-secret.yaml
# my-sealed-secret.yaml は Git に安全にコミット可能

# Sealed Secrets コントローラのインストール (Helm)
helm repo add sealed-secrets https://bitnami-labs.github.io/sealed-secrets
helm install sealed-secrets sealed-secrets/sealed-secrets -n kube-system
# External Secrets Operator: AWS Secrets Manager から値を取得
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: my-db-secret
  namespace: production
spec:
  refreshInterval: 1h
  secretStoreRef:
 name: aws-secrets-manager
 kind: SecretStore
  target:
 name: my-db-secret
  data:
  - secretKey: DB_PASSWORD
 remoteRef:
key: prod/myapp/db
property: password
詰まり3 解決策: Git に Kubernetes Secret の plain YAML をコミットしない。小規模チームは Sealed Secrets、AWS連携が前提の環境は External Secrets Operator(ESO)+ AWS Secrets Manager の組み合わせを選択する。

詰まり4: Multi-Cluster管理の複雑化 — ApplicationSet未使用による手動登録問題

なぜ詰まるか

複数のクラスタに同じアプリケーションをデプロイする場合、ArgoCD の Application リソースをクラスタ数分手動で作成・管理するパターンに陥ると、クラスタが増えるたびに登録作業が発生します。また、設定の一貫性を保つことが困難になり、クラスタ間で設定が乖離するリスクが高まります。

どう解くか

ApplicationSet の Cluster Generator を使い、クラスタ登録時に自動で Application を作成する仕組みにします。

# クラスタを ArgoCD に登録
argocd cluster add prod-cluster \
  --name production \
  --kubeconfig ~/.kube/config

argocd cluster add staging-cluster \
  --name staging \
  --kubeconfig ~/.kube/config

# 登録済みクラスタ一覧確認
argocd cluster list
# ApplicationSet: Cluster Generator で全クラスタに自動デプロイ
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: my-app-all-clusters
  namespace: argocd
spec:
  generators:
  - clusters:
selector:
  matchLabels:
 env: production
  template:
 metadata:
name: '{{name}}-my-app'
 spec:
project: production
source:
  repoURL: https://github.com/your-org/gitops-repo
  targetRevision: HEAD
  path: 'overlays/{{metadata.labels.env}}'
destination:
  server: '{{server}}'
  namespace: my-app
詰まり4 解決策: ApplicationSet の Cluster Generator を使い、クラスタ登録時に自動で Application を作成する。ラベルセレクタでクラスタをフィルタリングし、環境別 overlay と組み合わせることで一元管理を実現する。

詰まり5: Webhook障害でSyncが遅延 — Push通知が届かないケース

なぜ詰まるか

ArgoCD はデフォルトで3分おきに Git リポジトリをポーリングしますが、Webhook を設定することでプッシュ時に即座に同期できます。しかし、ファイアウォールや VPN の設定ミスにより GitHub/GitLab から ArgoCD Server への Webhook が届かない場合、変更が反映されるまで最大3分の遅延が生じます。CI/CD パイプラインの速度改善のために Webhook を設定したのに「効いていない」と気づかないケースが多発します。

どう解くか

Webhook の疎通確認を行い、到達できない環境ではポーリング間隔を短縮します。

# ArgoCD Server の Webhook 受信ログを確認
kubectl logs -n argocd deployment/argocd-server | grep -i webhook

# ポーリング間隔を3分から1分に短縮 (Webhook が使えない環境向け)
# argocd-repo-server の Deployment 内で引数に追加:
# --repo-cache-expiration 1m

# ArgoCD Application を手動で即時更新 (強制ポーリング)
argocd app get my-app --refresh
詰まり5 解決策: GitHub/GitLab 管理コンソールの Webhook Recent Deliveries で疎通確認する。Webhook が使えない環境(ファイアウォール制限)ではポーリング間隔(--repo-cache-expiration)を短縮する。ArgoCD の Public URL が Webhook 送信元から到達可能か確認することが重要。

詰まり6: CRD ordering問題 — CRD依存リソースの適用順序エラー

なぜ詰まるか

ArgoCD は Git 上のリソースをまとめて apply しますが、CRD が存在しない状態で CRD に依存するリソース(CR: Custom Resource)を apply しようとすると、「no matches for kind “XxxKind” in version “xxx.io/v1″」エラーが発生して Sync が失敗します。Helm チャートに CRD が含まれているケースや、cert-manager・Istio などを先行インストールする場合に頻発します。

どう解くか

argocd.argoproj.io/sync-wave アノテーションで適用順序を制御し、CRD を先に適用します。

# CRD マニフェスト: wave 0 (または -1) で最初に適用
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: myresources.example.com
  annotations:
 argocd.argoproj.io/sync-wave: "0"
spec:
  group: example.com
  names:
 kind: MyResource
 plural: myresources
  scope: Namespaced
  versions:
  - name: v1
 served: true
 storage: true
 schema:
openAPIV3Schema:
  type: object
---
# CR (Custom Resource): wave 5 — CRD 適用後に作成
apiVersion: example.com/v1
kind: MyResource
metadata:
  name: my-resource
  namespace: my-app
  annotations:
 argocd.argoproj.io/sync-wave: "5"
spec:
  replicas: 2
# Sync wave 動作確認
argocd app get my-app --show-operation

# wave 別の適用状況確認
kubectl get events -n argocd --sort-by='.lastTimestamp' | tail -20
詰まり6 解決策: CRD は sync-wave: "0"(または "-1")で最初に適用し、依存 CR は正の wave 値(例: "5")で順序制御する。Helm チャートの場合は installCRDs: true オプションまたは別 Application として CRD を先に分離する。

詰まり7: PR-based promotion が機能しない — dev→staging→prod 昇格フロー未定義

なぜ詰まるか

GitOps では「Git へのコミット = デプロイのトリガー」ですが、dev → staging → prod のプロモーションフローが定義されていないと、すべての環境に同じタイミングで変更が適用されてしまいます。または、手動でイメージタグを各 overlay に書き換えてコミットする作業が発生し、GitOps の自動化メリットが失われます。

どう解くか

GitHub Actions と Kustomize overlay を組み合わせた PR-based promotion フローを構築します。

# .github/workflows/promote-to-staging.yaml
name: Promote to staging
on:
  workflow_dispatch:
 inputs:
image_tag:
  description: 'Image tag to promote'
  required: true

jobs:
  promote:
 runs-on: ubuntu-latest
 steps:
 - uses: actions/checkout@v4
with:
  token: ${{ secrets.GITHUB_TOKEN }}

 - name: Update staging overlay
run: |
  cd overlays/staging
  kustomize edit set image \
 my-app=my-registry/my-app:${{ github.event.inputs.image_tag }}

 - name: Create PR for staging promotion
uses: peter-evans/create-pull-request@v6
with:
  title: "Promote: ${{ github.event.inputs.image_tag }} to staging"
  body: |
 staging 環境のイメージタグを更新。ArgoCD が PR マージ後に自動同期。
  branch: promote/staging-${{ github.event.inputs.image_tag }}
  base: main
# overlays/staging/kustomization.yaml (GitHub Actions による自動更新後)
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
images:
- name: my-app
  newTag: v1.2.3# GitHub Actions により自動更新
詰まり7 解決策: PR-based promotion は GitHub Actions で自動化し、各環境の Kustomize overlay を別 PR で更新する。dev → staging PR マージ → ArgoCD 自動同期 → staging 動作確認 → prod PR 作成 のフローを標準化することで、手動コミットによる設定ミスを排除する。

7. アンチパターン→正解パターン変換演習 (ArgoCD yaml + Kustomize + Helm 3形式)

§6で学んだ詰まりポイントを、今度は「自分の手で直す」演習形式で体験します。各問は「壊れたコード(NG)→ 解説 → 修正コード(OK)」の3段構成です。ArgoCD yaml / Kustomize / Helm の3形式を網羅しています。

演習解答セクションへ


演習1: Application の syncPolicy 設定ミス(ArgoCD yaml)

【NG】本番環境で Automated + selfHeal を有効化

# NG: 本番クラスタの Application
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-app-prod
  namespace: argocd
spec:
  project: production
  source:
 repoURL: https://github.com/your-org/gitops-repo
 targetRevision: main
 path: overlays/prod
  destination:
 server: https://prod-cluster.example.com
 namespace: production
  syncPolicy:
 automated:
prune: true
selfHeal: true # NG: 本番では危険

【解説】なぜ問題か

本番環境で selfHeal: true を設定すると、緊急対処のために kubectl patchkubectl edit で手動変更したリソースが、数秒以内に ArgoCD によって元の状態に戻されます。障害発生時に手動でホットパッチを当てても、ArgoCD が即座に上書きし、復旧作業を妨げる事態になります。また prune: true との組み合わせにより、意図しないリソース削除が自動実行されるリスクもあります。

【OK】本番は Manual Sync + prune を慎重に設定

# OK: 本番クラスタの Application
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-app-prod
  namespace: argocd
spec:
  project: production
  source:
 repoURL: https://github.com/your-org/gitops-repo
 targetRevision: main
 path: overlays/prod
  destination:
 server: https://prod-cluster.example.com
 namespace: production
  syncPolicy:
 syncOptions:
 - CreateNamespace=true
 - PruneLast=true # 削除は最後に実行(安全性向上)
 # automated セクションを削除 → 手動同期のみ
 # 本番デプロイは PR レビュー後に手動で argocd app sync を実行

演習2: AppProject で全 Namespace/クラスタを許可(ArgoCD yaml)

【NG】destinations に ワイルドカードを使用

# NG: AppProject の destinations 設定
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
  name: my-project
  namespace: argocd
spec:
  destinations:
  - namespace: '*' # NG: 全 Namespace を許可
 server: '*' # NG: 全クラスタを許可
  sourceRepos:
  - '*'# NG: 全リポジトリを許可

【解説】なぜ問題か

namespace: '*'server: '*' の組み合わせは、このプロジェクトに属する Application が任意のクラスタの任意の Namespace にデプロイできることを意味します。誤った Application 設定や操作ミスにより、kube-system など重要 Namespace への誤デプロイが発生するリスクがあります。チーム横断でプロジェクトを共有している場合、他チームのリソースを誤って上書きする事故も起きえます。

【OK】明示的な Namespace とクラスタを指定

# OK: AppProject の destinations 設定
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
  name: my-project
  namespace: argocd
spec:
  destinations:
  - namespace: production # 本番 Namespace のみ許可
 server: https://prod-cluster.example.com
  - namespace: staging
 server: https://staging-cluster.example.com
  sourceRepos:
  - 'https://github.com/your-org/gitops-repo' # 特定リポジトリのみ
  clusterResourceWhitelist:
  - group: ''
 kind: Namespace # Namespace リソースのみクラスタ級操作を許可

演習3: Kustomize で base を直接 prod 設定として使用(Kustomize)

【NG】overlays/prod が base の設定を上書きせず本番用設定を base に直接記述

# NG: base/kustomization.yaml に本番設定を直接記述
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- service.yaml

# NG: base/deployment.yaml
spec:
  replicas: 10  # 本番用レプリカ数を base に直接記述
  template:
 spec:
containers:
- name: my-app
  resources:
 requests:
cpu: "2"
memory: "4Gi" # 本番用リソース設定を base に直接記述

【解説】なぜ問題か

base に本番用の設定(replicas: 10、大きなリソース量)を直接記述すると、devstaging 環境でも同じ設定が適用されます。開発環境で不必要に大量のリソースを消費し、コストが増大します。また base の本来の役割(共通設定の管理)が失われ、環境別の差分管理が破綻します。

【OK】base は共通設定のみ、overlay で環境差分を管理

# OK: base/deployment.yaml — 共通設定のみ
spec:
  replicas: 1# デフォルト値(小さく設定)
  template:
 spec:
containers:
- name: my-app
  resources:
 requests:
cpu: "100m"
memory: "128Mi"

# OK: overlays/prod/kustomization.yaml — 本番差分のみ記述
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
patches:
- patch: |-
 - op: replace
path: /spec/replicas
value: 10
  target:
 kind: Deployment
 name: my-app
- patch: |-
 - op: replace
path: /spec/template/spec/containers/0/resources/requests/cpu
value: "2"
  target:
 kind: Deployment
 name: my-app

演習4: Helm values を ArgoCD Application に inline 記述(Helm)

【NG】Application spec の helm.values に全設定を inline 記述

# NG: Application の helm.values に大量の設定を inline 記述
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-helm-app-prod
  namespace: argocd
spec:
  source:
 repoURL: https://github.com/your-org/helm-charts
 chart: my-app
 targetRevision: 1.2.3
 helm:
values: |
  replicaCount: 10
  image:
 repository: my-registry/my-app
 tag: v1.2.3
  ingress:
 enabled: true
 hosts:
 - host: prod.example.com
  database:
 host: prod-db.example.com
 port: 5432
  # ... 100行以上の設定が続く

【解説】なぜ問題か

ArgoCD Application に values を inline で記述すると、Application リソース自体が肥大化し、Git の差分が追いにくくなります。また、複数環境(dev/staging/prod)で同じ Helm チャートを使う場合、それぞれの Application に重複した設定が散在します。values の変更履歴がチャートリポジトリとは別の Application YAML に混在するため、デプロイ履歴の追跡が困難になります。

【OK】values.yaml を別ファイルで管理し spec.sources で参照

# OK: values ファイルを GitOps リポジトリで管理
# gitops-repo/helm-values/my-app/prod/values.yaml
replicaCount: 10
image:
  repository: my-registry/my-app
  tag: v1.2.3
ingress:
  enabled: true
  hosts:
  - host: prod.example.com

---
# OK: Application で spec.sources を使い values を別リポジトリから参照
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-helm-app-prod
  namespace: argocd
spec:
  sources:
  - repoURL: https://github.com/your-org/helm-charts
 chart: my-app
 targetRevision: 1.2.3
 helm:
valueFiles:
- $values/helm-values/my-app/prod/values.yaml
  - repoURL: https://github.com/your-org/gitops-repo
 targetRevision: main
 ref: values # values ファイルの参照名
  destination:
 server: https://prod-cluster.example.com
 namespace: production

演習5: イメージタグに latest を使用(Kustomize)

【NG】Kustomize でイメージタグを latest に固定

# NG: overlays/prod/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
images:
- name: my-app
  newName: my-registry/my-app
  newTag: latest # NG: latest タグは GitOps と相性最悪

【解説】なぜ問題か

latest タグは mutable(可変)であるため、同じタグ名でも異なるイメージが指定される可能性があります。ArgoCD は Git の desired state(latest)と実際にデプロイされているイメージのダイジェストが異なっても、タグ名が一致しているとみなし Drift を検出できません。また、Pod の再起動時に意図しない新バージョンのイメージがプルされ、予期せぬ動作変更が生じます。デプロイ履歴と実際のイメージのバージョンが紐付けられないため、障害発生時の原因追跡も困難になります。

【OK】sha256 digest またはセマンティックバージョンタグを使用

# OK: overlays/prod/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
images:
- name: my-app
  newName: my-registry/my-app
  newTag: v1.2.3@sha256:abc123def456... # OK: digest で immutable を保証

# または ArgoCD Image Updater を使い自動更新
# annotations:
#argocd-image-updater.argoproj.io/image-list: my-app=my-registry/my-app:~v1.2
#argocd-image-updater.argoproj.io/my-app.update-strategy: semver

演習解答まとめ

NG のコア問題OK のポイント
演習1本番で selfHeal: true → 手動対処を即座に上書き本番は Manual Sync + PruneLast で安全を確保
演習2destinations: * で全クラスタ/NS を許可明示的なクラスタ・NS 指定で誤デプロイを防止
演習3base に本番設定を直接記述 → 全環境に波及base は共通設定のみ、overlay で環境差分を管理
演習4helm.values を inline 記述で Application が肥大化spec.sources で values ファイルを別リポジトリ管理
演習5latest タグで Drift 検出不能・意図せぬ更新sha256 digest または semver タグで immutable 保証

8. まとめ + EKS Vol4予告 + 落とし穴10選 + Vol1-2双方向クロスリンク

8-1. 5ゴール達成チェック

本記事を通じて、以下の5つのゴールを達成できたか確認しましょう。

  • [ ] (a) GitOps の本質を理解した — Pull型/Single source of truth/Declarative/Continuous reconciliation の4原則を説明できる
  • [ ] (b) ArgoCD の3階層を選定できる — Application/ApplicationSet/AppProject の役割と Repository 構成3パターン(Mono/Multi/App-of-Apps)を規模に応じて選択できる
  • [ ] (c) 環境分離 + Sync戦略を本番設計できる — dev/staging/prod × Auto/Manual/Self-Heal/Prune × Sync wave/hook を組み合わせた設計ができる
  • [ ] (d) Helm × Kustomize × Plain manifest を使い分けられる — ArgoCD Image Updater と組み合わせたイメージ自動更新を実装できる
  • [ ] (e) 詰まりポイント7選 + 演習5問を修得した — §6・§7のアンチパターンを正解パターンに変換できる

「動かす(Vol1)→ 見える(Vol2)→ 保つ(Vol3)」三段昇格の集大成として、EKS本番運用の全体像を把握できた状態です。

本記事で学んだスキルは、単に ArgoCD を「動かす」レベルにとどまりません。Git を唯一の真実として、クラスタ状態を継続的に調整し続ける GitOps の思想を体得することで、チーム全体のデプロイ品質と可観測性が根本から変わります。

本番導入のロードマップとしては、次のステップを推奨します。

Phase 1 (短期〜1ヶ月)

  • 開発環境から ArgoCD を導入し、Application + AppProject の基本構成を確立する
  • §4 で学んだ Sync 戦略(dev: Auto / staging: Manual / prod: Manual)を実装する
  • Sealed Secrets または ESO を導入し、Git への機密情報コミットを排除する

Phase 2 (中期〜3ヶ月)

  • §5 の ArgoCD Image Updater を CI/CD パイプラインに組み込み、イメージタグ自動更新を実現する
  • PR-based promotion フロー(GitHub Actions + Kustomize overlay)を標準化する
  • ArgoCD の HA 構成(argocd-application-controller × 2)で可用性を確保する

Phase 3 (長期〜6ヶ月)

  • ApplicationSet + Multi-Cluster 管理で複数クラスタの一元管理基盤を完成させる
  • App-of-Apps パターンで大規模マイクロサービスの ArgoCD 管理を整理する
  • Vol4 (セキュリティ・ガバナンス自動化) の内容と組み合わせ、OPA/Gatekeeper によるポリシー強制をデプロイパイプラインに追加する

8-2. 落とし穴10選

GitOps/ArgoCD を本番導入する際に踏みやすい落とし穴を整理します。

  1. 本番で selfHeal: true を設定 → 障害時の手動対処が即座に上書きされる(§6 詰まり1)
  2. AppProject の destinations に ワイルドカードを使用 → 誤デプロイで他チームリソースを破壊(§6 詰まり2)
  3. Kubernetes Secret を plain YAML で Git にコミット → Base64は暗号化ではなくエンコードのみ(§6 詰まり3)
  4. Application を手動でクラスタ数分作成 → ApplicationSet を使わないと管理不能(§6 詰まり4)
  5. latest タグでイメージを固定 → Drift 検出不能 + 意図せぬバージョン更新(§7 演習5)
  6. base に本番設定を直接記述 → 全環境に本番スペックが波及してコスト増大(§7 演習3)
  7. CRD と CR を同一 wave で apply → CRD が存在しない状態で CR が失敗(§6 詰まり6)
  8. ArgoCD RBAC と Kubernetes RBAC を混同 → UI 制御が機能しない(§6 詰まり2)
  9. ブランチ戦略なしで PR-based promotion を試みる → dev/staging/prod が同じブランチで管理不能(§6 詰まり7)
  10. ArgoCD の HA 構成を後回しにする → argocd-application-controller は StatefulSet で Pod 障害時にクラスタ全体の同期が止まる

fig06: EKS本番運用シリーズ Vol1-3 完結ロードマップ


8-3. EKS本番運用シリーズ Vol4予告

EKS本番運用 Vol4 近日公開: セキュリティ・ガバナンス自動化

  • OPA/Gatekeeper によるポリシー強制 — 非準拠マニフェストのデプロイをクラスタ側でブロック
  • Falco によるランタイム脅威検出 — コンテナ内の異常な syscall をリアルタイム検知
  • AWS Network Policy / Security Group for Pods — Pod レベルのネットワーク分離
  • Vol1-3 で構築した観測可能性 × GitOps 基盤をセキュリティ視点で強化

Vol3「保つ」の次ステップとして、EKS本番運用の仕上げをお届けします。


8-4. EKS本番運用シリーズ 全記事クロスリンク

Vol3「保つ」まで読了したことで、EKS 本番運用の骨格が揃いました。シリーズの前後を参照することで、より完成度の高い本番環境を設計できます。

EKS本番運用シリーズ(連載)

EKS クラスタの本番設計から始まり、IRSA で Pod に最小権限の IAM ロールを付与し、ALB Ingress Controller でトラフィックを制御する一連の実装を解説。本記事 §3 の ArgoCD ServiceAccount IRSA 設計の前提知識となります。

FluentBit によるコンテナログの CloudWatch Logs 転送、Container Insights による Node/Pod メトリクス可視化、ADOT を使ったトレース収集を統合した観測基盤を構築。本記事 §4 の ArgoCD Prometheus メトリクスとの接続点になります。

EKS関連記事(既存シリーズ)

Karpenter を使ったノード自動プロビジョニング。GitOps で NodePool 設定を管理することで、スケーリングポリシーもコードで管理できます。

IRSA の詳細実装ガイド。ArgoCD ServiceAccount への IAM Role 付与を深掘りする際に参照してください。

ALB Ingress と ArgoCD の組み合わせによる本番デプロイの実践ガイド。本記事の GitOps 全体像と組み合わせることで、より完成度の高い本番環境を構築できます。

EKS本番運用シリーズ Vol1-3 の完結を機に、「動かす・見える・保つ」の三層アーキテクチャが揃いました。Vol4 のセキュリティ・ガバナンス自動化と組み合わせ、完全な本番グレードの EKS 環境を実現してください。

GitOps 導入後の次の指針

GitOps を本番稼働させた後も、以下の観点で継続的に改善を進めることを推奨します。

  • Drift 検出の定期レビュー: argocd app list --output wide で OutOfSync 状態の Application を定期確認し、意図しない Drift を早期に発見する
  • ApplicationSet の段階的拡張: 単一クラスタから始め、安定稼働を確認してから Multi-Cluster 構成へ拡張する
  • GitOps リポジトリの整理: 時間とともに overlay が増加するため、kustomize build で実際の出力を定期的に確認し、不要な設定を整理する

「保つ」という行為は一度設定したら終わりではなく、クラスタとリポジトリの状態を継続的に一致させ続ける運用プロセスです。ArgoCD はその自動化を担うツールですが、最終的な設計判断と改善は人間が行います。Vol3 で学んだ原則を軸に、自チームの要件に合わせた GitOps 運用を育てていってください。


IAM/EKS の知識をAIエージェント開発に活かす実践ガイドとして、Bedrock Agents 本番運用 完全ガイド (AIシリーズ Vol1) もあわせてお読みください。

セキュリティ本格運用シリーズ (AWS本番運用5軸目)

本シリーズで習得した知識をセキュリティ運用に統合: セキュリティ本格運用 Vol1: Security Hub × GuardDuty × Audit Manager — Security Hub・GuardDuty・Audit Manager による脅威検出・コンプライアンス・ログ集約の3本柱を Terraform IaC で実装する。