Postupné nasazování a testování aplikací na lidech - kanárci, A/B, green/blue na příkladu kadeřníka

Představte si, že jste kadeřník a pořídil si přes Internet nějakou novou speciální barvu, která je lepší, krásnější, levnější, jednodušší, lesklejší a tak podobně. Můžete dnes ráno otevřít a aplikovat ji každému zákazníkovi. To je ale trochu riskantní - co když ta pochybná barva vlasy zničí? Tak asi provedeme nejdříve nějaký test na neživém, ale i tak by byla opatrnost na místě. V software je to podobné - dnes chci mluvit o canary release, A/B testing a green/blue nasazování a příště si vyzkoušíme některé implementace - App Service, Flagger v Kubernetes (s NGINX Ingress nebo Istio), implementace v rámci CI/CD s Azure DevOps.

Kadeřník a kanárci, A/B testing a green/blue

Vraťme se k příkladu kadeřníka a jeho nové, skvělé, ale trochu pochybné barvy. Samozřejmě ji nenasadíme hned živému zákazníkovi, ale použijeme testovacího panáka (naše testovací prostředí). Tam to vypadá dobře, ale přecijen jisté to není. Zákazníci jsou hodně variabilní, mají mnoho typů vlasů, každý může reagovat jinak. Zkrátka v produkci nás vždycky může překvapit scénář, s kterým jsme v testu nějak nepočítali.

První možností co s tím dál je canary release, tedy v průběhu dne si vyberu 5% zákazníků a těm dám novou barvu. Mohl bych trvdit, že stačí dát prvnímu a když to bude dobré, dávat i dalším, ale to není dobrý nápad. Barva nějakou dobu zraje a výsledek ve formě vypadaných vlasů se nedostaví ihned. Na vyhodnocení tedy potřebuji nějaký čás, třeba pár dní. Určitě potřebuji “sticky session”, takže když se u někoho rozhodnu pro novou barvu, dávam mu ji na celou hlavu a u koho zůstávám u staré, musím pořád sahat po staré barvě a ne mu na levou stranu lebky máznout trochu té nové. Jinak řečeno chci nasadit novou verzi aplikace a zajistit, že jen určité procento uživatelů pošlu na ní a současně z ní sbírám telemetrii a vyhodnocuji, jestli je vše OK (nevyrostla nadměrně latence s novou verzí nebo nevrací to teď častěji chybu?). Pokud se všechno zdá opravdu dobré, příští týden budu dávat barvu už 10% zákazníků a pokud nedojde ke katastrofě do měsíce přejdu jen na tu novou. V software mi chodí asi víc zákazníků denně, než do kadeřnictví a vzhledem k zátěži se také chyby projeví dříve, takže pravděpodobně nebudu pracovat ve dnech, ale spíš minutách či desítkách minut - pokud je vše OK, přisypu 5% třeba každou minutu.

Šlo by to udělat i jinak. Nová barva je riziko a někteří zákazníci ho neradi, ale jiným nevadí. Třeba mám zákazníky, kteří rádi experimentují a zcela dobrovolně si nechají novou barvu dát? Nebo to nedělají tak úplně zadarmo, ale mají slevu za to, že jsou pokusnými králíky. No a třeba je to taky tak, že mám kolegu kadeřníka a jsme domluveni, že tyhle věci si zkoušíme vzájemně na sobě. To by bylo A/B testování. Chci vyzkoušet novou barvu (verzi B) a vím přesně komu ho chci naservírovat. Zákazníkům se zaškrtnutým insiders nastavením, placeným testerům, svým vlastním zaměstnancům a tak podobně. Technicky to typicky vyřeším tak, že při komunikaci s webem nebo API bude klient posílat zvláštní header nebo cookie. Jinak je postup stejný - sbírám telemetrii a vyhodnocuji, jestli je všechno v pořádku a pokud ano, později to naroluji všem.

Představme si, že barva se musí vždycky namíchat a já mám jen jednu nádobu. Musím si tedy rozmíchat starou verzi a když chci přejít na novou, tak nádobu umýt a namixovat novější verzi a protože to pár minut trvá, poslat zákazníky mezitím na lavičku číst si časopisy. Pak je znovu posadím do křesla, zjistím, že se mi ta nová barva nepovedla a že to ani vůbec nejde na hlavu dát, takže je pošlu zpět a jdu míchat zase tu starou barvu. Takhle vypadá tradiční nasazování aplikace. Green/Blue deployment spočívá v tom, že si pořídím ještě druhou nádobu a namíchám starou i novou barvu současně. Beru tu starou a když se rozhodnu přejít na novou, jen ji začnu používat, nemixuji a nemám dlouhý výpadek. Když se potřebuji rychle vrátit k původní verzi, stále ji mám připravenou, takže i to udělám rychle. Samozřejmě to funguje dokonale pro bezestavové aplikace, s perzistencí je to složitější (například pokud migruji schéma databáze mezi verzemi), ale v moderním vývoji můžu mít potřebu nasazovat několikrát týdně a pokud pokaždé měním schéma databáze, tak bych se zamyslel, jestli nedělám něco špatně. Zkrátka green/blue deployment může být dobrá strategie pro minimalizaci výpadku při nasazování třeba alespoň pro většinu případů, když ne pro všechny.

Příklady implementací v Azure

V příštích článcích si vyzkoušíme řešení jedno podruhém, ale dnes zkusme rámcový pohled na pár možností.

Azure Application Services (WebApp)

První variantou ideální pro webové aplikace je platformní služba (PaaS) a její vlastnost Deployment Slots. Ty defacto znamenají přidání dalších nádob na barvu, což lze mimo jiné použít i pro budování vývojářských a testovacích protředí. Nás ale v kontextu dnešního článku zajímají až ty produkční, kdy jedno bude produkce (aktuální verze) a druhý slot, například s názvem prod-staging, bude nová verze. Ty už koukají do stejné datové perzistence, takže obě jsou vlastně produkční. Funkce “testing in production” je právě canary release. Můžu říct, že chci 5% uživatelů posílat na tuto verzi. Další funkce je přehození “predzahřátých” slotů, tedy green/blue deployment. Nová verze aplikace se v prod-staging slotu rozbalí, nainstaluje tak, jako se rozmíchá barva. Samotné překlopení na novou verzi je tak jen překopení slotů a restart procesu, tedy téměř bezvýpadkový scénář. A/B testing tady je možný v podobě rozdílných URL - oba sloty jsou živé a mají jiné URL. Je to jiné řešení, než tradičnější header nebo cookie, ale jako A/B test může posloužit.

Kubernetes a mikroslužby

To co je v PaaS na tlačítko, najdete v kontejnerových orchestrátorech jako je Azure Kubernetes Service taky a to mocnější a flexibilnější, ale daní je vyšší složitost nastavení - zkrátka není klikačka. Kubernetes samotný má objekt Deployment, který je schopen udělat rolling upgrade, ale nesplňuje složitější požadavky, které bych na to měl - canary podle procent (ne počtu replik), vyhodnocování telemetrie, A/B testing. Půjdeme na to jinak a budeme potřebovat dvě věci. Tou první je něco na data plane, ideálně L7 balancer (reverse proxy). Toho můžeme dosáhnout například s NGINX Ingress, což je jednoduché a efektivní pro API vystavené ven. Pokud máme potřebu řešit kanárky i mezi mikroslužbami uvnitř clusteru (tedy ty, které mluví napřímo vnitřkem), můžeme se vydat cestou Service Mesh, což je taky reverse proxy (ale místo proxy na vstupu do clusteru je to proxy u každé instance mikroslužby). K tomu by to chtělo nějaké řízení. To v Kubernetes dělá Flagger (nadstavbový operátor). Ten dokáže automatizovat celý proces. Definujete s ním jestli jde o canary release, A/B testing nebo green/blue. Flagger kromě toho poslouchá na telemetrii, kterou mu řeknete - například podíl odpovědí OK (200) a chyba (500). Pokud je chybovost menší jak 99% procent, roluj dál (třeba 5% každou minutu) nebo pokud je latence nové verze menší než 500ms, roluj dál. Kromě toho dokáže posílat webhook do externích gate systémů a integrovat se s nějakým dalším nástrojem - to může být cokoli, například jestli jsou k této nové verzi hlášeny incidenty, přišly crash reporty a tak podobně.

CI/CD nástroj jako je Azure DevOps

V Kubernetes jsem mluvil o tom, že potřebuji jednak něco na úrovni dataplane (třeba Ingress, který dokáže definovat procento kanárka nebo header pro A/B test) a pak řízení celého procesu (mluvil jsem o Flagger). Potřebujeme schopnost ovládat data plane, vyhodnocovat telemetri a gate a podle toho měnit procenta, případně proces ukončit (překlopit se jen na novou verzi nebo naopak rollback na starou). Tohle se dá řídit z Azure DevOps a potenciálně tím ovládat různé platformy - PaaS, kontejnery, IaaS, serverless.

Mnoho zdaru u nasazování aplikací a vašich návštěv kadeřníka. Příště si některé varianty vyzkoušíme prakticky.



Potřebujete v rámci ARM šablony spouštět nějakou pokročilou logiku? Zkuste ARM deployment scripts. Automatizace
Co se chystá ARM šablona udělat s vaším prostředím? Použijte what if. Automatizace
SLA a ceny pro Azure Kubernetes Service vs. EKS a GKE Kubernetes
Privátní leč cenově dostupná WebApp díky Private Link pro App Service v Azure AppService
Kubernetes praticky: DAPR a telemetrie, logy i distribuovaný tracing Kubernetes Kontejnery