Kubernetes Tipps & Tricks: Feature vum graziéisen Shutdown an NGINX a PHP-FPM

Eng typesch Konditioun wann Dir CI/CD an Kubernetes implementéiert: d'Applikatioun muss fäeg sinn nei Clientsufroen net akzeptéieren ier se komplett ophalen, an am wichtegsten, existéierend erfollegräich ofgeschloss.

Kubernetes Tipps & Tricks: Feature vum graziéisen Shutdown an NGINX a PHP-FPM

D'Konformitéit mat dëser Bedingung erlaabt Iech Null Downtime während der Deployment z'erreechen. Wéi och ëmmer, och wann Dir ganz populär Bündel benotzt (wéi NGINX a PHP-FPM), kënnt Dir Schwieregkeeten stoussen, déi zu engem Iwwerschoss vu Feeler mat all Deployment féieren ...

Theorie. Wéi de Pod lieft

Mir hu schonn am Detail iwwer de Liewenszyklus vun engem Pod publizéiert dësen Artikel. Am Kader vum Thema, dee mer diskutéiert ginn, interesséiere mir eis fir folgend: am Moment wou de Pod an de Staat kënnt Terminatioun, nei Ufroe stoppen dohinner ze schécken (pod ewechgeholl aus der Lëscht vun Endpunkte fir de Service). Also, fir Ënnerbriechungen beim Ofbau ze vermeiden, ass et genuch fir eis de Problem ze léisen fir d'Applikatioun korrekt ze stoppen.

Dir sollt och drun erënneren datt d'Default Gnod Period ass 30 Sekonnen: duerno gëtt de Pod ofgeschloss an d'Applikatioun muss Zäit hunn fir all Ufroe virun dëser Period ze behandelen. Remarque: obwuel all Ufro déi méi wéi 5-10 Sekonnen dauert scho problematesch ass, a graziéis Ausschalten hëlleft et net méi ...

Fir besser ze verstoen wat geschitt wann e Pod ofgeschloss ass, kuckt just de folgenden Diagramm:

Kubernetes Tipps & Tricks: Feature vum graziéisen Shutdown an NGINX a PHP-FPM

A1, B1 - Empfang vun Ännerungen iwwer den Zoustand vum Häerz
A2 - Depart SIGTERM
B2 - E Pod aus Endpunkten erofhuelen
B3 - Ännerunge kréien (d'Lëscht vun den Endpunkte gouf geännert)
B4 - Update iptables Regelen

Notéiert w.e.g.: Den Endpunkt Pod läschen an SIGTERM schécken geschitt net sequenziell, awer parallel. A wéinst der Tatsaach, datt Ingress net direkt déi aktualiséiert Lëscht vun Endpoints kritt, ginn nei Ufroe vu Clienten un de Pod geschéckt, wat e 500 Feeler während der Podterminatioun verursaacht (fir méi detailléiert Material zu dësem Thema, mir iwwersat). Dëse Problem muss op de folgende Weeër geléist ginn:

  • Schécken Verbindung: zoumaachen an Äntwert Header (wann dëst eng HTTP Applikatioun betrëfft).
  • Wann et net méiglech ass Ännerunge vum Code ze maachen, da beschreift de folgenden Artikel eng Léisung déi Iech erlaabt Ufroe bis zum Enn vun der graziéiser Period ze veraarbecht.

Theorie. Wéi NGINX a PHP-FPM hir Prozesser ofschléissen

NGINX

Fänke mer mat NGINX un, well alles méi oder manner evident domat ass. Tauchen an d'Theorie, léiere mir datt NGINX ee Masterprozess a verschidde "Aarbechter" huet - dëst sinn Kannerprozesser déi Client Ufroe veraarbechten. Eng praktesch Optioun gëtt ugebueden: de Kommando benotzen nginx -s <SIGNAL> Ofschloss Prozesser entweder am schnelle Shutdown oder graziéisen Shutdown Modus. Natierlech ass et déi lescht Optioun déi eis interesséiert.

Dann ass alles einfach: Dir musst derbäisetzen preStop-Hook e Kommando deen e graziéisen Shutdown-Signal schéckt. Dëst kann am Deployment gemaach ginn, am Containerblock:

       lifecycle:
          preStop:
            exec:
              command:
              - /usr/sbin/nginx
              - -s
              - quit

Elo, wann de Pod ausschalt, gesi mir déi folgend an den NGINX Container Logbicher:

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

An dëst wäert bedeiten wat mir brauchen: NGINX waart op Ufroe fir ze kompletéieren, a killt dann de Prozess. Wéi och ëmmer, hei ënnen wäerte mir och e gemeinsame Problem betruechten wéinst deem, och mam Kommando nginx -s quit de Prozess endet falsch.

An op dëser Etapp si mir fäerdeg mat NGINX: op d'mannst aus de Logbicher kënnt Dir verstoen datt alles funktionnéiert wéi et soll.

Wat ass den Deal mat PHP-FPM? Wéi behandelt et graziéis Shutdown? Loosst eis et erausfannen.

PHP-FPM

Am Fall vu PHP-FPM gëtt et e bësse manner Informatioun. Wann Dir konzentréieren op offiziell Handbuch laut PHP-FPM wäert et soen datt déi folgend POSIX Signaler ugeholl ginn:

  1. SIGINT, SIGTERM - séier Ofschloss;
  2. SIGQUIT - graziéis Ofschloss (wat mir brauchen).

Déi reschtlech Signaler sinn net an dëser Aufgab erfuerderlech, also wäerte mir hir Analyse ofginn. Fir de Prozess korrekt ofzeschléissen, musst Dir de folgende PreStop Hook schreiwen:

        lifecycle:
          preStop:
            exec:
              command:
              - /bin/kill
              - -SIGQUIT
              - "1"

Op den éischte Bléck ass dat alles wat néideg ass fir e graziéisen Ofschalten a béide Container ze maachen. Allerdéngs ass d'Aufgab méi schwéier wéi et schéngt. Drënner sinn zwee Fäll, an deenen e graziéisen Ofschloss net geschafft huet a kuerzfristeg Onverfügbarkeet vum Projet wärend der Deployment verursaacht huet.

Praxis. Méiglech Problemer mat graziéisen Ofschloss

NGINX

Als éischt ass et nëtzlech ze erënneren: nieft dem Kommando auszeféieren nginx -s quit Et gëtt nach eng Etapp op déi derwäert ass opmierksam ze maachen. Mir hunn en Thema begéint wou NGINX nach ëmmer SIGTERM géif schécken amplaz vum SIGQUIT-Signal, wouduerch d'Ufroe net korrekt fäerdeg sinn. Ähnlech Fäll kënnen z.B. hei. Leider konnte mir de spezifesche Grond fir dëst Verhalen net bestëmmen: et war e Verdacht iwwer d'NGINX Versioun, awer et gouf net bestätegt. D'Symptom war datt Messagen an den NGINX Container Logbicher observéiert goufen: "Open Socket #10 lénks a Verbindung 5", duerno huet de Pod opgehalen.

Mir kënnen esou e Problem observéieren, zum Beispill, aus den Äntwerten op der Ingress déi mir brauchen:

Kubernetes Tipps & Tricks: Feature vum graziéisen Shutdown an NGINX a PHP-FPM
Indicateuren vun Status Coden am Moment vun Détachement

An dësem Fall kréie mir just e 503 Fehlercode vum Ingress selwer: et kann net op den NGINX Container kommen, well et net méi zougänglech ass. Wann Dir d'Container Logbicher mat NGINX kuckt, enthalen se déi folgend:

[alert] 13939#0: *154 open socket #3 left in connection 16
[alert] 13939#0: *168 open socket #6 left in connection 13

No der Ännerung vum Stop Signal fänkt de Container richteg ze stoppen: dëst gëtt bestätegt duerch d'Tatsaach datt de 503 Feeler net méi observéiert gëtt.

Wann Dir en ähnleche Problem begéint, mécht et Sënn fir erauszefannen, wéi ee Stop-Signal am Container benotzt gëtt a wéi genau de PreStop-Hook ausgesäit. Et ass ganz méiglech, datt de Grond genee an dësem läit.

PHP-FPM ... a méi

De Problem mat PHP-FPM gëtt op eng trivial Manéier beschriwwen: et waart net op d'Fäerdegstellung vun de Kannerprozesser, et schléisst se of, dofir entstinn 502 Feeler beim Deployment an aner Operatiounen. Et gi verschidde Feelerberichter op bugs.php.net zënter 2005 (z hei и hei), déi dëse Problem beschreift. Awer Dir wäert héchstwahrscheinlech näischt an de Logbicher gesinn: PHP-FPM wäert d'Réalisatioun vu sengem Prozess annoncéieren ouni Feeler oder Drëtt Partei Notifikatiounen.

Et ass derwäert ze klären datt de Problem selwer zu engem manner oder méi groussen Ausmooss vun der Applikatioun selwer hänkt a sech net manifestéiere kann, zum Beispill an der Iwwerwaachung. Wann Dir et begéint, kënnt eng einfach Léisung fir d'éischt am Kapp: füügt e PreStop Hook mat sleep(30). Et erlaabt Iech all Ufroen auszefëllen, déi virdru waren (a mir akzeptéieren net nei, well Pod schonn kapabel vun Terminatioun), an no 30 Sekonnen wäert de Pod selwer mat engem Signal ophalen SIGTERM.

Et stellt sech eraus lifecycle fir de Container wäert esou ausgesinn:

    lifecycle:
      preStop:
        exec:
          command:
          - /bin/sleep
          - "30"

Wéi och ëmmer, wéinst der 30. Sekonnen sleep mir sinn staark mir wäerten d'Deployment Zäit erhéijen, well all Pod ofgeschloss gëtt Minimum 30 Sekonnen, wat schlecht ass. Wat kann iwwer dëst gemaach ginn?

Loosst eis un déi Partei verantwortlech fir déi direkt Ausféierung vun der Applikatioun wenden. An eisem Fall ass et PHP-FPM, wat par défaut iwwerwaacht net d'Ausféierung vu senge Kannerprozesser: De Masterprozess gëtt direkt ofgeschloss. Dir kënnt dëst Verhalen mat der Direktiv änneren process_control_timeout, déi spezifizéiert d'Zäitlimite fir Kannerprozesser fir Signaler vum Meeschter ze waarden. Wann Dir de Wäert op 20 Sekonnen setzt, deckt dëst déi meescht vun den Ufroen déi am Container lafen a stoppt de Masterprozess nodeems se ofgeschloss sinn.

Mat dësem Wëssen, loosst eis zréck op eise leschte Problem. Wéi scho gesot, Kubernetes ass keng monolithesch Plattform: Kommunikatioun tëscht senge verschiddene Komponenten dauert e bëssen Zäit. Dëst ass virun allem wouer wann mir d'Operatioun vun Ingresses an aner verbonne Komponenten betruechten, well wéinst sou enger Verspéidung am Moment vun der Deployment ass et einfach e Stroum vu 500 Feeler ze kréien. Zum Beispill kann e Feeler op der Bühn geschéien fir eng Ufro un en Upstream ze schécken, awer d'"Zäitlag" vun der Interaktioun tëscht Komponenten ass relativ kuerz - manner wéi eng Sekonn.

Dofir ass Am Ganzen mat der scho genannter Direktiv process_control_timeout Dir kënnt déi folgend Konstruktioun benotzen fir lifecycle:

lifecycle:
  preStop:
    exec:
      command: ["/bin/bash","-c","/bin/sleep 1; kill -QUIT 1"]

An dësem Fall wäerte mir d'Verzögerung mam Kommando kompenséieren sleep a vergréissert d'Deployment Zäit net vill: Gëtt et e merkbare Ënnerscheed tëscht 30 Sekonnen an engem? .. Tatsächlech ass et de process_control_timeoutan lifecycle nëmmen als "Sécherheetsnetz" am Fall vun Lag benotzt.

Am allgemengen dat beschriwwe Verhalen an déi entspriechend Léisung gëllen net nëmme fir PHP-FPM. Eng ähnlech Situatioun kann op eng oder aner Manéier entstoen wann Dir aner Sproochen/Kadere benotzt. Wann Dir net e graziéise Shutdown op aner Manéier fixéiere kënnt - zum Beispill andeems Dir de Code ëmschreift, sou datt d'Applikatioun korrekt Terminatiounssignaler veraarbecht - kënnt Dir déi beschriwwe Method benotzen. Et ass vläicht net déi schéinste, awer et funktionnéiert.

Praxis. Laden Tester fir d'Operatioun vum Pod ze kontrolléieren

Last Testen ass ee vun de Weeër fir ze kontrolléieren wéi de Container funktionnéiert, well dës Prozedur bréngt et méi no un déi richteg Kampfbedéngungen wann d'Benotzer de Site besichen. Fir déi uewe genannte Empfehlungen ze testen, kënnt Dir benotzen Yandex.Tankom: Et deckt all eis Besoinen perfekt. Déi folgend sinn Tipps a Empfehlungen fir Tester mat engem klore Beispill aus eiser Erfahrung duerch d'Grafike vu Grafana an Yandex.Tank selwer.

Déi wichtegst Saach hei ass kontrolléieren Ännerungen Schrëtt fir Schrëtt. Nodeems Dir eng nei Fix bäigefüügt hutt, lafen den Test a kuckt ob d'Resultater am Verglach zum leschte Laf geännert hunn. Soss wäert et schwéier sinn ineffektiv Léisungen z'identifizéieren, an op laang Siicht kann et nëmme Schued maachen (zum Beispill d'Verbreedungszäit erhéijen).

Eng aner Nuance ass d'Containerprotokoller während senger Kënnegung ze kucken. Gëtt Informatioun iwwer graziéisen Ofschloss do opgeholl? Ginn et Feeler an de Logbicher beim Zougang zu anere Ressourcen (zum Beispill zu engem Nopeschlänner PHP-FPM Container)? Feeler an der Applikatioun selwer (wéi am Fall mat NGINX uewen beschriwwen)? Ech hoffen, datt d'Aféierungsinformatioun aus dësem Artikel Iech hëllefe besser ze verstoen wat mam Container während senger Kënnegung geschitt.

Also ass den éischten Testlaf ouni lifecycle an ouni zousätzlech Direktiven fir den Applikatiounsserver (process_control_timeout an PHP-FPM). Den Zweck vun dësem Test war d'ongeféier Unzuel vu Feeler z'identifizéieren (an ob et do sinn). Och aus zousätzlech Informatioune sollt Dir wëssen datt d'Duerchschnëttszäit fir all Pod ongeféier 5-10 Sekonnen war bis et komplett fäerdeg war. D'Resultater sinn:

Kubernetes Tipps & Tricks: Feature vum graziéisen Shutdown an NGINX a PHP-FPM

D'Yandex.Tank Informatiounspanel weist e Spike vu 502 Feeler, déi zu der Zäit vum Asaz geschitt sinn an am Duerchschnëtt bis zu 5 Sekonnen gedauert hunn. Wahrscheinlech war dëst well existent Ufroe fir den alen Pod ofgeschloss goufen wann et ofgeschloss gouf. Duerno sinn 503 Fehler opgetaucht, wat d'Resultat vun engem gestoppt NGINX Container war, deen och Verbindunge wéinst dem Backend erofgelooss huet (wat verhënnert huet datt d'Ingress domat verbënnt).

Loosst eis kucken wéi process_control_timeout an PHP-FPM hëlleft eis op d'Réalisatioun vun Kand Prozesser wait, i.e. korrigéiert esou Feeler. Re-deployéieren mat dëser Direktiv:

Kubernetes Tipps & Tricks: Feature vum graziéisen Shutdown an NGINX a PHP-FPM

Et gi keng Feeler méi während der 500. Deployment! Den Détachement ass erfollegräich, graziéis Shutdown funktionnéiert.

Wéi och ëmmer, et ass derwäert un d'Thema mat Ingress Container ze erënneren, e klenge Prozentsaz vu Feeler an deenen mir wéinst enger Zäitlag kënne kréien. Fir se ze vermeiden, bleift just nach eng Struktur dobäi ze setzen sleep a widderhuelen d'Deployment. Wéi och ëmmer, an eisem besonnesche Fall waren keng Ännerungen ze gesinn (erëm, keng Feeler).

Konklusioun

Fir de Prozess graziéis ofzeschléissen, erwaarden mir dat folgend Verhalen vun der Applikatioun:

  1. Waart e puer Sekonnen an stoppen dann nei Verbindungen unzehuelen.
  2. Waart op all Ufroe fir all Keepalive Verbindungen ofzeschléissen déi net Ufroen ausféieren.
  3. Enn Äre Prozess.

Wéi och ëmmer, net all Applikatioune kënnen op dës Manéier funktionnéieren. Eng Léisung fir de Problem an de Kubernetes Realitéite ass:

  • derbäi e Pre-Stop Hook deen e puer Sekonnen waarden;
  • studéiert d'Konfiguratiounsdatei vun eisem Backend fir déi entspriechend Parameteren.

D'Beispill mat NGINX mécht et kloer datt och eng Applikatioun déi ufanks d'Terminatiounssignaler korrekt veraarbecht soll dat net maachen, also ass et kritesch fir 500 Fehler während der Applikatioun Deployment ze kontrolléieren. Dëst erlaabt Iech och de Problem méi breet ze kucken an net op eng eenzeg Pod oder Container ze fokusséieren, mee déi ganz Infrastruktur als Ganzt ze kucken.

Als Testinstrument kënnt Dir Yandex.Tank a Verbindung mat all Iwwerwaachungssystem benotzen (an eisem Fall goufen Daten aus Grafana mat engem Prometheus Backend fir den Test geholl). Probleemer mat graziéisen Ofschloss si kloer ënner schwéiere Lasten ze gesinn, déi de Benchmark generéiere kann, an d'Iwwerwaachung hëlleft d'Situatioun méi am Detail während oder nom Test ze analyséieren.

Als Äntwert op Feedback op den Artikel: et ass derwäert ze ernimmen datt d'Problemer a Léisungen hei a Relatioun mat NGINX Ingress beschriwwe ginn. Fir aner Fäll ginn et aner Léisungen, déi mir an de folgende Materialien vun der Serie betruechten.

PS

Aner aus der K8s Tipps & Tricks Serie:

Source: will.com

Setzt e Commentaire