Progressive Delivery Nedir? Canary, Blue-Green ve Flag
Summary
Progressive delivery, bir değişikliği production ortamına küçük ve kontrollü adımlarla yayınlama yaklaşımıdır. Her adım gerçek metriklerle kontrol edilir ve sonraki adım yalnızca sayılar tutarsa başlar. Kod deploy etmeyi kullanıcıya yayınlamaktan ayırır ve canary, blue-green deployment ile feature flag'leri bir araya getirir. Hata oranı ya da gecikme önceden tanımlanmış eşiği aşarsa otomatik geri alma devreye girer.
Progressive delivery nedir? Progressive delivery, bir değişikliği production ortamına küçük ve kontrollü adımlarla yayınlama yaklaşımıdır. Her adım gerçek metriklerle kontrol edilir ve bir sonraki adım yalnızca sayılar tutarsa başlar. Sayılar kötüleşirse yayın durur ya da kendiliğinden geri alınır. Böylece tüm kullanıcı kitlenizi tek bir deploy'a bağlamamış olursunuz.
Bunu muhtemelen tanıyorsunuz. Pull request onaylanır, CI yeşile döner, deploy salı öğleden sonra çıkar ve yirmi dakika sonra biri Slack'te checkout gecikmesinin neden iki katına çıktığını sorar. Progressive delivery bu konuşmayı kısaltmak ve sorunu trafiğin yüzde 100'ü yerine yüzde 5'ine yaşatmak için vardır.
Progressive delivery neyi değiştirir?
Klasik sürekli dağıtım tek bir soruya yanıt verir: bu değişikliği production'a güvenle gönderebilir miyiz? Progressive delivery ikinci bir soru ekler: bunu ilk kim görecek ve durdurmamız gerektiğini bize ne söyleyecek?
Asıl hamle, deploy etmek ile yayınlamak arasını ayırmaktır. Deploy etmek, yeni kodun sunucularda çalışması demektir. Yayınlamak ise kullanıcıların bu koda maruz kalması demektir. İkisi ayrıldığında, bir çarşamba öğleden sonra deploy yapabilir, yayını kendi temponuzda, seçtiğiniz bir kitleye ve geri dönüş yoluyla gerçekleştirebilirsiniz.
Okuyacağınız kaynakların çoğu üç yapı taşında hemfikirdir: kademeli trafik kaydırma (canary), paralel ortamlar (blue-green) ve feature flag'ler. Bunlar birbirinin rakibi değil. Olgun ekipler üçünü farklı katmanlarda birlikte kullanır.
Canary yayınlar: ne kadar trafik, karar kim veriyor?
Canary yayında yeni sürüme küçük bir trafik dilimi, örneğin yüzde 5, gönderilir; geri kalan trafik eski sürümde kalır. Hata oranı, gecikme ve doygunluk eşiklerinizin içinde kaldıkça dilim büyür: yüzde 5, yüzde 25, yüzde 50, yüzde 100. Eşikler aşılırsa trafik geri döner.
Tuzak şurada: ince ayarlı bir bölme yapabilmek için trafiği gerçekten bölebilen bir bileşen gerekir. Argo Rollouts dokümantasyonu hassas canary yüzdelerinin bir service mesh ya da ingress controller gibi bir trafik yöneticisi gerektirdiğini belirtiyor. Böyle bir bileşen yoksa yalnızca replica sayısına dayalı kaba bir kontrol elde edersiniz. Yani "yüzde 5" aslında yirmi pod'dan "bir pod" anlamına gelebilir.
Aşamalı bir canary'nin Argo Rollouts manifest'inde nasıl göründüğü aşağıda. Kasıtlı olarak kısa tutuldu.
strategy:
canary:
steps:
- setWeight: 5
- pause: { duration: 10m } # dashboard'ları izle ya da analiz çalıştır
- setWeight: 25
- pause: { duration: 10m }
- setWeight: 100Servisiniz o kadar az trafik alıyorsa ki yüzde 5, saatte birkaç istek demekse canary'yi atlayın. Ya sonsuza kadar bir sinyal beklersiniz ya da daha kötüsü, gürültüyü güvenlik sanarsınız. Düşük trafikli servislerde ilk kapı olarak iç kullanıcılara yönelik feature flag'ler daha iyi bir seçimdir.
İlk dilimi seçerken trafik hacmini düşünün. Yüzde 5'lik bir dilim, dakikada binlerce istek alan bir serviste birkaç dakika içinde anlamlı bir sinyal üretir. Ama dakikada yüz istek alan bir serviste aynı dilim, hata oranında gerçek bir fark görmek için çok uzun süre bekletir. Bu yüzden adımları sabit bir yüzdeye göre değil, her adımda en az birkaç yüz istekten oluşan bir örneklem toplanacak süreye göre planlayın.

Blue-green deployment: tam ikinci bir ortam ne zaman değer?
Blue-green, iki tam production ortamı çalıştırır. Blue kullanıcılara hizmet verir. Green yeni sürümü alır ve boşta iken test edilir. Memnun kalındığında trafik bir taraftan diğerine geçer.
Argo Rollouts dokümanlarına göre geçiş tek seferde olur: yeni sürüm doğrulanana kadar eski sürüm tüm production trafiğini tutar, ardından bölme yüzde 0'dan yüzde 100'e çıkar. Güçlü yanı da zayıf yanı da budur. Geri almak tek bir geri çevirme kadar hızlıdır. Ama test, gerçek kullanıcılar gelmeden önce yapılır ve iki taraf çalışırken altyapı maliyeti iki katına çıkar.
Kısmi yayının kafa karıştırıcı ya da riskli olacağı bir servis için değer: örneğin iki sürümün aynı anda istek işlemesinin asla kabul edilemeyeceği bir ödeme akışı. Veritabanı migration'ı iki sürümde aynı anda çalışamıyorsa atlayın, çünkü o zaman "anında geri alma" bir masaldır.
Bir pratik not: blue-green kurulumunda asıl geçişin kendisi de bir hata noktasıdır. Yük dengeleyici ya da DNS değişikliği yapılmadan önce green ortamı gerçek trafiğe benzeyen bir yükle ısıtın, bağlantı havuzlarını, cache'leri ve arka plan işlerini hazır hale getirin. Aksi halde trafik geçtiği anda yeni sürümün ilk gerçek hatası, geri almanın da ilk gerçek testi olur.

Feature flag'ler nerede devreye girer?
Canary ve blue-green altyapı seviyesinde çalışır. Feature flag ise uygulamanın içinde çalışır. Flag, bir kod yolunu çalışma zamanında değiştirilebilen bir koşulla sarar ve yeniden deploy gerektirmez.
Bu, flag'leri kutudaki en ince taneli araç yapar. Bir özelliği önce çalışanlara, sonra hesapların yüzde 1'ine, sonra bir müşteri segmentine açabilir ve yanlış davranırsa saniyeler içinde kapatabilirsiniz. Bazı ekipler flag'leri birçok tekniğin yalnızca biri sayar; başkaları ise tüm yaklaşımı mümkün kılan unsur olarak görür. Pratikte ikinci görüş ayakta kalır: sunucuya göre değil kitleye göre yayın yapmak istediğiniz an bir flag'e ihtiyacınız olur.
Flag tasarlarken iki varsayılanı kontrol edin. Flag kapalıyken eski kod yolu birebir aynı davranmalı ve flag değerlendirilemediğinde güvenli bir değer dönmelidir. Flag servisine ulaşılamadığında uygulamanın yavaşlamaması ya da çökmemesi, her yayından önce test edilmesi gereken bir özelliktir.
Ama flag'lerin de bir maliyeti var. Her flag, testlerinizin kapsaması gereken bir dal ve birinin kapatması gereken bir temizlik işidir. Mekanizmayı ve bu borcu daha uzun anlattığımız yazı için feature flag nedir sayfasına bakabilirsiniz. Her flag'i varsayılan olarak kısa ömürlü sayın; bir sahibi ve bir kaldırma tarihi olsun.
LaunchDarkly ve Statsig yönetim katmanını satar: hedefleme kuralları, denetim kayıtları, kademeli yüzde yayınları ve deneyler.
Bir yayını progressive yapan şey nedir, sadece yavaş değil?
Otomasyon. Bir insan dashboard'a bakarken on dakika bekleyen bir yayın yavaş bir deploy'dur. Bir makine metrikleri kontrol edip kararı verdiğinde progressive delivery olur.
Desen her yerde aynıdır:
Yayından önce sinyalleri tanımlayın: hata oranı, p95 gecikme ve checkout tamamlanma gibi bir iş metriği.
"Dur" anlamına gelen eşikleri birinin kafasında değil, konfigürasyonda yazılı olarak tanımlayın.
Kontrolcünün bu sinyallere göre ilerletmesine, beklemesine ya da geri almasına izin verin.
Argo Rollouts, kontrollerin geçip geçmemesine bağlı olarak bir rollout'un otomatik ilerletilebilmesi ya da durdurulabilmesi için metrik sağlayıcılarla entegre olur. İncelediğimiz kaynaklardan biri meseleyi açıkça söylüyor: otomatik geri alma olmayan progressive delivery, yavaş bir deploy'dan ibarettir. Biz de buna katılıyoruz.

Yayını izlemek için hangi metrikler kapı olmalı?
Küçük tutun. Zaten güvendiğiniz üç ya da dört sinyal, hiç alarm kurmadığınız yirmi sinyalden daha iyidir.
Çalışabilir bir başlangıç seti şöyle: canary'nin HTTP 5xx oranı ile referans (baseline) sürümün oranı, canary ve baseline'ın p95 gecikmesi, doygunluk (CPU, bellek, kuyruk derinliği) ve bir ürün metriği. Canary'yi "geçen haftayla" değil, aynı anda baseline ile karşılaştırın; çünkü trafik örüntüleri değişir.
Gözlemlenebilirlik yığınınız tam burada bir lüks olmaktan çıkar. Metrikleri sürüme ya da flag varyantına göre ayıramıyorsanız canary'yi baseline'dan ayıramazsınız ve tüm yaklaşım çöker. Gözlemlenebilirlik nedir yazımız bunun nasıl kurulacağını anlatıyor.
Progressive delivery, trunk-based development ile nasıl ilişkili?
İkisi birbirine iyi oturur. Trunk-based development dalları kısa tutar ve küçük değişiklikleri sık sık birleştirir. Risk, tamamlanmamış ya da test edilmemiş işin main'e daha sık ulaşmasıdır. Progressive delivery bunu güvenli hale getirir: kod trunk'a girer, flag arkasında yayınlanır ve kademeli olarak açılır.
Küçük partiler ve kademeli maruziyet hata ayıklamayı da ucuzlatır. Canary başarısız olduğunda şüpheli listesi kırk değişiklik değil, tek bir değişikliktir. Bir haftalık birleştirilmiş commit'i gece 23:00'te bisect eden herkes bunun ne demek olduğunu bilir.
10 ila 30 mühendisli bir ekip için gerçekçi ilk adım nedir?
Service mesh kurarak başlamayın. Size bir "dur" düğmesi veren en küçük şeyle başlayın.
1. hafta: riskli bir özelliği bir flag arkasına koyun ve önce kendi ekibinize açın.
2. hafta: hata oranı ve gecikme için sürüm bazlı dashboard'lar ekleyin. Araçlarınız sürüme göre ayıramıyorsa önce onu düzeltin.
3. hafta ve sonrası: durumsuz bir servisi iki ya da üç adımlı, hata oranında otomatik durdurmalı bir canary kontrolcüsüne taşıyın.
Üçüncü haftanın sonunda ekipte herkesin bir flag'in sahibini ve kaldırma tarihini bildiğini görmek istersiniz. Bu alışkanlık yoksa progressive delivery kısa sürede ölü flag üretmeye başlar ve her biri, bir gün birinin bozmaktan korktuğu bir kod parçasına dönüşür.
Bunu "güven hissiyle" değil saatlerle ölçün. Kaç olayın küçük bir kullanıcı diliminde kaldığını ve geri almanın ne kadar sürdüğünü sayın. Bu iki sayı, yaklaşımın ekibinizde işe yarayıp yaramadığını size söyler.
Progressive rollout'lar genelde nerede bozulur?
Üç yer var ve hiçbiri kontrolcü değil.
Veritabanı migration'ları. Canary demek, aynı anda aynı veritabanına vuran iki kod sürümü demektir. N+1 sürümü, N sürümünün hâlâ okuduğu bir kolonu silerse ya da yeniden adlandırırsa, canary baseline'ı yere serer. Sıkıcı ama doğru çözüm expand and contract: önce yeni kolonu ekleyin, hem eskiyi hem yeniyi yazan kodu yayınlayın, veriyi doldurun, okumaları geçirin ve eski kolonu en son kaldırın.
Sticky session'lar ve cache'ler. Bir kullanıcı her istekte eski ve yeni sürüm arasında gidip geliyorsa, kimsenin yeniden üretemediği hatalar çıkar. Kullanıcıyı rollout süresince bir varyanta sabitleyin: cookie, hesap kimliği ya da flag değerlendirmesi ile.
Geriden gelen metrikler. Saatte bir güncellenen bir dönüşüm metriği on dakikalık bir canary adımını kapılayamaz. Rollout sırasında hızlı sinyallere (hatalar, gecikme) göre karar verin ve yavaş iş metriğini, yüzde 50'den yüzde 100'e geçmeden önce gözden geçirin.
Repo'da neyin canlı olduğunu nasıl takip edersiniz?
Progressive delivery bir yayını config dosyalarına, flag tanımlarına, rollout manifest'lerine ve dashboard'lara yayar. Birkaç ay sonra "yeni fatura yolunu hangi flag koruyor ve sahibi kim?" sorusu alışıldık bir rutine döner: grep, blame ve sonra birine sormak.
Bu bir araç sorunu değil, kod okuma sorunu. Repo'yu flag anahtarına göre arayıp her referansı çağrı noktasına kadar takip etmek, ölü flag'leri ve yarım kalmış rollout'ları bulmanın en hızlı yoludur. "Bu flag nerede değerlendiriliyor ve kapalıyken ne olur?" sorusunu gerçek kodunuzdan yanıtlayan bir araç, burada bir dashboard'dan daha fazla zaman kazandırır.
Neyi atlarsınız?
Altyapı faturanız zaten bir tartışma konusuysa her şey için blue-green'i atlayın. Trafiği neredeyse hiç olmayan servislerde canary'leri atlayın. Gece 03:00'te ekipteki kimsenin hata ayıklayamadığı rollout araçlarını atlayın.
Asıl sorun seçtiğiniz strateji değil. Asıl sorun, kodu göndermek ile production'da ne yaptığını bilmek arasındaki boşluk. Progressive delivery bu boşluğu trafiğin bir dilimi kadar daraltır ve ilk dilim belirleyici olandır: onu küçük tutun, gözlemlenebilir kılın ve bir kapatma düğmesi verin.