Deployment və release strategiyaları
Deployment və release strategiyaları
Bir çox komandada deploy hadisədir. Cümə günü edilmir, Slack kanalında hamı nəfəsini tutub gözləyir. Ch02-də deployability-ni belə soruşmuşduq: "merge olundu"dan "production-dadır"a qədər nə qədər vaxt keçir və bu nə dərəcədə risklidir? Deploy qorxuludursa, komanda onu seyrək edir. Seyrək deploy-lar böyük olur, böyük deploy-lar isə daha tez-tez sınır. Qorxu öz-özünü doğruldur.
Bu fəslin məqsədi deploy-u adi, darıxdırıcı əməliyyata çevirməkdir. Bunun üçün dəyişikliyi kiçik saxlamaq, onu mərhələlərlə yaymaq, problemi istifadəçilərin çoxu görməmişdən əvvəl tutmaq və geri qayıtmağı ucuzlaşdırmaq lazımdır. Ch07-nin dili ilə desək, burada danışılan hər strategiya deploy-un failure domain-ini kiçiltmək və MTTR-i azaltmaq üçün tactic-dir.
Deploy release deyil
Deploy kodun production-a çatdırılmasıdır. Release isə dəyişikliyin istifadəçiyə açılmasıdır. Ənənəvi olaraq bu ikisi eyni anda baş verir: yeni build qalxır və hamı yeni davranışı dərhal görür. Elə buna görə deploy riskli olur: texniki risk (yeni binary işləyəcəkmi?) və məhsul riski (istifadəçilər yeni feature-u necə qarşılayacaq?) bir ana yığılır.
Bu ikisini ayırmaq riski iki kiçik hissəyə bölür. Kod əvvəlcə söndürülmüş halda production-a gedir və real infrastructure-da işlədiyi yoxlanılır. Feature isə sonra, ayrıca qərarla, əvvəl daxili istifadəçilərə, sonra kiçik faizə, sonra hamıya açılır. Problem çıxanda rollback üçün yeni deploy lazım olmur, release geri alınır.
Aşağıdakı strategiyaları bu ayrılığa görə iki qrupa bölmək olar: rolling, blue-green və canary deploy-u idarə edir, feature flag-lər isə release-i.
Kiçik və tez-tez
Deploy-un riski onun ölçüsü ilə artır. Üç sətirlik dəyişiklik sınanda səbəbi bir dəqiqəyə tapırsınız. İki həftəlik iş yığınında, yəni qırx commit-də isə əvvəlcə hansı commit-in günahkar olduğunu axtarmalısınız. Kiçik batch həm sınma ehtimalını, həm də bərpa vaxtını azaldır.
DORA tədqiqatları bunu dörd metrika ilə ölçür:
- Deployment frequency: nə qədər tez-tez production-a deploy edirsiniz.
- Lead time for changes: commit-dən production-a qədər keçən vaxt.
- Change failure rate: deploy-ların neçə faizi incident və ya rollback-a səbəb olur.
- Time to restore (MTTR): uğursuz dəyişiklikdən sonra bərpa vaxtı.
Tədqiqatların əsas nəticəsi intuisiyaya ziddir: sürət və sabitlik bir-birinə qarşı deyil. Ən yaxşı komandalar həm gündə bir neçə dəfə deploy edir, həm də daha az sınır. Çünki tez-tez deploy edən komanda prosesi avtomatlaşdırmağa məcburdur.
Rolling və blue-green: versiyanı necə dəyişmək
Rolling deployment
Rolling deployment-də instance-lar qrup-qrup yeni versiyaya keçir: load balancer bir instance-ı traffic-dən çıxarır, onu yeniləyir, health check-dən keçəndən sonra geri qaytarır və növbətiyə keçir.
Üstünlüyü sadəlikdir: əlavə infrastructure tələb etmir. Qiyməti isə iki yerdə ödənir. Birincisi, deploy boyunca iki versiya eyni anda işləyir: eyni istifadəçinin bir request-i köhnə, növbətisi yeni versiyaya düşə bilər. Deməli, yeni versiya köhnə ilə eyni API-ni, eyni queue mesaj formatını və eyni database schema-sını başa düşməlidir. Ch08-dəki backward compatibility tələbi burada service-in öz versiyaları arasında da işləyir. İkincisi, rollback yavaşdır: geri qayıtmaq başqa bir rolling deployment deməkdir və yüz instance-lıq sistemdə bu dəqiqələr çəkir.
Blue-green deployment
Blue-green deployment-də iki tam mühit var. "Blue" hazırda traffic qəbul edir, yeni versiya "green"-də qaldırılır və orada yoxlanılır. Hazır olanda load balancer və ya DNS bütün traffic-i bir anda green-ə keçirir. Problem çıxsa, switch geri çevrilir. Rollback saniyələr çəkir, çünki blue hələ də işləyir.
Qiyməti açıqdır: switch anında ikiqat infrastructure lazımdır. Daha az görünən problem isə database-dir. İki mühit adətən eyni database-i paylaşır, çünki data-nı iki nüsxədə sinxron saxlamaq ayrıca layihədir. Bu o deməkdir ki, green-in schema dəyişikliyi blue ilə də uyğun olmalıdır, əks halda "ani rollback" vədi yalan çıxır. Bu problemə migration bölməsində qayıdacağıq.
Canary release: riski ölçərək genişləndirmək
Canary release yeni versiyanı əvvəlcə traffic-in kiçik hissəsinə verir, məsələn 1%-ə, və qərarı metrikalara əsasən verir: hər şey normaldırsa 5%, 25%, 100%; pisləşirsə dərhal geri. Bu, birbaşa failure domain-i kiçiltmək deməkdir: səhv build istifadəçilərin hamısına yox, yüzdə birinə çatır və error budget-in yalnız kiçik hissəsini yeyir.
Canary-ni gücləndirən avtomatlaşdırmadır. Canary analysis yeni versiyanın SLI-larını (ch07) eyni anda işləyən köhnə versiyanın SLI-ları ilə müqayisə edir: error rate, p99 latency, saturation. Müqayisə mütləq hədlə yox, baseline ilə aparılır, çünki gecə saat üçdə və axşam pik saatda normal error rate fərqlidir. Fərq hədd keçirsə, sistem insanı gözləmədən rollback edir.
Canary-nin şərtləri var. Kiçik faizdə statistik nəticə çıxarmaq üçün kifayət qədər traffic lazımdır: dəqiqədə on request-lik service-də 1% canary heç nə demir. İstifadəçi canary-yə "yapışdırılmalıdır", əks halda hər səhifə yenilənəndə fərqli versiya görür. Rolling-dəki kimi iki versiya eyni anda işlədiyi üçün compatibility tələbi də qalır.
Machine Learning kitabında canary-yə model baxımından baxdıq: orada əsas sual model-in keyfiyyətidir, burada isə deploy-un texniki sağlamlığı. Shadow mode isə daha da ehtiyatlıdır: traffic yeni versiyaya kopyalanır, amma cavabı istifadəçiyə qaytarılmır. Bu, yalnız side effect-i olmayan, oxuma əməliyyatları üçün təhlükəsizdir.
Feature flag-lər: release-i kodla idarə etmək
Feature flag kodun içində runtime-da dəyişdirilə bilən şərtdir: if flags.enabled("new-checkout", user). O, deploy ilə release arasındakı ayrılığı reallaşdırır və bir neçə fərqli iş görür:
- Tədrici açılış: əvvəl komanda, sonra beta istifadəçilər, sonra faizlə hamı.
- Kill switch: problemli feature-u və ya ağır əməliyyatı deploy etmədən söndürmək. Ch11-dəki graceful degradation çox vaxt məhz belə flag-lərlə həyata keçirilir.
- A/B test: istifadəçiləri qruplara bölüb variantları biznes metrikası ilə müqayisə etmək.
Flag-lərin qiyməti texniki borcdur. Hər flag kodda iki yol yaradır və on aktiv flag nəzəri olaraq 1024 kombinasiya deməkdir, onların çoxu heç vaxt test olunmur. Köhnəlmiş flag-lər isə təhlükəlidir: 2012-ci ildə Knight Capital köhnə flag-i yeni məqsədlə təkrar istifadə etdi, səkkiz server-dən birinə yeni kod deploy olunmamışdı və flag orada illər əvvəlki ölü kodu oyatdı. Şirkət 45 dəqiqədə 440 milyon dollar itirdi. Qayda: hər release flag-inin sahibi və silinmə tarixi olsun, flag-in silinməsi feature-un "bitdi" tərifinə daxil edilsin.
Daha bir incəlik: flag dəyişikliyi pipeline-dan keçməyən deploy-dur. Ch07-də config-i ən təhlükəli failure domain-lərdən biri adlandırmışdıq: bütün region-lara bir anda yayılan səhv flag hər hansı səhv build qədər sistemi yıxa bilər. Ona görə flag dəyişiklikləri də audit olunmalı və mərhələlərlə yayılmalıdır.
| Strategiya | Risk (blast radius) | İnfrastructure xərci | Rollback sürəti | Mürəkkəblik | Nə vaxt uyğundur |
|---|---|---|---|---|---|
| Rolling | Orta: səhv tədricən hamıya çatır | Aşağı | Yavaş (yeni rollout) | Aşağı | Stateless service-lər, backward compatible dəyişikliklər |
| Blue-green | Yüksək: switch anında hamı | Yüksək (ikiqat mühit) | Ani | Orta | Ani switch lazımdırsa, traffic az olduğu üçün canary mənasızdırsa |
| Canary | Aşağı: əvvəl 1–5% | Aşağı–orta | Sürətli, avtomatik | Yüksək (routing, metrika, analysis) | Yüksək traffic, yaxşı SLI-lar, tez-tez deploy |
| Feature flag | Aşağı, feature səviyyəsində | Aşağı (flag service) | Ani, deploy-suz | Kodda artır, borc yığılır | Məhsul riski, tədrici açılış, eksperimentlər |
Bu strategiyalar bir-birini əvəz etmir. Yetkin pipeline adətən canary ilə deploy edir və feature flag ilə release edir.
Database migration-ları: expand–contract
Kodu geri qaytarmaq asandır, data-nı yox. Schema dəyişikliyi deploy-un ən riskli hissəsidir: yeni sütunu silib köhnə versiyaya qayıtmaq olar, amma silinmiş sütunun data-sını yox. Üstəlik, rolling, blue-green və canary-də köhnə və yeni versiya eyni database-ə eyni anda müraciət edir. Böyük cədvəldə ALTER TABLE uzun lock da tuta bilər.
Həll yolu breaking dəyişikliyi bir neçə kiçik, ayrıca deploy olunan və hər biri geri qaytarıla bilən addıma bölməkdir. Bu, expand–contract (və ya parallel change) adlanır. Nümunə: users.name sütununun adını full_name etmək.
- Expand.
full_namesütununu nullable olaraq əlavə edin. Köhnə kod onu görmür, heç nə sınmır. - Dual write. Kodu yeniləyin: hər iki sütuna yazsın, hələ də
name-dən oxusun. - Backfill. Köhnə sətirləri hissə-hissə, database-i boğmadan
full_name-ə köçürün. - Oxumanı keçirin. Kod
full_name-dən oxusun, amma hər iki sütuna yazmağa davam etsin. Problem çıxsa, geri qayıtmaq təhlükəsizdir, çünkinamehələ aktualdır. - Köhnəyə yazmağı dayandırın. Köhnə versiyanın heç bir instance-ı qalmadığına əmin olandan sonra.
- Contract. Bir müddət gözləyib
namesütununu silin. Yalnız bu addım geri qaytarılmır.
Bir ad dəyişikliyi üçün altı deploy çox görünür, amma alternativ maintenance pəncərəsidir. Eyni pattern API field-ləri və queue mesaj formatları üçün də işləyir.
Chaos engineering: bərpanın işlədiyini yoxlamaq
Ch07-də failover-i, ch11-də timeout, circuit breaker və bulkhead-i dizayn etdik. Onların real failure zamanı işləyəcəyini hardan bilirik? Heç vaxt işə düşməyən failover adətən ilk dəfə lazım olanda sınır.
Chaos engineering bu sualı eksperimentlə yoxlayır. Məqsəd "production-da sındırmaq" deyil, intizamlı eksperimentdir:
- Steady state. Sistemin normal halını SLI ilə təyin edin: "checkout uğur faizi 99.9%-dən yuxarıdır."
- Hipotez. "Bir AZ itəndə steady state pozulmayacaq."
- Kiçik blast radius. Bir instance ilə, staging-də, sonra production traffic-inin kiçik hissəsində başlayın. Eksperimenti dərhal dayandırmaq üçün abort şərti olsun.
- Öyrənmə. Hipotez təsdiqlənmirsə, real outage-dən əvvəl zəif nöqtə tapılıb.
Başlamağın ən ucuz yolu game day-dir: komanda planlı şəkildə bir failure ssenarisini canlandırır, məsələn database primary-ni söndürür, və alert-lərin, runbook-ların, failover-in necə işlədiyini birlikdə izləyir. Şərt yaxşı observability-dir: nə baş verdiyini görə bilmirsinizsə, eksperiment yox, sadəcə outage etmiş olursunuz. Bu mövzuya observability fəslində qayıdacağıq.
Hazırkı sisteminiz haqqında suallar
- Son ay neçə dəfə deploy etdiniz və neçəsi rollback və ya hotfix tələb etdi? Lead time-ınızın ən uzun hissəsi hansı mərhələdir?
- Səhv build production-a çatsa, istifadəçilərin neçə faizi onu görəcək və rollback neçə dəqiqə çəkəcək?
- Kodunuzda neçə feature flag var? Ən köhnəsi nə vaxt yaradılıb və onu kim silməlidir?
- Failover və ya circuit breaker-lərinizdən hansı son dəfə qəsdən test olunub? Heç biri test olunmayıbsa, ilk game day üçün hansı ssenarini seçərdiniz?