CI/CD Nedir? Bir Uygulama Production’a Nasıl Gider?
Commit'ten canlı trafiğe giden yolu; CI kontrolleri, değişmez artifact, staging, onay, migration ve rollback kararlarıyla birlikte tasarlayalım.
Bir uygulamayı production'a taşımak, sunucuda son kodu çekip yeniden başlatmaktan ibaret değildir. Asıl amaç hangi değişikliğin, hangi kontrollerden geçerek, hangi koşullarda kullanıcılara ulaştığını tekrar edilebilir hale getirmektir. CI/CD bu sürecin otomasyon ve geri bildirim tarafını düzenler.
Örnek olarak Node.js ile yazılmış bir sipariş API'si düşünelim. Bir commit doğru çalışsa bile yanlış environment değişkeni, uyumsuz veritabanı migration'ı veya eksik kapanma davranışı canlı sistemde sorun çıkarabilir. Pipeline yalnızca kodun derlenmesini kontrol ederse bu risklerin büyük kısmını görmez.
CI, delivery ve deployment aynı kavram değil
Continuous Integration, küçük değişikliklerin düzenli olarak ortak kod tabanına katılması ve otomatik doğrulanmasıdır. Lint, tip kontrolü ve testler bu geri bildirimin parçalarıdır. Amacı hatayı yayın gününde değil, değişiklik küçükken fark etmektir.
Continuous Delivery, doğrulanmış değişikliklerin yayınlanabilir durumda tutulmasıdır; production'a geçiş insan kararı içerebilir. Continuous Deployment ise gerekli kontrollerden geçen değişikliklerin otomatik canlıya alınmasıdır. “CD kullanıyoruz” denildiğinde hangi anlamın kastedildiğini netleştirmek ekip beklentilerini hizalar.
Bir süreç manuel onay içerdiği için kötü değildir. Esas sorun onayın neyi doğruladığının belirsiz olması ve ardından elle yapılan adımların kayıt dışı kalmasıdır.
Commit'ten artifact'a
Sağlıklı bir akışta kaynak kod bir kez derlenir, test edilir ve sürüm kimliğiyle paketlenir. Aynı artifact staging ve production arasında ilerler. Her ortamda yeniden build almak, test edilen paket ile yayınlanan paketin farklılaşmasına neden olabilir.
Pull request
→ lint + tip kontrolü + test
→ kod inceleme
→ main
→ image oluştur + tara + registry'ye gönder
→ staging
→ smoke test + onay
→ production
→ sağlık ve kullanıcı etkisi kontrolü
Image tag'i okunabilir bir işaret olabilir, fakat içerik kimliğini sabitlemek için digest kullanmak daha güçlüdür. Commit SHA'sını deployment kaydına eklemek de arıza anında hangi kodun çalıştığını bulmayı kolaylaştırır.
Küçük bir CI örneği
Aşağıdaki GitHub Actions örneği Node.js projesindeki mevcut lint, test ve build script'lerini çalıştırır. Node sürümünü projenizin desteklediği sürüme göre seçin.
name: verify
on:
pull_request:
push:
branches: [main]
permissions:
contents: read
jobs:
checks:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
cache: npm
- run: npm ci
- run: npm run lint
- run: npm test
- run: npm run build
Bu yalnızca doğrulama pipeline'ıdır; kendiliğinden deployment yapmaz. npm ci, lock dosyasına göre kurulum yapar. Gerçek projede üçüncü taraf action'ları doğrulanmış tam commit SHA'larına sabitlemek, tag değişikliği riskini azaltır. GitHub'ın güvenli workflow rehberi izinleri ve bağımlılık güvenini ayrıca ele alır.
Staging neden tek başına garanti değildir?
Staging, environment ayrımlarını ve servisler arası bağlantıları test etmek için değerlidir. Ancak veri hacmi, trafik şekli ve eşzamanlılık production'dan farklıysa aynı sonuç garanti edilmez.
Örneğin boş veritabanında hızlı çalışan bir migration, milyonlarca kayıtta uzun kilitler oluşturabilir. Testte var olan bir API anahtarı production secret store içinde eksik olabilir. Bu nedenle deployment öncesi kontrol, yalnızca HTTP 200 değil; ayarlar, izinler, migration davranışı ve kritik kullanıcı işlemlerini de kapsamalıdır.
GitHub Actions environments; onay, erişim ve eşzamanlı deployment kontrolü için kullanılabilir. Özelliklerin kullanılabilirliği plan ve repository koşullarına göre değişebilir. Deployment kontrolü belgesi bu mekanizmaları açıklar.
Migration ve rollback birlikte tasarlanmalı
Uygulama image'ını geri almak kolay olabilir. Fakat yeni sürüm bir veritabanı sütununu sildiyse eski binary artık çalışmayabilir. Bu yüzden rollback planı yalnızca önceki tag'i kaydetmek değildir.
Bir seçenek expand-and-contract yaklaşımıdır: önce yeni alanı geriye uyumlu ekleyin, kodu iki şemayla çalışabilir hale getirin, veriyi taşıyın ve eski alanı daha sonraki sürümde kaldırın. Ödeme veya stok gibi geri alınamaz yan etkilerde ayrıca telafi süreci gerekir.
Canary veya kademeli trafik aktarımı, hatanın etki alanını küçültebilir. Ancak iki sürümün aynı anda çalışabilmesi için API ve veri modeli uyumluluğu da korunmalıdır.
Yayından sonra pipeline bitmez
Deployment sonrası hata oranı, gecikme ve kritik işlem başarısını önceki durumla karşılaştırın. Yeni sürüm sağlıksızsa trafik aktarımını durduracak koşulları önceden tanımlayın. Kapanan instance'ın mevcut istekleri bitirebilmesi için graceful shutdown ve trafik boşaltma sürelerini hizalayın.
Örnek API için yayın kabul kriteri şöyle olabilir: temel sipariş akışı çalışıyor, yeni 5xx artışı yok, kuyruk gecikmesi büyümüyor ve önceki sürüme dönüş yolu hazır. Sayısal eşikler gerçek sistemin normal davranışından türetilmelidir.
İyi CI/CD, daha hızlı komut çalıştırmanın ötesinde, küçük ve izlenebilir değişikliklerle güvenilir yayın yapabilme becerisidir.
İlgili Yazılar
Reverse Proxy Nedir? Nginx ile Gerçek Bir Kullanım Senaryosu
Node.js uygulamasını Nginx arkasına alırken URI yönlendirme, forwarded header, timeout ve 502/504 teşhisinin nasıl birlikte tasarlanacağını inceleyelim.
Monitoring ve Logging Arasındaki Fark: Sistemde Sorun Olduğunu Nasıl Anlarız?
Metrik, log ve trace verilerini kullanıcı etkisi etrafında birleştirelim; SLI/SLO, anlamlı alarmlar ve yüksek cardinality sorununu pratik örneklerle ele alalım.
Terraform ile Infrastructure as Code Mantığını Anlamak
Terraform'u komut otomasyonu yerine istenen durum yönetimi olarak ele alalım; plan, state, drift, bağımlılık grafiği ve güvenli apply sürecini örnekleyelim.