Ako sme dostali nasadenia na nula chýb 502
Pri každom nasadení backendu Mythex zlyhalo niekoľko požiadaviek s 502 Bad Gateway. Nebolo ich veľa — ale 502 počas nasadenia znamená, že klik niekoho neurobil nič alebo sa na chvíľu zasekol build, ktorý niekto sledoval. Vysledovali sme to k dvom samostatným problémom: samoopravný watchdog, ktorý bojoval proti nasadeniam, a medzera medzi tým, kedy server prestal počúvať, a kedy load balancer prestal posielať prevádzku. Počas troch po sebe nasledujúcich produkčných nasadení po opravách sa počet znížil z 10 na 6 a potom na 0.
Nastavenie
Naše API a orchestrátor bežia ako kontajnery na malej skupine serverov za AWS Application Load Balancer (ALB). Nasadenie aktualizuje jeden server naraz: vyprázdni staré kontajnery, spustí nové a pokračuje ďalej. Na každom serveri beží watchdog, ktorý kontroluje, či sú kontajnery spustené, a reštartuje všetko, čo nebeží — existuje preto, aby sa zrútený proces o tretej ráno vrátil bez toho, aby sa niekto musel zobudiť.
Obe veci sú samy o sebe rozumné. Spolu však nefungovali.
Problém 1: watchdog súťažil s nasadením
Watchdog bežal raz za minútu a na jedinom neúspešnom health checku „liečil“. Nasadenie zámerne vyprázdňuje služby až na 150 sekúnd — počas tejto doby má health check zámerne zlyhávať. Watchdog sa tak spustil počas každého jedného nasadenia.
Väčšinou prehral súboj neškodne. Raz zvíťazil: prepísal compose súbor (popis toho, ktoré kontajnery majú bežať) uprostred nasadenia a nechal server bez akéhokoľvek gateway kontajnera — pričom deployment job ohlásil úspech.
Opravy:
- Jeden zámok. Nasadenie teraz berie rovnaký súborový zámok ako bootstrap skript servera, takže watchdog a nasadenie nikdy nemôžu bežať naraz.
- Štyri údery, nie jeden. Watchdog potrebuje štyri po sebe idúce neúspešné kontroly, kým zasiahne. Vyprázdňovaná služba už nevyzerá ako mŕtva.
- Jedna definícia. Compose súbor má teraz presne jeden zdroj, publikovaný na servery, namiesto kópií, ktoré sa mohli rozísť.
- Overovať, nie dôverovať. Deployment job už neuspeje len preto, že príkaz vrátil výsledok. Pred úspechom skontroluje API, orchestrátor, gateway a publish worker na každom serveri.
Problém 2: server odišiel skôr než prevádzka
Druhý problém bol tichší. Keď nasadenie vyprázdňuje server, server začne na svoj health endpoint odpovedať 503, aby load balancer odstránil server z rotácie. Ten to robil 5 sekúnd a potom sa vypol.
ALB však kontroluje zdravie len v pravidelných intervaloch a pred tým, než prestane smerovať na cieľ, potrebuje niekoľko neúspešných kontrol za sebou — celkovo asi 60 sekúnd. Takže približne 55 sekúnd load balancer posielal skutočné požiadavky serveru, ktorý už prestal počúvať. Tie boli naše 502.
Oprava spočívala v tom, aby sa tieto dve časové osi zhodovali:
- Target group teraz kontroluje každých 5 sekúnd a označí cieľ ako nezdravý po 2 neúspechoch — približne do 10 sekúnd.
- Vyprázdnenie ďalej obsluhuje skutočnú prevádzku 15 sekúnd potom, čo začne zlyhávať health checky, takže vždy existuje prekrytie.
- Tieto nastavenia sú v skripte, ktorý pripravuje infraštruktúru, nie v konzole, ktorú niekto raz klikol.
Aby čísla držali pohromade
Časové limity ako tieto na sebe závisia. Vyprázdnenie musí trvať dlhšie, ako balancer potrebuje na zistenie problému; vyprázdnenie plus vypnutie musí skončiť skôr, než je kontajner násilne ukončený. Ľahko sa môže stať, že niekto o šesť mesiacov zmení jedno číslo a nenápadne znovu zavedie túto chybu.
Preto sme tieto vzťahy zapísali ako testy: vyprázdnenie musí byť dlhšie ako interval health checku násobený prahom neúspechov; čas na opätovné označenie za zdravý musí zostať krátky; celé vyprázdnenie sa musí zmestiť do grace periódy zastavenia kontajnera. Zmeníte jedno číslo bez ostatných a CI zlyhá. Samotné testy sme tiež mutačne otestovali — zmenili sme každé číslo na nesprávnu hodnotu a overili, že ho test zachytí.
Meranie nasadenia sa ľahko pokazí
Naše prvé meranie hovorilo, že čisté nasadenie je rozbité asi na 3 %. Nebolo. Počítali sme každú odpoveď inú ako 200, ale 503 z health endpointu počas vyprázdňovania nie je chyba — je to vyprázdňovanie, ktoré robí svoju prácu: hovorí balanceru, aby si tento server nevyberal, kým stále obsluhuje skutočné požiadavky.
Čo používatelia pociťujú, je 502: požiadavka nedosiahla nič. Počítanie iba týchto dalo skutočný obraz — 10, potom 6, potom 0 počas troch produkčných nasadení.
Čo sme si z toho odniesli
- Samoopravné systémy musia vedieť o plánovanom výpadku. Watchdog, ktorý nevie rozlíšiť nasadenie od zrútenia, sa nakoniec pustí do boja s nasadením.
- Vyprázdňovanie je handshake. Server musí obsluhovať, kým load balancer dokázateľne neprestane posielať prevádzku, a toto časovanie sa nastavuje na balancere, nie na serveri.
- Invarianty zapisujte ako testy. Prevádzkové čísla sa časom rozchádzajú. Testy, ktoré ich vzájomne spájajú, nie.
- Rozhodnite, čo meriate, skôr než začnete merať. „Chyby“ boli zlá metrika; „požiadavky, ktoré nedosiahli nič“ bola správna.
Ak publikujete aplikáciu na Mythex, nič z toho nevidíte — a v tom je zmysel. Súvisiace: ako vaša publikovaná aplikácia zostáva dostupná počas opätovného publikovania.