GitOps con ArgoCD: Deploy Dichiarativo e Rollout Progressivi
GitOps e il paradigma che trasforma Git da repository di codice a single source of truth per lo stato del cluster Kubernetes. L'idea e semplice ma potente: tutto cio che e deployato nel cluster deve essere descritto in manifest YAML versionati in Git. Un agente nel cluster (ArgoCD) osserva il repository e garantisce che lo stato reale del cluster converga sempre con lo stato desiderato in Git. Se qualcuno applica manualmente un hotfix direttamente con kubectl, ArgoCD lo rileva e lo annulla automaticamente.
In questo articolo vedremo come configurare ArgoCD da zero, implementare il pattern App of Apps per gestire decine di applicazioni in modo dichiarativo, usare ApplicationSet per multi-cluster e multi-environment, e integrare Argo Rollouts per canary deploy e blue-green senza downtime.
Cosa Imparerai
- Installazione e configurazione di ArgoCD con Helm
- Creare Application ArgoCD per il deploy sincronizzato con Git
- Pattern App of Apps per gestire molte applicazioni
- ApplicationSet: deploy su multi-cluster e multi-environment automatizzato
- Sync policies: automated sync, self-heal, pruning
- Argo Rollouts: canary con analisi statistica, blue-green, traffic splitting
- RBAC ArgoCD per ambienti multi-team
- Notifiche Slack/Teams sugli eventi di deploy
Installazione 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
Prima Application ArgoCD
Una Application ArgoCD e la risorsa principale: definisce da dove prendere i manifest (source) e dove deployarli (destination):
# 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
Struttura del Repository Git per GitOps
La struttura del repo GitOps impatta direttamente la manutenibilita. Il pattern piu comune e separare il repo del codice applicativo dal repo dei manifest 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 Pattern
Con App of Apps, una singola Application ArgoCD (la "root app") gestisce tutte le altre Application ArgoCD. E il pattern piu scalabile per cluster con molte applicazioni:
# 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: Multi-Cluster e Multi-Environment
ApplicationSet genera automaticamente multiple Application ArgoCD da un template. Ideale per deployare la stessa applicazione su molti cluster o ambienti:
# 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 Rollouts: Canary Deploy e Blue-Green
Argo Rollouts estende Kubernetes con strategie di deployment avanzate: canary con analisi statistica, blue-green con switch manuale o automatico, traffic splitting con Istio o ingress 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
Canary Deploy con Analisi Automatica
# 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)
)
Gestione del Rollout tramite 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
Notifiche ArgoCD per Slack e Teams
# 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
Best Practices GitOps con ArgoCD
Checklist GitOps di Produzione
- Repo separati per app code e manifest K8s: Il repo GitOps non deve contenere codice applicativo. Separa config da codice
- Image tag nel GitOps repo (non "latest"): Il tag dell'immagine deve essere un SHA o versione specifica, non "latest" - per reproducibilita
- Review obbligatoria per production: I PR verso il branch production richiedono almeno un'approvazione. ArgoCD non deve applicare automaticamente senza review in prod
- Secret con External Secrets Operator: Non mettere mai Secret in chiaro nel repo GitOps. Usa ESO con AWS Secrets Manager o Vault
- Self-heal in dev, manuale in prod: Il self-heal automatico e utile in dev/staging ma rischioso in prod (potrebbe annullare hotfix urgenti)
- Usa Kustomize o Helm, non raw YAML: Il templating permette riuso degli overlay per ambiente evitando duplicazione
Conclusioni e Prossimi Passi
ArgoCD trasforma il deploy Kubernetes da un'operazione manuale e rischiosa a un processo automatizzato, auditabile e reversibile. La combinazione di App of Apps per la gestione dichiarativa dell'intero cluster e Argo Rollouts per i canary deploy progressivi crea una pipeline di delivery che bilancia velocita e sicurezza.
Il prossimo passo naturale dopo GitOps e l'osservabilita: senza metriche e logging, non puoi sapere se il tuo canary sta avendo successo o sta introducendo regressioni. L'articolo 11 di questa serie - Prometheus, Grafana e OpenTelemetry - completa il quadro.
Prossimi Articoli della Serie Kubernetes at Scale
Serie Correlate
- DevSecOps - GitOps + security scanning nel pipeline
- Platform Engineering - ArgoCD come componente dell'IDP
- Terraform e Infrastructure as Code - provisioning del cluster prima del GitOps

Commenti
Caricamento commenti...
Accedi per commentare