GitOps ve Terraform: Kombinasyon Neden Güçlü?

GitOps, Kubernetes uygulama dağıtımını dönüştürdü: Git kaynak haline geldi Gerçek şu ki, bir kontrolör sürekli olarak istenen durumu gerçek durumla uzlaştırır, her değişiklik bir çekme isteğinden geçer. 2026'da aynı paradigma geçerli olacak Terraform ile yönetilen bulut altyapısı için çok önemli bir farkla Geleneksel CI/CD: Bas ve unut tetikleyicisi yerine, uzlaşma devam et Bu, sapmaları otomatik olarak algılar ve düzeltir.

GitHub Actions veya Atlantis e'ye dayalı geleneksel Terraform iş akışlarındaki sorun ben kimim reaktif: Birisi AWS konsolunda manuel değişiklik yapıyor ve kimse yok bir sonraki boru hattı çalışana kadar bunu bilir. Terraform için GitOps ile her HCL kodu ile gerçek durum arasındaki tutarsızlık bir uyarıya dönüşür veya düzeltilir yapılandırılmış politikaya göre otomatik olarak.

Ne Öğreneceksiniz

  • IaC için GitOps mimarisi: çekme modeli ve itme modeli
  • Flux Terraform Controller: kurulum, Terraform nesnesi CRD'si ve mutabakat
  • S3 ve IRSA arka ucuyla Kubernetes'ten Terraform durum yönetimi
  • Spacelift: yığınlar, Rego politikaları, RBAC ve onay iş akışları
  • Sürüklenme tespiti: Yetkisiz sapmalara karşı Slack/PagerDuty uyarısı
  • Kritik ortamlara yönelik model: otomatik iyileştirme ve manuel onay

IaC için Çekme Modeli ve İtme Modeli

GitOps ile geleneksel CI/CD arasındaki temel ayrım senkronizasyon modelidir. içinde itme modeli (GitHub Actions, Jenkins), boru hattı her taahhütte devreye giriyor ve altyapıdaki değişiklikleri “itirir”. içinde çekme modeli (saf GitOps), Küme içinde çalışan bir aracı sürekli olarak istenen durumu depodan "çeker" ve uzlaşın. Bu farkın güvenlik ve dayanıklılık açısından derin etkileri vardır:

# Push Model (GitHub Actions) — richiede credenziali cloud nella pipeline
# Il runner GitHub deve avere accesso outbound al cloud provider
# Problem: se il job fallisce a meta, lo state puo essere inconsistente

# Pull Model (Flux TF Controller) — l'agente vive dentro il cluster
# Solo il cluster Kubernetes ha le credenziali cloud (via IRSA o Workload Identity)
# Vantaggio: single point of trust, nessuna credenziale nelle GitHub Secrets
# Vantaggio: riconciliazione continua ogni N minuti, non solo su commit

# Confronto security:
# Push Model: GitHub runner --[credenziali]--> AWS/Azure/GCP
# Pull Model: Kubernetes pod -[IRSA/WI]--> AWS/Azure/GCP
#             Git repository -[SSH/HTTPS]--> Flux controller (dentro cluster)

Flux Terraform Kontrol Cihazı

Il Flux Terraform Kontrol Cihazı (tf denetleyicisi) ve bir Kubernetes denetleyicisi Terraform'u GitOps dünyasına getiren açık kaynak. Bu bir Flux topluluk projesi (Weaveworks + bağımsız bakımcı) Flux'u çalışma yeteneğiyle genişletiyor Terraform'u yerel Kubernetes mutabakat döngüleri olarak planlar ve uygular.

Kurulum

# Prerequisiti: cluster Kubernetes + Flux installato
# Installa Flux sul cluster (se non presente)
flux install

# Installa il TF Controller tramite HelmRelease
cat <<'EOF' | kubectl apply -f -
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: HelmRepository
metadata:
  name: tf-controller
  namespace: flux-system
spec:
  interval: 1h
  url: https://weaveworks.github.io/tf-controller
---
apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
  name: tf-controller
  namespace: flux-system
spec:
  interval: 1h
  chart:
    spec:
      chart: tf-controller
      version: "0.16.x"
      sourceRef:
        kind: HelmRepository
        name: tf-controller
        namespace: flux-system
  values:
    replicaCount: 1
    resources:
      limits:
        cpu: "1"
        memory: 1Gi
      requests:
        cpu: 200m
        memory: 512Mi
    # Runner pods: eseguono il processo terraform effettivo
    runner:
      image:
        tag: "v1.5.x-flux"
EOF

# Verifica installazione
kubectl get pods -n flux-system | grep tf-controller
# NAME                                          READY   STATUS    RESTARTS
# tf-controller-6d8f9b4b5-xn7q2               1/1     Running   0

GitRepository ve Terraform CRD yapılandırması

İş akışı iki Kubernetes nesnesine dayanmaktadır: GitRepository hangisine işaret ediyor HCL kodunun bulunduğu depo ve bir nesne Terraform (CRD özel) tanımlayan neyle barışmalı.

# 1. GitRepository: sorgente del codice HCL
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: GitRepository
metadata:
  name: infra-repo
  namespace: flux-system
spec:
  interval: 1m          # Controlla il repo ogni minuto
  url: https://github.com/myorg/terraform-infra
  ref:
    branch: main
  secretRef:
    name: github-ssh-key  # Secret con chiave SSH o token

---
# 2. Terraform CRD: definisce il modulo da riconciliare
apiVersion: infra.contrib.fluxcd.io/v1alpha2
kind: Terraform
metadata:
  name: aws-networking
  namespace: flux-system
spec:
  # Intervallo di riconciliazione
  interval: 10m

  # Sorgente HCL
  sourceRef:
    kind: GitRepository
    name: infra-repo
  path: ./environments/prod/networking   # Path nel repo

  # Approvazione automatica (auto-apply) o manuale
  approvePlan: auto

  # Gestione del drift: se lo stato reale differisce dal desired
  # force: riconcilia automaticamente
  # drift: solo alert, non corregge
  enableInventory: true

  # Backend per lo state (S3 con IRSA)
  backendConfig:
    customConfiguration: |
      backend "s3" {
        bucket         = "myorg-terraform-state-prod"
        key            = "networking/terraform.tfstate"
        region         = "eu-west-1"
        dynamodb_table = "terraform-state-lock"
        encrypt        = true
      }

  # Variabili passate al modulo
  vars:
    - name: environment
      value: prod
    - name: aws_region
      value: eu-west-1

  # Variabili da Secret Kubernetes (per segreti)
  varsFrom:
    - kind: Secret
      name: terraform-vars-prod
      varsKeys:
        - db_password
        - api_key

Kubernetes'ten AWS Erişimi için IRSA

Kubernetes e'den AWS kimlik doğrulaması için en iyi uygulamalar IRSA (Hizmet Hesapları için IAM Rolleri): Terraform bölmesi, kullanıcı tarafından imzalanmış bir JWT belirteci alır. herhangi bir anahtar olmadan geçici AWS kimlik bilgileriyle değiştirilen küme kümeye sabit kodlanmıştır.

# Crea il Service Account con annotazione IRSA
kubectl create serviceaccount tf-runner -n flux-system

kubectl annotate serviceaccount tf-runner \
  -n flux-system \
  eks.amazonaws.com/role-arn=arn:aws:iam::123456789:role/TerraformRunnerRole

# IAM Role Trust Policy (da configurare su AWS):
# {
#   "Version": "2012-10-17",
#   "Statement": [{
#     "Effect": "Allow",
#     "Principal": {
#       "Federated": "arn:aws:iam::123456789:oidc-provider/oidc.eks.eu-west-1.amazonaws.com/..."
#     },
#     "Action": "sts:AssumeRoleWithWebIdentity",
#     "Condition": {
#       "StringEquals": {
#         "oidc.eks.eu-west-1.amazonaws.com/...:sub":
#           "system:serviceaccount:flux-system:tf-runner"
#       }
#     }
#   }]
# }

# Aggiorna il CRD Terraform per usare il Service Account
# Aggiungi nella spec:
# serviceAccountName: tf-runner

Drift Algılama ve Bildirimler

Altyapının gerçek durumu bundan farklı olduğunda kayma meydana gelir HCL kodunda açıklanmıştır - genellikle bulut konsolunda manuel değişiklikler için. TF Kontrolörü her mutabakat döngüsündeki sapmayı tespit eder ve bunu aracılığıyla bildirir. o Alert Flux tarafından.

# Alert Flux per notifiche Slack sul drift
apiVersion: notification.toolkit.fluxcd.io/v1beta2
kind: Provider
metadata:
  name: slack-infra
  namespace: flux-system
spec:
  type: slack
  channel: "#infra-alerts"
  secretRef:
    name: slack-webhook-url

---
apiVersion: notification.toolkit.fluxcd.io/v1beta2
kind: Alert
metadata:
  name: terraform-drift-alert
  namespace: flux-system
spec:
  providerRef:
    name: slack-infra
  eventSeverity: warning
  eventSources:
    - kind: Terraform
      name: "*"   # Tutti gli oggetti Terraform
  # Invia alert per questi eventi:
  # - drift detected
  # - reconciliation failed
  # - plan pending approval
# Verificare lo stato di drift manualmente
kubectl get terraform -n flux-system
# NAME              READY   STATUS                          AGE
# aws-networking    True    Reconciliation succeeded        2h
# aws-database      False   Drift detected: 3 resources     15m

# Dettaglio del drift
kubectl describe terraform aws-database -n flux-system | grep -A 20 "Conditions:"
# Conditions:
#   Last Transition Time:  2026-03-20T10:30:00Z
#   Message:               Drift detected: aws_db_instance.main (tags changed),
#                           aws_security_group.db (ingress rule added manually)
#   Reason:                TerraformOutputsWritten
#   Status:                False
#   Type:                  Ready

Spacelift: Terraform için GitOps Enterprise

Uzay asansörü ve düşünceli bir SaaS platformu (kendi kendine barındırılan seçeneğiyle). Terraform'u kurumsal ortamlarda çalıştıran ekipler için. TF Kontrolörün aksine Kubernetes kümesinin içinde yaşayan Spacelift, kapsamlı kullanıcı arayüzü ve gelişmiş politikalar sunuyor yazılı Rego (OPA ile aynı dil), ayrıntılı RBAC e Tam denetim takibi ile onay iş akışı.

Temel Uzay Asansörü Kavramları

# Struttura Spacelift
# Stack = equivalente di un workspace Terraform
# Ogni stack ha:
# - Source: GitHub/GitLab repository + branch + path
# - Runner image: immagine Docker con Terraform + provider
# - Environment variables: variabili e segreti
# - Policies: regole Rego applicate a plan/apply
# - Contexts: set di variabili condivisibili tra stack

# Creare uno stack via Spacelift API (Terraform provider spacelift):
resource "spacelift_stack" "networking_prod" {
  name        = "networking-prod"
  repository  = "terraform-infra"
  branch      = "main"
  project_root = "environments/prod/networking"

  # Auto-deploy su push al branch
  autodeploy = false   # Per prod: richiede approvazione manuale

  # Terraform version
  terraform_version = "1.9.x"

  labels = ["team:platform", "env:prod", "tier:networking"]
}

resource "spacelift_context_attachment" "networking_prod" {
  context_id = spacelift_context.aws_prod.id
  stack_id   = spacelift_stack.networking_prod.id
  priority   = 1
}

Spacelift'te Politika Rego

Rego politikaları Spacelift'in güçlü noktasıdır: korkulukları tanımlamanıza olanak tanır Onay istenip istenmeyeceğine karar verilmeden önce her plan üzerinde değerlendirilen kompleksler, engelle veya otomatik uygula. Ve temelde programlanabilir bir kapı.

# policy: require-approval-for-destructive-changes.rego
# Richiede approvazione umana se il plan contiene distruzioni

package spacelift

# Nega auto-apply se ci sono risorse da distruggere
deny[sprintf("Destroy richiede approvazione: %s", [resource])] {
  change := input.terraform.resource_changes[_]
  change.change.actions[_] == "delete"
  resource := change.address
}

# Blocca completamente se piu di 5 risorse vengono distrutte
deny["Piu di 5 destroy in un singolo plan: richiede approvazione senior"] {
  destroy_count := count([c |
    c := input.terraform.resource_changes[_]
    c.change.actions[_] == "delete"
  ])
  destroy_count > 5
}

# Warn (non blocca) per modifiche ai security group
warn[sprintf("Security group modificato: %s", [resource])] {
  change := input.terraform.resource_changes[_]
  change.type == "aws_security_group"
  change.change.actions[_] != "no-op"
  resource := change.address
}
# policy: cost-control.rego
# Blocca istanze grandi in ambienti non-prod

package spacelift

expensive_instance_types := {
  "m5.4xlarge", "m5.8xlarge", "m5.16xlarge",
  "c5.4xlarge", "c5.9xlarge",
  "r5.4xlarge", "r5.8xlarge"
}

deny[msg] {
  # Leggi i tag dallo stack Spacelift
  not contains(input.spacelift.stack.labels[_], "env:prod")

  # Cerca istanze EC2 con instance_type costoso
  change := input.terraform.resource_changes[_]
  change.type == "aws_instance"
  instance_type := change.change.after.instance_type
  expensive_instance_types[instance_type]

  msg := sprintf(
    "Istanza %s di tipo %s non consentita in ambienti non-prod",
    [change.address, instance_type]
  )
}

Onay İş Akışı Spacelift

# Spacelift approval workflow con notifiche Slack

# 1. Developer fa push al branch feature/add-rds
# 2. Spacelift crea automaticamente un preview run
# 3. La policy Rego valuta il plan: contiene 1 destroy (vecchio RDS)
# 4. Spacelift blocca l'auto-deploy e notifica Slack
#    "Run #abc123 richiede approvazione: destroy aws_db_instance.old_db"
# 5. Senior engineer esamina il plan su Spacelift UI
# 6. Approva cliccando "Confirm" oppure aggiunge commento e rifiuta
# 7. Spacelift esegue l'apply o notifica il developer del blocco

# Via Spacelift CLI (spacectl):
spacectl stack run list --id networking-prod
# ID        COMMIT    STATE           CREATED AT
# abc123    f3a8b91   PENDING_REVIEW  2026-03-20 10:30
# xyz789    a1c2d3e   FINISHED        2026-03-19 14:22

spacectl run confirm --run abc123 --stack networking-prod
# Run abc123 confirmed, applying...

Gelişmiş Kayma Algılama: Uyarı ve Otomatik Düzeltme

Açık bir müdahale stratejisi eşlik etmiyorsa, sürüklenme tespiti yeterli değildir. Her birinin kendi değiş tokuşları olan üç yaklaşım vardır:

# Approccio 1: Solo Alert (ambienti critici, audit trail necessario)
# Il drift viene rilevato e segnalato, ma non corretto automaticamente
# Uso: database di produzione, networking critico

# Approccio 2: Auto-Remediation per drift minore
# Modifiche ai tag, aggiornamenti di patch: correggi automaticamente
# Blocca e avvisa per modifiche strutturali

# Approccio 3: Full Auto-Apply (ambienti dev/staging)
# Qualsiasi drift viene corretto immediatamente dal controller

---
# Esempio Flux TF Controller: configurazione per approccio ibrido
apiVersion: infra.contrib.fluxcd.io/v1alpha2
kind: Terraform
metadata:
  name: aws-networking-prod
  namespace: flux-system
spec:
  interval: 5m
  approvePlan: "auto"    # "auto" per ambienti non critici

  # Plan runner: genera il piano ma NON lo applica
  # L'apply richiede un secondo passaggio (manuale o automatico)
  planOnly: false

  # Dopo quanti drift consecutivi inviare un alert critico
  # (configurato via Flux Alert con severita error)
  retryInterval: 1m
  timeout: 5m
# Script di scheduled drift check (alternativa leggera senza GitOps controller)
#!/bin/bash
# drift-check.sh — eseguito ogni ora via cron o GitHub Actions scheduled

set -euo pipefail

ENVIRONMENTS=("dev" "staging" "prod")
SLACK_WEBHOOK="${SLACK_DRIFT_WEBHOOK}"

for ENV in "${ENVIRONMENTS[@]}"; do
  cd "/infra/environments/${ENV}"

  # Inizializza senza output
  terraform init -reconfigure -input=false -no-color > /dev/null 2>&1

  # Esegui plan e cattura l'exit code
  # 0 = no changes, 1 = error, 2 = changes detected (drift)
  set +e
  terraform plan -detailed-exitcode -no-color -out=/tmp/plan-${ENV} 2>&1
  EXITCODE=$?
  set -e

  if [ $EXITCODE -eq 2 ]; then
    CHANGES=$(terraform show -no-color /tmp/plan-${ENV} | \
      grep -E "^\s+(#|~|\+|-)" | head -20)

    curl -s -X POST "$SLACK_WEBHOOK" \
      -H "Content-Type: application/json" \
      -d "{
        \"text\": \"*DRIFT DETECTED* in environment: ${ENV}\n\`\`\`${CHANGES}\`\`\`\"
      }"
    echo "Drift alert sent for ${ENV}"
  elif [ $EXITCODE -eq 0 ]; then
    echo "${ENV}: no drift detected"
  else
    echo "ERROR: terraform plan failed for ${ENV}" >&2
    exit 1
  fi
done

Karşılaştırma: TF Kontrol Cihazı vs Spacelift vs Atlantis

Hangi Aracı Ne Zaman Kullanmalı?

  • Akı TF Kontrol Cihazı: Kubernetes için halihazırda Flux/Argo kullanan ekip, saf ve açık kaynaklı GitOps istiyor, AWS altyapısını IRSA ile yönetiyor. Kendi kendine barındırılan, ücretsiz, orta düzeyde öğrenme eğrisi.
  • Uzay asansörü: Karmaşık RBAC gereksinimlerine sahip kurumsal ekip, denetim izleme, birden fazla onaylayanla onay iş akışı, gelişmiş Rego politikaları. Ücretli SaaS, mükemmel kullanıcı deneyimi, kullanıma hazır entegrasyonlar (Slack, PagerDuty, Jira).
  • Atlantis: Halkla ilişkiler temelli paradigmada kalmak isteyen ekip Saf GitOps. Yorumları doğrudan PR'de planlayın/uygulayın. Kendi kendine barındırılan, ücretsiz, çok olgun. Yerel sürekli mutabakatı yoktur.
  • Terraform Bulutu/Kurumsal: Ekosistemde zaten mevcutsa doğal seçim HashiCorp, yerel Sentinel politika dili, Vault entegrasyonu. 10. Maddeye bakınız.

Üretimde GitOps IaC için En İyi Uygulamalar

# Repository structure per GitOps Terraform
terraform-infra/
├── modules/                    # Moduli riusabili (non riconciliati direttamente)
│   ├── networking/
│   ├── compute/
│   └── database/
├── environments/
│   ├── dev/
│   │   ├── networking/         # Stack separati per ogni layer
│   │   │   ├── main.tf
│   │   │   └── terraform.auto.tfvars
│   │   ├── compute/
│   │   └── database/
│   ├── staging/
│   └── prod/
│       ├── networking/         # Ogni ambiente ha il suo state isolato
│       ├── compute/
│       └── database/
├── flux/                       # Manifesti Flux per i CRD Terraform
│   ├── dev/
│   │   ├── networking-tf.yaml
│   │   └── compute-tf.yaml
│   └── prod/
│       ├── networking-tf.yaml  # approvePlan: "auto" o manuale
│       └── compute-tf.yaml
└── policies/                   # Policy Rego (se Spacelift)
    ├── require-approval.rego
    └── cost-control.rego

Anti-Desen: Uzlaşma Çok Agresif

Ayarlamak interval: 1m ile approvePlan: auto ortamlar üzerinde üretim ve tehlikeli: henüz ana hatlarıyla birleştirilmemiş bir değişiklik incelemeden önce uygulanmıştır. Altın kural: Çevre ne kadar kritik olursa o kadar uzun sürer ve aralık daha sıkıdır ve onay sürecidir. Prod'da aralığı kullanın 30m+ ve yapısal değişiklikler için her zaman manuel onay gerektirir.

Sonuçlar ve Sonraki Adımlar

Terraform için GitOps, Kod olarak Altyapının olgunluğunu temsil ediyor: artık değil tetikleme tabanlı işlem hatları ancak sürekli mutabakat, işlem hatlarında artık kimlik bilgisi yok ancak kümenin yerel kimlikleri, artık "bu değişikliği kimin yaptığı" değil, denetim izleri Git'te tamamlayın. Flux TF Denetleyicisi Kubernetes'te yerel ekipler için ideal seçimdir. Spacelift ise Rego politika motoruyla kurumsal gereksinimleri karşılıyor.

Komple Seri: Terraform ve IaC

  • Madde 01 — Sıfırdan Terraform: HCL, Sağlayıcı ve Planla-Uygula-Yok Et
  • Madde 02 — Yeniden Kullanılabilir Terraform Modüllerinin Tasarlanması
  • Madde 03 — Terraform Durumu: S3/GCS ile Uzak Arka Uç
  • Madde 04 — CI/CD'de Terraform: GitHub Eylemleri ve Atlantis
  • Madde 05 — IaC Testi: Terratest ve Terraform Testi
  • Madde 06 — IaC güvenliği: Checkov, Trivy ve OPA
  • Madde 07 — Terraform Çoklu Bulut: AWS + Azure + GCP
  • Madde 08 (bu) — Terraform için GitOps: Flux TF Denetleyicisi, Spacelift ve Drift Detection
  • Madde 09 — Terraform, Pulumi ve OpenTofu: Karşılaştırma 2026
  • Madde 10 — Terraform Kurumsal Kalıpları: Çalışma Alanı, Sentinel ve Ekip Ölçeklendirme