Flux CD v2 + Kustomize için Eksiksiz Geliştirici Rehberi

14 Ağustos 2026 · netologist · 25 dakika, 5217 kelime ·

Flux v2 ve Kustomize ile GitOps yapmak için mimari, CRD’ler, kalıplar (pattern) ve en iyi uygulamaları (best practices) kapsayan derinlemesine, uygulamaya dönük, üretim odaklı bir referans rehber.


İçindekiler

  1. Temel Kavramlar
  2. Flux v2 Mimarisi
  3. Kurulum & Bootstrap
  4. Kustomize Temelleri
  5. Flux Kaynak (Source) API’leri
  6. Kustomization CRD (Flux)
  7. Repository Yapı Kalıpları
  8. Çoklu Ortam & Çok Kiracılılık (Multi-Tenancy)
  9. Bağımlılık Yönetimi
  10. Secret (Gizli Bilgi) Yönetimi
  11. HelmRelease & Helm Entegrasyonu
  12. Image Otomasyonu
  13. Health Check, Pruning & Reconciliation
  14. Bildirimler & Uyarılar (Notifications & Alerts)
  15. İleri Seviye Kustomize Kalıpları
  16. En İyi Uygulamalar Kontrol Listesi
  17. Sorun Giderme & Debug
  18. CLI Hızlı Referans
  19. Tam Referans Repository Yapısı

1. Temel Kavramlar

1.1 GitOps Nedir?

GitOps, deklaratif altyapı ve uygulama durumunun tek gerçek kaynağının (single source of truth) Git olduğu bir işletim modelidir. Bir reconciler (Flux), istenen durumu (Git) mevcut durumla (cluster) sürekli karşılaştırır ve ikisini birbirine yakınsatır (converge).

Temel GitOps ilkeleri:

1.2 Kustomize Nedir?

Kustomize, kubectl içine gömülü (kubectl apply -k), template kullanmayan bir yapılandırma özelleştirme aracıdır. Helm’deki gibi placeholder/template kullanmak yerine Kustomize şöyle çalışır:

1.3 Flux v2 Nedir?

Flux v2 (aynı zamanda “GitOps Toolkit” olarak da anılır), GitOps sürekli teslimatını (continuous delivery) uygulayan Kubernetes-native controller’lardan (CRD + controller) oluşan bir kümedir. Tek parça (monolitik) bir binary olan Flux v1’den farklı olarak Flux v2, her biri tek bir sorumluluğu üstlenen, birleştirilebilir (composable) uzman controller’lardan oluşur:

ControllerSorumluluk
source-controllerKaynakları (Git, Helm, OCI, Bucket) çeker ve artifact olarak önbelleğe alır
kustomize-controllerKaynaklardan Kustomize overlay’lerini derler (build) ve uygular
helm-controllerHelmRelease üzerinden Helm release’lerini deklaratif olarak yönetir
notification-controllerOlayları/uyarıları Slack, MS Teams, webhook vb. hedeflere iletir
image-reflector-controllerContainer registry’lerini yeni image tag’leri için tarar
image-automation-controllerImage tag güncellemelerini geri Git’e yazar

1.4 Neden Flux + Kustomize Birlikte?

Flux, Kustomization CRD’si aracılığıyla Kustomize overlay’lerini yerel (native) olarak birinci sınıf vatandaş (first-class citizen) olarak anlar. Bu kombinasyon size şunları sağlar:


2. Flux v2 Mimarisi

                ┌─────────────────────┐
   Git Repo --> │  source-controller   │ --> Artifact (tar, önbelleğe alınmış)
   OCI Repo --> │  (polling / webhook)  │
   Helm Repo -->│                      │
   Bucket    -->│                      │
                └─────────┬────────────┘
                          │ Artifact'i izler
                          v
                ┌─────────────────────┐
                │ kustomize-controller │ --> kubectl apply -k (build+apply)
                └─────────┬────────────┘
                          │
                ┌─────────────────────┐
                │   helm-controller    │ --> Helm install/upgrade
                └─────────┬────────────┘
                          │
                ┌─────────────────────┐
                │ notification-controller│ --> Slack/Teams/Webhook olayları
                └─────────────────────┘

                ┌────────────────────────────┐
                │ image-reflector-controller  │ --> registry'leri tarar
                │ image-automation-controller │ --> tag güncellemelerini Git'e commit eder
                └────────────────────────────┘

Kilit tasarım ilkesi: her controller yalnızca Kubernetes Custom Resource’ları ile çalışır. Harici bir veritabanı veya state store yoktur — cluster’ın etcd’si zaten state store’dur, Git ise istenen-durum deposudur.

2.1 Toolkit API Grupları

API GrubuKind’lar
source.toolkit.fluxcd.ioGitRepository, OCIRepository, HelmRepository, HelmChart, Bucket
kustomize.toolkit.fluxcd.ioKustomization
helm.toolkit.fluxcd.ioHelmRelease
notification.toolkit.fluxcd.ioAlert, Provider, Receiver
image.toolkit.fluxcd.ioImageRepository, ImagePolicy, ImageUpdateAutomation

3. Kurulum & Bootstrap

3.1 Flux CLI Kurulumu

curl -s https://fluxcd.io/install.sh | sudo bash
# veya
brew install fluxcd/tap/flux

3.2 Ön Kontrol (Pre-flight Check)

flux check --pre

3.3 Bootstrap (GitHub örneği)

flux bootstrap controller’ları kurar ve onların manifestlerini Git repo’nuza commit eder; böylece Flux kendi kendisini de GitOps ile yönetir.

export GITHUB_TOKEN=<token>
export GITHUB_USER=<kullanici>

flux bootstrap github \
  --owner=$GITHUB_USER \
  --repository=fleet-infra \
  --branch=main \
  --path=clusters/production \
  --personal

Bu komut şunu oluşturur:

clusters/production/flux-system/
├── gotk-components.yaml   # controller'lar, CRD'ler, RBAC
├── gotk-sync.yaml         # kendine işaret eden GitRepository + Kustomization
└── kustomization.yaml

3.4 GitLab / Genel Git için Bootstrap

flux bootstrap gitlab \
  --owner=my-group \
  --repository=fleet-infra \
  --branch=main \
  --path=clusters/production \
  --token-auth

Native bootstrap desteği olmayan sağlayıcılar için (Bitbucket, Azure DevOps, on-prem Git) flux bootstrap git kullanın:

flux bootstrap git \
  --url=ssh://[email protected]/fleet-infra.git \
  --branch=main \
  --path=clusters/production \
  --private-key-file=./id_ed25519

3.5 Çoklu Cluster Bootstrap Kalıbı

clusters/
├── staging/
│   └── flux-system/
├── production-eu/
│   └── flux-system/
└── production-us/
    └── flux-system/

Her cluster kendi flux-system senkronizasyon yoluna sahiptir; hepsi aynı repository’ye ancak farklı dizinlere işaret eder — bu, bir “filo (fleet)” yönetim modelini mümkün kılar.

3.6 Kaldırma (Uninstall)

flux uninstall --namespace=flux-system

4. Kustomize Temelleri

4.1 kustomization.yaml Anatomisi

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
  - deployment.yaml
  - service.yaml
  - ../../base

namePrefix: prod-
nameSuffix: "-v1"
namespace: production

commonLabels:
  app.kubernetes.io/managed-by: flux
  environment: production

commonAnnotations:
  team: platform-engineering

images:
  - name: myapp
    newName: registry.example.com/myapp
    newTag: 1.4.2

replicas:
  - name: myapp
    count: 3

configMapGenerator:
  - name: app-config
    literals:
      - LOG_LEVEL=info
    files:
      - config.properties

secretGenerator:
  - name: app-secret
    envs:
      - secrets.env

patches:
  - path: patch-resources.yaml
    target:
      kind: Deployment
      name: myapp

components:
  - ../../components/istio-sidecar

4.2 Base & Overlay Modeli

base/
├── kustomization.yaml
├── deployment.yaml
├── service.yaml
└── configmap.yaml

overlays/
├── dev/
│   ├── kustomization.yaml
│   └── patch-replicas.yaml
├── staging/
│   ├── kustomization.yaml
│   └── patch-resources.yaml
└── production/
    ├── kustomization.yaml
    ├── patch-resources.yaml
    └── patch-hpa.yaml

Base, kanonik ve ortamdan bağımsız (environment-agnostic) manifestleri içerir. Overlay’ler, base’e resources: [../../base] üzerinden referans verir ve yama/dönüşüm uygular.

4.3 Strategic Merge Patch vs JSON 6902

Strategic Merge Patch (çoğu düzenleme için tercih edilir — alan bazında birleştirir, containers listesindeki elemanları name alanına göre eşleştirmek gibi Kubernetes liste semantiğini anlar):

# patch-resources.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  template:
    spec:
      containers:
        - name: myapp
          resources:
            limits:
              cpu: "1"
              memory: 512Mi
patches:
  - path: patch-resources.yaml
    target:
      kind: Deployment
      name: myapp

JSON 6902 Patch (kesin, yol (path) tabanlı — alan silme veya dizi index işlemleri için kullanışlı):

patches:
  - target:
      kind: Deployment
      name: myapp
    patch: |-
      - op: replace
        path: /spec/replicas
        value: 5
      - op: remove
        path: /spec/template/spec/containers/0/livenessProbe

4.4 Generator’lar

ConfigMapGenerator — içerik özetine (hash) dayalı, immutable ConfigMap’ler üretir; içerik değiştiğinde otomatik olarak rollout tetikler:

configMapGenerator:
  - name: app-config
    literals:
      - ENV=production
    files:
      - application.yaml
    options:
      disableNameSuffixHash: false   # otomatik rollout için hash suffix'i koru

Üretilen isim örneğin app-config-8f92bd7c6t olur. app-config‘e referans veren herhangi bir Deployment, otomatik olarak hash’li isme göre yeniden yazılır (nameReference transformer) — ve ConfigMap adı değiştiği için Kubernetes bir rolling restart tetikler.

SecretGenerator:

secretGenerator:
  - name: db-secret
    type: Opaque
    envs:
      - db.env

⚠️ Asla düz metin (plaintext) secret commit etmeyin. SOPS veya External Secrets ile birleştirin (bkz. Bölüm 10).

4.5 Component’lar (yeniden kullanılabilir kısmi overlay’ler)

Component’lar (kustomize.config.k8s.io/v1alpha1 Component kind’ı ile tanıtılmıştır), birden fazla overlay’e karıştırılabilecek yeniden kullanılabilir, birleştirilebilir konfigürasyon parçalarının enjekte edilmesine olanak tanır:

# components/istio-sidecar/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1alpha1
kind: Component

patches:
  - path: inject-sidecar-annotation.yaml
    target:
      kind: Deployment

Bir overlay içinde kullanımı:

components:
  - ../../components/istio-sidecar
  - ../../components/pod-disruption-budget

Component’lar, aksi takdirde az ortak yapıya sahip overlay’ler arasında çapraz kesişen (cross-cutting) konuları (ör. sidecar’lar, PDB’ler, network policy’ler) paylaşmanın önerilen yoludur.

4.6 Transformer Referansı

AlanAmaç
namePrefix / nameSuffixTüm kaynak isimlerinin başına/sonuna metin ekler
namespaceTüm namespace’li kaynaklara bir namespace zorlar
commonLabelsLabel ekler + label selector’ları tutarlı şekilde günceller
commonAnnotationsTüm kaynaklara annotation ekler
imagesImage adını/tag’ini/digest’ini geçersiz kılar (override)
replicasKaynak adına göre replica sayısını geçersiz kılar
vars (deprecated)Eski değişken ikamesi — yerini replacements almıştır
replacementsKaynaklar arası modern alan-alan değer kopyalama
patchesStrategicMerge (deprecated)Eski — patches kullanın
patchesJson6902 (deprecated)Eski — patches kullanın

4.7 replacements (modern değişken ikamesi)

replacements:
  - source:
      kind: ConfigMap
      name: app-config
      fieldPath: data.API_URL
    targets:
      - select:
          kind: Deployment
          name: myapp
        fieldPaths:
          - spec.template.spec.containers.[name=myapp].env.[name=API_URL].value

Bu, eski vars: alanının yerini alır; vars: Kustomize’ın deklaratif, yan etkisiz (side-effect-free) build modelini bozduğu için deprecated hale getirilmiştir.

4.8 Sıralama & Merge Semantiği

4.9 Yerel Doğrulama & Build

kustomize build overlays/production
kubectl kustomize overlays/production        # eşdeğeri, yerleşik kustomize'ı kullanır
kubectl apply -k overlays/production          # build + apply
kubectl diff -k overlays/production           # canlı cluster'a karşı değişiklikleri önizle

Merge etmeden önce her zaman yerel olarak (veya CI’da) kustomize build çalıştırın — bu, overlay hatalarını Flux’tan önce yakalamanın #1 yöntemidir.


5. Flux Kaynak (Source) API’leri

5.1 GitRepository

apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
  name: podinfo
  namespace: flux-system
spec:
  interval: 1m
  url: https://github.com/stefanprodan/podinfo
  ref:
    branch: master
  ignore: |
    /*
    !/kustomize
  secretRef:
    name: https-credentials

Önemli alanlar:

5.2 OCIRepository (Flux v2, sadece Helm chart’ları değil, OCI’ı da bir kaynak olarak destekler)

apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: OCIRepository
metadata:
  name: podinfo
  namespace: flux-system
spec:
  interval: 5m
  url: oci://ghcr.io/stefanprodan/manifests/podinfo
  ref:
    tag: latest
  layerSelector:
    mediaType: "application/vnd.cncf.flux.content.v1.tar+gzip"
    operation: extract

OCI, immutable ve versiyonlanmış manifest paketleri için giderek Git’in yerini alan bir dağıtım mekanizması olarak tercih edilmektedir — “manifestleri build edip push etme” adımını Git gerçek kaynağından ayırır.

5.3 HelmRepository

apiVersion: source.toolkit.fluxcd.io/v1
kind: HelmRepository
metadata:
  name: podinfo
  namespace: flux-system
spec:
  interval: 10m
  url: https://stefanprodan.github.io/podinfo
  # type: oci   # OCI tabanlı Helm repo'ları için

5.4 Bucket

apiVersion: source.toolkit.fluxcd.io/v1
kind: Bucket
metadata:
  name: my-artifacts
  namespace: flux-system
spec:
  interval: 5m
  provider: aws
  bucketName: my-manifests-bucket
  endpoint: s3.amazonaws.com
  region: eu-west-1
  secretRef:
    name: aws-credentials

5.5 Kaynak Doğrulaması (Tedarik Zinciri Güvenliği)

spec:
  verify:
    provider: cosign
    secretRef:
      name: cosign-pub

Yalnızca kriptografik olarak imzalanmış kaynakların (commit’ler veya OCI artifact’leri) uzlaştırılmasını (reconcile) zorunlu kılar — önemli bir tedarik zinciri güvenlik kontrolü.


6. Kustomization CRD (Flux)

Bu, Flux’ın kendi Kustomization nesnesidir — Kustomize aracının kullandığı sade kustomization.yaml dosyasıyla karıştırılmamalıdır. Flux’ın Kustomization CRD’si, kustomize-controller‘a bir kaynaktan bir Kustomize overlay’i derlemesini (build) ve uygulamasını söyler.

apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: podinfo
  namespace: flux-system
spec:
  interval: 10m
  retryInterval: 2m
  timeout: 3m
  sourceRef:
    kind: GitRepository
    name: podinfo
  path: "./kustomize"
  prune: true
  wait: true
  targetNamespace: default
  dependsOn:
    - name: infra-controllers
  patches:
    - patch: |
        - op: add
          path: /spec/template/spec/topologySpreadConstraints
          value: []
      target:
        kind: Deployment
        name: podinfo
  postBuild:
    substitute:
      cluster_env: production
    substituteFrom:
      - kind: ConfigMap
        name: cluster-vars
      - kind: Secret
        name: cluster-secrets
        optional: true
  healthChecks:
    - apiVersion: apps/v1
      kind: Deployment
      name: podinfo
      namespace: default
  force: false
  suspend: false

6.1 Önemli Alanların Açıklaması

AlanAmaç
sourceRefHangi kaynaktan (GitRepository/OCIRepository/Bucket) build yapılacağı
pathKaynak artifact içindeki, kustomization.yaml dosyasını barındıran dizin
pruneGit’ten kaldırılan kaynakları siler (çöp toplama) — gerçek GitOps için elzemdir
waitTüm uygulanan kaynakların hazır (ready) olmasını, Ready=True işaretlenmeden önce bekler
healthChecksKontrol edilecek kaynakların açık listesi (wait: true olduğunda otomatik olarak da çıkarılır)
dependsOnSıralama — bu Kustomization, bağımlılıkları Ready olana kadar reconcile olmaz
patchesKustomize build’den sonra uygulanan Flux seviyesi yamalar — Git overlay’ini değiştirmeden son-mil (last-mile) geçersiz kılmalar için
postBuild.substitute / substituteFromRender edilmiş manifestlere karşı ${VAR} stilinde değişken ikamesi
targetNamespaceTüm kaynakları bir namespace’e zorlar (Kustomize’ın namespace: alanı gibi ama build sonrası uygulanır)
forceImmutable alan çakışması olan kaynakları hata vermek yerine yeniden oluşturur (dikkatli kullanın)
timeoutApply + health check için başarısız sayılmadan önceki maksimum süre
retryIntervalBir hatadan sonra yeniden denemeden önceki bekleme (backoff) süresi
suspendNesneyi silmeden reconciliation’ı duraklatır
decryptionSOPS decryption sağlayıcı yapılandırması
serviceAccountNameApply RBAC’ı için belirli bir ServiceAccount’u impersonate eder (çok kiracılılık!)

6.2 Pratikte postBuild.substitute

Kustomize’ın kendisinde runtime template mekanizması olmadığından, Flux, Kustomize build adımından sonra hafif ${VAR} ikamesi için postBuild.substitute‘u sunar — overlay’leri çoğaltmadan cluster’a özgü değerler için kullanışlıdır.

# kaynak repo içindeki bir manifestte
metadata:
  annotations:
    cluster: "${cluster_name}"
spec:
  postBuild:
    substitute:
      cluster_name: "eu-prod-1"
    substituteFrom:
      - kind: ConfigMap
        name: cluster-vars

Çözümlenemeyen (resolve edilemeyen) değişkenler, bir varsayılan değer sağlanmadıkça build’in başarısız olmasına neden olur: ${cluster_name:=default-value}.

6.3 Çok Kiracılılık için Impersonation

spec:
  serviceAccountName: tenant-a-reconciler

Bu ServiceAccount’a bağlı RBAC ile birleştiğinde, belirli bir Kustomization‘ın neyi uygulamaya yetkili olduğunu sınırlar — takımların cluster-admin eşdeğeri apply yetkisine sahip olmaması gereken çok kiracılı cluster’lar için kritiktir.


7. Repository Yapı Kalıpları

7.1 Monorepo (tek repo, çoklu cluster & uygulama)

fleet-infra/
├── clusters/
│   ├── staging/
│   │   ├── flux-system/
│   │   └── infrastructure.yaml   # Kustomization -> infrastructure/
│   │   └── apps.yaml             # Kustomization -> apps/staging
│   └── production/
│       ├── flux-system/
│       ├── infrastructure.yaml
│       └── apps.yaml
├── infrastructure/
│   ├── base/
│   │   ├── cert-manager/
│   │   ├── ingress-nginx/
│   │   └── monitoring/
│   └── overlays/
│       ├── staging/
│       └── production/
└── apps/
    ├── base/
    │   └── podinfo/
    └── overlays/
        ├── staging/
        └── production/

7.2 Polyrepo (uygulamalar ayrı repo’larda, merkezi bir fleet repo’su tarafından referans verilir)

fleet-infra/                 # merkezi kontrol repo'su
└── clusters/production/
    ├── flux-system/
    └── podinfo-source.yaml  # uygulama repo'suna işaret eden GitRepository

podinfo/                     # ayrı uygulama repo'su
├── src/
└── deploy/
    ├── base/
    └── overlays/

Ödünleşimler (Trade-off’lar):

KalıpArtılarEksiler
MonorepoBasit, uygulamalar arası atomik değişiklikler, tek PR inceleme akışıBüyüyebilir; izinler için daha geniş etki alanı (blast radius)
PolyrepoNet sahiplik sınırları, bağımsız release temposuDaha fazla hareketli parça; paylaşılan altyapı için repo’lar arası koordinasyon

7.3 “Apps of Apps” / Fleet Kalıbı

Her cluster için, bir apps dizinine referans veren üst düzey bir Kustomization; bu dizinin kendisi de birçok uygulama seviyesi Kustomization nesnesini (her mikroservis için bir tane) toplayan bir Kustomize overlay’idir:

# clusters/production/apps.yaml
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: apps
  namespace: flux-system
spec:
  interval: 10m
  path: "./apps/production"
  prune: true
  sourceRef:
    kind: GitRepository
    name: flux-system
  dependsOn:
    - name: infrastructure
apps/production/kustomization.yaml
resources:
  - podinfo-kustomization.yaml
  - frontend-kustomization.yaml
  - backend-kustomization.yaml

Buradaki her *-kustomization.yaml, bir Kustomize overlay’i değil, bir Flux Kustomization CRD örneğidir — bu kalıp, her uygulamanın bağımsız olarak izlenmesine (track), health check yapılmasına ve bağımlılık sırasına konmasına olanak tanır.


8. Çoklu Ortam & Çok Kiracılılık (Multi-Tenancy)

8.1 Ortam Overlay Örneği

# apps/overlays/production/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - ../../base/podinfo
namespace: podinfo
patches:
  - path: patch-replicas.yaml
  - path: patch-resources.yaml
images:
  - name: podinfo
    newTag: 6.5.4
# patch-replicas.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: podinfo
spec:
  replicas: 5

8.2 Flux ile Kiracı (Tenant) İzolasyonu

Kalıp A — Kiracı başına namespace + RBAC impersonation:

apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: tenant-a
  namespace: flux-system
spec:
  targetNamespace: tenant-a
  serviceAccountName: tenant-a-reconciler
  sourceRef:
    kind: GitRepository
    name: tenant-a-repo
  path: "./"
  prune: true
apiVersion: v1
kind: ServiceAccount
metadata:
  name: tenant-a-reconciler
  namespace: tenant-a
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: tenant-a-reconciler
  namespace: tenant-a
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin      # ClusterRoleBinding değil, RoleBinding ile namespace'e kapsamlandırılmıştır
subjects:
  - kind: ServiceAccount
    name: tenant-a-reconciler
    namespace: tenant-a

Kalıp B — flux create tenant iskelesi (scaffolding):

Flux, bir çok kiracılık örnek üreticisiyle birlikte gelir:

flux create tenant tenant-a \
  --with-namespace=tenant-a \
  --export > tenant-a.yaml

Bu, Flux’ın resmi çok kiracılık rehberini takip ederek, o kiracıya kapsamlandırılmış bir Namespace, ServiceAccount, RoleBinding ve GitRepository + Kustomization iskelesini oluşturur.

8.3 Cluster API / Fleet Yönetimi

Çok sayıda cluster’ı yönetmek için, Flux’ı Cluster API ile veya her cluster dizininin bağımsız olarak bootstrap edildiği ancak overlay kalıtımı (inheritance) yoluyla ortak infrastructure/base ve apps/base katmanlarını paylaştığı bir fleet repo’suyla birleştirin.


9. Bağımlılık Yönetimi

9.1 Flux Kustomization’ları Arasında dependsOn

apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: apps
  namespace: flux-system
spec:
  dependsOn:
    - name: infra-controllers
    - name: infra-configs
  sourceRef:
    kind: GitRepository
    name: flux-system
  path: "./apps/production"
  interval: 10m
  prune: true

Flux, DAG’ı (yönlü döngüsüz graf) çözer ve bağımlılıkları önce reconcile eder; bunların Ready koşulunu bekler (ki bu da wait: true + health check’lerin geçmesine bağlıdır).

9.2 Tipik Katmanlama

infra-controllers  (CRD'ler: cert-manager, ingress-nginx, prometheus-operator)
        │
        v
infra-configs      (ClusterIssuer, IngressClass, Grafana dashboard'ları — önce controller gerektiren CR'ler)
        │
        v
apps               (altyapının hazır olmasına bağlı gerçek iş yükleri)

9.3 Kustomization İçi Sıralama (tek overlay)

Tek bir Kustomize overlay’i içinde sıralama şunlarla kontrol edilir:

  1. Nihai kustomize build çıktısındaki resources: liste sırası.
  2. Kubernetes’in kendi eventual consistency (nihai tutarlılık) yapısı (çoğu kaynağın kesin bir sıralamaya ihtiyacı yoktur — ama CRD’lerin CR’lerden önce gelmesi gerekir).

CRD-sonra-CR sıralama sorunları Flux Kustomization’ları arasında olduğunda, bunları dependsOn ile ayrı Kustomization nesnelerine bölün; çünkü kustomize build, bir CR admission webhook’u doğrulama yapmadan önce CRD kaydının tamamlanacağını garanti etmez.

9.4 wait ve Health Check Etkileşimi

spec:
  wait: true
  timeout: 5m

wait: true olduğunda, siz açıkça healthChecks: ile listeyi daraltmadığınız sürece Flux, uygulanan her kaynak için (Deployment’lar, StatefulSet’ler, status.conditions[type=Ready]‘e sahip custom resource’lar vb.) otomatik olarak health check çıkarır.


10. Secret (Gizli Bilgi) Yönetimi

Asla düz metin secret’leri Git’e commit etmeyin. Üç baskın kalıp:

10.1 SOPS (Secrets OPerationS) + Flux Native Decryption

# age veya GPG kullanarak SOPS ile şifreleme
sops --encrypt --age <age-public-key> secret.yaml > secret.enc.yaml
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: apps
spec:
  decryption:
    provider: sops
    secretRef:
      name: sops-age
kubectl create secret generic sops-age \
  --namespace=flux-system \
  --from-file=age.agekey

Flux, .sops.yaml ile yönetilen dosyaları reconcile zamanında şeffaf bir şekilde çözer (decrypt). SOPS kısmi şifrelemeyi destekler (yalnızca data:/stringData: değerleri), böylece manifestin geri kalanı Git’te diff edilebilir kalır.

10.2 Sealed Secrets (Bitnami)

kubeseal ile istemci tarafında şifreleyin, yalnızca cluster içindeki sealed-secrets-controller tarafından çözülür (cluster başına asimetrik şifreleme):

kubeseal --format=yaml < secret.yaml > sealed-secret.yaml

sealed-secret.yaml dosyasını commit edin — yalnızca hedef cluster’ın controller’ı onu çözebildiği için güvenlidir.

10.3 External Secrets Operator (ESO)

Runtime’da harici bir kasadan (AWS Secrets Manager, Vault, Azure Key Vault, GCP Secret Manager) secret’leri çeker — Git’te hiç şifreli materyal bulunmaz, sadece bir referans bulunur:

apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: db-credentials
spec:
  secretStoreRef:
    name: aws-secrets-manager
    kind: ClusterSecretStore
  target:
    name: db-credentials
  data:
    - secretKey: password
      remoteRef:
        key: prod/db/password

10.4 Karşılaştırma

YöntemGit’te secret var mı?RotasyonKarmaşıklık
SOPSŞifreli, evetDeğişiklikte manuel yeniden şifrelemeDüşük
Sealed SecretsŞifreli, evetDeğişiklikte manuel yeniden mühürlemeDüşük-Orta
External Secrets OperatorHayır (sadece referans)Otomatik (polling aralığı)Orta

Öneri: Küçük-orta ölçekli takımlar için en yaygın benimsenen Flux-native kalıp, age ile SOPS’tur; merkezi bir secret kasası zaten mevcutsa veya ölçek büyükse ESO tercih edilir.


11. HelmRelease & Helm Entegrasyonu

Flux, Helm chart’larını helm-controller aracılığıyla deklaratif olarak yönetebilir; Helm’in template gücünü GitOps reconciliation’ı ve Kustomize’ın overlay yamalamasıyla birleştirir.

apiVersion: source.toolkit.fluxcd.io/v1
kind: HelmRepository
metadata:
  name: bitnami
  namespace: flux-system
spec:
  interval: 30m
  url: https://charts.bitnami.com/bitnami
---
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
  name: redis
  namespace: flux-system
spec:
  interval: 10m
  chart:
    spec:
      chart: redis
      version: "18.x"
      sourceRef:
        kind: HelmRepository
        name: bitnami
      interval: 10m
  values:
    architecture: replication
    auth:
      enabled: true
      existingSecret: redis-auth
  install:
    remediation:
      retries: 3
  upgrade:
    remediation:
      retries: 3
      remediateLastFailure: true
    cleanupOnFail: true
  test:
    enable: true
  driftDetection:
    mode: enabled

11.1 Values Katmanlama (Kustomize + Helm)

Kustomize’ın strategic merge özelliğini kullanarak bir HelmRelease‘in values:‘ini ortam bazında yamalayın:

# overlays/production/patch-redis-values.yaml
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
  name: redis
spec:
  values:
    replica:
      replicaCount: 3
patches:
  - path: patch-redis-values.yaml
    target:
      kind: HelmRelease
      name: redis

11.2 valuesFrom (harici values kaynakları)

spec:
  valuesFrom:
    - kind: ConfigMap
      name: redis-values
      valuesKey: values.yaml
    - kind: Secret
      name: redis-secret-values
      valuesKey: values.yaml
      optional: true

11.3 Drift Tespiti & İyileştirme (Remediation)

spec:
  driftDetection:
    mode: enabled       # warn | enabled | disabled
    ignore:
      - paths: ["/spec/replicas"]
        target:
          kind: Deployment

driftDetection (Flux 2.12+), Helm tarafından yönetilen kaynaklara yapılan manuel kubectl edit tarzı değişiklikleri tespit eder ve otomatik olarak düzeltebilir; bu, Helm release’lerinin sessizce sapmasına (drift) neden olan uzun süredir devam eden bir GitOps boşluğunu kapatır.

11.4 OCI Tabanlı Helm Chart’ları

apiVersion: source.toolkit.fluxcd.io/v1
kind: HelmRepository
metadata:
  name: my-oci-charts
spec:
  type: oci
  url: oci://ghcr.io/my-org/charts
  interval: 30m

12. Image Otomasyonu

Yeni container image tag’lerini otomatik olarak tespit eder ve güncellemeyi geri Git’e commit eder.

12.1 ImageRepository (bir registry’yi tarar)

apiVersion: image.toolkit.fluxcd.io/v1beta2
kind: ImageRepository
metadata:
  name: podinfo
  namespace: flux-system
spec:
  image: ghcr.io/stefanprodan/podinfo
  interval: 5m

12.2 ImagePolicy (hangi tag’in “en son” olduğunu seçer)

apiVersion: image.toolkit.fluxcd.io/v1beta2
kind: ImagePolicy
metadata:
  name: podinfo
  namespace: flux-system
spec:
  imageRepositoryRef:
    name: podinfo
  policy:
    semver:
      range: ">=6.0.0 <7.0.0"
  # alternatifler:
  # policy:
  #   alphabetical:
  #     order: asc
  # filterTags:
  #   pattern: '^main-[a-fA-F0-9]+-(?P<ts>[0-9]+)$'
  #   extract: '$ts'

12.3 ImageUpdateAutomation (değişikliği geri Git’e yazar)

apiVersion: image.toolkit.fluxcd.io/v1beta2
kind: ImageUpdateAutomation
metadata:
  name: flux-system
  namespace: flux-system
spec:
  interval: 30m
  sourceRef:
    kind: GitRepository
    name: flux-system
  git:
    checkout:
      ref:
        branch: main
    commit:
      author:
        email: [email protected]
        name: fluxcdbot
      messageTemplate: "chore: update image {{range .Updated.Images}}{{println .}}{{end}}"
    push:
      branch: main
  update:
    path: "./apps/production"
    strategy: Setters

12.4 Manifestleri Otomatik Güncellemeler için İşaretleme

image: ghcr.io/stefanprodan/podinfo:6.5.3 # {"$imagepolicy": "flux-system:podinfo"}

Setters stratejisi, image satırını, otomasyon controller’ının tam olarak hangi alanı güncelleyeceğini bilmesi için işaretler (annotate) — cerrahi hassasiyette, yorum tabanlı ve diff-dostudur.


13. Health Check, Pruning & Reconciliation

13.1 Pruning (Çöp Toplama)

spec:
  prune: true

prune: true olduğunda, Flux belirli bir Kustomization tarafından uygulanan kaynakları izler (nesnenin status’unda saklanan bir envanter aracılığıyla) ve bir sonraki reconciliation’da Git’ten kaldırılan kaynakları siler. Bu, Flux’ı gerçek anlamda deklaratif yapan şeydir — bu olmadan, silinen manifestler cluster’da sonsuza kadar yetim (orphaned) kaynaklar bırakırdı.

13.2 Özel Health Check’ler

spec:
  wait: true
  timeout: 3m
  healthChecks:
    - apiVersion: apps/v1
      kind: Deployment
      name: podinfo
      namespace: default
    - apiVersion: helm.toolkit.fluxcd.io/v2
      kind: HelmRelease
      name: redis
      namespace: flux-system

Flux, status.conditions[type=Ready]‘i (Deployment’lar için Available) kontrol eder ve listelenen tüm kaynaklar geçene kadar Kustomization‘ın Ready işaretlenmesini engeller — bu, downstream dependsOn zincirlerinin sadece “kubectl apply başarılı oldu"ya değil, gerçek uygulama hazır olma durumuna dayandığı durumlarda kritiktir.

13.3 Reconciliation Tetikleyicileri

apiVersion: notification.toolkit.fluxcd.io/v1
kind: Receiver
metadata:
  name: github-receiver
  namespace: flux-system
spec:
  type: github
  events:
    - "push"
  secretRef:
    name: receiver-token
  resources:
    - apiVersion: source.toolkit.fluxcd.io/v1
      kind: GitRepository
      name: flux-system

13.4 Askıya Alma / Devam Ettirme (Suspend / Resume)

flux suspend kustomization podinfo
flux resume kustomization podinfo

Manuel müdahale ederken bir kaynağın reconcile edilmesini dondurmak, ardından kontrolü tekrar Git’e devretmek için olay müdahalesinde (incident response) kullanışlıdır.


14. Bildirimler & Uyarılar (Notifications & Alerts)

14.1 Provider (hedef)

apiVersion: notification.toolkit.fluxcd.io/v1beta3
kind: Provider
metadata:
  name: slack
  namespace: flux-system
spec:
  type: slack
  channel: gitops-alerts
  secretRef:
    name: slack-url

14.2 Alert (ne gönderilecek, nereden)

apiVersion: notification.toolkit.fluxcd.io/v1beta3
kind: Alert
metadata:
  name: on-call-alerts
  namespace: flux-system
spec:
  providerRef:
    name: slack
  eventSeverity: error
  eventSources:
    - kind: Kustomization
      name: '*'
    - kind: HelmRelease
      name: '*'
  exclusionList:
    - ".*upgrade.*has.*started.*"

14.3 Desteklenen Sağlayıcılar

Slack, MS Teams, Discord, Google Chat, genel Webhook, PagerDuty, Opsgenie, Prometheus Alertmanager, GitHub/GitLab commit status, Sentry ve daha fazlası — hepsi aynı Provider/Alert kalıbı üzerinden.


15. İleri Seviye Kustomize Kalıpları

15.1 patchesStrategicMerge vs Satır İçi (Inline) Yamalar vs Yama Dosyaları

Modern Kustomize, inline YAML veya JSON6902 içeren birleşik patches: alanını tercih eder:

patches:
  - target:
      kind: Deployment
      labelSelector: "app.kubernetes.io/component=api"
    patch: |
      - op: replace
        path: /spec/replicas
        value: 2

target: içindeki labelSelector / annotationSelector, her kaynağı isimle listelemeden birden fazla kaynağı aynı anda yamalamanıza olanak tanır — çapraz kesişen değişiklikler için güçlüdür.

15.2 Global Değişiklikler için Joker (Wildcard) Hedefli patches

patches:
  - patch: |
      - op: add
        path: /metadata/labels/cost-center
        value: "platform"
    target:
      kind: Deployment|StatefulSet|DaemonSet

15.3 resources: + components: ile Birden Fazla Overlay’i Birleştirme (mixins)

resources:
  - ../../base/podinfo
components:
  - ../../components/network-policies
  - ../../components/pod-security
  - ../../components/monitoring

15.4 Uzak (Remote) Base’ler (dikkatli kullanın)

resources:
  - https://github.com/org/repo//path/to/base?ref=v1.2.3

Uzak base’ler çalışır ama ?ref=‘i sıkı bir şekilde sabitlemediğiniz (pin) sürece versiyon sabitleme disiplinini atlar. Denetlenebilirlik (auditability) ve offline build’ler için genellikle Flux’ın GitRepository + yerel path: kombinasyonu, uzak Kustomize base’lerine tercih edilir.

15.5 Custom Resource Davranışı için configurations (eski, çoğunlukla yerini almış)

Eski Kustomize sürümleri, isim referansları, değişken ikamesi vb. için CRD’lerin nasıl ele alınacağını Kustomize’a öğretmek amacıyla configurations: dosyaları kullanırdı. Modern Kustomize, en yaygın CRD kurallarını otomatik olarak algılar; özel transformer yapılandırmalarına artık nadiren ihtiyaç duyulur.

15.6 buildMetadata (kaynak kökenini (provenance) işaretleme)

buildMetadata: [originAnnotations, transformerAnnotations, managedByLabel]

Bir kaynağın hangi dosya/base tarafından üretildiğini gösteren config.kubernetes.io/origin gibi annotation’lar ekler — derinlemesine katmanlı overlay’leri debug etmek için kullanışlıdır.

15.7 Özel Şema Doğrulaması için openapi Alanı

openapi:
  path: crd-schema.json

Kustomize’ın özel CRD merge-key semantiğini (ör. hangi dizi alanının name ile anahtarlanmış bir “map” gibi davrandığını) anlamasını sağlar; CR’ler üzerinde doğru strategic-merge davranışı için önemlidir.

15.8 Birden Fazla Selector ile Yama Hedefleme

patches:
  - patch: |-
      - op: add
        path: /spec/template/spec/nodeSelector
        value:
          workload-type: batch
    target:
      kind: Deployment
      annotationSelector: "workload=batch"
      namespace: jobs

15.9 Yaygın Kustomize Tuzaklarından Kaçınma


16. En İyi Uygulamalar Kontrol Listesi

16.1 Repository & Yapı

16.2 Güvenlik (Safety) & Güvenilirlik

16.3 Güvenlik (Security)

16.4 Versiyonlama & Değişiklik Yönetimi

16.5 Gözlemlenebilirlik (Observability)

16.6 Kustomize Hijyeni


17. Sorun Giderme & Debug

17.1 Genel Durum Kontrolü

flux get all -A
flux get sources git -A
flux get kustomizations -A
flux get helmreleases -A

17.2 Belirli Bir Kustomization’ı İnceleme

flux get kustomization podinfo -n flux-system
kubectl describe kustomization podinfo -n flux-system
kubectl get kustomization podinfo -n flux-system -o yaml

status.conditions‘a bakın — yaygın koşul (condition) türleri: Ready, Reconciling, Stalled, HealthCheckFailed.

17.3 Reconciliation’ı Zorlama

flux reconcile source git flux-system
flux reconcile kustomization podinfo --with-source

17.4 Olayları (Events) Görüntüleme

flux events --for Kustomization/podinfo -n flux-system
kubectl get events -n flux-system --field-selector involvedObject.name=podinfo

17.5 Bir Kustomize Build’ini Yerel Olarak Debug Etme

# Flux'ın kullandığı tam ref'i klonlayın/checkout edin
git clone <repo> && cd repo && git checkout <ref>
kustomize build ./path/to/kustomization

Çıktıyı kubectl diff -k ./path ile cluster’da gerçekte olanla karşılaştırın.

17.6 Yaygın Hatalar & Çözümler

BelirtiMuhtemel SebepÇözüm
Kustomization Reconcilingde takılı kalıyorBağımlılık Ready değil, veya kaynak asla sağlıklı hale gelmiyordependsOn hedefini kontrol edin ve flux get kustomization <bağımlılık> çalıştırın
HealthCheckFailedDeployment CrashLoopBackOff / probe başarısızAltta yatan iş yükünde kubectl logs/describe çalıştırın
build failed: ... accumulating resourcesBozuk resources: yolu, yazım hatası veya eksik dosyaYeniden üretmek için yerel olarak kustomize build çalıştırın
Apply sırasında field is immutableImmutable bir alan değiştirilmiş (ör. selector, PVC boyut küçültme)Dikkatli bir şekilde force: true ayarlayın, veya manuel olarak silip yeniden oluşturun
context deadline exceededYavaş başlayan iş yükleri için timeout çok kısaspec.timeout‘u artırın
Secret’ler çözülmüyorYanlış decryption.secretRef veya süresi dolmuş SOPS anahtarıSecret’in flux-system‘da mevcut olduğunu ve .sops.yaml kurallarıyla eşleştiğini doğrulayın
Image tag güncellenmiyorImagePolicy filtresi yeni tag’lerle eşleşmiyor, veya işaretleyici (marker) yorum eksikImagePolicy.policy regex/semver aralığını ve {"$imagepolicy": ...} işaretleyicisini kontrol edin
Git sağlayıcısından too many open files / rate limitingBirçok kaynak için polling aralığı çok agresifinterval‘ı artırın, sıkı polling yerine webhook Receiver kullanın

17.7 Dry-Run ve Diff

flux diff kustomization podinfo --path ./clusters/production

flux diff (yeni Flux CLI sürümlerinde mevcut), terraform plan‘a benzer şekilde uygulamadan neyin değişeceğini render eder — merge öncesi inceleme için vazgeçilmezdir.


18. CLI Hızlı Referans

# Bootstrap
flux bootstrap github --owner=org --repository=fleet-infra --branch=main --path=clusters/production

# Durum
flux check
flux get all -A
flux get kustomizations -A
flux get sources all -A
flux get helmreleases -A
flux get images all -A

# Reconcile
flux reconcile source git flux-system
flux reconcile kustomization <isim> --with-source
flux reconcile helmrelease <isim>

# Askıya Alma / Devam Ettirme
flux suspend kustomization <isim>
flux resume kustomization <isim>

# Kaynakları imperative olarak oluşturma (iskele, sonra YAML'a export)
flux create source git podinfo --url=https://github.com/x/podinfo --branch=main --export > source.yaml
flux create kustomization podinfo --source=GitRepository/podinfo --path="./kustomize" --prune=true --export > kustomization.yaml
flux create helmrelease redis --chart=redis --source=HelmRepository/bitnami --export > helmrelease.yaml
flux create tenant tenant-a --with-namespace=tenant-a --export > tenant-a.yaml

# Olaylar & Loglar
flux events
flux logs --follow
flux logs --level=error

# Kaldırma
flux uninstall --namespace=flux-system

# Kustomize (sade araç)
kustomize build overlays/production
kubectl apply -k overlays/production
kubectl diff -k overlays/production
kustomize edit set image myapp=registry.example.com/myapp:1.4.2
kustomize edit set replicas myapp=5
kustomize edit add resource deployment.yaml
kustomize edit add patch --path patch.yaml --kind Deployment

19. Tam Referans Repository Yapısı

fleet-infra/
├── clusters/
│   ├── staging/
│   │   ├── flux-system/
│   │   │   ├── gotk-components.yaml
│   │   │   ├── gotk-sync.yaml
│   │   │   └── kustomization.yaml
│   │   ├── infrastructure.yaml        # Flux Kustomization -> infrastructure/overlays/staging
│   │   └── apps.yaml                  # Flux Kustomization -> apps/overlays/staging
│   └── production/
│       ├── flux-system/
│       ├── infrastructure.yaml
│       └── apps.yaml
│
├── infrastructure/
│   ├── base/
│   │   ├── cert-manager/
│   │   │   ├── namespace.yaml
│   │   │   ├── helmrelease.yaml
│   │   │   └── kustomization.yaml
│   │   ├── ingress-nginx/
│   │   ├── monitoring/
│   │   │   ├── kube-prometheus-stack/
│   │   │   └── grafana-dashboards/
│   │   └── kustomization.yaml
│   └── overlays/
│       ├── staging/
│       │   ├── kustomization.yaml
│       │   └── patch-resources.yaml
│       └── production/
│           ├── kustomization.yaml
│           └── patch-resources.yaml
│
├── apps/
│   ├── base/
│   │   └── podinfo/
│   │       ├── deployment.yaml
│   │       ├── service.yaml
│   │       ├── hpa.yaml
│   │       └── kustomization.yaml
│   └── overlays/
│       ├── staging/
│       │   ├── kustomization.yaml
│       │   ├── patch-replicas.yaml
│       │   └── podinfo-kustomization.yaml   # Flux Kustomization CRD
│       └── production/
│           ├── kustomization.yaml
│           ├── patch-replicas.yaml
│           ├── patch-resources.yaml
│           └── podinfo-kustomization.yaml
│
├── components/
│   ├── network-policies/
│   │   ├── kustomization.yaml         # kind: Component
│   │   └── deny-all-ingress.yaml
│   └── pod-disruption-budget/
│       ├── kustomization.yaml
│       └── pdb.yaml
│
├── tenants/
│   ├── tenant-a/
│   │   ├── namespace.yaml
│   │   ├── rbac.yaml
│   │   ├── source.yaml
│   │   └── kustomization.yaml
│   └── tenant-b/
│
└── .sops.yaml

Ek: Hızlı Referans — Flux Kustomization vs Kustomize kustomization.yaml

Flux Kustomization (CRD)Kustomize kustomization.yaml
APIkustomize.toolkit.fluxcd.io/v1kustomize.config.k8s.io/v1beta1
AmaçBir controller’a neyi, nereden, ne sıklıkla reconcile edeceğini söylerBir manifest kümesinin nasıl build edileceğini tanımlar (patch’ler, generator’lar)
Cluster’da yaşıyor mu?Evet (canlı bir Kubernetes nesnesi)Hayır — build zamanında tüketilen bir dosyadır
Yama içerir mi?Build sonrası son-mil patches: eklenebilirAna amacı patch’ler/generator’lar/transformer’lardır
Health check var mı?EvetHayır (sadece build aracı, runtime farkındalığı yok)
Pruning var mı?Evet (prune: true)Hayır (Kustomize’ın kendisinde önceki durum kavramı yoktur)

Rehberin sonu. İngilizce versiyon için flux2-kustomize-guide-en.md dosyasına bakınız.