Ang Nawawalang Swap File na Nag-freeze sa Aming mga Server
Noong Setyembre 24, huminto sa pagsagot ang isa sa aming production server. Minarkahan ito ng load balancer na unhealthy at hindi maabot ng aming remote-command tool, pero walang nag-crash at walang pinatay dahil sa sobrang memory. Nag-thrash ang server: dahil walang swap space at pinapayagan ang mga container na gumamit ng mas maraming memory kaysa sa mayroon ang makina, ginugugol ng Linux ang oras nito sa pagpapaalis at muling pagbasa ng mga file na kailangan nito para tumakbo, at halos walang progreso. Inayos ito ng 2 GB na swap file sa bawat server. Mas kawili-wili ang aral tungkol sa health checks.
Ano ang itsura ng "nag-hang"
- Nag-time out ang health checks ng load balancer sa server na iyon.
- Nanatiling "Pending" ang mga command na ipinadala sa pamamagitan ng AWS Systems Manager at hindi tumakbo kailanman.
- Walang out-of-memory kill sa logs. Walang prosesong namatay.
Isang linggo bago iyon, inilipat namin ang production sa mas maliliit na ARM server na may tig-2 GB na RAM. Ang aming staging server, mas maliit pa, ay nag-freeze sa parehong paraan habang nag-u-unpack ng container image sa isang deploy.
Bakit walang memory error?
Pinapatay lang ng Linux ang isang proseso kapag talagang naubusan na ito ng memory na maaari nitong bawiin. Bago umabot doon, binabawi nito ang memory mula sa page cache, ang mga kopya ng file na itinatago nito sa RAM, kasama ang code ng bawat tumatakbong programa.
Sa aming mga server, ang pinagsamang memory limits ng mga container ay umabot sa humigit-kumulang 3.3 GB sa makinang may humigit-kumulang 1.8 GB na magagamit. Karaniwang hindi nila lahat ginagamit ang buong limit nang sabay. Pero noong ginawa nila, patuloy na pinapaalis ng kernel ang program code mula sa cache para magkaroon ng puwang, at pagkatapos kailangan itong basahin muli mula sa disk sa sandaling tumakbo muli ang code na iyon. Ang siklong iyon, ang thrashing, ay maaaring gawing halos ganap na hindi tumutugon ang makina habang hindi naman teknikal na naubusan ng memory. Kaya walang napapatay, at walang nakakabawi.
Kung walang swap, walang mapaglalagyan ang kernel ng memory na nailaan pero bihirang gamitin, kaya kailangan nitong kunin ito mula sa cache.
Ang ayos
Ngayon, gumagawa ang bootstrap script ng server ng 2 GB swap file na may mababang swappiness setting (10) tuwing mag-boot o maaayos ang isang server. Ang mababang swappiness ay nangangahulugang mas gusto pa rin ng kernel na itago ang working memory sa RAM, pero ang mga pahinang bihirang galawin ay maaaring ilipat sa disk sa halip na pilitin palabas ang program code sa cache. Inilapat namin ito nang live sa parehong production server at sa staging, at muling pina-publish ng deploy pipeline ang bootstrap script sa bawat production deploy para makuha rin ito ng server na pinalitan.
Ang bahaging mas nakakabahala: nanatili ang hindi malusog na server
Gumagamit ang server group namin ng EC2 health checks, ang "tumatakbo ba ang makina?", hindi ang load balancer health checks, ang "sumasagot ba ito sa mga request?". Kaya ang server na isinuko na ng load balancer ay malusog pa rin para sa group. Hindi na ito kailanman papalitan. Tahimik na tatakbo ang production sa iisang server hanggang mapansin ng isang tao at i-reboot ang isa pa.
Mukhang halatang ayos ang paglipat ng group sa load-balancer health checks, pero hindi ito diretso para sa amin: sa panahon ng deploy, sinasadya ng mga server na sagutin ng error ang kanilang health endpoint para maubos ng balancer ang mga ito (tingnan ang paano namin nakuha ang zero 502s sa deploy). Ang group na nagpapalit ng server batay sa signal na iyon ay papalitan ang mga ito sa gitna ng bawat deploy.
Kaya sa ngayon, nagdagdag kami ng hakbang sa deploy checklist namin: pagkatapos ng bawat deploy, tingnan ang health ng bawat target sa load balancer, hindi lang kung pumasa ang deploy job. Kapag nakabitin sa "Pending" ang mga command papunta sa isang server, nag-tha-thrash ito; i-reboot ito; wala na ito sa rotation.
Ang natutunan namin
- "Hindi nag-crash" ay hindi ibig sabihin na "malusog". Ang thrashing ay walang ginagawang error, bagkus sobrang pagkabagal na huminto na sa pagsagot ang makina.
- Kailangan ng swap ang maliliit na server. Kahit kaunti lang, na may mababang swappiness, ay nagbibigay sa kernel ng mapaglalagyan ng malamig na memory.
- Ang memory limits na pinagsama ay lumalampas sa makina ay isang taya. Minsan natatalo ka. Alamin kung kailan ka nagtaya.
- Alamin kung aling health check ang pinagkakatiwalaan ng autoscaling mo. Ang health check na nagtatanong lang kung "naka-on ba ang VM?" ay hindi papalit sa server na tumigil nang gumana.