ProHoster > Blogs > AdministrÄcija > Kubernetes padomi un triki: graciozas izslÄgÅ”anas iespÄjas NGINX un PHP-FPM
Kubernetes padomi un triki: graciozas izslÄgÅ”anas iespÄjas NGINX un PHP-FPM
Tipisks nosacÄ«jums, ievieÅ”ot CI/CD Kubernetes: lietojumprogrammai ir jÄspÄj nepieÅemt jaunus klientu pieprasÄ«jumus pirms pilnÄ«gas apstÄÅ”anÄs, un pats galvenais, veiksmÄ«gi pabeigt esoÅ”os.
AtbilstÄ«ba Å”im nosacÄ«jumam ļauj sasniegt nulles dÄ«kstÄves izvietoÅ”anas laikÄ. TomÄr pat tad, ja izmantojat ļoti populÄrus komplektus (piemÄram, NGINX un PHP-FPM), varat saskarties ar grÅ«tÄ«bÄm, kas izraisÄ«s kļūdu pieaugumu katrÄ izvietoÅ”anas reizÄ...
Teorija. KÄ pods dzÄ«vo
MÄs jau esam detalizÄti publicÄjuÅ”i pÄksts dzÄ«ves ciklu Å”is raksts. ApskatÄmÄs tÄmas kontekstÄ mÅ«s interesÄ sekojoÅ”ais: brÄ«dÄ«, kad pods nonÄk stÄvoklÄ« Beidzas, tai vairs netiek sÅ«tÄ«ti jauni pieprasÄ«jumi (pod noÅemts no pakalpojuma galapunktu saraksta). TÄdÄjÄdi, lai izvairÄ«tos no dÄ«kstÄves izvietoÅ”anas laikÄ, mums pietiek ar pareizu lietojumprogrammas apturÄÅ”anas problÄmu.
Jums arÄ« jÄatceras, ka noklusÄjuma labvÄlÄ«bas periods ir 30 sekundes: pÄc tam aplikÄcijas darbÄ«ba tiks pÄrtraukta, un lietojumprogrammai ir jÄbÅ«t laikam, lai apstrÄdÄtu visus pieprasÄ«jumus pirms Ŕī perioda. PiezÄ«me: lai gan jebkurÅ” pieprasÄ«jums, kas aizÅem vairÄk nekÄ 5-10 sekundes, jau ir problemÄtisks, un gracioza izslÄgÅ”ana vairs nepalÄ«dzÄs...
Lai labÄk izprastu, kas notiek, kad pods tiek pÄrtraukts, vienkÄrÅ”i apskatiet Å”o diagrammu:
A1, B1 - IzmaiÅu saÅemÅ”ana par pavarda stÄvokli
A2 - IzbraukŔana SIGTERM
B2 ā podnieka noÅemÅ”ana no galapunktiem
B3 ā izmaiÅu saÅemÅ”ana (ir mainÄ«ts beigu punktu saraksts)
B4 ā atjauniniet iptables noteikumus
LÅ«dzu, Åemiet vÄrÄ: galapunkta apgabala dzÄÅ”ana un SIGTERM nosÅ«tÄ«Å”ana nenotiek secÄ«gi, bet paralÄli. Un sakarÄ ar to, ka Ingress nekavÄjoties nesaÅem atjauninÄto galapunktu sarakstu, uz pod tiks nosÅ«tÄ«ti jauni klientu pieprasÄ«jumi, kas pod pÄrtraukÅ”anas laikÄ radÄ«s 500 kļūdu. (lai iegÅ«tu sÄ«kÄku materiÄlu par Å”o jautÄjumu, mÄs tulkots). Å Ä« problÄma ir jÄatrisina Å”Ädos veidos:
Sūtīt savienojumu: aizveriet atbildes galvenes (ja tas attiecas uz HTTP lietojumprogrammu).
Ja kodÄ nav iespÄjams veikt izmaiÅas, nÄkamajÄ rakstÄ ir aprakstÄ«ts risinÄjums, kas ļaus apstrÄdÄt pieprasÄ«jumus lÄ«dz labvÄlÄ«gÄ perioda beigÄm.
Teorija. KÄ NGINX un PHP-FPM pÄrtrauc savus procesus
nginx
SÄksim ar NGINX, jo ar to viss ir vairÄk vai mazÄk skaidrs. Iedziļinoties teorijÄ, mÄs uzzinÄm, ka NGINX ir viens galvenais process un vairÄki "darbinieki" - tie ir pakÄrtotie procesi, kas apstrÄdÄ klientu pieprasÄ«jumus. Tiek nodroÅ”inÄta Ärta opcija: izmantojot komandu nginx -s <SIGNAL> pÄrtraukt procesus ÄtrÄs izslÄgÅ”anas vai graciozÄs izslÄgÅ”anas režīmÄ. AcÄ«mredzot mÅ«s interesÄ pÄdÄjais variants.
Tad viss ir vienkÄrÅ”i: jums jÄpievieno preStop-ÄÄ·is komanda, kas nosÅ«tÄ«s graciozu izslÄgÅ”anas signÄlu. To var izdarÄ«t sadaÄ¼Ä IzvietoÅ”ana konteinera blokÄ:
Tagad, kad pods tiks izslÄgts, NGINX konteinera žurnÄlos redzÄsim Å”Ädu informÄciju:
2018/01/25 13:58:31 [notice] 1#1: signal 3 (SIGQUIT) received, shutting down
2018/01/25 13:58:31 [notice] 11#11: gracefully shutting down
Un tas nozÄ«mÄs to, kas mums nepiecieÅ”ams: NGINX gaida, lÄ«dz tiks pabeigti pieprasÄ«jumi, un pÄc tam nogalina procesu. TomÄr tÄlÄk mÄs apsvÄrsim arÄ« izplatÄ«tu problÄmu, kuras dÄļ pat ar komandu nginx -s quit process beidzas nepareizi.
Un Å”ajÄ posmÄ ar NGINX esam galÄ: vismaz no žurnÄliem var saprast, ka viss darbojas kÄ nÄkas.
KÄds sakars ar PHP-FPM? KÄ tas apstrÄdÄ graciozo izslÄgÅ”anu? IzdomÄsim.
PHP-FPM
PHP-FPM gadÄ«jumÄ informÄcijas ir nedaudz mazÄk. Ja koncentrÄjaties uz oficiÄlÄ rokasgrÄmata saskaÅÄ ar PHP-FPM tas pateiks, ka tiek pieÅemti Å”Ädi POSIX signÄli:
SIGINT, SIGTERM - Ätra izslÄgÅ”ana;
SIGQUIT ā gracioza izslÄgÅ”ana (tas, kas mums vajadzÄ«gs).
AtlikuÅ”ie signÄli Å”ajÄ uzdevumÄ nav nepiecieÅ”ami, tÄpÄc mÄs to analÄ«zi izlaidÄ«sim. Lai pareizi pÄrtrauktu procesu, jums bÅ«s jÄuzraksta Å”Äds preStop ÄÄ·is:
No pirmÄ acu uzmetiena tas ir viss, kas nepiecieÅ”ams, lai veiktu graciozu izslÄgÅ”anu abos konteineros. TomÄr uzdevums ir grÅ«tÄks, nekÄ Å”Ä·iet. TÄlÄk ir norÄdÄ«ti divi gadÄ«jumi, kad gracioza izslÄgÅ”ana nedarbojÄs un izraisÄ«ja Ä«slaicÄ«gu projekta nepieejamÄ«bu izvietoÅ”anas laikÄ.
Prakse. IespÄjamas problÄmas ar graciozu izslÄgÅ”anu
nginx
PirmkÄrt, ir lietderÄ«gi atcerÄties: papildus komandas izpildei nginx -s quit Ir vÄl viens posms, kam ir vÄrts pievÄrst uzmanÄ«bu. MÄs saskÄrÄmies ar problÄmu, kuras dÄļ NGINX joprojÄm sÅ«tÄ«ja SIGTERM, nevis SIGQUIT signÄlu, kÄ rezultÄtÄ pieprasÄ«jumi netika pareizi pabeigti. LÄ«dzÄ«gus gadÄ«jumus var atrast, piemÄram, Å”eit. DiemžÄl mÄs nevarÄjÄm noteikt konkrÄtu Ŕīs uzvedÄ«bas iemeslu: bija aizdomas par NGINX versiju, taÄu tÄs neapstiprinÄjÄs. Simptoms bija tÄds, ka NGINX konteinera žurnÄlos tika novÄroti ziÅojumi: "atvÄrta ligzda #10, kas atstÄta savienojumÄ 5", pÄc kura pods apstÄjÄs.
MÄs varam novÄrot Å”Ädu problÄmu, piemÄram, no mums nepiecieÅ”amajÄm atbildÄm par Ingress:
Statusa kodu indikatori izvietoÅ”anas laikÄ
Å ajÄ gadÄ«jumÄ mÄs saÅemam tikai kļūdas kodu 503 no paÅ”as Ingress: tas nevar piekļūt NGINX konteineram, jo āātas vairs nav pieejams. Ja skatÄties uz konteineru žurnÄliem, izmantojot NGINX, tie satur Å”Ädu informÄciju:
[alert] 13939#0: *154 open socket #3 left in connection 16
[alert] 13939#0: *168 open socket #6 left in connection 13
PÄc apstÄÅ”anÄs signÄla maiÅas konteiners sÄk pareizi apstÄties: to apstiprina fakts, ka kļūda 503 vairs netiek novÄrota.
Ja rodas lÄ«dzÄ«ga problÄma, ir lietderÄ«gi noskaidrot, kÄds apturÄÅ”anas signÄls tiek izmantots konteinerÄ un kÄ tieÅ”i izskatÄs preStop ÄÄ·is. PilnÄ«gi iespÄjams, ka iemesls slÄpjas tieÅ”i tajÄ.
PHP-FPM... un vairÄk
PHP-FPM problÄma ir aprakstÄ«ta triviÄli: tas negaida bÄrnu procesu pabeigÅ”anu, tas pÄrtrauc tos, tÄpÄc izvietoÅ”anas un citu darbÄ«bu laikÄ rodas 502 kļūdas. VietnÄ bugs.php.net kopÅ” 2005. gada ir vairÄki kļūdu ziÅojumi (piem Å”eit Šø Å”eit), kas apraksta Å”o problÄmu. Bet jÅ«s, visticamÄk, neko neredzÄsit žurnÄlos: PHP-FPM paziÅos par sava procesa pabeigÅ”anu bez kļūdÄm vai treÅ”o puÅ”u paziÅojumiem.
Ir vÄrts precizÄt, ka pati problÄma var bÅ«t mazÄkÄ vai lielÄkÄ mÄrÄ atkarÄ«ga no paÅ”as lietojumprogrammas un var neizpausties, piemÄram, uzraudzÄ«bÄ. Ja ar to saskaraties, vispirms nÄk prÄtÄ vienkÄrÅ”s risinÄjums: pievienojiet preStop ÄÄ·i ar sleep(30). Tas ļaus jums izpildÄ«t visus pieprasÄ«jumus, kas bija iepriekÅ” (un mÄs nepieÅemam jaunus, jo pod jau spÄjÄ«gs uz Beidzas), un pÄc 30 sekundÄm pats pods beigsies ar signÄlu SIGTERM.
IzrÄdÄs, ka lifecycle konteiners izskatÄ«sies Å”Ädi:
TomÄr sakarÄ ar 30-sek sleep mÄs stingri mÄs pagarinÄsim izvietoÅ”anas laiku, jo katrs pods tiks pÄrtraukts minimums 30 sekundes, kas ir slikti. Ko Å”ajÄ sakarÄ var darÄ«t?
VÄrsÄ«simies pie personas, kas ir atbildÄ«ga par pieteikuma tieÅ”u izpildi. MÅ«su gadÄ«jumÄ tÄ ir PHP-FPMKurÅ” pÄc noklusÄjuma neuzrauga savu pakÄrtoto procesu izpildi: galvenais process tiek nekavÄjoties pÄrtraukts. Varat mainÄ«t Å”o darbÄ«bu, izmantojot direktÄ«vu process_control_timeout, kas nosaka laika ierobežojumus bÄrnprocesiem, lai gaidÄ«tu signÄlus no galvenÄ. Ja iestatÄt vÄrtÄ«bu uz 20 sekundÄm, tas aptvers lielÄko daļu vaicÄjumu, kas darbojas konteinerÄ, un apturÄs galveno procesu, tiklÄ«dz tie bÅ«s pabeigti.
Ar Ŕīm zinÄÅ”anÄm atgriezÄ«simies pie pÄdÄjÄs problÄmas. KÄ minÄts, Kubernetes nav monolÄ«ta platforma: saziÅa starp tÄs dažÄdajÄm sastÄvdaļÄm aizÅem kÄdu laiku. Tas jo Ä«paÅ”i attiecas uz Ingresses un citu saistÄ«to komponentu darbÄ«bu, jo Å”Ädas kavÄÅ”anÄs dÄļ izvietoÅ”anas laikÄ ir viegli iegÅ«t 500 kļūdu pieaugumu. PiemÄram, kļūda var rasties pieprasÄ«juma nosÅ«tÄ«Å”anas posmÄ uz augÅ”u, taÄu mijiedarbÄ«bas ālaika nobÄ«deā starp komponentiem ir diezgan Ä«sa - mazÄka par sekundi.
TÄdÄļ KopÄ ar jau minÄto direktÄ«vu process_control_timeout varat izmantot Å”Ädu konstrukciju lifecycle:
Å ajÄ gadÄ«jumÄ mÄs kompensÄsim kavÄÅ”anos ar komandu sleep un nepalieliniet izvietoÅ”anas laiku: vai ir ievÄrojama atŔķirÄ«ba starp 30 sekundÄm un vienu? .. PatiesÄ«bÄ tÄ ir process_control_timeoutUn lifecycle izmanto tikai kÄ ādroŔības tÄ«kluā kavÄÅ”anÄs gadÄ«jumÄ.
VispÄrÄ«gi runÄjot aprakstÄ«tÄ rÄ«cÄ«ba un atbilstoÅ”ais risinÄjums attiecas ne tikai uz PHP-FPM. LÄ«dzÄ«ga situÄcija tÄ vai citÄdi var rasties, lietojot citas valodas/ietvarus. Ja graciozo izslÄgÅ”anu nevarat novÄrst citos veidos, piemÄram, pÄrrakstot kodu, lai lietojumprogramma pareizi apstrÄdÄtu beigu signÄlus, varat izmantot aprakstÄ«to metodi. Tas var nebÅ«t tas skaistÄkais, bet tas darbojas.
Prakse. Slodzes pÄrbaude, lai pÄrbaudÄ«tu podziÅa darbÄ«bu
Slodzes pÄrbaude ir viens no veidiem, kÄ pÄrbaudÄ«t konteinera darbÄ«bu, jo Ŕī procedÅ«ra tuvina to reÄliem kaujas apstÄkļiem, kad lietotÄji apmeklÄ vietni. Lai pÄrbaudÄ«tu iepriekÅ” minÄtos ieteikumus, varat izmantot Yandex.Tankom: Tas lieliski apmierina visas mÅ«su vajadzÄ«bas. TÄlÄk ir sniegti padomi un ieteikumi testÄÅ”anas veikÅ”anai, izmantojot skaidru piemÄru no mÅ«su pieredzes, pateicoties paÅ”as Grafana un Yandex.Tank diagrammÄm.
VissvarÄ«gÄkais Å”eit ir pÄrbaudiet izmaiÅas soli pa solim. PÄc jauna labojuma pievienoÅ”anas palaidiet testu un pÄrbaudiet, vai rezultÄti ir mainÄ«juÅ”ies salÄ«dzinÄjumÄ ar iepriekÅ”Äjo palaiÅ”anu. PretÄjÄ gadÄ«jumÄ bÅ«s grÅ«ti noteikt neefektÄ«vus risinÄjumus, un ilgtermiÅÄ tas var tikai kaitÄt (piemÄram, palielinÄt izvietoÅ”anas laiku).
VÄl viena nianse ir apskatÄ«t konteinera žurnÄlus tÄ darbÄ«bas pÄrtraukÅ”anas laikÄ. Vai tur ir ierakstÄ«ta informÄcija par graciozo izslÄgÅ”anu? Vai, piekļūstot citiem resursiem (piemÄram, blakus esoÅ”ajam PHP-FPM konteineram), žurnÄlos ir kļūdas? Kļūdas paÅ”Ä lietojumprogrammÄ (kÄ iepriekÅ” aprakstÄ«tajÄ gadÄ«jumÄ ar NGINX)? Ceru, ka Ŕī raksta ievadinformÄcija palÄ«dzÄs jums labÄk izprast, kas notiek ar konteineru tÄ darbÄ«bas pÄrtraukÅ”anas laikÄ.
TÄtad, pirmais testa brauciens notika bez lifecycle un bez papildu direktÄ«vÄm lietojumprogrammu serverim (process_control_timeout PHP-FPM). Å Ä« testa mÄrÄ·is bija noteikt aptuveno kļūdu skaitu (un to, vai tÄdas ir). TurklÄt, Åemot vÄrÄ papildu informÄciju, jums vajadzÄtu zinÄt, ka katras podziÅas vidÄjais izvietoÅ”anas laiks bija aptuveni 5ā10 sekundes, lÄ«dz tas bija pilnÄ«bÄ gatavs. RezultÄti ir:
Yandex.Tank informÄcijas panelÄ« ir redzams 502 kļūdu pieaugums, kas radÄs izvietoÅ”anas laikÄ un ilga vidÄji lÄ«dz 5 sekundÄm. IespÄjams, tas bija tÄpÄc, ka esoÅ”ie pieprasÄ«jumi vecajam podam tika pÄrtraukti, kad tas tika pÄrtraukts. PÄc tam parÄdÄ«jÄs 503 kļūdas, ko izraisÄ«ja apturÄts NGINX konteiners, kas arÄ« pÄrtrauca savienojumus aizmugursistÄmas dÄļ (kas neļÄva Ingress tai izveidot savienojumu).
PaskatÄ«simies, kÄ process_control_timeout PHP-FPM palÄ«dzÄs mums sagaidÄ«t bÄrnu procesu pabeigÅ”anu, t.i. izlabot Å”Ädas kļūdas. AtkÄrtoti izvietot, izmantojot Å”o direktÄ«vu:
500. izvietoÅ”anas laikÄ kļūdu vairs nav! IzvietoÅ”ana ir veiksmÄ«ga, graciozi izslÄgÅ”anas darbi.
TomÄr ir vÄrts atcerÄties problÄmu ar Ingress konteineriem ā nelielu daļu kļūdu, kuras mÄs varam saÅemt laika nobÄ«des dÄļ. Lai no tiem izvairÄ«tos, atliek tikai pievienot struktÅ«ru ar sleep un atkÄrtojiet izvietoÅ”anu. TomÄr mÅ«su konkrÄtajÄ gadÄ«jumÄ nekÄdas izmaiÅas nebija redzamas (atkal nekÄdu kļūdu).
SecinÄjums
Lai pabeigtu procesu, mÄs sagaidÄm Å”Ädu lietojumprogrammas darbÄ«bu:
Uzgaidiet dažas sekundes un pÄc tam pÄrtrauciet jaunu savienojumu pieÅemÅ”anu.
Pagaidiet, lÄ«dz tiek pabeigti visi pieprasÄ«jumi, un aizveriet visus saglabÄtos savienojumus, kas neizpilda pieprasÄ«jumus.
Pabeidziet savu procesu.
TomÄr ne visas lietojumprogrammas var darboties Å”ÄdÄ veidÄ. Viens problÄmas risinÄjums Kubernetes realitÄtÄ ir:
pievienojot pirms apstÄÅ”anÄs ÄÄ·i, kas gaidÄ«s dažas sekundes;
pÄtot mÅ«su aizmugursistÄmas konfigurÄcijas failu, lai iegÅ«tu atbilstoÅ”os parametrus.
PiemÄrÄ ar NGINX ir skaidrs, ka pat lietojumprogramma, kurai sÄkotnÄji bÅ«tu pareizi jÄapstrÄdÄ pÄrtraukÅ”anas signÄli, to var nedarÄ«t, tÄpÄc lietojumprogrammas izvietoÅ”anas laikÄ ir ļoti svarÄ«gi pÄrbaudÄ«t 500 kļūdas. Tas arÄ« ļauj aplÅ«kot problÄmu plaÅ”Äk un nekoncentrÄties uz vienu podiÅu vai konteineru, bet gan aplÅ«kot visu infrastruktÅ«ru kopumÄ.
KÄ testÄÅ”anas rÄ«ku varat izmantot Yandex.Tank kopÄ ar jebkuru uzraudzÄ«bas sistÄmu (mÅ«su gadÄ«jumÄ dati tika Åemti no Grafana ar Prometheus aizmugursistÄmu pÄrbaudei). ProblÄmas ar graciozu izslÄgÅ”anu ir skaidri redzamas pie lielas slodzes, ko var radÄ«t etalons, un uzraudzÄ«ba palÄ«dz detalizÄtÄk analizÄt situÄciju testa laikÄ vai pÄc tÄ.
Atbildot uz atsauksmÄm par rakstu: ir vÄrts pieminÄt, ka Å”eit ir aprakstÄ«tas problÄmas un risinÄjumi saistÄ«bÄ ar NGINX Ingress. Citos gadÄ«jumos ir citi risinÄjumi, kurus mÄs varam apsvÄrt turpmÄkajos sÄrijas materiÄlos.