ArgoCD を使用した GitOps: 宣言的デプロイとプログレッシブ ロールアウト
GitOps は、Git をコード リポジトリから 唯一の真実の情報源 Kubernetes クラスターのステータス。アイデアはシンプルですが強力です。すべてが展開されます。 クラスター内のは、Git でバージョン管理された YAML マニフェストに記述する必要があります。クラスター内のエージェント (ArgoCD) リポジトリを監視し、クラスターの実際の状態が常に収束していることを確認します。 Git で望ましい状態にします。誰かが手動でホットフィックスを直接適用した場合 kubectl、ArgoCD がそれを検出し、自動的にキャンセルします。
この記事では、その設定方法について説明します アルゴCD ゼロから実装する パターン アプリの中のアプリ 数十のアプリケーションを宣言的に管理するには、 使う アプリケーションセット マルチクラスターおよびマルチ環境に対応し、統合する アルゴのロールアウト ダウンタイムのないカナリア展開とブルーグリーン向け。
何を学ぶか
- Helm を使用した ArgoCD のインストールと構成
- Git と同期してデプロイするためのアプリケーション ArgoCD を作成する
- 多くのアプリケーションを管理するための App of Apps パターン
- ApplicationSet: 自動化されたマルチクラスターおよびマルチ環境の展開
- 同期ポリシー: 自動同期、自己修復、プルーニング
- Argo ロールアウト: 統計分析を備えたカナリア、Blue-Green、トラフィック分割
- マルチチーム環境用の ArgoCD RBAC
- 導入イベントに関する Slack/Teams の通知
ArgoCD のインストール
# Installa ArgoCD con Helm (raccomandato per produzione)
helm repo add argo https://argoproj.github.io/argo-helm
helm repo update
helm install argocd argo/argo-cd \
--namespace argocd \
--create-namespace \
--version 7.6.0 \
--set global.domain=argocd.company.com \
--set server.ingress.enabled=true \
--set server.ingress.ingressClassName=nginx \
--set configs.params."server.insecure"=true \
--set dex.enabled=false # disabilita se non usi SSO
# Ottieni la password admin iniziale
kubectl -n argocd get secret argocd-initial-admin-secret \
-o jsonpath="{.data.password}" | base64 -d
# Accedi con ArgoCD CLI
argocd login argocd.company.com
argocd account update-password
# Verifica stato
argocd version
kubectl get pods -n argocd
最初のアプリケーション ArgoCD
Una 応用 ArgoCD が主要なリソースです。どこから取得するかを定義します。 マニフェスト (ソース) とそれらをデプロイする場所 (宛先) を取得します。
# application-api-service.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: api-service-production
namespace: argocd
labels:
team: team-alpha
environment: production
finalizers:
- resources-finalizer.argocd.argoproj.io # elimina risorse K8s quando Application viene eliminata
spec:
project: team-alpha # ArgoCD Project per RBAC
source:
repoURL: https://github.com/company/k8s-manifests
targetRevision: main # branch/tag/commit SHA
path: apps/api-service/production # path nel repo
destination:
server: https://kubernetes.default.svc # cluster locale
namespace: team-alpha-production
syncPolicy:
automated:
prune: true # elimina risorse non piu presenti in Git
selfHeal: true # ripristina modifiche manuali non autorizzate
syncOptions:
- CreateNamespace=true # crea namespace se non esiste
- PrunePropagationPolicy=foreground
- ApplyOutOfSyncOnly=true # applica solo le risorse cambiate
retry:
limit: 5
backoff:
duration: 5s
factor: 2
maxDuration: 3m
# Ignorare alcune differenze (es. annotation aggiunte dal cluster)
ignoreDifferences:
- group: apps
kind: Deployment
jsonPointers:
- /spec/replicas # ignora modifiche manuali al numero di repliche
GitOps 用の Git リポジトリの構造
GitOps リポジトリの構造は、保守性に直接影響します。一番多いパターン common を作成し、アプリケーション コード リポジトリを K8s マニフェスト リポジトリから分離します。
# Struttura raccomandata del repo k8s-manifests:
k8s-manifests/
├── apps/ # manifest applicazioni
│ ├── api-service/
│ │ ├── base/ # Kustomize base
│ │ │ ├── deployment.yaml
│ │ │ ├── service.yaml
│ │ │ └── kustomization.yaml
│ │ ├── dev/
│ │ │ ├── kustomization.yaml # overlays per dev
│ │ │ └── resources-patch.yaml
│ │ ├── staging/
│ │ │ └── kustomization.yaml
│ │ └── production/
│ │ ├── kustomization.yaml
│ │ └── hpa.yaml
│ └── worker-service/
│ └── ...
├── platform/ # risorse platform (ingress, cert-manager, etc.)
│ ├── ingress-nginx/
│ ├── cert-manager/
│ └── monitoring/
└── argocd/ # App of Apps: Application resources
├── root-app.yaml # App of Apps root
├── team-alpha.yaml
└── platform.yaml
# Kustomize base per api-service
# base/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- service.yaml
commonLabels:
app: api-service
managed-by: argocd
# production/kustomization.yaml - overlay con 3 repliche
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
bases:
- ../base
replicas:
- name: api-service
count: 3
images:
- name: company.registry.io/api-service
newTag: "v2.5.1" # aggiornato dalla CI/CD pipeline
patchesStrategicMerge:
- resources-patch.yaml
アプリのアプリパターン
App of Apps では、単一の ArgoCD アプリケーション (「ルート アプリケーション」) がすべてのアプリケーションを管理します。 他の ArgoCD アプリケーション。これは、多くのアプリケーションを含むクラスターにとって最もスケーラブルなパターンです。
# argocd/root-app.yaml - la App of Apps root
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: root-app
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/company/k8s-manifests
targetRevision: main
path: argocd/ # questa cartella contiene le Application resources
destination:
server: https://kubernetes.default.svc
namespace: argocd
syncPolicy:
automated:
prune: true
selfHeal: true
---
# argocd/team-alpha.yaml - Application che punta agli overlay di team-alpha
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: team-alpha-production
namespace: argocd
spec:
project: team-alpha
source:
repoURL: https://github.com/company/k8s-manifests
targetRevision: main
path: apps/api-service/production
kustomize:
images:
- company.registry.io/api-service:v2.5.1 # aggiornato dalla CI
destination:
server: https://kubernetes.default.svc
namespace: team-alpha-production
syncPolicy:
automated:
prune: true
selfHeal: true
ApplicationSet: マルチクラスターとマルチ環境
アプリケーションセット 1 つのアプリケーションから複数の ArgoCD アプリケーションを自動的に生成します テンプレート。同じアプリケーションを多くのクラスターまたは環境にデプロイする場合に最適です。
# applicationset-multi-env.yaml
# Deploy api-service su dev, staging e production dallo stesso template
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: api-service-all-envs
namespace: argocd
spec:
generators:
- list:
elements:
- environment: dev
namespace: team-alpha-dev
replicaCount: "1"
imageTag: "latest"
cluster: in-cluster
- environment: staging
namespace: team-alpha-staging
replicaCount: "2"
imageTag: "v2.5.0"
cluster: in-cluster
- environment: production
namespace: team-alpha-production
replicaCount: "5"
imageTag: "v2.4.9" # production usa tag stabile
cluster: production-cluster
template:
metadata:
name: 'api-service-{{environment}}'
labels:
environment: '{{environment}}'
spec:
project: team-alpha
source:
repoURL: https://github.com/company/k8s-manifests
targetRevision: main
path: 'apps/api-service/{{environment}}'
kustomize:
images:
- 'company.registry.io/api-service:{{imageTag}}'
destination:
server: '{{cluster}}'
namespace: '{{namespace}}'
syncPolicy:
automated:
prune: true
selfHeal: '{{eq environment "production" | not}}' # no selfHeal in prod
Argo のロールアウト: Canary デプロイと Blue-Green
Argo Rollouts は、高度なデプロイメント戦略で Kubernetes を拡張します: 分析機能を備えたカナリア 統計、手動または自動切り替えによる Blue-Green、Istio によるトラフィック分割、または NGINX 入力:
# Installa Argo Rollouts
kubectl create namespace argo-rollouts
kubectl apply -n argo-rollouts \
-f https://github.com/argoproj/argo-rollouts/releases/latest/download/install.yaml
# Installa plugin kubectl
curl -LO https://github.com/argoproj/argo-rollouts/releases/latest/download/kubectl-argo-rollouts-linux-amd64
chmod +x kubectl-argo-rollouts-linux-amd64
sudo mv kubectl-argo-rollouts-linux-amd64 /usr/local/bin/kubectl-argo-rollouts
自動分析を使用したカナリア展開
# rollout-canary.yaml
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: api-service
namespace: team-alpha-production
spec:
replicas: 10
selector:
matchLabels:
app: api-service
template:
metadata:
labels:
app: api-service
spec:
containers:
- name: api
image: company.registry.io/api-service:v2.5.1
resources:
requests:
cpu: 250m
memory: 512Mi
limits:
cpu: 500m
memory: 1Gi
strategy:
canary:
# Step 1: 10% traffico alla nuova versione
# Step 2: analisi automatica per 5 minuti
# Step 3: se ok, vai al 30% poi 100%
steps:
- setWeight: 10 # 10% traffico al canary
- analysis: # analisi automatica
templates:
- templateName: success-rate
args:
- name: service-name
value: api-service
- pause: {duration: 5m}
- setWeight: 30
- pause: {duration: 5m}
- setWeight: 100
# Canary Service: il nuovo Service per il traffico canary
canaryService: api-service-canary
stableService: api-service-stable
# Traffic routing con NGINX Ingress
trafficRouting:
nginx:
stableIngress: api-service-ingress
---
# AnalysisTemplate: definisce i criteri di successo
apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
name: success-rate
namespace: team-alpha-production
spec:
args:
- name: service-name
metrics:
- name: success-rate
interval: 1m
successCondition: result[0] >= 0.95 # 95% di successo richiesto
failureLimit: 3 # fallisce dopo 3 misurazioni consecutive < 95%
provider:
prometheus:
address: http://prometheus.monitoring.svc:9090
query: |
sum(rate(http_requests_total{service="{{args.service-name}}",status=~"2.."}[5m]))
/
sum(rate(http_requests_total{service="{{args.service-name}}"}[5m]))
- name: latency-p99
interval: 1m
successCondition: result[0] < 0.5 # P99 < 500ms
provider:
prometheus:
address: http://prometheus.monitoring.svc:9090
query: |
histogram_quantile(0.99,
sum(rate(http_request_duration_seconds_bucket{service="{{args.service-name}}"}[5m])) by (le)
)
CLI によるロールアウト管理
# Visualizza stato del rollout in tempo reale
kubectl argo rollouts get rollout api-service -n team-alpha-production --watch
# Promuovi manualmente al prossimo step (se pause)
kubectl argo rollouts promote api-service -n team-alpha-production
# Rollback immediato se qualcosa va storto
kubectl argo rollouts abort api-service -n team-alpha-production
kubectl argo rollouts undo api-service -n team-alpha-production
# Dashboard UI di Argo Rollouts
kubectl argo rollouts dashboard &
# Apri http://localhost:3100
Slack および Teams の ArgoCD 通知
# argocd-notifications-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-notifications-cm
namespace: argocd
data:
service.slack: |
token: $slack-token
template.app-deployed: |
message: |
:rocket: Application *{{.app.metadata.name}}* deployed to *{{.app.spec.destination.namespace}}*
Image: `{{index .app.status.summary.images 0}}`
Sync: {{.app.status.sync.status}}
template.app-health-degraded: |
message: |
:red_circle: Application *{{.app.metadata.name}}* health degraded!
{{range .app.status.conditions}}{{.message}}{{end}}
trigger.on-deployed: |
- description: Application is synced and healthy
send:
- app-deployed
when: app.status.operationState.phase in ['Succeeded'] and
app.health.status == 'Healthy'
trigger.on-health-degraded: |
- description: Application has degraded
send:
- app-health-degraded
when: app.health.status == 'Degraded'
---
# Applica annotazione sull'Application per ricevere notifiche
kubectl annotate app api-service-production \
notifications.argoproj.io/subscribe.on-deployed.slack="deployments-channel" \
-n argocd
ArgoCD を使用した GitOps のベスト プラクティス
本番環境の GitOps チェックリスト
- K8s アプリのコードとマニフェストの個別のリポジトリ: GitOps リポジトリにはアプリケーション コードを含めることはできません。コードから構成を分離する
- GitOps リポジトリのイメージ タグ (「最新」ではない): 再現性を高めるため、イメージ タグは「最新」ではなく、SHA またはバージョン固有である必要があります
- 本番環境での必須レビュー: ブランチプロダクションへの PR には少なくとも 1 つの承認が必要です。 ArgoCD は本番環境でのレビューなしに自動的に適用されるべきではありません
- 外部シークレットを使用したシークレット演算子: GitOps リポジトリでは決して Secret を明らかにしないでください。 AWS Secrets Manager または Vault で ESO を使用する
- 開発では自己修復、本番では手動: 自動自己修復は開発/ステージングでは便利ですが、本番環境では危険です (緊急のホットフィックスがキャンセルされる可能性があります)
- 生の YAML ではなく、KusTOMize または Helm を使用します。 テンプレート化により、重複を避けて環境ごとにオーバーレイを再利用できます
結論と次のステップ
ArgoCD は、Kubernetes のデプロイを手動で危険な操作からプロセスに変換します。 自動化され、監査可能で、元に戻すことができます。管理用アプリの組み合わせ クラスター全体の宣言型およびプログレッシブ カナリア デプロイメント用の Argo ロールアウトにより、 スピードとセキュリティのバランスをとった配信パイプライン。
GitOps の次の自然なステップは可観測性です。メトリクスとロギングを使用せず、 カナリアが成功しているのか、それとも退行を引き起こしているのかを知ることができます。記事 このシリーズの 11 個 (Prometheus、Grafana、OpenTelemetry) で全体像が完成します。
Kubernetes at Scale シリーズの今後の記事
関連シリーズ
- DevSecOps — GitOps + パイプラインでのセキュリティ スキャン
- プラットフォームエンジニアリング — IDP のコンポーネントとしての ArgoCD
- Terraform とコードとしてのインフラストラクチャ — GitOps 前のクラスター プロビジョニング







