GitOps: governare ambienti e deploy senza rituali oscuri 🧭
GitOps è una di quelle parole che in molti usano come sinonimo elegante di “deploy via Git”. Peccato che non basti committare un file YAML per fare GitOps. Il punto vero è un altro: Git diventa la fonte di verità dichiarativa per ambienti e configurazioni, mentre un controller riconcilia in modo continuo lo stato reale con quello desiderato.
Se vuoi solo una pipeline che fa deploy, parti da CI/CD. Se vuoi che l’ambiente sia descritto, verificabile, revisionabile e riportato automaticamente allo stato atteso, allora sei nel territorio GitOps.
Cos’è GitOps davvero 🤔
In pratica GitOps significa questo:
- lo stato desiderato dell’ambiente vive in Git
- ogni modifica passa da commit, review e audit trail
- un operatore nel cluster o nell’ambiente legge il repository e applica il cambiamento
- la riconciliazione è continua, non “una volta sola durante il deploy”
La differenza importante rispetto a molte pipeline classiche è che non chiedi alla CI di “spingere” configurazioni in giro. Chiedi invece a un controller di leggere il repository e convergere verso lo stato dichiarato.
Quando ha senso usarlo ✅
GitOps funziona particolarmente bene quando hai:
- ambienti Kubernetes o comunque piattaforme dichiarative
- più ambienti da mantenere coerenti
- bisogno di audit trail chiaro su configurazioni e deploy
- team che vogliono review e rollback via pull request invece che SSH creativo in produzione
- necessità di rilevare e correggere il drift infrastrutturale o applicativo
Ha molto meno senso quando:
- l’ambiente è fortemente manuale o imperativo
- il team non ha ancora disciplina minima su repository, review e branching
- la piattaforma target non si presta bene a riconciliazione e stato dichiarato
Flusso operativo tipico 🔄
Il flusso più sano, semplificando, è questo:
flowchart LR
A[Commit applicazione] --> B[CI build e test]
B --> C[Pubblicazione artefatto immutabile]
C --> D[Aggiornamento manifest o Helm values in Git]
D --> E[Pull request e review]
E --> F[Merge su main]
F --> G[Controller GitOps rileva il delta]
G --> H[Riconcilia ambiente]
H --> I[Osservabilità e verifica]
Qui la CI produce artefatti, ma non resta proprietaria dello stato runtime. La responsabilità dello stato desiderato passa al repository GitOps e al controller che lo osserva.
Modello di riconciliazione GitOps 🧠
La parte più importante di GitOps non è il commit. È la riconciliazione continua. In altre parole: il sistema non “applica una volta e spera”. Confronta di continuo stato desiderato e stato reale, segnala divergenze e, quando configurato per farlo, corregge da solo.
stateDiagram-v2
[*] --> DesiredInGit
DesiredInGit --> Reconciling: nuovo commit o refresh
Reconciling --> Healthy: stato reale allineato
Healthy --> Drifted: modifica manuale / stato divergente
Drifted --> Reconciling: rilevazione drift
Reconciling --> Degraded: sync fallita / policy bloccante
Degraded --> Reconciling: fix e nuovo tentativo
Healthy --> [*]
Questo è il motivo per cui GitOps ha senso soprattutto su piattaforme dichiarative: il controller deve poter osservare, confrontare e convergere senza inventarsi metà della logica a runtime.
Tool e componenti tipici 🛠️
I mattoni più comuni sono questi:
- Argo CD: molto diffuso in Kubernetes, ottimo per applicazioni, sync policy e visibilità dello stato.
- Flux CD: approccio solido e modulare, spesso scelto da chi vuole forte integrazione cloud-native.
- Helm: utile come packaging layer, ma non coincide con GitOps; da solo non basta.
- Kustomize: ottimo per overlay ambientali senza trasformare i valori in una caccia al tesoro.
- External Secrets / Vault / SOPS: fondamentali per non infilare segreti in chiaro nel repository come se fosse il 2009.
Una stack minimale, molto comune, è questa:
- CI che builda e pubblica un artefatto immutabile
- registry per immagini o pacchetti
- repository GitOps separato per manifest e valori ambientali
- controller nel cluster con sync policy, health check e diff visibile
- osservabilità su sync, drift, rollout e rollback
Best practice che evitano dolore inutile 🧱
1. Separa codice applicativo e configurazione runtime 📦
Mescolare tutto nello stesso repository può funzionare su team piccoli, ma spesso conviene distinguere:
- repository del codice applicativo
- repository dei manifest o delle configurazioni di deploy
- eventualmente repository platform condivisi
L’obiettivo non è fare più repository “per sport”, ma evitare accoppiamenti inutili e chiarire ownership, review e promozione tra ambienti.
2. Promuovi artefatti, non ricostruire 🚚
GitOps non annulla una best practice CI/CD fondamentale: l’artefatto va costruito una volta sola. La promozione tra ambienti dovrebbe cambiare riferimenti, versioni o parametri, non ricompilare tutto come se nulla fosse successo.
3. Gestisci i segreti in modo serio 🔐
GitOps ama Git, ma Git non è un secret manager. Usa strumenti di cifratura o integrazione con vault e limita l’accesso in modo rigoroso. Un repository pieno di credenziali è un esercizio di post-mortem anticipato.
4. Rendi il drift visibile e governato 🧪
Il drift non va solo corretto: va prima rilevato. Se qualcuno cambia una risorsa a mano in produzione, devi saperlo subito. Decidi esplicitamente quando consentire self-healing automatico e quando richiedere intervento umano.
5. Usa policy e guardrail 🚧
GitOps senza policy rischia di essere solo “automazione veloce di errori versionati”. Integra:
- policy admission
- validazione dei manifest
- controlli di sicurezza
- regole di naming, tagging e limiti di risorse
6. Definisci una strategia chiara per repository e promozione 🗂️
Una delle prime decisioni che invecchia male, se presa in fretta, è la struttura dei repository. Alcuni team usano un mono-repo con overlay ambientali, altri separano applicazione, configurazione e piattaforma. Nessuna delle due scelte è magica: conta soprattutto che sia coerente e governabile.
Domande utili da chiudere subito:
- chi può modificare i manifest di produzione?
- la promozione tra ambienti avviene via merge, cherry-pick o aggiornamento automatico di versioni?
- i valori specifici di ambiente sono pochi e leggibili o stanno già degenerando in folklore YAML?
Se ogni ambiente ha la propria logica speciale, GitOps smette di semplificare e inizia a collezionare eccezioni.
7. Non trasformare GitOps in una discarica di responsabilità 🧯
GitOps è ottimo per descrivere e riconciliare stato desiderato. È pessimo se lo usi per infilare dentro qualsiasi automazione ti passa per la testa. Alcune cose dovrebbero restare fuori dal controller GitOps o essere governate con attenzione:
- job una tantum distruttivi
- migrazioni DB non idempotenti
- provisioning infrastrutturale pesante nello stesso layer applicativo
- logiche di business mascherate da configurazione
Più il repository GitOps diventa una valigia dove infili tutto, più perdi chiarezza operativa e rollback affidabile.
Relazione con IaC e CI/CD 🔗
GitOps, CI/CD e IaC non sono rivali. Sono livelli diversi dello stesso film:
- CI/CD costruisce, testa e pubblica artefatti
- IaC definisce infrastruttura e servizi come codice
- GitOps usa Git come fonte di verità e riconcilia automaticamente lo stato desiderato
Una combinazione sana è questa: IaC per creare cluster, rete, storage e identity; CI/CD per buildare artefatti; GitOps per governare configurazioni applicative e deploy continui.
Un modo semplice per leggerla è questo:
- IaC prepara il terreno
- CI/CD costruisce il pacco
- GitOps decide quale versione deve vivere in ogni ambiente e ne sorveglia lo stato
Errori comuni da evitare 🚫
Scambiare GitOps per “kubectl apply da pipeline”: se la CI spinge manifest direttamente nel cluster, sei più vicino a una pipeline tradizionale che a GitOps.
Tenere i segreti in chiaro nel repo: pratica comoda, fino al giorno in cui diventa una lezione molto costosa.
Overlay ambientali ingestibili: se ogni ambiente ha 14 eccezioni, non hai un modello dichiarativo. Hai un puzzle ostile.
Sync automatico ovunque e sempre: l’auto-sync è potente, ma va governato. In produzione senza guardrail può trasformare un errore in un incidente molto efficiente.
Nessuna osservabilità sul controller: se non sai perché un sync è fallito o cosa è stato corretto, stai guidando bendato con un dashboard “molto carino”.
In breve 🧾
GitOps funziona bene quando vuoi ambienti descritti in Git, riconciliazione continua, audit trail e rollback disciplinati. Non è una religione e non sostituisce CI/CD o IaC: li completa. Se implementato bene, riduce configurazioni manuali, drift silenzioso e deploy “artigianali” che invecchiano male.