Bir yazılımı canlıya almak sadece kodun sunucuya kopyalanmasından ibaret değil, aynı zamanda operasyonel maliyet, kullanıcı deneyimi ve iş sürekliliği gibi kritik faktörleri doğrudan etkileyen bir süreç. Yıllardır farklı projelerde, farklı ölçeklerde sistemleri devreye alırken, “en iyi” deploy stratejisinin diye bir şey olmadığını, her seçimin kendine göre bir bedeli olduğunu defalarca gördüm.
Bu yazıda, CI/CD süreçlerimde sıkça karşılaştığım ve uyguladığım üç temel deploy stratejisini, tecrübelerime dayanarak maliyet ve verimlilik ekseninde ele alacağım. Amacım, sadece teknik detayları değil, aynı zamanda bu stratejilerin işinize ve kariyerinize nasıl yansıdığını, hangi trade-off’ları göze almanız gerektiğini somut örneklerle ortaya koymak.
Deploy Stratejisi Seçiminin Önemi ve Maliyet İlişkisi
Yanlış seçilmiş bir deploy stratejisi, başta görünmeyen ama zamanla biriken ciddi maliyetlere yol açabilir. Bu maliyetler sadece sunucu kirası değil, aynı zamanda geliştirici zamanı, mühendislik eforu, kaybedilen müşteri ve marka itibarı gibi unsurları da kapsar. Bir üretim ERP’sinde, basit bir deploy hatası yüzünden sevkiyatların durduğunu, bunun da bekleyen tırlara ve ciddi bir maliyete yol açtığını bizzat deneyimledim. İşte bu yüzden deploy stratejisi seçimi, sadece DevOps ekibinin değil, tüm iş birimlerinin yakından ilgilenmesi gereken bir konu.
Yaptığımız her deploy, aslında bir risk yönetimi eylemidir. Bu riski minimuma indirmek için ne kadar yatırım yaptığımız, seçtiğimiz stratejiyle doğrudan alakalı. Örneğin, sürekli kesinti yaşayan bir uygulama, operasyonel olarak sürekli müdahale gerektirir, bu da mühendislik ekibinin değerli zamanını hata düzeltmeye ayırmasına neden olur. Bu durum, yeni özellik geliştirmeye ayrılması gereken eforu azaltarak uzun vadede ürünün rekabet gücünü zayıflatır. Benim için bir stratejinin verimliliği, sadece hızlı deploy olmakla değil, aynı zamanda olası hataları ne kadar hızlı tespit edip, ne kadar az maliyetle geri dönebildiğimizle de ölçülür.
1. Recreate Stratejisi: Basitliğin Bedeli
Recreate, adından da anlaşılacağı gibi, mevcut uygulama instance’larını tamamen kapatıp, yeni versiyonu baştan oluşturarak devreye alma yöntemidir. Bu, deploy stratejileri arasında en basit olanıdır ve genellikle küçük projelerde veya geliştirme/test ortamlarında tercih edilir.
Nasıl Çalışır?
- Mevcut çalışan tüm uygulama instance’ları durdurulur.
- Mevcut instance’lar tamamen silinir.
- Uygulamanın yeni versiyonuyla yeni instance’lar oluşturulur ve başlatılır.
Avantajları ve Dezavantajları
Avantajları:
- Basitlik: Konfigürasyonu ve yönetimi en kolay stratejidir. Ekstra bir tooling veya karmaşık routing gerektirmez.
- Kolay Anlaşılır: Ekip içinde herkesin kolayca kavrayabileceği bir akışı vardır.
- Kaynak Tüketimi: Genellikle ekstra sunucu kaynaklarına ihtiyaç duymaz (çünkü eskiyi kapatıp yeniyi açar).
Dezavantajları:
- Downtime (Kesinti): En büyük dezavantajı budur. Eski versiyon kapanıp yenisi açılana kadar uygulama tamamen erişilemez hale gelir. Bu kesinti süresi, uygulamanın başlatma süresine ve veritabanı migration’larının karmaşıklığına bağlı olarak dakikalarca sürebilir. Erken aşama MVP’lerde bu kesintiler kullanıcıların ani çıkışlarına, hatta yarım kalan işlemlerde veri kaybına yol açabilir.
- Kullanıcı Deneyimi: Kesinti, kullanıcı deneyimini doğrudan olumsuz etkiler. Özellikle e-ticaret siteleri veya finans uygulamaları gibi sürekli erişim gerektiren sistemlerde kabul edilemezdir.
- Risk: Yeni versiyonun başlamaması durumunda, uygulama uzun süre kapalı kalabilir. Geri dönüş (rollback) süreci de yine aynı kesintiyi gerektirir.
Gerçek Dünya Senaryosu ve Benim Bakışım
Küçük bir projenin veya kendi kişisel web sitemin backend’inde, yani günde birkaç yüz isteği karşılayan ve birkaç dakikalık kesintinin kabul edilebilir olduğu senaryolarda Recreate stratejisini kullanırım. Örneğin, docker-compose ile yönettiğim basit bir servis için aşağıdaki gibi bir deploy akışı yeterli olabilir:
#!/bin/bash
echo "Uygulama durduruluyor ve eski imajlar siliniyor..."
docker-compose down --rmi all
echo "Yeni imajlar build ediliyor..."
docker-compose build
echo "Uygulama başlatılıyor..."
docker-compose up -d
echo "Deploy tamamlandı. Uygulama birkaç saniye içinde erişilebilir olacak."
Bu akış, uygulamanın ayağa kalkma süresine bağlı olarak imaj build’i ile birlikte kısa ama gözle görülür bir kesintiye yol açar. Bu süre, düşük trafikli bir blog sitesi veya dahili bir araç için kabul edilebilirken, yüksek trafiğe sahip bir platform için kesinlikle uygun değildir. Bence Recreate, öğrenme aşamasında veya çok düşük bütçeli, düşük kritiklikteki projelerde başlanabilecek bir nokta, ancak büyüme hedefleri olan her uygulamada bir an önce terk edilmesi gereken bir stratejidir.
2. Rolling Update: Dengeli Bir Yaklaşım
Rolling Update, Recreate’in kesinti dezavantajını gidermek için geliştirilmiş, daha sofistike bir stratejidir. Bu yöntemde, mevcut uygulama instance’ları kademeli olarak, yenileriyle değiştirilir. Uygulama, deploy süresince erişilebilir kalır, ancak kısa bir süre için hem eski hem de yeni versiyon aynı anda çalışabilir.
Nasıl Çalışır?
- Yeni versiyonun bir veya daha fazla instance’ı başlatılır.
- Bu yeni instance’lar sağlıklı kabul edildiğinde, eski versiyonun bir veya daha fazla instance’ı durdurulur.
- Bu süreç, tüm eski instance’lar yeni versiyonla değiştirilene kadar devam eder.
Avantajları ve Dezavantajları
Avantajları:
- Kesinti Azalması: Uygulama, deploy süresince genellikle erişilebilir kalır. Kullanıcılar kesinti yaşamaz veya çok kısa, fark edilmeyen anlık kesintiler yaşayabilir.
- Daha Güvenli Rollback: Bir sorun tespit edildiğinde, deploy durdurulabilir ve eski versiyona daha kolay bir şekilde geri dönülebilir, çünkü eski instance’ların bir kısmı hala çalışıyor olabilir.
- Kaynak Verimliliği: Blue/Green gibi çift altyapı gerektirmez, bu da maliyet açısından daha avantajlıdır.
Dezavantajları:
- Versiyon Çarpıklığı (Version Skew): Deploy süresince eski ve yeni versiyon aynı anda çalıştığı için, bu iki versiyonun birbiriyle uyumlu olması gerekir. Özellikle API’lerde veya veritabanı şemasında yapılan değişiklikler bu durumu karmaşıklaştırabilir. Uyumsuz şema değişiklikleri yüzünden eski ve yeni versiyon arasında kalan
PATCHgibi operasyonlar, fark edilmesi zor veri tutarsızlıklarına (örneğin bozulan sepet kayıtlarına) yol açabilir. - Daha Yavaş Rollout: Kademeli değişim, tüm deploy sürecinin daha uzun sürmesine neden olabilir.
- Karmaşık Sağlık Kontrolleri: Yeni instance’ların “sağlıklı” olduğunu doğru bir şekilde belirlemek için robust sağlık kontrolleri (health checks) gereklidir.
Gerçek Dünya Senaryosu ve Benim Bakışım
Çoğu orta ölçekli ve kritik uygulamalar için Rolling Update, maliyet ve güvenilirlik arasında iyi bir denge sunar. Kubernetes Deployment objeleri varsayılan olarak Rolling Update stratejisini kullanır ve maxSurge ile maxUnavailable parametreleriyle bu süreci çok ince ayarlayabiliriz.
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 3
selector:
matchLabels:
app: my-app
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # Mevcut instance'lara ek olarak kaç yeni instance oluşturulabilir
maxUnavailable: 1 # Aynı anda kaç instance'ın kullanılamaz olabileceği
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app-container
image: my-registry/my-app:v2.0 # Yeni imaj versiyonu
ports:
- containerPort: 8080
livenessProbe: # Uygulamanın çalışıp çalışmadığını kontrol eder
httpGet:
path: /health
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
readinessProbe: # Uygulamanın istek almaya hazır olup olmadığını kontrol eder
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 3
Yukarıdaki Kubernetes konfigürasyonunda maxSurge: 1 ve maxUnavailable: 1 ile, mevcut 3 instance’tan biri yeni versiyona geçirilirken, toplamda 4 instance’a kadar çıkılabilir veya 2 instance’a kadar düşülebilir. Bu sayede deploy sırasında uygulamanın performansı korunmaya çalışılır. Ancak, versiyon çarpıklığı riskini azaltmak için, API’lerimi her zaman geriye dönük uyumlu (backward compatible) tasarlamaya özen gösteririm. Veritabanı şeması değişikliklerini de her zaman iki aşamalı yaparım: önce uyumsuzluğu engelleyen değişiklikler, sonra zorunlu değişiklikler. veritabanı şema migration stratejileri
3. Blue/Green Deployment: Sıfır Kesinti Hedefi
Blue/Green deployment, adından da anlaşılacağı gibi, “mavi” ve “yeşil” olmak üzere iki özdeş üretim ortamının paralel olarak çalıştırılması prensibine dayanır. Bir ortam (örneğin “mavi”) canlı trafiği karşılarken, diğer ortam (“yeşil”) yeni versiyonla güncellenir. Testler tamamlandıktan sonra, trafik yeşil ortama yönlendirilir ve mavi ortam beklemede kalır veya bir sonraki deploy için güncellenir. Bu strateji, sıfıra yakın kesinti süresi ve anında geri dönüş yeteneği sunar.
Nasıl Çalışır?
- “Mavi” ortam canlı trafiği işlerken, “yeşil” ortam yeni uygulama versiyonuyla kurulur ve test edilir.
- Tüm testler başarılı olduğunda, bir load balancer veya DNS ayarları değiştirilerek tüm canlı trafik “yeşil” ortama yönlendirilir.
- “Mavi” ortam artık aktif değildir. İstenirse yedek olarak tutulur veya bir sonraki deploy için “yeşil” ortamın yerini almak üzere güncellenir.
Avantajları ve Dezavantajları
Avantajları:
- Sıfır Kesinti: Trafik doğrudan yeni ortama yönlendirildiği için kullanıcılar hiçbir kesinti yaşamaz.
- Anında Rollback: Eğer “yeşil” ortamda bir sorun tespit edilirse, trafik anında “mavi” ortama geri yönlendirilebilir. Bu, en hızlı geri dönüş mekanizmalarından biridir.
- İzolasyonlu Test: Yeni versiyon, canlıya alınmadan önce tamamen izole bir ortamda gerçek trafik simülasyonlarıyla test edilebilir.
Dezavantajları:
- Altyapı Maliyeti: En büyük dezavantajı, iki tam teşekküllü üretim ortamını sürekli olarak hazırda tutma gerekliliğidir. Bu, sunucu, veritabanı ve ağ kaynaklarının iki katı anlamına gelir. İşin kritikliği yükseldikçe (örneğin finansal bir modülde) bu çift maliyet, kesintinin getireceği riskin yanında kabul edilebilir hale gelir; karar aslında bir risk-fayda analizidir.
- Durum Yönetimi (Stateful Services): Veritabanları gibi durum tutan (stateful) servislerin yönetimi karmaşıktır. İki ortamın veritabanlarını senkronize tutmak veya migration’ları dikkatlice yönetmek gerekir.
- Karmaşık Konfigürasyon: Load balancer, DNS ve ağ konfigürasyonları daha karmaşıktır.
Gerçek Dünya Senaryosu ve Benim Bakışım
Blue/Green, finans, sağlık veya telekomünikasyon gibi iş sürekliliğinin kritik olduğu sektörlerde yaygın olarak kullanılır. Kendi üretim ERP’sinde, ana modüllere gelen güncellemeler için Blue/Green benzeri bir yapı kurmuştuk. Buradaki asıl zorluk, veritabanı migration’larını kesintisiz ve geriye dönük uyumlu olacak şekilde tasarlamaktı. Genellikle bu tip bir deploy için aşağıdaki gibi bir Nginx konfigürasyonu veya bulut sağlayıcılarının load balancer özellikleri kullanılır:
# Nginx conf example for Blue/Green
upstream blue_servers {
server 192.168.1.10; # Blue ortamdaki sunucu IP'leri
server 192.168.1.11;
}
upstream green_servers {
server 192.168.1.20; # Green ortamdaki sunucu IP'leri
server 192.168.1.21;
}
server {
listen 80;
server_name myapp.example.com;
location / {
# Canlı trafiği yönlendireceğimiz ortamı burada belirleriz.
# Deploy sırasında bu 'include' satırı değiştirilir veya otomatik araçlarla güncellenir.
include /etc/nginx/current_target_env.conf;
}
}
current_target_env.conf dosyası içinde proxy_pass http://blue_servers; veya proxy_pass http://green_servers; satırını değiştirerek trafik yönlendirilir. Bu, benim gibi bare-metal ve container hibrit dağıtım seven biri için oldukça pratik bir yöntemdir.
4. Canary Deployment ve A/B Testleri: Kontrollü Risk ve Optimizasyon
Canary deployment, Blue/Green’in kontrollü geçiş özelliğini daha da ileri taşıyan bir stratejidir. Yeni versiyon, ilk olarak kullanıcıların küçük bir yüzdesine (genellikle %1-5) sunulur. Bu “kanarya grubu”ndan gelen geri bildirimler ve metrikler dikkatlice izlenir. Eğer her şey yolundaysa, yeni versiyon kademeli olarak daha fazla kullanıcıya açılır. Bu, risk yönetimini en üst düzeye çıkaran bir yaklaşımdır.
Nasıl Çalışır?
- Uygulamanın yeni versiyonu (“canary”) küçük bir sunucu grubuna veya kullanıcı segmentine deploy edilir.
- Bu canary grubunun performansı, hata oranları, kullanıcı deneyimi metrikleri yakından izlenir.
- Eğer canary versiyonu stabilse ve beklentileri karşılıyorsa, kademeli olarak daha fazla kullanıcıya açılır.
- Bu süreç, tüm kullanıcıların yeni versiyona geçmesiyle tamamlanır.
Avantajları ve Dezavantajları
Avantajları:
- Minimum Risk: Büyük çaplı bir sorun yaşanması durumunda sadece küçük bir kullanıcı grubunun etkilenmesini sağlar. Bu, hata anında oluşan zararı minimize eder. Örneğin yeni bir algoritmayı canlıya alırken, olası hataların yalnızca küçük bir kullanıcı dilimine ulaşmasını sağlayabilirsiniz.
- Gerçek Dünya Testi: Uygulamanın yeni versiyonu, gerçek kullanıcılar ve gerçek trafikle test edilir. Bu, test ortamlarında yakalanamayan edge case’lerin ortaya çıkmasına yardımcı olur.
- A/B Testi Entegrasyonu: Canary deploy, aynı zamanda A/B testleri için de kullanılabilir. Farklı özellik setlerini farklı kullanıcı gruplarına sunarak hangi versiyonun daha iyi performans gösterdiğini ölçebiliriz.
Dezavantajları:
- Karmaşık İzleme (Monitoring): Metriklerin, logların ve trace’lerin çok detaylı ve anlık olarak izlenmesi gerekir. Alert fatigue riski yüksektir.
- Trafik Yönlendirme Karmaşıklığı: Kullanıcıları belli yüzdelik dilimlere ayırmak için gelişmiş load balancer veya servis ağı (service mesh) yetenekleri gereklidir.
- Daha Uzun Rollout Süresi: Kademeli geçiş nedeniyle tüm deploy süreci daha uzun sürebilir.
Gerçek Dünya Senaryosu ve Benim Bakışım
Canary deploy, özellikle büyük ölçekli ve kritik öneme sahip, sürekli yeni özellikler eklenen uygulamalar için idealdir. Örneğin, bir mobil uygulamanın yeni bir versiyonunu Play Store’a yüklerken, ilk başta %5’lik bir kullanıcı grubuna açıp, hataları kontrol ettikten sonra yaygınlaştırma stratejisi sıkça kullanılır.
Trafik yönlendirme tarafında, Nginx gibi reverse proxy’ler veya Istio gibi service mesh çözümleri kullanılabilir. Örneğin, Nginx’te split_clients modülü ile trafiği yüzdelik dilimlere ayırmak mümkündür:
# Nginx conf example for Canary Deployment
http {
map $cookie_ab_test $backend_pool {
default green_servers; # %95'i yeni versiyona (Green)
"~^blue" blue_servers; # %5'i eski versiyona (Blue)
}
# Alternatif olarak IP bazlı veya Header bazlı ayrım yapılabilir.
# split_clients $remote_addr $canary_traffic {
# 5% canary; # %5 trafiği canary'ye
# * production; # Kalanı ana ortama
# }
upstream blue_servers { server 192.168.1.10; }
upstream green_servers { server 192.168.1.20; }
upstream canary_servers { server 192.168.1.30; } # Canary ortamı
server {
listen 80;
server_name myapp.example.com;
location / {
# proxy_pass http://$backend_pool; # Cookie bazlı örnek
proxy_pass http://canary_traffic; # split_clients bazlı örnek
}
}
}
Bu karmaşıklık, beraberinde ciddi bir monitoring yükü de getirir. Prometheus, Grafana, ELK Stack gibi araçlarla metrikleri, logları ve trace’leri anlık olarak izlemek hayati önem taşır. Aksi takdirde, küçük bir canary grubundaki sorunu fark edemeyip, tüm kullanıcılara yaygınlaştırma hatasına düşebiliriz. observability ile sistemlerinizi izleme
Strateji Seçiminde Dikkate Alınan Kritik Faktörler ve Benim Yaklaşımım
Doğru deploy stratejisini seçmek, uygulamanın özel ihtiyaçlarına, bütçesine, ekibin olgunluğuna ve işin kritiklik seviyesine göre değişir. Tek bir “herkese uyan” çözüm yoktur. Kendi projelerimde bir deploy stratejisi seçerken dikkate aldığım bazı kritik faktörler şunlar:
- Kabul Edilebilir Kesinti Süresi (Downtime Tolerance):
- Saatler/Dakikalar: Dahili araçlar, kişisel siteler (Recreate).
- Saniyeler: Çoğu ticari uygulama, arka plan servisleri (Rolling Update).
- Sıfır: Finans, sağlık, e-ticaret (Blue/Green, Canary).
- Altyapı Maliyeti: Her stratejinin getirdiği ek kaynak ihtiyacı (sunucular, load balancer’lar, storage). Blue/Green ve Canary, altyapı maliyetini artırır.
- Geri Dönüş (Rollback) Süresi ve Karmaşıklığı: Bir hata durumunda ne kadar hızlı ve güvenli bir şekilde eski versiyona dönebiliriz? Blue/Green ve Canary bu konuda çok avantajlıdır.
- Ekibin Olgunluğu ve Yetkinliği: Ekibin karmaşık deploy süreçlerini yönetme, izleme ve sorun giderme yeteneği. Recreate en az yetkinlik gerektirirken, Canary en fazlasını ister.
- Uygulamanın Kritiklik Seviyesi: Uygulamanın iş süreçleri üzerindeki etkisi. Finansal bir sistemle bir blog sitesinin deploy gereksinimleri farklıdır.
- Test Kapsamı ve Otomasyon: Yeni versiyonun ne kadar iyi test edildiği. Kapsamlı otomatik testler, daha agresif deploy stratejilerini destekleyebilir.
Bence, bir deploy stratejisi seçerken “en iyisi” yerine “en uygunu”nu bulmak esastır. Benim genel yaklaşımım, mümkün olduğunca Rolling Update ile başlayıp, uygulamanın kritikliği ve trafik hacmi arttıkça Blue/Green veya Canary’ye geçiş yapmaktır. Bu geçiş, hem altyapı maliyetlerini optimize etmeme hem de ekibin süreçlere yavaş yavaş adapte olmasına olanak tanır.
Sonuç
Bu üç (artı bonus olarak Canary) stratejiyi yıllarca farklı projelerde uyguladıktan sonra vardığım sonuç net: deploy stratejisi seçimi teknik bir tercih gibi görünse de aslında bir risk ve maliyet yönetimi kararı. Recreate’in basitliği cazip ama her kesinti dakikasının bir bedeli var; Blue/Green’in sıfır kesintisi gönül rahatlığı veriyor ama iki kat altyapıyı sürekli ayakta tutmanın faturasını da unutmamak gerekiyor. “En iyi strateji” diye bir şey yok, yalnızca bağlamınıza “en uygun” olan var.
Benim pratik tavsiyem, olabildiğince Rolling Update ile başlamak. Çoğu uygulama için maliyet ve güvenilirlik arasında en dengeli noktayı o tutuyor; Kubernetes gibi modern platformlarda zaten varsayılan olduğu için ekstra bir karmaşıklık da getirmiyor. Uygulamanın trafiği ve iş kritikliği arttıkça, MTTR’ı sıfıra yaklaştırmanın gerçekten para kazandırdığı eşiği geçtiğinizde Blue/Green’e; sürekli yeni özellik akışı olan, gerçek kullanıcıyla doğrulanması gereken büyük ölçekli sistemlerde ise Canary’ye terfi ettirin. Bu kademeli geçiş, hem cebinizi hem de ekibinizin öğrenme eğrisini koruyor — bir gecede en karmaşık stratejiye atlamak, çoğu zaman çözdüğünden fazla sorun yaratıyor.
Son olarak şunu vurgulamak isterim: hangi stratejiyi seçerseniz seçin, sağlam sağlık kontrolleri, geriye dönük uyumlu veritabanı migration’ları ve düzgün bir gözlemlenebilirlik (observability) katmanı olmadan hiçbiri sizi gerçekten korumaz. Strateji, yalnızca bu temellerin üzerine kurulduğunda işe yarıyor. Deploy’u bir korku anı olmaktan çıkarıp sıradan, sıkıcı bir rutine dönüştürebildiğinizde — işte o zaman doğru stratejiyi doğru şekilde kurmuşsunuz demektir.