Kubernetes Deployment Stratejileri: Recreate, RollingUpdate, Blue/Green ve Canary
Bir uygulamayı Kubernetes’e deploy etmek işin kolay kısmı. Asıl soru şu: v1 çalışırken v2'ye nasıl geçeceğiz? Kullanıcılar kesinti yaşayacak mı, yeni versiyon hatalıysa ne kadar hızlı geri döneceğiz, geçiş sırasında cluster’a ne kadar ek yük bineceği… Bütün bunları belirleyen şey deployment stratejisi.
Bu yazıda Kubernetes’in yerleşik iki stratejisini (Recreate ve RollingUpdate) uygulamalı olarak inceleyeceğiz. Ardından Blue/Green, Canary, A/B Testing ve Shadow gibi ileri seviye stratejilere geçip hepsini karşılaştıracağız. Yazının sonunda kullanılan tüm komutların toplu bir listesi de var.
İçindekiler
- Rollout Nedir? Arka Planda Ne Oluyor?
- Recreate Stratejisi
- RollingUpdate Stratejisi
- Rollout Yönetimi: Durum, Geçmiş ve Geri Alma
- Blue/Green Deployment
- Canary Deployment
- Diğer Stratejiler: Ramped, A/B Testing, Shadow
- Karşılaştırma: Hangisi Ne Zaman?
- Büyük Cluster’larda Dikkat Edilmesi Gerekenler
- 2026 İtibarıyla Bilinmesi Gerekenler
- Özet
- Kaynaklar
1. Rollout Nedir? Arka Planda Ne Oluyor?
Rollout, bir Deployment’ın bir versiyondan diğerine geçiş sürecidir. Bu geçişin nasıl olacağını ve hangi kurallarla yürüyeceğini deployment stratejisi belirler.
Deployment’ın pod template’inde bir değişiklik yaptığınızda (örneğin image’ı nginx'ten httpd'ye güncellediğinizde) arka tarafta şunlar olur:
- Deployment, yeni template için yeni bir ReplicaSet oluşturur.
- Yeni ReplicaSet, yeni image ile pod’ları ayağa kaldırır.
- Eski ReplicaSet’in pod’ları seçilen stratejiye göre kapatılır.
- Eski ReplicaSet silinmez,
0replika ile saklanır. Geri dönüş (rollout undo) bu sayede mümkün olur.
Strateji, Deployment YAML’ında spec.strategy alanıyla belirlenir. Kubernetes Deployment objesi yerleşik olarak iki strateji tipi sunar:
Tip Davranış Recreate Önce tüm eski pod'ları siler, sonra yenilerini oluşturur. RollingUpdate Eski pod'ları kademeli olarak yenileriyle değiştirir. Varsayılan budur.
Blue/Green, Canary gibi stratejiler Deployment objesinin bir “type” değeri değildir. Bunlar Service, Gateway API veya Argo Rollouts gibi araçlarla kurulan desenlerdir. Bunlara 5. ve 6. bölümlerde geleceğiz.
2. Recreate Stratejisi
Nasıl çalışır?
Strateji Recreate seçilirse Deployment önce tüm eski pod'ları siler. Son pod da sistemden kaldırıldığı anda yeni versiyonun pod'ları ayağa kaldırılır. Kubernetes, Recreate stratejisinde yeni pod'ları oluşturmadan önce terminating durumdaki pod'ların tamamen kapanmasını bekler.
v1 v1 v1 → (boş) → v2 v2 v2
↑ kesintiNe zaman kullanılır?
Diyelim ki bir uygulamanız var ve bu uygulamanın iki versiyonunun aynı anda çalışması sorun çıkarıyor. Örneğin:
- İki versiyon aynı veritabanına farklı şemayla yazıyorsa,
- Uygulama tek bir kaynağa (dosya, lock, lisans) exclusive erişim istiyorsa,
- Yeni versiyon devreye girdiğinde eski versiyondaki tüm işlemlerin sonlanmasını istiyorsanız.
Bu gibi durumlarda “her şeyi silip sıfırdan oluştur” yaklaşımına ihtiyaç duyulabilir.
Neden genelde tercih edilmez?
Çünkü kesinti yaratır. Tüm pod’lar kapatıldığı anda trafik gider. Yeni pod’ların ayağa kalkıp hazır hale gelmesi bir saniye bile sürse, dışarıdan erişen kullanıcılar bu sürede sisteme erişemez. Uygulamanızın böyle bir kısıtı yoksa, yani eski ve yeni versiyon bir arada çalışabiliyorsa, Recreate seçmek yanlış bir tercih olur.
Örnek YAML: my-webapp-recreate.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-webapp-recreate
labels:
app: my-webapp
environment: dev
spec:
replicas: 3
selector:
matchLabels:
app: my-webapp
release: recreate
strategy:
type: Recreate
template:
metadata:
labels:
app: my-webapp
release: recreate
spec:
containers:
- name: my-webapp
image: nginx:1.27-alpine
ports:
- name: http
containerPort: 80
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 200m
memory: 128MiYAML’ı kısaca okuyalım:
spec.replicas: Kaç pod çalışacağını belirler (burada 3). Bu alantemplate.specaltında değil, doğrudan Deployment'ınspec'i altındadır.spec.selector: Deployment'ın hangi pod'ları yöneteceğini label üzerinden seçer.template.metadata.labelsile eşleşmek zorundadır.release: recreatelabel'ı, aynıapp: my-webapplabel'ını taşıyan diğer Deployment'larla karışmayı önler.spec.strategy.type: Recreate: Stratejiyi belirler.template: Oluşturulacak pod'ların şablonudur. Image'ılatestyerine sabit bir etiketle (nginx:1.27-alpine) vermek, hangi versiyonun çalıştığını her zaman net tutar.resources: Scheduler'ın pod'u yerleştirirken kullandığı kaynak istekleri ve üst sınırlar.
Uygulama Adımları
İzleme için iki ayrı terminal açıp aşağıdaki watch komutlarını çalıştırmak süreci canlı görmeyi kolaylaştırır.
1. Deployment’ı oluşturun
kubectl apply -f my-webapp-recreate.yamldeployment.apps/my-webapp-recreate created2. Pod’ları izleyin
watch kubectl get pods -l app=my-webappNAME READY STATUS RESTARTS AGE
my-webapp-recreate-7c9d5f6b8d-4kqzp 1/1 Running 0 12s
my-webapp-recreate-7c9d5f6b8d-h2xvw 1/1 Running 0 12s
my-webapp-recreate-7c9d5f6b8d-tn8rb 1/1 Running 0 12smy-webapp-recreate 3 pod ile ayağa kalktı. Pod adlarındaki 7c9d5f6b8d kısmı, pod'un ait olduğu ReplicaSet'in hash'idir. -l app=my-webapp ile sadece bu uygulamanın pod'larını listeliyoruz; cluster'daki diğer pod'lar çıktıyı kalabalıklaştırmıyor.
watchkomutu Linux/macOS/WSL'de bulunur. Windows'ta native olarak yoksakubectl get pods -l app=my-webapp -wkullanabilirsiniz.
3. ReplicaSet’leri izleyin
watch kubectl get replicasets -l app=my-webappNAME DESIRED CURRENT READY AGE
my-webapp-recreate-7c9d5f6b8d 3 3 3 13smy-webapp-recreate için tek bir ReplicaSet var ve 3/3 hazır.
4. Image’ı güncelleyin
kubectl set image deployment/my-webapp-recreate my-webapp=nginx:1.28-alpinedeployment.apps/my-webapp-recreate image updatedmy-webapp=nginx:1.28-alpine ifadesinde soldaki my-webapp container adı, sağdaki nginx:1.28-alpine yeni image'dır.
Pod’ları izleyen terminale baktığınızda, 3 pod’un birden Terminating durumuna geçtiğini görürsünüz. Hepsi kapandıktan sonra yeni ReplicaSet'in 3 pod'u oluşturulur. Recreate stratejisi budur: hepsini siler, yeniden oluşturur.
5. Yeni image’ı doğrulayın
kubectl get deployment my-webapp-recreate -o jsonpath='{.spec.template.spec.containers[0].image}'nginx:1.28-alpine6. Temizlik
kubectl delete -f my-webapp-recreate.yamldeployment.apps "my-webapp-recreate" deleted3. RollingUpdate Stratejisi
Nasıl çalışır?
RollingUpdate, eski pod’ları kademeli olarak yenileriyle değiştirir. Belirlediğiniz değerlere göre birkaç yeni pod oluşturur, birkaç eski pod’u siler ve bu döngüyü tüm pod’lar yeni versiyona geçene kadar sürdürür. Böylece sistemde her zaman belirlediğiniz sayıda pod ayakta kalır ve uygulama çalışmaya devam eder.
v1 v1 v1 v1 → v1 v1 v2 v2 → v2 v2 v2 v2Strateji alanı hiç yazılmazsa Deployment varsayılan olarak RollingUpdate kullanır.
maxSurge ve maxUnavailable
RollingUpdate’in hızını ve güvenliğini iki opsiyonel parametre belirler:
Parametre Anlamı Varsayılan maxSurge Geçiş sırasında replicas sayısının üzerine en fazla kaç ek pod çıkılabilir? 25% maxUnavailable Geçiş sırasında en fazla kaç pod hazır olmayan (unavailable) durumda olabilir? 25%
Örnek: replicas: 10, maxSurge: 2, maxUnavailable: 2
- Sistemde aynı anda en fazla 10 + 2 = 12 pod bulunabilir.
- Her an en az 10 − 2 = 8 pod hazır olmak zorundadır.
Bu iki sınır aynı anda uygulanır. Yani controller “önce 2 oluştur, bekle, sonra 2 sil” diye sıralı çalışmaz. Sınırlar izin verdiği sürece aynı döngüde hem yeni pod oluşturup hem eski pod silebilir. Geçişin kaçarlı kaçarlı yapılacağını bu değerlerle belirlersiniz.
Değerler sayı (2) veya yüzde ("25%") olarak girilebilir. Yüzde girildiğinde dikkat edilecek birkaç nokta var:
- Yüzde işareti sona yazılır:
25%doğru,%25yanlış. maxSurgeyukarı,maxUnavailableaşağı yuvarlanır. Örneğinreplicas: 10ile varsayılan değerler maxSurge = 3 (2.5 → 3), maxUnavailable = 2 (2.5 → 2) sonucunu verir.- İkisi aynı anda
0olamaz. Olsaydı rollout hiç ilerleyemezdi.
Sık kullanılan kombinasyonlar:
Ayar Sonuç maxSurge: 1, maxUnavailable: 0 Kapasite hiç düşmez, her seferinde tek pod değişir. Güvenli ama yavaş. maxSurge: 0, maxUnavailable: 1 Ek kaynak gerekmez, ama kapasite geçici olarak düşer. Kaynağı kısıtlı cluster'lar için. maxSurge: 25%, maxUnavailable: 25% Varsayılan. Hız ve güvenlik dengesi.
Örnek YAML: my-webapp-rolling.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-webapp-rolling
labels:
app: my-webapp
environment: dev
spec:
replicas: 10
selector:
matchLabels:
app: my-webapp
release: rolling
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 2
maxUnavailable: 2
template:
metadata:
labels:
app: my-webapp
release: rolling
spec:
containers:
- name: my-webapp
image: nginx:1.27-alpine
ports:
- name: http
containerPort: 80
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 200m
memory: 128Mi
readinessProbe:
httpGet:
path: /
port: http
initialDelaySeconds: 3
periodSeconds: 5Bu örnekte 10 replika oluşturuyoruz. Güncelleme yaptığımızda yeni bir ReplicaSet oluşacak ve ikişerli adımlarla 10 pod’un tamamı yeni versiyona geçecek. readinessProbe sayesinde Kubernetes, yeni pod gerçekten yanıt vermeye başlamadan onu hazır saymaz; eski pod'lar da bu yüzden erkenden silinmez.
strategy alanını hiç yazmazsanız Deployment aşağıdaki varsayılanla oluşturulur:
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%Uygulama Adımları
1. Deployment’ı oluşturun
kubectl apply -f my-webapp-rolling.yamldeployment.apps/my-webapp-rolling created2. Pod’ları izleyin
watch kubectl get pods -l app=my-webappNAME READY STATUS RESTARTS AGE
my-webapp-rolling-6f8b7d9c54-2fjzn 1/1 Running 0 18s
my-webapp-rolling-6f8b7d9c54-5wq7k 1/1 Running 0 18s
my-webapp-rolling-6f8b7d9c54-8hdlp 1/1 Running 0 18s
... (toplam 10 adet my-webapp-rolling-6f8b7d9c54 pod'u)10 pod oluştu ve hepsi 6f8b7d9c54 hash'li ReplicaSet'e ait.
3. ReplicaSet’leri izleyin (ayrı bir terminalde)
watch kubectl get replicasets -l app=my-webapp4. Değişiklik nedenini ekleyip image’ı güncelleyin
kubectl annotate deployment/my-webapp-rolling kubernetes.io/change-cause="nginx 1.27 -> 1.28"
kubectl set image deployment/my-webapp-rolling my-webapp=nginx:1.28-alpinedeployment.apps/my-webapp-rolling annotated
deployment.apps/my-webapp-rolling image updated5. Geçişi gözlemleyin
Güncelleme devam ederken ReplicaSet çıktısı:
NAME DESIRED CURRENT READY AGE
my-webapp-rolling-5d4c8b7f96 8 8 4 7s
my-webapp-rolling-6f8b7d9c54 4 4 4 46sBu anı okuyalım:
- Toplam pod: 8 (yeni) + 4 (eski) = 12 →
replicas + maxSurgesınırında. - Hazır pod: 4 (yeni) + 4 (eski) = 8 →
replicas − maxUnavailablesınırında.
Yani Kubernetes, verdiğimiz iki sınırı da sonuna kadar kullanarak ikişerli adımlarla geçişi sürdürüyor.
Aynı süreci tek komutla da takip edebilirsiniz:
kubectl rollout status deployment/my-webapp-rollingWaiting for deployment "my-webapp-rolling" rollout to finish: 4 of 10 updated replicas are available...
Waiting for deployment "my-webapp-rolling" rollout to finish: 8 of 10 updated replicas are available...
deployment "my-webapp-rolling" successfully rolled outGüncelleme tamamlandığında:
NAME DESIRED CURRENT READY AGE
my-webapp-rolling-5d4c8b7f96 10 10 10 15s
my-webapp-rolling-6f8b7d9c54 0 0 0 54sYeni ReplicaSet (5d4c8b7f96) 10/10 hazır hale geldi, eski ReplicaSet (6f8b7d9c54) 0'a indi. Eski ReplicaSet'in silinmediğine dikkat edin; geri dönüş için saklanıyor.
6. Geçmişi kontrol edin
kubectl rollout history deployment/my-webapp-rollingdeployment.apps/my-webapp-rolling
REVISION CHANGE-CAUSE
1 <none>
2 nginx 1.27 -> 1.287. Temizlik
kubectl delete -f my-webapp-rolling.yamlRollingUpdate’in zayıf noktaları
- Geçiş sırasında iki versiyon aynı anda trafik alır. Bazı kullanıcılar v1'e, bazıları v2'ye gider. API uyumluluğu bozuksa sorun çıkar.
- Trafik oranını kontrol edemezsiniz. Oran, o anki pod oranına bağlıdır.
- Otomatik metrik analizi yoktur. Yeni versiyon hata oranını artırsa bile, pod’lar “Ready” olduğu sürece rollout devam eder.
- Readiness probe olmadan güvenli değildir. Kubernetes, pod’un gerçekten trafik almaya hazır olup olmadığını ancak readiness probe ile bilir. Probe yoksa container başladığı anda pod hazır sayılır ve eski pod’lar erkenden silinebilir.
Bu yüzden production’da RollingUpdate’i şu alanlarla birlikte kullanmak iyi bir pratiktir:
spec:
minReadySeconds: 10 # Pod hazır olduktan sonra kaç saniye "available" sayılmayı beklesin
progressDeadlineSeconds: 600 # Rollout bu sürede ilerlemezse başarısız işaretlenir (varsayılan 600)
revisionHistoryLimit: 10 # Kaç eski ReplicaSet saklansın (varsayılan 10)
template:
spec:
containers:
- name: my-webapp
image: nginx:1.28-alpine
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 54. Rollout Yönetimi: Durum, Geçmiş ve Geri Alma
kubectl rollout alt komutları, deployment stratejisinden bağımsız olarak her Deployment'ta kullanılabilir.
1. Rollout durumunu takip edin
kubectl rollout status deployment/my-webapp-rollingRollout bitene kadar bekler ve sonucu yazar. CI/CD pipeline’larında deploy adımının başarılı olup olmadığını anlamak için çok kullanılır.
Get Özcan Kara’s stories in your inbox
Join Medium for free to get updates from this writer.
2. Değişiklik nedenini kaydedin
kubectl annotate deployment/my-webapp-rolling kubernetes.io/change-cause="nginx 1.27 -> 1.28"Eski eğitimlerde görülen --record flag'i deprecated durumdadır. Bunun yerine kubernetes.io/change-cause annotation'ını kullanın. Bu değer rollout history çıktısında görünür.
3. Rollout geçmişini görüntüleyin
kubectl rollout history deployment/my-webapp-rolling
kubectl rollout history deployment/my-webapp-rolling --revision=2İkinci komut belirli bir revizyonun pod template detayını gösterir.
4. Bir önceki versiyona geri dönün
kubectl rollout undo deployment/my-webapp-rolling5. Belirli bir revizyona geri dönün
kubectl rollout undo deployment/my-webapp-rolling --to-revision=16. Rollout’u duraklatın ve devam ettirin
kubectl rollout pause deployment/my-webapp-rolling
# Bu arada birden fazla değişiklik yapabilirsiniz
kubectl set image deployment/my-webapp-rolling my-webapp=nginx:1.29-alpine
kubectl set resources deployment/my-webapp-rolling -c my-webapp --limits=cpu=200m,memory=256Mi
kubectl rollout resume deployment/my-webapp-rollingPause sırasında yapılan değişiklikler tek bir rollout olarak uygulanır.
7. Image değiştirmeden pod’ları yeniden başlatın
kubectl rollout restart deployment/my-webapp-rollingConfigMap/Secret güncellemesinden sonra pod’ların yeniden okumasını sağlamak için sıkça kullanılır. Seçili stratejiye göre (RollingUpdate ise kademeli) çalışır.
Not: GitOps (ArgoCD, Flux) kullanıyorsanız
kubectl set imageverollout undogibi imperative komutlar Git'teki durumla çelişir ve bir sonraki senkronizasyonda geri alınır. Bu ortamlarda geri dönüşü Git üzerinde commit'i revert ederek yapmak gerekir.
5. Blue/Green Deployment
Nasıl çalışır?
İki ayrı ortam aynı anda tam kapasiteyle çalışır:
- Blue: Şu an canlı trafiği alan mevcut versiyon (v1)
- Green: Yeni versiyon (v2), trafik almıyor ama tamamen hazır
Green test edilip doğrulandıktan sonra trafik tek hamlede Blue’dan Green’e çevrilir. Sorun çıkarsa trafik aynı hızla Blue’ya geri çevrilir.
┌─────────┐
Service ──┤ Blue v1 │ ← trafik burada
└─────────┘
┌──────────┐
│ Green v2 │ ← hazır, test ediliyor
└──────────┘Geçiş sonrası: Service selector → GreenKubernetes’te Blue/Green için ayrı bir strategy.type yoktur. En basit hali, iki Deployment ve selector'ı değiştirilen bir Service ile kurulur.
Örnek YAML: bluegreen.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-blue
spec:
replicas: 3
selector:
matchLabels:
app: myapp
version: blue
template:
metadata:
labels:
app: myapp
version: blue
spec:
containers:
- name: web
image: nginx
ports:
- containerPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-green
spec:
replicas: 3
selector:
matchLabels:
app: myapp
version: green
template:
metadata:
labels:
app: myapp
version: green
spec:
containers:
- name: web
image: httpd
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: myapp
spec:
selector:
app: myapp
version: blue # Trafik şu an Blue'da
ports:
- port: 80
targetPort: 80Uygulama Adımları
1. Her iki ortamı ve Service’i oluşturun
kubectl apply -f bluegreen.yaml2. İki versiyonun da hazır olduğunu doğrulayın
kubectl get pods -l app=myapp --show-labels
kubectl rollout status deployment/myapp-green3. Service’in şu an hangi pod’lara gittiğini kontrol edin
kubectl get endpointslices -l kubernetes.io/service-name=myapp4. Green’i canlıya almadan test edin
kubectl port-forward deployment/myapp-green 8080:80
curl http://localhost:80805. Trafiği Green’e çevirin
kubectl patch service myapp -p '{"spec":{"selector":{"app":"myapp","version":"green"}}}'6. Sorun çıkarsa Blue’ya geri dönün
kubectl patch service myapp -p '{"spec":{"selector":{"app":"myapp","version":"blue"}}}'7. Her şey yolundaysa eski ortamı kapatın
kubectl scale deployment/myapp-blue --replicas=0
# veya bir sonraki sürüm için Blue'yu yeni versiyonla güncelleyinArtıları ve eksileri
Artı Eksi Anında geçiş ve anında geri dönüş Geçiş süresince 2 kat kaynak gerekir Kullanıcılar aynı anda iki versiyonu görmez Veritabanı şema değişiklikleri iki versiyonla da uyumlu olmalı Canlıya almadan önce production ortamında test Uzun süren bağlantılar (WebSocket vb.) geçişte kopabilir
6. Canary Deployment
Nasıl çalışır?
Adını madenlerde zehirli gazı erken fark etmek için kullanılan kanaryalardan alır. Yeni versiyon önce trafiğin küçük bir kısmına (örneğin %5 veya %10) açılır. Hata oranı, gecikme gibi metrikler izlenir. Sorun yoksa oran kademeli olarak artırılır (%25 → %50 → %100). Sorun varsa sadece küçük bir kullanıcı grubu etkilenmiş olur ve canary geri çekilir.
v1 %90 / v2 %10 → v1 %50 / v2 %50 → v2 %100Yöntem 1: Sadece Kubernetes ile (replika oranı)
İki Deployment aynı app label'ını taşır, Service ise sadece app label'ına bakar. Trafik oranı pod oranına eşit olur.
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-stable
spec:
replicas: 9
selector:
matchLabels:
app: myapp
track: stable
template:
metadata:
labels:
app: myapp
track: stable
spec:
containers:
- name: web
image: nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-canary
spec:
replicas: 1
selector:
matchLabels:
app: myapp
track: canary
template:
metadata:
labels:
app: myapp
track: canary
spec:
containers:
- name: web
image: httpd
---
apiVersion: v1
kind: Service
metadata:
name: myapp
spec:
selector:
app: myapp # track label'ı yok, iki Deployment'a da gider
ports:
- port: 801. Stable ve canary’yi oluşturun (yaklaşık %10 canary)
kubectl apply -f canary.yaml2. Canary oranını artırın (%50)
kubectl scale deployment/myapp-canary --replicas=5
kubectl scale deployment/myapp-stable --replicas=53. Canary başarılıysa stable’ı yeni versiyona taşıyın ve canary’yi kapatın
kubectl set image deployment/myapp-stable web=httpd
kubectl rollout status deployment/myapp-stable
kubectl scale deployment/myapp-stable --replicas=10
kubectl scale deployment/myapp-canary --replicas=04. Sorun çıkarsa canary’yi hemen kapatın
kubectl scale deployment/myapp-canary --replicas=0Bu yöntemin sınırı açık: %1'lik bir canary için 99 stable pod gerekir ve trafik oranını pod sayısından bağımsız ayarlayamazsınız.
Yöntem 2: Gateway API ile ağırlıklı trafik
Gateway API’nin HTTPRoute kaynağı, trafiği pod sayısından bağımsız olarak ağırlığa göre bölebilir. Stable ve canary için iki ayrı Service tanımlanır:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: myapp-route
spec:
parentRefs:
- name: my-gateway
hostnames:
- "myapp.example.com"
rules:
- backendRefs:
- name: myapp-stable-svc
port: 80
weight: 90
- name: myapp-canary-svc
port: 80
weight: 101. Route’u oluşturun
kubectl apply -f httproute-canary.yaml2. Ağırlığı değiştirmek için YAML’daki weight değerlerini güncelleyip tekrar uygulayın
kubectl apply -f httproute-canary.yaml
kubectl get httproute myapp-route -o yamlBunun için cluster’da bir Gateway API implementasyonu (Envoy Gateway, Istio, Cilium, NGINX Gateway Fabric, Traefik vb.) kurulu olmalıdır.
Yöntem 3: Argo Rollouts / Flagger ile progressive delivery
Production’da canary genellikle otomatikleştirilir. Argo Rollouts, Deployment yerine Rollout adlı bir kaynak sunar ve Blue/Green ile Canary'yi, ingress/service mesh entegrasyonunu, metrik analizini ve bu metriklere göre otomatik ilerleme ya da geri dönüşü destekler.
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: myapp
spec:
replicas: 10
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: web
image: nginx
strategy:
canary:
steps:
- setWeight: 10
- pause: {duration: 5m}
- setWeight: 50
- pause: {} # Manuel onay bekler
- setWeight: 100Argo Rollouts kubectl eklentisiyle kullanılan komutlar:
1. Rollout’u canlı izleyin
kubectl argo rollouts get rollout myapp --watch2. Image’ı güncelleyin
kubectl argo rollouts set image myapp web=httpd3. Manuel pause adımını onaylayın
kubectl argo rollouts promote myapp4. Sorun varsa rollout’u iptal edin (trafik stable’a döner)
kubectl argo rollouts abort myappPrometheus metriklerine bağlanan bir AnalysisTemplate eklediğinizde, örneğin hata oranı %1'i geçerse rollout otomatik olarak geri alınır. ArgoCD kullanan ekipler için doğal tercih Argo Rollouts'tur. Flux kullananlar ise genellikle Flagger'ı tercih eder.
7. Diğer Stratejiler: Ramped, A/B Testing, Shadow
Ramped (Yavaş RollingUpdate)
Aslında RollingUpdate’in maxSurge: 1, maxUnavailable: 0 ile ayarlanmış halidir. Pod'lar birer birer değiştirilir. Kapasite hiç düşmez; ısınma süresi uzun olan uygulamalarda minReadySeconds ile birlikte kullanılır.
A/B Testing
Canary’ye benzer, ama trafik rastgele yüzdeye göre değil, belirli kurallara göre yönlendirilir: HTTP header, cookie, kullanıcı bölgesi, cihaz tipi gibi. Amaç teknik doğrulamadan çok iş metriği ölçmektir (dönüşüm oranı, tıklama vb.). Kubernetes’te native değildir; Gateway API HTTPRoute header eşleştirmesi, service mesh veya feature flag araçlarıyla kurulur.
rules:
- matches:
- headers:
- name: x-beta-user
value: "true"
backendRefs:
- name: myapp-v2-svc
port: 80
- backendRefs:
- name: myapp-v1-svc
port: 80Shadow (Mirroring)
Canlı trafiğin bir kopyası yeni versiyona gönderilir, ama yeni versiyonun yanıtları kullanıcıya dönmez. Gerçek trafikle performans ve doğruluk testi yapılır, kullanıcı hiç etkilenmez. Dikkat: yeni versiyon veritabanına yazıyorsa veya ödeme gibi yan etkili işlemler yapıyorsa, bu işlemler iki kez gerçekleşebilir. Gateway API’de RequestMirror filtresiyle veya service mesh ile kurulur.
Hangisi en çok kullanılıyor?
Pratikte RollingUpdate açık ara en yaygın stratejidir; çünkü varsayılandır, ek araç gerektirmez ve çoğu stateless servis için yeterlidir. Olgun platform ekipleri genellikle RollingUpdate’i standart olarak kullanır, kritik servisler için Canary ekler, Blue/Green’i ise geri dönüş hızının kaynak maliyetinden daha önemli olduğu sistemlere ayırır. Recreate daha çok dev ortamlarında ve özel kısıtı olan uygulamalarda karşımıza çıkar.
9. Büyük Cluster’larda Dikkat Edilmesi Gerekenler
300–400 node’lu, binlerce container çalıştıran projelerde deployment stratejisi detayları çok daha kritik hale gelir. Aynı anda 200 container’ı 200 makinede birden oluşturmaya kalkarsanız ani memory/CPU baskısı, image pull fırtınası (registry’ye aynı anda yüzlerce istek) ve scheduling gecikmeleri yaşayabilirsiniz. Geçişin yavaş ve kontrollü olması gerekir; küçük detaylar ince eleyip sık dokunmalıdır.
Pratik öneriler:
maxSurge'ü kaynak kapasitesine göre ayarlayın. Yüzde değerler büyük replika sayılarında beklenenden fazla ek pod demek olabilir (1000 replikada %25 = 250 ek pod).- Resource
requeststanımlayın. Scheduler, ek pod'ların sığıp sığmayacağına bunlara bakarak karar verir. - PodDisruptionBudget (PDB) kullanın. Node bakımı ve drain işlemlerinde minimum kapasiteyi korur.
- Image’ları önceden çekin veya yakın bir registry mirror kullanın (ör. Harbor proxy cache).
progressDeadlineSecondsvekubectl rollout statusile takılan rollout'ları CI/CD'de yakalayın.
Kubernetes küçük iş yükleri için uygun mu?
3–5 pod’luk basit bir uygulama için Kubernetes’in getirdiği operasyonel yük (control plane, ağ, güvenlik, yükseltmeler) çoğu zaman kazançtan fazladır. Bu ölçekte Docker Compose, bir PaaS veya managed container servisi (Cloud Run, ECS, App Service) daha pratik olabilir. Öte yandan managed Kubernetes (EKS, GKE, AKS) ve k3s gibi hafif dağıtımlar bu eşiği düşürdü; ekip zaten Kubernetes kullanıyorsa küçük servisleri de aynı platformda tutmak mantıklı olabilir.
10. 2026 İtibarıyla Bilinmesi Gerekenler
- Güncel sürüm: Kubernetes v1.37 (“Garhwal”) Ağustos 2026'da yayınlandı. Bu yazıdaki Deployment API’si (
apps/v1),Recreate/RollingUpdatevemaxSurge/maxUnavailabledavranışı yıllardır stabil; eski kaynaklardaki temel bilgiler hâlâ geçerli. - Ingress NGINX emekliye ayrıldı. Topluluk projesi olan
kubernetes/ingress-nginxMart 2026 itibarıyla bakım almıyor; yeni güvenlik yamaları çıkmayacak. Eski canary yazılarının çoğunginx.ingress.kubernetes.io/canary-weightannotation'ını kullanır. Yeni kurulumlarda bunun yerine Gateway API (HTTPRouteağırlıkları) veya başka bir desteklenen controller tercih edilmeli. - Gateway API artık trafik yönetiminin standardı. Canary, A/B ve mirroring için vendor-bağımsız bir yol sunuyor; Argo Rollouts da Gateway API ile entegre çalışabiliyor.
--recordflag'i deprecated. Değişiklik nedeninikubernetes.io/change-causeannotation'ı ile kaydedin.- Terminating pod’ların görünürlüğü: Deployment ve ReplicaSet status’una eklenen
terminatingReplicasalanı v1.35'te beta oldu. Bir sonraki adım olarak Deployment'laraspec.podReplacementPolicyalanı eklenmesi (KEP-5882) üzerinde çalışılıyor; bu alan, yeni pod'ların eski pod'lar tamamen kapanmadan mı yoksa kapandıktan sonra mı oluşturulacağını seçmeyi hedefliyor. Özellikle GPU gibi kıt kaynaklı iş yükleri için takip etmeye değer.
11. Komut Kopya Kağıdı
Deploy ve izleme
kubectl apply -f <dosya>.yaml # Oluştur / güncelle
kubectl delete -f <dosya>.yaml # Sil
kubectl get deployments # Deployment listesi
kubectl get replicasets # ReplicaSet listesi (kısaltma: rs)
kubectl get pods -l app=<label> --show-labels # Label'a göre pod listesi
kubectl describe deployment <ad> # Detay, event'ler, strateji
watch kubectl get pods # 2 saniyede bir yenile
kubectl get pods -w # watch alternatifiGüncelleme
kubectl set image deployment/<ad> <container>=<image>
kubectl set resources deployment/<ad> -c <container> --limits=cpu=200m,memory=256Mi
kubectl edit deployment <ad>
kubectl scale deployment/<ad> --replicas=<sayı>
kubectl annotate deployment/<ad> kubernetes.io/change-cause="<açıklama>"Rollout yönetimi
kubectl rollout status deployment/<ad>
kubectl rollout history deployment/<ad>
kubectl rollout history deployment/<ad> --revision=<n>
kubectl rollout undo deployment/<ad>
kubectl rollout undo deployment/<ad> --to-revision=<n>
kubectl rollout pause deployment/<ad>
kubectl rollout resume deployment/<ad>
kubectl rollout restart deployment/<ad>Blue/Green
kubectl patch service <svc> -p '{"spec":{"selector":{"app":"<app>","version":"green"}}}'
kubectl get endpointslices -l kubernetes.io/service-name=<svc>
kubectl port-forward deployment/<ad> 8080:80Argo Rollouts
kubectl argo rollouts get rollout <ad> --watch
kubectl argo rollouts set image <ad> <container>=<image>
kubectl argo rollouts promote <ad>
kubectl argo rollouts abort <ad>
kubectl argo rollouts undo <ad>12. Kaynaklar
Türkçe
- TÜBİTAK BİLGEM YTE, Kubernetes Dağıtım Stratejileri (2025)
Resmi dokümantasyon
- Kubernetes Docs: Deployments
- Kubernetes v1.37 Sürüm Duyurusu
- Ingress NGINX: Kubernetes Steering ve Security Response Committee açıklaması
- Gateway API
- Argo Rollouts: Concepts
- KEP-3973: Consider Terminating Pods in Deployments
- KEP-5882: Deployment Pod Replacement Policy








