Nedostajuća swap datoteka koja je zamrznula naše servere
Dana 24. septembra jedan od naših produkcijskih servera prestao je odgovarati. Load balancer ga je označio kao nezdravog, a naš alat za daljinske komande nije mogao da ga dostigne, ali ništa se nije srušilo i ništa nije ubijeno zbog prevelike upotrebe memorije. Server je bio u thrashingu: bez swap prostora i uz kontejnere kojima je bilo dozvoljeno da koriste više memorije nego što mašina ima, Linux je trošio vrijeme na izbacivanje i ponovno čitanje fajlova koji su mu bili potrebni da radi, i gotovo da nije napredovao. Dodavanje swap datoteke od 2 GB na svaki server to je riješilo. Zanimljivija lekcija ticala se provjera zdravlja.
Kako je izgledalo „zamrznuto“
- Provjere zdravlja load balancera istekle su na tom serveru.
- Komande poslate kroz AWS Systems Manager ostajale su u statusu „Pending“ i nikada se nisu izvršile.
- U logovima nije bilo kill-a zbog memorije. Nijedan proces nije umro.
Sedmicu ranije preselili smo produkciju na manje ARM servere s po 2 GB RAM-a. Naš stejdžing server, još manji, zamrznuo se na isti način dok je raspakovao kontejner sliku tokom deploya.
Zašto nije bilo greške u memoriji?
Linux ubija proces samo kada zaista ostane bez memorije koju može povratiti. Prije te tačke, memoriju uzima iz page cachea, kopija fajlova koje drži u RAM-u, uključujući kod svakog pokrenutog programa.
Na našim serverima zbirna memorijska ograničenja kontejnera iznosila su oko 3,3 GB na mašini s otprilike 1,8 GB upotrebljivo. Obično ne koriste svi svoj limit istovremeno. Kada su to radili, kernel je izbacivao kod programa iz keša da napravi mjesta, a onda ga ponovo čitao s diska čim bi taj kod ponovo bio pokrenut. Taj ciklus, thrashing, može učiniti mašinu gotovo potpuno nereagujućom, a da tehnički nikada ne ostane bez memorije. Zato se ništa ne ubija, i ništa se ne oporavi.
Bez swapa, kernel nema gdje da stavi memoriju koja je alocirana ali se rijetko koristi, pa je mora uzeti iz keša.
Popravka
Skripta za bootstrap servera sada kreira swap datoteku od 2 GB s niskim swappiness podešavanjem (10) svaki put kada se server pokrene ili popravi. Nizak swappiness znači da kernel i dalje preferira držanje radne memorije u RAM-u, ali stranice kojih se rijetko dotiče mogu preći na disk umjesto da izbacuju kod programa iz keša. Primijenili smo to uživo na oba produkcijska servera i na stejdžing, a deploy pipeline ponovo objavljuje bootstrap skriptu pri svakom produkcijskom deployu, pa i zamijenjeni server to dobija.
Ono što nas je više zabrinulo: nezdravi server je ostao
Naša grupa servera koristila je EC2 provjere zdravlja, odgovor na pitanje „da li mašina radi?“, a ne provjere zdravlja load balancera, odgovor na pitanje „da li odgovara na zahtjeve?“. Tako je server kojeg je load balancer odustao od njega i dalje bio zdrav iz perspektive grupe. Nikada ne bi bio zamijenjen. Produkcija bi tiho radila na jednom serveru dok neko ne primijeti i ne restartuje drugi.
Prebacivanje grupe na provjere zdravlja load balancera zvuči kao očigledna popravka, ali za nas nije jednostavno: tokom deploya, serveri namjerno vraćaju grešku na health endpoint kako bi balancer prestao da ih koristi (pogledajte kako smo došli do nula 502 grešaka pri deployu). Grupa koja mijenja servere na osnovu tog signala mijenjala bi ih usred svakog deploya.
Zato smo za sada dodali korak u našu listu za deploy: nakon svakog deploya provjerite zdravlje svakog targeta na load balanceru, a ne samo to da li je deploy job prošao. Ako komande za server ostaju u statusu „Pending“, server thrashuje; restartujte ga, već je izvan rotacije.
Šta smo iz toga izvukli
- „Ne pada“ nije isto što i „zdrav“. Thrashing ne proizvodi grešku, samo usporavanje tako ekstremno da mašina prestane odgovarati.
- Mali serveri trebaju swap. Čak i malo, uz nizak swappiness, daje kernelu mjesto gdje može da stavi hladnu memoriju.
- Memorijski limiti čiji zbir premašuje mašinu su opklada. Ponekad je izgubite. Znajte kada ste je napravili.
- Znajte kojoj provjeri zdravlja vaš autoscaling vjeruje. Provjera koja samo pita „da li je VM uključen?“ neće zamijeniti server koji je prestao da radi.