Kaip pasiekėme, kad diegimai neturėtų 502 klaidų
Kiekvieną kartą diegdami Mythex backend, keli užklausos nutrūkdavo su 502 Bad Gateway. Ne daug — bet diegimo metu 502 reiškia, kad kažkieno paspaudimas nieko nepadarė arba build, kurį jie stebėjo, akimirkai sustojo. Problemą atsekėme iki dviejų atskirų dalykų: savaime gydančio sargiklio, kuris kovojo su mūsų diegimais, ir tarpo tarp to, kada serveris nustojo klausytis, ir to, kada apkrovos balansuotojas nustojo siųsti jam srautą. Trijuose iš eilės gamybiniuose diegimuose po pataisymų skaičius sumažėjo nuo 10 iki 6 ir galiausiai iki 0.
Sąranka
Mūsų API ir orkestratorius veikia kaip konteineriai nedidelėje serverių grupėje už AWS Application Load Balancer (ALB). Diegimas atnaujina po vieną serverį: nuleidžia senus konteinerius, paleidžia naujus ir pereina prie kito. Sargiklis kiekviename serveryje tikrina, ar konteineriai veikia, ir perkrauna bet kurį, kuris neveikia — jis egzistuoja tam, kad 3 val. nakties sugedęs procesas grįžtų be kieno nors pažadinimo.
Abu šie dalykai atskirai yra pagrįsti. Kartu — ne.
1 problema: sargiklis lenktyniavo su diegimu
Sargiklis veikė kartą per minutę ir „gydė“ po vieno nepavykusio sveikatos patikrinimo. Diegimas tyčia nuleidžia paslaugas iki 150 sekundžių — per tą laiką sveikatos patikrinimas turi nepavykti. Taigi sargiklis suveikdavo kiekvieno diegimo metu.
Dažniausiai jis pralaimėdavo lenktynes be žalos. Kartą jis laimėjo: viduryje diegimo perrašė compose failą (aprašą, kurie konteineriai turi veikti) ir paliko serverį be jokio šliuzo konteinerio — o diegimo darbas pranešė apie sėkmę.
Pataisymai:
- Vienas užraktas. Diegimas dabar paima tą patį failo užraktą kaip serverio bootstrap scenarijus, todėl sargiklis ir diegimas niekada nevyksta vienu metu.
- Keturi įspėjimai, o ne vienas. Sargiklis reikalauja keturių iš eilės nepavykusių patikrinimų prieš veikdamas. Nuleidžiama paslauga nebeatrodo kaip mirusi.
- Vienas apibrėžimas. Compose failas dabar turi vieną šaltinį, paskelbtą serveriams, o ne kopijas, kurios galėtų nesutapti.
- Tikrinkite, nepasitikėkite. Diegimo darbas nebepraeina tik todėl, kad komanda grąžino kodą. Prieš pavykdamas jis patikrina kiekvieno serverio API, orkestratoriaus, šliuzo ir publikavimo darbuotojo veikimą.
2 problema: serveris išėjo anksčiau nei srautas
Antroji problema buvo tylesnė. Kai diegimas nuleidžia serverį, serveris savo sveikatos galiniam taškui pradeda atsakyti 503, kad apkrovos balansuotojas jį išimtų iš eismo. Mūsų serveris taip darė 5 sekundes, tada išsijungdavo.
Bet ALB sveikatą tikrino tik retkarčiais ir reikalavo kelių nepavykusių patikrinimų iš eilės, kol nustojo nukreipti į tikslą — iki maždaug 60 sekundžių nuo pradžios iki galo. Taigi maždaug 55 sekundes apkrovos balansuotojas toliau siuntė tikras užklausas serveriui, kuris jau nebeklausė. Tai ir buvo mūsų 502 klaidos.
Pataisymas — suderinti abi laiko skales:
- Tikslinė grupė dabar tikrina kas 5 sekundes ir pažymi tikslą kaip nesveiką po 2 nesėkmių — apie 10 sekundžių, kol pastebi.
- Nuleidimas toliau aptarnauja tikrą srautą 15 sekundžių po to, kai pradeda nepraeiti sveikatos patikrinimai, todėl visada lieka persidengimas.
- Šie nustatymai gyvena scenarijuje, kuris paruošia infrastruktūrą, o ne konsolėje, kurią kažkas kartą paspaudė.
Skaičių suderinimas tarpusavyje
Tokie laiko limitai priklauso vienas nuo kito. Nuleidimas turi trukti ilgiau nei balansuotojui reikia pastebėti; nuleidimas kartu su išsijungimu turi baigtis, kol konteineris priverstinai nužudomas. Lengva, kad kas nors po šešių mėnesių pakeistų vieną skaičių ir netyčia grąžintų klaidą.
Todėl tuos ryšius užrašėme kaip testus: nuleidimas turi būti ilgesnis nei sveikatos patikrinimo intervalas, padaugintas iš nesėkmių slenksčio; laikas iki vėl pažymėto sveiku turi likti trumpas; visas nuleidimas turi tilpti į konteinerio sustabdymo laukimo laiką. Pakeiskite vieną skaičių be kitų — CI nepavyksta. Patys testus išbandėme mutacijomis: kiekvieną skaičių pakeitėme į klaidingą reikšmę ir patikrinome, ar testas tai pagauna.
Diegimo matavimas lengvai suklysta
Mūsų pirmasis matavimas sakė, kad švarus diegimas buvo sugadintas maždaug 3%. Taip nebuvo. Skaičiavome kiekvieną ne 200 atsakymą, o 503 iš sveikatos galinio taško nuleidimo metu nėra nesėkmė — tai nuleidimas daro savo darbą, sakydamas balansuotojui nerinktis to serverio, kol jis toliau aptarnauja tikras užklausas.
Tai, ką jaučia vartotojai, yra 502: užklausa nepasiekė nieko. Skaičiuojant tik juos, gavome tikrą vaizdą — 10, tada 6, tada 0 per tris gamybinius diegimus.
Ką iš to pasiėmėme
- Savaime gydančiai sistemai reikia žinoti apie planuotus gedimus. Sargiklis, kuris negali atskirti diegimo nuo avarijos, galiausiai kovos su diegimu.
- Nuleidimas yra rankos paspaudimas. Serveris turi toliau aptarnauti, kol balansuotojas įrodomai nustoja siųsti srautą, o tas laikas nustatomas balansuotojyje, ne serveryje.
- Invariantus užkoduokite testais. Operaciniai skaičiai dreifuoja. Testai, siejantys juos tarpusavyje, — ne.
- Nuspręskite, ką matuojate, prieš matuodami. „Klaidos“ buvo klaidinga metrika; „užklausos, kurios nepasiekė nieko“ — teisinga.
Jei publikuojate programėlę Mythex, nieko iš to nematote — tuo ir esmė. Susiję: kaip jūsų publikuota programėlė išlieka veikianti, kol ją iš naujo publikuojate.