Jak jsme se dostali při nasazení na nula chyb 502
Při každém nasazení backendu Mythexu několik požadavků selhalo s 502 Bad Gateway. Nebylo jich mnoho, ale 502 během nasazení znamená, že něčí kliknutí nic neudělalo, nebo se build, který sledoval, na chvíli zasekl. Vystopovali jsme to ke dvěma samostatným problémům: k samoléčícímu watchdogu, který s nasazeními soupeřil, a k mezeře mezi tím, kdy server přestal naslouchat, a kdy load balancer přestal posílat provoz. Přes tři po sobě jdoucí produkční nasazení po opravách počet klesl z 10 na 6 a pak na 0.
Nastavení
Naše API a orchestrátor běží jako kontejnery na malé skupině serverů za AWS Application Load Balancerem (ALB). Nasazení aktualizuje jeden server najednou: vyprázdní staré kontejnery, spustí nové a jde dál. Watchdog na každém serveru kontroluje, že kontejnery běží, a restartuje cokoli, co neběží – existuje proto, aby se spadlý proces ve 3 ráno vrátil bez toho, aby někdo musel vstávat.
Oba jsou rozumné samy o sobě. Dohromady rozumné nebyly.
Problém 1: watchdog závodil s nasazením
Watchdog běžel jednou za minutu a „léčil“ po jediné neúspěšné kontrole zdraví. Nasazení záměrně vyprazdňuje služby až na 150 sekund – během nichž má kontrola zdraví správně selhávat. Watchdog tedy zasahoval při každém nasazení.
Většinou prohrál závod neškodně. Jednou vyhrál: přepsal compose soubor (popis toho, které kontejnery mají běžet) uprostřed nasazení a nechal server bez jakéhokoli gateway kontejneru – zatímco úloha nasazení hlásila úspěch.
Opravy:
- Jeden zámek. Nasazení nyní bere stejný zámek souboru jako bootstrap skript serveru, takže watchdog a nasazení nikdy nemohou běžet současně.
- Čtyři údery, ne jeden. Watchdog potřebuje čtyři po sobě jdoucí neúspěšné kontroly, než zasáhne. Vyprazdňovaná služba už nevypadá jako mrtvá.
- Jedna definice. Compose soubor má nyní jediný zdroj, publikovaný na servery, místo kopií, které se mohly rozejít.
- Ověřovat, ne věřit. Úloha nasazení už neuspěje jen proto, že příkaz vrátil výsledek. Před úspěchem zkontroluje API, orchestrátor, gateway a publikační worker na každém serveru.
Problém 2: server odešel dřív, než provoz
Druhý problém byl tišší. Když nasazení vyprazdňuje server, začne jeho zdravotní endpoint odpovídat 503, aby ho load balancer vyřadil z provozu. Ten to dělal 5 sekund, pak se vypnul.
ALB ale kontroloval zdraví jen občas a potřeboval několik neúspěchů po sobě, než přestal směrovat na cíl – až asi 60 sekund celkem. Takže zhruba 55 sekund load balancer posílal skutečné požadavky serveru, který už přestal naslouchat. Tyto požadavky byly naše 502.
Oprava spočívala v tom, aby se dvě časové osy shodovaly:
- Cílová skupina nyní kontroluje každých 5 sekund a cíl označí za nezdravý po 2 neúspěších – asi 10 sekund na zjištění.
- Vyprazdňování obsluhuje skutečný provoz ještě 15 sekund poté, co začne selhávat zdravotní kontrola, takže se vždy překrývá.
- Tato nastavení žijí ve skriptu, který infrastrukturu zřizuje, ne v konzoli, kterou kdosi jednou naklikal.
Držet čísla pohromadě
Časové limity tohoto druhu na sobě závisejí. Vyprazdňování musí trvat déle, než load balancer potřebuje na zjištění; vyprazdňování plus vypnutí musí skončit dřív, než je kontejner násilně ukončen. Snadno se může stát, že někdo změní jedno číslo za šest měsíců a tiše znovu zavede chybu.
Proto jsme ty vztahy zapsali jako testy: vyprazdňování musí být delší než interval kontroly krát práh selhání; čas do opětovného označení za zdravý musí zůstat krátký; celé vyprazdňování se musí vejít do grace periody zastavení kontejneru. Změníte-li jedno číslo bez ostatních, CI spadne. Testy samotné jsme také otestovali mutacemi – každé číslo jsme změnili na špatnou hodnotu a ověřili, že to test chytí.
Měření nasazení je snadno špatně
Naše první měření říkalo, že čisté nasazení je rozbité z asi 3 %. Nebylo. Počítali jsme každou odpověď, která nebyla 200, a 503 ze zdravotního endpointu během vyprazdňování není selhání – je to vyprazdňování, které dělá svou práci, a říká load balanceru, ať na tento server nevybírá, zatímco dál obsluhuje skutečné požadavky.
To, co uživatel pocítí, je 502: požadavek nedosáhl ničeho. Počítání jen těchto dalo skutečný obraz – 10, pak 6, pak 0 přes tři produkční nasazení.
Co jsme si z toho odnesli
- Samoléčení potřebuje vědět o plánovaném výpadku. Watchdog, který nerozliší nasazení od pádu, nakonec s nasazením začne bojovat.
- Vyprazdňování je handshake. Server musí obsluhovat, dokud load balancer prokazatelně nepřestane posílat provoz, a ten čas nastavuje balancer, ne server.
- Invarianty zapisujte jako testy. Provozní čísla se rozcházejí. Testy, které je vztahují k sobě navzájem, ne.
- Rozhodněte, co měříte, dřív než měříte. „Chyby“ byla špatná metrika; „požadavky, které nedosáhly ničeho“ byla správná.
Pokud publikujete aplikaci na Mythexu, nic z toho pro vás není vidět – a o to jde. Související: jak váš publikovaný web zůstává online i během opětovného publikování.