この記事の要点
• ArgoCDでGitリポジトリとKubernetesクラスタを自動同期する
• アプリケーション定義をコードとして管理し、宣言的デプロイを実現
• App of Appsパターンで複数環境・マイクロサービスを一元管理
GitOpsとArgoCD
GitOpsは、Gitリポジトリを唯一の信頼できる情報源(Single Source of Truth)とし、システムの望ましい状態を宣言的に管理する運用モデルです。
GitOpsの原則
- 宣言的定義: システムの望ましい状態をGitで管理
- バージョン管理: すべての変更をGitコミットとして記録
- 自動反映: Gitの状態とクラスタを自動で一致させる
- 継続的調整: 差分を検出し自動修復(Self-Healing)
ポイント: ArgoCDはPull型デプロイを採用し、クラスタ内のエージェントがGitを監視します。
Push型 vs Pull型デプロイ
| 方式 | 動作 | セキュリティ | 例 |
|---|---|---|---|
| Push型 | CI/CDが直接クラスタに書き込む | 外部にクラスタ認証情報が必要 | GitHub Actions + kubectl |
| Pull型 | クラスタ内エージェントがGitを監視 | 認証情報がクラスタ内で完結 | ArgoCD, Flux |
ArgoCDのインストール
# 名前空間の作成
kubectl create namespace argocd
# ArgoCDのインストール
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
# インストール確認
kubectl get pods -n argocd
# 初期パスワードの取得
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d
# ポートフォワードでUIにアクセス
kubectl port-forward svc/argocd-server -n argocd 8080:443
# ブラウザで https://localhost:8080 を開く
# ユーザー名: admin
# パスワード: 上記コマンドで取得した値
実践メモ: 本番環境ではIngress経由でArgoCDにアクセスし、SSOやRBACを設定します。
Ingress設定
# argocd-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: argocd-server-ingress
namespace: argocd
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/ssl-passthrough: "true"
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
spec:
ingressClassName: nginx
rules:
- host: argocd.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: argocd-server
port:
name: https
tls:
- hosts:
- argocd.example.com
secretName: argocd-tls
ArgoCD CLI
# CLIのインストール(macOS)
brew install argocd
# Linux
curl -sSL -o argocd-linux-amd64 https://github.com/argoproj/argo-cd/releases/latest/download/argocd-linux-amd64
sudo install -m 555 argocd-linux-amd64 /usr/local/bin/argocd
# ログイン
argocd login localhost:8080 --username admin --password <初期パスワード>
# パスワード変更
argocd account update-password
Applicationの作成
最小構成
# application.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-app
namespace: argocd
spec:
# プロジェクト(default or カスタム)
project: default
# Gitソース
source:
repoURL: https://github.com/example/my-app-manifests.git
targetRevision: main
path: kubernetes
# デプロイ先クラスタ
destination:
server: https://kubernetes.default.svc
namespace: production
# 同期ポリシー
syncPolicy:
automated:
prune: true # Gitから削除されたリソースを削除
selfHeal: true # クラスタ側の手動変更を自動修復
allowEmpty: false
syncOptions:
- CreateNamespace=true
retry:
limit: 5
backoff:
duration: 5s
factor: 2
maxDuration: 3m
# Applicationの作成
kubectl apply -f application.yaml
# または CLI経由
argocd app create my-app \
--repo https://github.com/example/my-app-manifests.git \
--path kubernetes \
--dest-server https://kubernetes.default.svc \
--dest-namespace production \
--sync-policy automated \
--auto-prune \
--self-heal
# アプリケーション一覧
argocd app list
# 詳細確認
argocd app get my-app
# 同期(手動)
argocd app sync my-app
# ロールバック
argocd app rollback my-app 3
注意: automated同期ではprune: trueにするとGitから削除したリソースがクラスタからも削除されます。意図しない削除に注意してください。
Helmチャートのデプロイ
# helm-application.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-helm-app
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/example/helm-charts.git
targetRevision: main
path: charts/my-app
helm:
# values.yaml上書き
valueFiles:
- values-production.yaml
parameters:
- name: replicaCount
value: "5"
- name: image.tag
value: "v1.2.3"
# Helm release name
releaseName: my-app
destination:
server: https://kubernetes.default.svc
namespace: production
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
Kustomizeのデプロイ
# kustomize-application.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-kustomize-app
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/example/kustomize-manifests.git
targetRevision: main
path: overlays/production
kustomize:
# イメージタグの上書き
images:
- myregistry.io/my-app:v1.2.3
# ネームプレフィックス
namePrefix: prod-
# 共通ラベル
commonLabels:
env: production
destination:
server: https://kubernetes.default.svc
namespace: production
syncPolicy:
automated:
prune: true
selfHeal: true
App of Apps パターン
複数のアプリケーションを一元管理するパターン。
# apps/root-app.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: root-app
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/example/argocd-apps.git
targetRevision: main
path: apps/production
destination:
server: https://kubernetes.default.svc
namespace: argocd
syncPolicy:
automated:
prune: true
selfHeal: true
# apps/production/frontend.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: frontend
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/example/frontend.git
targetRevision: main
path: k8s
destination:
server: https://kubernetes.default.svc
namespace: frontend
syncPolicy:
automated:
prune: true
selfHeal: true
# apps/production/backend.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: backend
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/example/backend.git
targetRevision: main
path: k8s
destination:
server: https://kubernetes.default.svc
namespace: backend
syncPolicy:
automated:
prune: true
selfHeal: true
ポイント: App of Appsパターンでは、ルートアプリが子アプリケーションを管理し、環境ごとにディレクトリを分けます。
プロジェクト管理
# project.yaml
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: platform
namespace: argocd
spec:
description: Platform team services
# デプロイ可能なGitリポジトリ
sourceRepos:
- https://github.com/example/*
# デプロイ可能なクラスタと名前空間
destinations:
- namespace: '*'
server: https://kubernetes.default.svc
- namespace: 'kube-system'
server: https://prod-cluster.example.com
# 許可するリソース種別
clusterResourceWhitelist:
- group: '*'
kind: '*'
# 拒否するリソース種別
namespaceResourceBlacklist:
- group: ''
kind: ResourceQuota
- group: ''
kind: LimitRange
# RBAC
roles:
- name: developer
description: Developer role
policies:
- p, proj:platform:developer, applications, get, platform/*, allow
- p, proj:platform:developer, applications, sync, platform/*, allow
groups:
- platform-developers
実践メモ: AppProjectでチームごとにデプロイ権限を分離し、マルチテナント運用を実現できます。
Sync Waves と Hooks
Sync Waves
リソースの適用順序を制御します。
# database-secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: db-credentials
annotations:
argocd.argoproj.io/sync-wave: "0" # 最初に適用
stringData:
username: myapp
password: changeme
# database-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgres
annotations:
argocd.argoproj.io/sync-wave: "1" # 2番目
spec:
# ...
# app-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
annotations:
argocd.argoproj.io/sync-wave: "2" # 最後
spec:
# ...
Resource Hooks
# db-migration-job.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: db-migration
annotations:
argocd.argoproj.io/hook: PreSync
argocd.argoproj.io/hook-delete-policy: HookSucceeded
spec:
template:
spec:
containers:
- name: migrate
image: myregistry.io/my-app:v1.2.3
command: ["npm", "run", "migrate"]
restartPolicy: Never
| Hook | 実行タイミング |
|---|---|
PreSync | 同期前 |
Sync | 通常リソースと同時 |
PostSync | 同期後 |
SyncFail | 同期失敗時 |
Skip | スキップ |
マルチクラスタ管理
# クラスタの登録
argocd cluster add prod-cluster --name production
# クラスタ一覧
argocd cluster list
# Application定義
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-app-prod
spec:
destination:
server: https://prod-cluster.example.com # 外部クラスタ
namespace: production
注意: マルチクラスタ構成では、ArgoCDが各クラスタにServiceAccountを作成します。最小権限の原則に従って設定してください。
Notification設定
# argocd-notifications-cm.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-notifications-cm
namespace: argocd
data:
service.slack: |
token: $slack-token
template.app-deployed: |
message: |
Application {{.app.metadata.name}} is now running version {{.app.status.sync.revision}}.
slack:
attachments: |
[{
"title": "{{.app.metadata.name}}",
"title_link": "{{.context.argocdUrl}}/applications/{{.app.metadata.name}}",
"color": "#18be52",
"fields": [{
"title": "Sync Status",
"value": "{{.app.status.sync.status}}",
"short": true
}, {
"title": "Repository",
"value": "{{.app.spec.source.repoURL}}",
"short": true
}]
}]
trigger.on-deployed: |
- when: app.status.operationState.phase in ['Succeeded']
send: [app-deployed]
# Application with notification
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-app
annotations:
notifications.argoproj.io/subscribe.on-deployed.slack: platform-alerts
Image Updater
# Image Updaterのインストール
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj-labs/argocd-image-updater/stable/manifests/install.yaml
# Application with image auto-update
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-app
annotations:
argocd-image-updater.argoproj.io/image-list: myapp=myregistry.io/my-app
argocd-image-updater.argoproj.io/myapp.update-strategy: semver
argocd-image-updater.argoproj.io/myapp.allow-tags: regexp:^v[0-9]+\.[0-9]+\.[0-9]+$
argocd-image-updater.argoproj.io/write-back-method: git
spec:
source:
repoURL: https://github.com/example/my-app-manifests.git
targetRevision: main
path: k8s
kustomize:
images:
- myregistry.io/my-app:v1.0.0 # Image Updaterが自動更新
ポイント: Image Updaterはコンテナレジストリを監視し、新しいタグを検出すると自動的にGitリポジトリとArgoCDを更新します。