Jedného dňa sme počas plánovanej aktualizácie klastra k8s zistili, že takmer všetky naše PODy (približne 500 z 1 000) na nových uzloch sa nedali spustiť a minúty sa rýchlo zmenili na hodiny. Aktívne pátrame po hlavnej príčine, ale po troch hodinách boli PODS stále v stave ContainerCreating
.
Našťastie to nebolo produkčné prostredie a obdobie údržby bolo naplánované na víkend. Mali sme čas na prešetrenie problému bez akéhokoľvek tlaku.
Kde by ste mali začať hľadať hlavnú príčinu? Chceli by ste sa dozvedieť viac o riešení, ktoré sme našli? Pripútajte sa a užívajte si!
Problém bol v tom, že sme mali veľké množstvo obrázkov dockerov, ktoré bolo potrebné stiahnuť a spustiť na každom uzle v klastri súčasne. Dôvodom bolo, že viacero súbežných stiahnutí obrazu dokovacieho zariadenia na jednom uzle môže viesť k vysokému využitiu disku a predĺženiu doby studeného štartu.
Procesu CD trvá z času na čas až 3 hodiny, kým sa stiahnu obrázky. Tentoraz sa to však úplne zaseklo, pretože množstvo PODS počas upgradu EKS (inline, keď vymeníme všetky uzly v klastri) bolo príliš vysoké.
Všetky naše aplikácie fungujú v k8s (založené na EKS ). Aby sme ušetrili naše náklady na DEV env, používame spotové inštancie.
Pre uzly používame obraz AmazonLinux2 .
Vo vývojovom prostredí máme veľké množstvo funkčných pobočiek (FB), ktoré sú neustále nasadzované do nášho klastra Kubernetes. Každý FB má svoju vlastnú sadu aplikácií a každá aplikácia má svoju vlastnú sadu závislostí (vo vnútri obrázka).
V našom projekte je takmer 200 aplikácií a toto číslo rastie. Každá aplikácia používa jeden zo 7 základných obrázkov doku s veľkosťou ~2 GB. Maximálna celková veľkosť archivovaného obrázka (v pokladnici ) je približne 3 GB.
Všetky obrázky sú uložené v registri Amazon Elastic Container Registry (ECR).
Pre uzly používame predvolený typ zväzku gp3 EBS.
Predĺžený čas studeného štartu: Spustenie nového modulu s novým obrázkom môže trvať viac ako 1 hodinu, najmä ak sa na jednom uzle vytiahne viacero obrázkov súčasne.
Chyby ErrImagePull: Časté ErrImagePull
alebo uviaznutie v stave ContainerCreating
, čo naznačuje problémy s načítaním obrázka.
Vysoké využitie disku: Využitie disku zostáva počas procesu sťahovania obrazu takmer 100 %, predovšetkým kvôli intenzívnym vstupom/výstupom disku potrebným na dekompresiu (napr. „unpigz“).
Problémy s DaemonSet systému: Niektoré systémové DaemonSets (ako aws-node
alebo ebs-csi-node
) sa presunuli do stavu „nepripravený“ kvôli tlaku disku, čo má vplyv na pripravenosť uzla.
Žiadna vyrovnávacia pamäť obrázkov na uzloch: Pretože používame bodové inštancie, nemôžeme použiť lokálny disk na ukladanie obrázkov do vyrovnávacej pamäte.
To vedie k mnohým zastaveným nasadeniam na vetvách funkcií, najmä preto, že rôzne FB majú rozdielne sady základných obrázkov.
Po rýchlom skúmaní sme zistili, že hlavným problémom bol tlak disku na uzly procesom unpigz
. Tento proces je zodpovedný za dekompresiu obrázkov doku. Predvolené nastavenia pre typ hlasitosti gp3 EBS sme nemenili, pretože to nie je vhodné pre náš prípad.
Ako prvý krok sme sa rozhodli znížiť počet PODov na uzloch.
Hlavnou myšlienkou riešenia je zahriať uzly pred spustením procesu CD najväčšou časťou obrazu dockeru (vrstva závislostí JS), ktorá sa používa ako koreňový obraz pre všetky naše aplikácie. Máme aspoň 7 typov koreňových obrázkov so závislosťami JS, ktoré súvisia s typom aplikácie. Poďme teda analyzovať pôvodný dizajn CI/CD.
V našom potrubí CI/CD máme 3 piliere:
Originálny kanál CI/CD:
V kroku Init
it: pripravíme prostredie/premenné, definujeme sadu obrázkov na prebudovanie atď...
V kroku Build
: vytvoríme obrázky a pošleme ich do pokladne
V kroku Deploy
: nasadíme obrázky do k8 (aktualizácia nasadení atď.)
Viac podrobností o pôvodnom dizajne CICD:
main
pobočky. V procese CI vždy analyzujeme množinu obrázkov, ktoré boli zmenené na FB a prestavujeme ich. main
vetva je vždy stabilná, pretože definícia by mala byť vždy najnovšia verzia základných obrázkov.Existujú požiadavky na proces zahrievania.
Povinné:
ContainerCreating
.Je pekné mať vylepšenia:
Po analýze požiadaviek a obmedzení sme sa rozhodli implementovať proces zahrievania, ktorý by predhrieval uzly so základnými obrázkami vyrovnávacej pamäte JS. Tento proces by sa spustil pred spustením procesu CD, čím sa zabezpečí, že uzly sú pripravené na nasadenie FB a máme maximálnu šancu zasiahnuť do vyrovnávacej pamäte.
Toto zlepšenie sme rozdelili do troch veľkých krokov:
Vytvorte množinu uzlov (skupinu virtuálnych uzlov) pre každý FB
Pridajte základné obrázky do skriptu cloud-init pre nové uzly
Pridajte krok pred nasadením na spustenie DaemonSet so sekciou initContainers
, aby ste si stiahli potrebné obrazy dokovacích staníc do uzlov pred spustením procesu CD.
Vytvorte novú množinu uzlov pre každý FB prostredníctvom volania API (do systému automatického škálovania tretej strany) z nášho kanála CI.
Vyriešené problémy:
Izolácia : Každý FB má svoj vlastný súbor uzlov, ktorý zabezpečuje, že prostredie nie je ovplyvnené inými FB.
Flexibilita : Môžeme ľahko zmeniť typ uzla a jeho životnosť.
Efektivita nákladov : Uzly môžeme vymazať ihneď po vymazaní FB.
Transparentnosť : Môžeme ľahko sledovať využitie a výkon uzlov (každý uzol má značku súvisiacu s FB).
Efektívne využitie inštancií spotu : Inštancia spotu začína s už preddefinovanými základnými obrázkami, to znamená, že po spustení bodového uzla sú na uzle už základné obrázky (z hlavnej vetvy).
Stiahnite si všetky základné obrázky JS z hlavnej vetvy do nových uzlov pomocou cloud-init
skriptu.
Zatiaľ čo sa obrázky sťahujú na pozadí, proces CD môže pokračovať v vytváraní nových obrázkov bez akýchkoľvek problémov. Okrem toho budú ďalšie uzly (ktoré budú vytvorené systémom automatického škálovania) z tejto skupiny vytvorené s aktualizovanými údajmi cloud-init
, ktoré už majú pokyny na stiahnutie obrázkov pred spustením.
Vyriešené problémy:
Riešenie problému : Tlak na disk je preč, pretože sme aktualizovali skript cloud-init
pridaním sťahovania základných obrázkov z hlavnej pobočky. To nám umožňuje trafiť cache pri prvom spustení FB.
Efektívne využitie inštancií spotu : Inštancia spotu začína s aktualizovanými údajmi cloud-init
. To znamená, že po spustení bodového uzla sú na uzle už základné obrázky (z hlavnej vetvy).
Vylepšený výkon : Proces CD môže pokračovať v vytváraní nových obrazov bez akýchkoľvek problémov.
Táto akcia pridala ~17 sekúnd (volanie API) do nášho kanála CI/CD.
Táto akcia dáva zmysel len prvýkrát, keď spustíme FB. Nabudúce nasadíme naše aplikácie do už existujúcich uzlov, ktoré už majú základné obrázky, ktoré sme dodali pri predchádzajúcom nasadení.
Tento krok potrebujeme, pretože obrázky FB sa líšia od obrázkov hlavnej pobočky. Pred spustením procesu CD musíme stiahnuť základné obrázky FB do uzlov. Pomôže to zmierniť predĺžené časy studeného štartu a vysoké využitie disku, ktoré môže nastať, keď sa súčasne stiahne viacero ťažkých obrazov.
Ciele kroku pred nasadením
Zabráňte tlaku disku : Postupne sťahujte najťažšie obrázky dokovacieho zariadenia. Po kroku init-deploy už máme základné obrázky na uzloch, čo znamená, že máme veľkú šancu na nájdenie cache.
Zlepšite efektivitu nasadenia : Zaistite, aby boli uzly predhriate základnými obrázkami dokovacieho zariadenia, čo vedie k rýchlejšiemu (takmer okamžite) spusteniu zariadenia POD.
Vylepšenie stability : Minimalizujte pravdepodobnosť výskytu chýb ErrImagePull
/ ContainerCreating
a zabezpečte, aby sady systémových démonov zostali v stave „pripravenosti“.
V rámci tohto kroku pridáme k procesu CD 10–15 minút.
Podrobnosti o kroku pred nasadením:
initContainers
.initContainers
sa spustí pred spustením hlavného kontajnera, čím sa zabezpečí, že sa potrebné obrázky stiahnu pred spustením hlavného kontajnera.Porovnanie pôvodných a aktualizovaných krokov s procesom predhrievania.
Krok | Krok nasadenia | Krok pred nasadením | Nasadiť | Celkový čas | Dif |
---|---|---|---|---|---|
Bez predohrevu | 0 | 0 | 11 m 21 s | 11 m 21 s | 0 |
S predhrievaním | 8 sekúnd | 58 sekúnd | 25 sekúnd | 1 m 31 s | -9m 50s |
Hlavná vec je, že čas „Deploy“ sa zmenil (z prvého príkazu na použitie do stavu Spustenia modulov) z 11 m 21 s na 25 sekúnd. Celkový čas sa zmenil z 11m 21s na 1m 31s.
Dôležitý bod, ak neexistujú žiadne základné obrázky z hlavnej vetvy, čas „nasadenia“ bude rovnaký ako pôvodný čas alebo o niečo viac. Ale aj tak sme vyriešili problém s tlakom disku a časom studeného štartu.
Hlavný problém ContainerCreating
bol vyriešený procesom zahrievania. Ako výhodu sme výrazne skrátili čas studeného štartu PODov.
Tlak disku bol preč, pretože už máme základné obrázky na uzloch. Systémové sady démonov sú v „pripravenom“ a „zdravom“ stave (pretože nie je žiadny tlak na disk) a nezaznamenali sme žiadne chyby ErrImagePull
súvisiace s týmto problémom.
PS: Chcel by som poďakovať skvelému technickému tímu v Justt ( https://www.linkedin.com/company/justt-ai ) za neúnavnú prácu a skutočne kreatívny prístup k akémukoľvek problému, ktorému čelia s Najmä pokrik Ronnymu Sharabymu, vynikajúcemu lídrovi, ktorý je zodpovedný za skvelú prácu, ktorú tím odvádza. Teším sa na ďalšie a ďalšie skvelé príklady toho, ako vaša kreativita ovplyvňuje produkt Justt.