← blog · 19 Eylül 2026

Kubernetes'te Politika Uygulama: OPA Gatekeeper mı Kyverno mu, Ne Zaman Hangisi

RBAC kimin ne yapabileceğini belirler ama neyin geçerli bir kaynak olduğunu belirlemez. Admission controller tabanlı politika motorları bu boşluğu dolduruyor; OPA Gatekeeper, Kyverno ve Kubernetes'in kendi ValidatingAdmissionPolicy'sini karşılaştırıp hangisinin nerede işe yaradığını, hangi tuzakların beklediğini anlatıyoruz.

RBAC'ın çizmediği sınır

Bir kümede RBAC iyi kurulmuşsa kimin hangi namespace'e pod yazabileceğini, kimin Secret okuyabileceğini net biçimde tarif eder. Ama RBAC'ın hiç ilgilenmediği bir soru vardır: yazılan pod'un kendisi makul mü? latest etiketli bir imaj mı çekiyor, privileged: true mu çalışıyor, gerekli kaynak limitleri var mı, zorunlu bir etiket setiyle mi geldi? Bu sorular yetkilendirme değil doğrulama sorularıdır ve RBAC'ın kapsamına hiç girmez. Bir geliştirici pod oluşturma yetkisine sahipse, o pod'un içeriği üzerinde -imaj kaynağından ayrıcalık seviyesine kadar- hiçbir sınır yoktur.

Bu boşluk, admission controller katmanında kapatılır. Kubernetes API sunucusu bir isteği kabul etmeden önce sırasıyla kimlik doğrulama, yetkilendirme, mutating admission webhook'ları ve validating admission webhook'ları aşamalarından geçirir; nesne etcd'ye ancak bu zincirin sonunda yazılır. Son yıllarda bu katmanı kullanan üç farklı yaklaşım olgunlaştı: OPA Gatekeeper, Kyverno ve Kubernetes'in kendi native ValidatingAdmissionPolicy kaynağı. Üçü de aynı problemi çözüyor ama farklı bedeller karşılığında.

Üç yaklaşımın gerçek hâli

OPA Gatekeeper, Open Policy Agent projesinin Kubernetes'e özel dağıtımıdır. Politikalar Rego dilinde yazılır ve iki parçaya bölünür: ConstraintTemplate politikanın mantığını tanımlar, Constraint ise o şablonu hangi kaynaklara, hangi parametrelerle uygulayacağını belirtir.

apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
  name: k8srequiredlabels
spec:
  crd:
    spec:
      names:
        kind: K8sRequiredLabels
      validation:
        openAPIV3Schema:
          type: object
          properties:
            labels:
              type: array
              items: { type: string }
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8srequiredlabels
        violation[{"msg": msg}] {
          required := input.parameters.labels
          provided := input.review.object.metadata.labels
          missing := required[_]
          not provided[missing]
          msg := sprintf("eksik etiket: %v", [missing])
        }
---
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
metadata:
  name: require-team-label
spec:
  match:
    kinds: [{ apiGroups: [""], kinds: ["Namespace"] }]
  parameters:
    labels: ["team"]

Rego, genel amaçlı bir sorgu dilidir; bu güç, birden fazla kaynağı birbirine karşı doğrulamak (örneğin bir Ingress'in referans verdiği Service'in gerçekten var olup olmadığını kontrol etmek) gibi karmaşık senaryolarda işe yarar. Bedeli ise öğrenme eğrisidir: ekipte daha önce Rego yazan kimse yoksa ilk birkaç politika beklenenden uzun sürer.

Kyverno aynı problemi Kubernetes'in kendi YAML alışkanlığıyla çözer. Ayrı bir dil öğrenmeden, pattern tabanlı eşleştirme ya da (yeni sürümlerde) CEL ifadeleriyle politika yazılır.

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-team-label
spec:
  validationFailureAction: Enforce
  rules:
    - name: check-team-label
      match:
        any:
          - resources: { kinds: ["Namespace"] }
      validate:
        message: "team etiketi zorunlu"
        pattern:
          metadata:
            labels:
              team: "?*"

Kyverno'nun asıl farkı sadece validate değil, aynı motorun mutate ve generate kurallarını da desteklemesi: eksik bir alanı otomatik doldurabilir ya da bir Namespace oluşturulduğunda ona bağlı bir NetworkPolicy'yi kendisi üretebilir. Gatekeeper'da bu üretim (generate) yeteneği yoktur, sadece doğrular ve isteğe bağlı mutasyon yapar.

Üçüncü yol, harici bir bileşen kurmadan gelir: Kubernetes 1.30'dan itibaren GA olan ValidatingAdmissionPolicy, CEL ifadeleriyle doğrulama kuralını doğrudan API sunucusunun içinde çalıştırır, ayrı bir webhook pod'una ihtiyaç duymadan.

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
  name: require-team-label
spec:
  failurePolicy: Fail
  matchConstraints:
    resourceRules:
      - apiGroups: [""]
        apiVersions: ["v1"]
        resources: ["namespaces"]
  validations:
    - expression: "has(object.metadata.labels.team)"
      message: "team etiketi zorunlu"
---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicyBinding
metadata:
  name: require-team-label-binding
spec:
  policyName: require-team-label
  validationActions: ["Deny"]

Burada kazanç işletimsel: harici bir webhook servisinin ayakta olup olmadığı, ağ gecikmesi eklediği ya da kendi Deployment'ının güncellenmesi gerektiği gibi bir bağımlılık yok. Bedeli ise kapsam: mutasyon ya da kaynak üretimi yapamaz, yalnızca doğrulama içindir, ve CEL Rego kadar ifade gücüne sahip değildir.

Tuzaklar

Üç yaklaşımın da paylaştığı ortak risk failurePolicy alanıdır. Fail seçilirse, politika motorunun webhook'u geçici olarak yanıt vermediğinde (pod yeniden başlıyor, node tahliye ediliyor) o kaynak türüne dokunan hiçbir istek geçemez; küme genelinde deploy işlemleri durabilir. Ignore seçilirse motor çöktüğünde politikalar sessizce devre dışı kalır ve kimse fark etmez. Pratikte doğru yaklaşım, politika motorunun kendi namespace'ini namespaceSelector ile hariç tutmak (aksi hâlde motor kendi güncellemesini kendi webhook'una takılıp bloke edebilir) ve Fail politikasını yalnızca motorun yüksek kullanılabilirlikle (en az iki replika, PodDisruptionBudget ile) çalıştığından emin olduktan sonra kullanmaktır.

İkinci tuzak, bir politikayı doğrudan Enforce/Deny moduyla üretime sürmektir. Hem Gatekeeper hem Kyverno bir denetim (audit/dryrun) modu sunar: politika hangi mevcut kaynakların ihlalde olduğunu raporlar ama hiçbir isteği reddetmez. Yeni bir politikayı önce bu modda birkaç gün çalıştırıp mevcut kümedeki ihlalleri temizlemeden zorunlu hâle getirmek, üretimde beklenmedik deploy engellenmelerine yol açar. ValidatingAdmissionPolicy'de aynı kademeli geçiş validationActions alanına Warn veya Audit yazılarak taklit edilir.

Üçüncü tuzak performansla ilgilidir: her admission isteği zincirdeki her webhook'a senkron olarak gider. Çok sayıda karmaşık Rego kuralı çalıştıran bir Gatekeeper kurulumu, yoğun deploy dönemlerinde API sunucusu gecikmesine ölçülebilir katkı yapar. Politika sayısı arttıkça match bloklarını mümkün olduğunca dar tutmak (her kaynağa değil, sadece ilgili kind ve namespace'e uygulamak) gecikmeyi kontrol altında tutar.

Deploy etmeden önce test etmek

Bir politikayı doğrudan kümeye uygulayıp sonucu canlıda görmek, hangi motoru seçerseniz seçin kötü bir alışkanlıktır. Gatekeeper'ın gator komut satırı aracı, örnek Kubernetes nesnelerini bir ConstraintTemplate ve Constraint çiftine karşı kümeye hiç dokunmadan çalıştırır ve hangi nesnenin hangi gerekçeyle reddedileceğini yerel olarak gösterir. Kyverno tarafında aynı işi kyverno apply <policy.yaml> --resource <test-objesi.yaml> ya da CI'a bağlanabilen kyverno test komutu görür; bir politika deposunda beklenen sonuçları (pass/fail) tanımlayan test dosyaları tutup her değişiklikte otomatik çalıştırmak mümkündür. ValidatingAdmissionPolicy içindeki CEL ifadeleri için ayrı bir CLI yoktur, ama ifade nispeten kısa olduğundan çoğu ekip önce kubectl create --dry-run=server ile deneyip API sunucusunun CEL'i nasıl değerlendirdiğini doğrudan gözlemler. Bu üç yöntemin ortak noktası, bir politika değişikliğinin sonucunu önce yerelde ya da CI'da görmek, üretimdeki ilk deploy'da öğrenmemektir.

Ne zaman hangisi

Ekipte OPA deneyimi zaten varsa ya da politikanın birden fazla kaynağı birbirine karşı doğrulaması gerekiyorsa (bir Deployment'ın referans verdiği ConfigMap'in var olup olmadığını kontrol etmek gibi) Gatekeeper'ın Rego'su bu tür sorguları doğal olarak ifade eder. Sıfırdan başlayan, ekipte yeni bir dil öğrenme maliyetine girmek istemeyen ve mutate/generate ihtiyacı olan (eksik alanları otomatik tamamlamak, ilişkili kaynakları kendiliğinden üretmek) ekipler için Kyverno daha az sürtünmeyle aynı sonuca ulaşır. Yalnızca basit, tek kaynağa bakan doğrulama kuralları yazılacaksa ve harici bir bileşen kurmadan işi bitirmek öncelikliyse, ValidatingAdmissionPolicy en az hareketli parçaya sahip seçenektir; küçük kümelerde ayrıca bir Deployment, bir Service, bir sertifika yönetimi eklemeden başlanabilir.

Hiçbirini seçmemek gereken durum da var: birkaç kişilik, tek namespace'lik bir kümede bu sorunlar genelde PR incelemesiyle ya da basit bir CI doğrulamasıyla (manifestleri kubeconform gibi bir araçla şemaya karşı kontrol etmek) yeterince kapanır. Admission tabanlı bir politika motoru kurmanın asıl getirisi, birden fazla ekibin aynı kümeyi paylaştığı ve merkezi bir ekibin standartları elle değil otomatik olarak zorlamak istediği andan itibaren başlar.