Salta al contenuto principale

10 - GitOps con ArgoCD: Deploy Dichiarativo e Rollout Progressivi

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...

Cosa ne pensi di questo articolo?

10 - GitOps con ArgoCD: Deploy Dichiarativo e Rollout Progressivi
Kubernetes AvanzatoFoto:panumas nikhomkhaiPexels

In Breve

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...

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.

Serie Correlate

Prova Questi Strumenti

Strumenti gratuiti correlati a questo argomento.

Commenti

Caricamento commenti...

Accedi per commentare

Discuti questo articolo nella community

Unisciti al gruppo Telegram per discutere con altri sviluppatori, fare domande e condividere le tue esperienze.

Ti è piaciuto questo articolo?

Esplora altri contenuti sul blog o scopri i miei progetti