Sari la conținut
← Perspective

5 min readDe Kicked Team

GitOps: Infrastructure as Code făcut corect

GitOps înseamnă mai mult decât a ține configurările în Git. Este un model operațional complet, în care Git este singura sursă de adevăr și reconcilierea este continuă. Iată cum îl implementăm noi.

  • DevOps
  • GitOps
  • Kubernetes
  • Infrastructure

„Ținem Terraform-ul în Git” nu este GitOps. Este version control. GitOps este un model operațional în care:

  1. Întregul sistem este descris declarativ
  2. Starea dorită trăiește în Git
  3. Modificările se fac prin pull request-uri
  4. Un controller reconciliază continuu starea reală cu starea dorită

Ultimul punct este cel care separă GitOps de „configurări într-un repo”.

De ce GitOps?

Administrăm infrastructură pentru zeci de clienți. Înainte de GitOps, deploy-urile arătau așa:

Developer → SSH into server → Run commands → Hope it works → Forget what they changed

Cu GitOps:

Developer → Open PR → Review → Merge → Automated reconciliation → Drift detection

Beneficiile se adună:

  • Audit trail — Fiecare modificare este un commit Git cu autor, timestamp și review
  • Rollbackgit revert este butonul tău de „undo”
  • Reproductibilitate — Ridici un mediu identic din același repo
  • Detectarea drift-ului — Controller-ul alertează când realitatea se abate de la Git
  • Self-service — Developerii pot face modificări de infrastructură prin PR-uri, fără acces SSH

Cele două pattern-uri: Push vs. Pull

Bazat pe push (CI/CD tradițional)

Git Push → CI Pipeline → kubectl apply / terraform apply → Cluster

Pipeline-ul are credențiale pentru a modifica infrastructura. Funcționează, dar are dezavantaje:

  • Sistemul de CI are nevoie de acces larg la producție
  • Fără reconciliere continuă — drift-ul rămâne nedetectat
  • Eșecurile din pipeline pot lăsa starea aplicată parțial

Bazat pe pull (GitOps)

Git Push → Controller (in-cluster) → Detects diff → Reconciles → Cluster matches Git

Controller-ul rulează în interiorul cluster-ului și trage starea dorită din Git. Acesta este modelul GitOps.

Stack-ul nostru GitOps

ArgoCD pentru Kubernetes

ArgoCD este controller-ul nostru GitOps principal pentru workload-urile Kubernetes. Urmărește repo-urile Git și se asigură că cluster-ul le corespunde.

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: production-api
  namespace: argocd
spec:
  project: production
  source:
    repoURL: https://github.com/kicked-ro/infrastructure
    targetRevision: main
    path: apps/production/api
  destination:
    server: https://kubernetes.default.svc
    namespace: production
  syncPolicy:
    automated:
      prune: true        # Delete resources removed from Git
      selfHeal: true     # Revert manual changes
    syncOptions:
      - CreateNamespace=true

Alegeri-cheie de configurare:

  • selfHeal: true — Dacă cineva editează manual o resursă, ArgoCD o readuce la loc. Git este sursa de adevăr, întotdeauna.
  • prune: true — Resursele șterse din Git sunt șterse din cluster. Fără resurse zombie.
  • Sincronizare automată — Merge-ul în main declanșează deploy-ul. Fără butoane apăsate manual.

Terraform + Atlantis pentru resurse cloud

Pentru infrastructura cloud (VM-uri, DNS, networking) folosim Terraform cu Atlantis, într-un flux bazat pe PR-uri:

Developer opens PR with Terraform change
  → Atlantis runs `terraform plan`
  → Plan output posted as PR comment
  → Reviewer approves
  → Atlantis runs `terraform apply`
  → State updated, PR merged

Nimeni nu rulează terraform apply local. Niciodată.

Renovate pentru actualizarea dependențelor

Menținerea la zi a imaginilor de bază, a versiunilor de Helm chart-uri și a provider-ilor Terraform este un job cu normă întreagă. Renovate îl automatizează:

{
  "$schema": "https://docs.renovatebot.com/renovate-schema.json",
  "extends": ["config:recommended"],
  "kubernetes": {
    "fileMatch": ["apps/.+\\.yaml$"]
  },
  "regexManagers": [
    {
      "fileMatch": ["apps/.+\\.yaml$"],
      "matchStrings": ["image: (?<depName>.*?):(?<currentValue>.*?)\\s"],
      "datasourceTemplate": "docker"
    }
  ]
}

Renovate deschide PR-uri pentru fiecare actualizare. ArgoCD le face deploy când sunt merge-uite. Supply chain complet automatizat.

Structura repository-ului

Am ajuns la această structură după multe iterații:

infrastructure/
├── apps/
│   ├── production/
│   │   ├── api/
│   │   │   ├── deployment.yaml
│   │   │   ├── service.yaml
│   │   │   └── kustomization.yaml
│   │   ├── web/
│   │   └── workers/
│   └── staging/
│       └── ... (mirrors production)
├── platform/
│   ├── cert-manager/
│   ├── ingress-nginx/
│   ├── monitoring/
│   └── external-secrets/
├── terraform/
│   ├── networking/
│   ├── dns/
│   └── compute/
└── renovate.json

Apps sunt workload-urile. Platform este infrastructura partajată. Terraform sunt resursele de la nivelul cloud. Fiecare director este o ArgoCD Application.

Secretele în GitOps

Singurul lucru pe care nu îl poți pune în Git: secretele. Abordarea noastră:

  1. Sealed Secrets — Criptezi secretele cu o cheie specifică cluster-ului. Versiunea criptată trăiește în Git. Doar cluster-ul le poate decripta.
  2. External Secrets Operator — Referențiezi secrete din Vault/AWS SSM. Git stochează referința, nu valoarea.

Preferăm External Secrets Operator pentru producție, pentru că rotația secretelor este automată.

Lecții învățate

  1. Începe cu o singură aplicație — Nu încerca să treci toată infrastructura pe GitOps în prima săptămână
  2. Impune selfHeal — Dacă oamenii pot ocoli Git, o vor face, iar sursa ta de adevăr devine o minciună
  3. Review-urile de PR sunt obligatorii — Chiar și pentru inginerul senior. Mai ales pentru inginerul senior
  4. Testează întâi în staging — ArgoCD ApplicationSets fac promovarea între medii trivială
  5. Monitorizează starea de sync — O aplicație blocată în „OutOfSync” este o bombă cu ceas

Rezultatul

De când am adoptat GitOps în toată infrastructura noastră:

  • Zero modificări neautorizate în producție
  • 4 minute timp mediu de deploy (de la merge la rulare)
  • 100% audit trail pentru fiecare modificare de infrastructură
  • Disaster recovery într-un singur click (îndrepți ArgoCD către repo, gata)

GitOps nu este doar o strategie de deploy — este o filosofie operațională. Dacă încă intri prin SSH pe servere ca să faci modificări, hai să vorbim.