Sitemap
Özcan Kara

Özcan Kara

Software Development Engineer

Kubernetes Deployment Stratejileri: Recreate, RollingUpdate, Blue/Green ve Canary

15 min readSep 17, 2026

--

Press enter or click to view image in full size

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

  1. Rollout Nedir? Arka Planda Ne Oluyor?
  2. Recreate Stratejisi
  3. RollingUpdate Stratejisi
  4. Rollout Yönetimi: Durum, Geçmiş ve Geri Alma
  5. Blue/Green Deployment
  6. Canary Deployment
  7. Diğer Stratejiler: Ramped, A/B Testing, Shadow
  8. Karşılaştırma: Hangisi Ne Zaman?
  9. Büyük Cluster’larda Dikkat Edilmesi Gerekenler
  10. 2026 İtibarıyla Bilinmesi Gerekenler
  11. Özet
  12. 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, 0 replika 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
↑ kesinti

Ne 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: 128Mi

YAML’ı kısaca okuyalım:

  • spec.replicas: Kaç pod çalışacağını belirler (burada 3). Bu alan template.spec altında değil, doğrudan Deployment'ın spec'i altındadır.
  • spec.selector: Deployment'ın hangi pod'ları yöneteceğini label üzerinden seçer. template.metadata.labels ile eşleşmek zorundadır. release: recreate label'ı, aynı app: my-webapp label'ını taşıyan diğer Deployment'larla karışmayı önler.
  • spec.strategy.type: Recreate: Stratejiyi belirler.
  • template: Oluşturulacak pod'ların şablonudur. Image'ı latest yerine 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.yaml
deployment.apps/my-webapp-recreate created

2. Pod’ları izleyin

watch kubectl get pods -l app=my-webapp
NAME                                  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 12s

my-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.

watch komutu Linux/macOS/WSL'de bulunur. Windows'ta native olarak yoksa kubectl get pods -l app=my-webapp -w kullanabilirsiniz.

3. ReplicaSet’leri izleyin

watch kubectl get replicasets -l app=my-webapp
NAME                            DESIRED   CURRENT   READY   AGE
my-webapp-recreate-7c9d5f6b8d 3 3 3 13s

my-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-alpine
deployment.apps/my-webapp-recreate image updated

my-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-alpine

6. Temizlik

kubectl delete -f my-webapp-recreate.yaml
deployment.apps "my-webapp-recreate" deleted

3. 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 v2

Strateji 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, %25 yanlış.
  • maxSurge yukarı, maxUnavailable aşağı yuvarlanır. Örneğin replicas: 10 ile varsayılan değerler maxSurge = 3 (2.5 → 3), maxUnavailable = 2 (2.5 → 2) sonucunu verir.
  • İkisi aynı anda 0 olamaz. 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: 5

Bu ö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.yaml
deployment.apps/my-webapp-rolling created

2. Pod’ları izleyin

watch kubectl get pods -l app=my-webapp
NAME                                 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-webapp

4. 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-alpine
deployment.apps/my-webapp-rolling annotated
deployment.apps/my-webapp-rolling image updated

5. 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 46s

Bu anı okuyalım:

  • Toplam pod: 8 (yeni) + 4 (eski) = 12 → replicas + maxSurge sınırında.
  • Hazır pod: 4 (yeni) + 4 (eski) = 8 → replicas − maxUnavailable sı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-rolling
Waiting 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 out

Güncelleme tamamlandığında:

NAME                           DESIRED   CURRENT   READY   AGE
my-webapp-rolling-5d4c8b7f96 10 10 10 15s
my-webapp-rolling-6f8b7d9c54 0 0 0 54s

Yeni 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-rolling
deployment.apps/my-webapp-rolling
REVISION CHANGE-CAUSE
1 <none>
2 nginx 1.27 -> 1.28

7. Temizlik

kubectl delete -f my-webapp-rolling.yaml

RollingUpdate’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: 5

4. 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-rolling

Rollout 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-rolling

5. Belirli bir revizyona geri dönün

kubectl rollout undo deployment/my-webapp-rolling --to-revision=1

6. 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-rolling

Pause 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-rolling

ConfigMap/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 image ve rollout undo gibi 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 → Green

Kubernetes’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: 80

Uygulama Adımları

1. Her iki ortamı ve Service’i oluşturun

kubectl apply -f bluegreen.yaml

2. İki versiyonun da hazır olduğunu doğrulayın

kubectl get pods -l app=myapp --show-labels
kubectl rollout status deployment/myapp-green

3. Service’in şu an hangi pod’lara gittiğini kontrol edin

kubectl get endpointslices -l kubernetes.io/service-name=myapp

4. Green’i canlıya almadan test edin

kubectl port-forward deployment/myapp-green 8080:80
curl http://localhost:8080

5. 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üncelleyin

Artı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 %100

Yö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: 80

1. Stable ve canary’yi oluşturun (yaklaşık %10 canary)

kubectl apply -f canary.yaml

2. Canary oranını artırın (%50)

kubectl scale deployment/myapp-canary --replicas=5
kubectl scale deployment/myapp-stable --replicas=5

3. 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=0

4. Sorun çıkarsa canary’yi hemen kapatın

kubectl scale deployment/myapp-canary --replicas=0

Bu 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: 10

1. Route’u oluşturun

kubectl apply -f httproute-canary.yaml

2. 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 yaml

Bunun 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: 100

Argo Rollouts kubectl eklentisiyle kullanılan komutlar:

1. Rollout’u canlı izleyin

kubectl argo rollouts get rollout myapp --watch

2. Image’ı güncelleyin

kubectl argo rollouts set image myapp web=httpd

3. Manuel pause adımını onaylayın

kubectl argo rollouts promote myapp

4. Sorun varsa rollout’u iptal edin (trafik stable’a döner)

kubectl argo rollouts abort myapp

Prometheus 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: 80

Shadow (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.

Press enter or click to view image in full size
Press enter or click to view image in full size

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 requests tanı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).
  • progressDeadlineSeconds ve kubectl rollout status ile 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/RollingUpdate ve maxSurge/maxUnavailable davranışı yıllardır stabil; eski kaynaklardaki temel bilgiler hâlâ geçerli.
  • Ingress NGINX emekliye ayrıldı. Topluluk projesi olan kubernetes/ingress-nginx Mart 2026 itibarıyla bakım almıyor; yeni güvenlik yamaları çıkmayacak. Eski canary yazılarının çoğu nginx.ingress.kubernetes.io/canary-weight annotation'ını kullanır. Yeni kurulumlarda bunun yerine Gateway API (HTTPRoute ağı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.
  • --record flag'i deprecated. Değişiklik nedenini kubernetes.io/change-cause annotation'ı ile kaydedin.
  • Terminating pod’ların görünürlüğü: Deployment ve ReplicaSet status’una eklenen terminatingReplicas alanı v1.35'te beta oldu. Bir sonraki adım olarak Deployment'lara spec.podReplacementPolicy alanı 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 alternatifi

Gü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:80

Argo 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>

--

--