Awgrymiadau a thriciau Kubernetes: nodweddion cau gosgeiddig yn NGINX a PHP-FPM

Amod nodweddiadol wrth weithredu CI/CD yn Kubernetes: rhaid i'r cais allu peidio â derbyn ceisiadau cleient newydd cyn stopio'n llwyr, ac yn bwysicaf oll, cwblhau'r rhai presennol yn llwyddiannus.

Awgrymiadau a thriciau Kubernetes: nodweddion cau gosgeiddig yn NGINX a PHP-FPM

Mae cydymffurfio â'r amod hwn yn caniatáu ichi gyflawni dim amser segur yn ystod y defnydd. Fodd bynnag, hyd yn oed wrth ddefnyddio bwndeli poblogaidd iawn (fel NGINX a PHP-FPM), gallwch ddod ar draws anawsterau a fydd yn arwain at ymchwydd o wallau gyda phob defnydd ...

Damcaniaeth. Sut mae pod yn byw

Rydym eisoes wedi cyhoeddi'n fanwl am gylchred bywyd pod yr erthygl hon. Yng nghyd-destun y pwnc dan sylw, mae gennym ddiddordeb yn y canlynol: ar hyn o bryd pan fydd y pod yn mynd i mewn i'r wladwriaeth Terfynu, mae ceisiadau newydd yn peidio â chael eu hanfon ato (pod tynnu o'r rhestr o bwyntiau terfyn ar gyfer y gwasanaeth). Felly, er mwyn osgoi amser segur yn ystod y defnydd, mae'n ddigon i ni ddatrys y broblem o atal y cais yn gywir.

Dylech hefyd gofio mai'r cyfnod gras rhagosodedig yw 30 eiliad: ar ôl hyn, bydd y pod yn cael ei derfynu a rhaid i'r cais gael amser i brosesu pob cais cyn y cyfnod hwn. Nodyn: er bod unrhyw gais sy'n cymryd mwy na 5-10 eiliad eisoes yn broblematig, ac ni fydd cau i lawr yn osgeiddig yn ei helpu mwyach ...

Er mwyn deall yn well beth sy'n digwydd pan fydd pod yn dod i ben, edrychwch ar y diagram canlynol:

Awgrymiadau a thriciau Kubernetes: nodweddion cau gosgeiddig yn NGINX a PHP-FPM

A1, B1 - Derbyn newidiadau am gyflwr yr aelwyd
A2 - SIGTERM Ymadawiad
B2 - Tynnu pod o fannau terfyn
B3 - Derbyn newidiadau (mae'r rhestr o bwyntiau terfyn wedi newid)
B4 - Diweddaru rheolau iptables

Sylwch: nid yw dileu'r pod diweddbwynt ac anfon SITERM yn digwydd yn olynol, ond yn gyfochrog. Ac oherwydd y ffaith nad yw Ingress yn derbyn y rhestr wedi'i diweddaru o Endpoints ar unwaith, bydd ceisiadau newydd gan gleientiaid yn cael eu hanfon at y pod, a fydd yn achosi gwall 500 yn ystod terfynu'r pod. (am ddeunydd manylach ar y mater hwn, rydym ni wedi ei gyfieithu). Mae angen datrys y broblem hon yn y ffyrdd canlynol:

  • Anfon Cysylltiad: cau penawdau ymateb (os yw hyn yn ymwneud â chymhwysiad HTTP).
  • Os nad yw'n bosibl gwneud newidiadau i'r cod, yna mae'r erthygl ganlynol yn disgrifio datrysiad a fydd yn caniatáu ichi brosesu ceisiadau tan ddiwedd y cyfnod gosgeiddig.

Damcaniaeth. Sut mae NGINX a PHP-FPM yn terfynu eu prosesau

NGINX

Gadewch i ni ddechrau gyda NGINX, gan fod popeth yn fwy neu'n llai amlwg ag ef. Gan blymio i'r theori, rydyn ni'n dysgu bod gan NGINX un broses feistr a nifer o "weithwyr" - mae'r rhain yn brosesau plant sy'n prosesu ceisiadau cleientiaid. Darperir opsiwn cyfleus: defnyddio'r gorchymyn nginx -s <SIGNAL> terfynu prosesau naill ai yn y modd diffodd cyflym neu gau i lawr gosgeiddig. Yn amlwg, yr opsiwn olaf sydd o ddiddordeb i ni.

Yna mae popeth yn syml: mae angen ichi ychwanegu ato preStop-bachyn gorchymyn a fydd yn anfon signal cau i lawr gosgeiddig. Gellir gwneud hyn yn Defnyddio, yn y bloc cynhwysydd:

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

Nawr, pan fydd y pod yn cau, fe welwn y canlynol yn logiau cynhwysydd NGINX:

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

A bydd hyn yn golygu'r hyn sydd ei angen arnom: mae NGINX yn aros am geisiadau i'w cwblhau, ac yna'n lladd y broses. Fodd bynnag, isod byddwn hefyd yn ystyried problem gyffredin oherwydd hynny, hyd yn oed gyda'r gorchymyn nginx -s quit mae'r broses yn dod i ben yn anghywir.

Ac ar hyn o bryd rydyn ni wedi gorffen gyda NGINX: o leiaf o'r logiau gallwch chi ddeall bod popeth yn gweithio fel y dylai.

Beth yw'r fargen â PHP-FPM? Sut mae'n delio â chau i lawr yn osgeiddig? Gadewch i ni chyfrif i maes.

PHP-FPM

Yn achos PHP-FPM, mae ychydig yn llai o wybodaeth. Os ydych chi'n canolbwyntio ar llawlyfr swyddogol yn ôl PHP-FPM, bydd yn dweud bod y signalau POSIX canlynol yn cael eu derbyn:

  1. SIGINT, SIGTERM - cau i lawr yn gyflym;
  2. SIGQUIT — cau i lawr gosgeiddig (yr hyn sydd ei angen arnom).

Nid oes angen y signalau sy'n weddill yn y dasg hon, felly byddwn yn hepgor eu dadansoddiad. I derfynu'r broses yn gywir, bydd angen i chi ysgrifennu'r bachyn preStop canlynol:

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

Ar yr olwg gyntaf, dyma'r cyfan sydd ei angen i gyflawni cau gosgeiddig yn y ddau gynhwysydd. Fodd bynnag, mae'r dasg yn anoddach nag y mae'n ymddangos. Isod mae dau achos lle na weithiodd cau gosgeiddig a lle nad oedd y prosiect ar gael yn y tymor byr yn ystod y defnydd.

Ymarfer. Problemau posibl gyda chau i lawr gosgeiddig

NGINX

Yn gyntaf oll, mae'n ddefnyddiol cofio: yn ogystal â gweithredu'r gorchymyn nginx -s quit Mae un cam arall y mae'n werth rhoi sylw iddo. Daethom ar draws mater lle byddai NGINX yn dal i anfon SITERM yn lle'r signal SIGQUIT, gan achosi i geisiadau beidio â chwblhau'n gywir. Gellir dod o hyd i achosion tebyg, er enghraifft, yma. Yn anffodus, nid oeddem yn gallu pennu'r rheswm penodol am yr ymddygiad hwn: roedd amheuaeth am y fersiwn NGINX, ond ni chafodd ei gadarnhau. Y symptom oedd y gwelwyd negeseuon yn y logiau cynhwysydd NGINX: msgstr "soced agored #10 ar ôl yng nghysylltiad 5", ac ar ôl hynny stopiodd y pod.

Gallwn sylwi ar broblem o’r fath, er enghraifft, o’r ymatebion ar yr Ingress rydym angen:

Awgrymiadau a thriciau Kubernetes: nodweddion cau gosgeiddig yn NGINX a PHP-FPM
Dangosyddion codau statws ar adeg eu defnyddio

Yn yr achos hwn, dim ond cod gwall 503 a dderbyniwn gan Ingress ei hun: ni all gael mynediad i'r cynhwysydd NGINX, gan nad yw bellach yn hygyrch. Os edrychwch ar y logiau cynhwysydd gyda NGINX, maent yn cynnwys y canlynol:

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

Ar ôl newid y signal stopio, mae'r cynhwysydd yn dechrau stopio'n gywir: cadarnheir hyn gan y ffaith nad yw'r gwall 503 bellach yn cael ei arsylwi.

Os byddwch chi'n dod ar draws problem debyg, mae'n gwneud synnwyr i ddarganfod pa signal stopio sy'n cael ei ddefnyddio yn y cynhwysydd a beth yn union yw'r bachyn preStop. Mae'n ddigon posibl bod y rheswm yn gorwedd yn union yn hyn.

PHP-FPM... a mwy

Disgrifir y broblem gyda PHP-FPM mewn ffordd ddibwys: nid yw'n aros i brosesau plentyn gael eu cwblhau, mae'n eu terfynu, a dyna pam mae gwallau 502 yn digwydd yn ystod y defnydd a gweithrediadau eraill. Mae sawl adroddiad nam ar bugs.php.net ers 2005 (ee yma и yma), sy'n disgrifio'r broblem hon. Ond mae'n debyg na fyddwch yn gweld unrhyw beth yn y logiau: bydd PHP-FPM yn cyhoeddi bod ei broses wedi'i chwblhau heb unrhyw wallau na hysbysiadau trydydd parti.

Mae'n werth egluro y gall y broblem ei hun ddibynnu i raddau llai neu fwy ar y cais ei hun ac efallai na fydd yn amlygu ei hun, er enghraifft, wrth fonitro. Os byddwch chi'n dod ar ei draws, daw ateb syml i'r meddwl yn gyntaf: ychwanegwch fachyn preStop gyda sleep(30). Bydd yn caniatáu ichi gwblhau pob cais a oedd o'r blaen (ac nid ydym yn derbyn rhai newydd, ers pod eisoes gallu Terfynu), ac ar ôl 30 eiliad bydd y pod ei hun yn gorffen gyda signal SIGTERM.

Mae'n ymddangos bod lifecycle oherwydd bydd y cynhwysydd yn edrych fel hyn:

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

Fodd bynnag, oherwydd y 30 eiliad sleep rydym llawer byddwn yn cynyddu'r amser lleoli, gan y bydd pob pod yn cael ei derfynu lleiafswm 30 eiliad, sy'n ddrwg. Beth ellir ei wneud am hyn?

Gadewch i ni droi at y parti sy'n gyfrifol am weithredu'r cais yn uniongyrchol. Yn ein hachos ni y mae PHP-FPMPa yn ddiofyn nid yw'n monitro gweithrediad ei brosesau plentyn: Mae'r broses meistr yn cael ei derfynu ar unwaith. Gallwch newid yr ymddygiad hwn gan ddefnyddio'r gyfarwyddeb process_control_timeout, sy'n nodi'r terfynau amser ar gyfer prosesau plentyn i aros am signalau gan y meistr. Os byddwch yn gosod y gwerth i 20 eiliad, bydd hyn yn cwmpasu'r rhan fwyaf o'r ymholiadau sy'n rhedeg yn y cynhwysydd a bydd yn atal y brif broses unwaith y byddant wedi'u cwblhau.

Gyda'r wybodaeth hon, gadewch i ni ddychwelyd at ein problem olaf. Fel y crybwyllwyd, nid yw Kubernetes yn llwyfan monolithig: mae cyfathrebu rhwng ei wahanol gydrannau yn cymryd peth amser. Mae hyn yn arbennig o wir pan fyddwn yn ystyried gweithrediad Ingresses a chydrannau cysylltiedig eraill, oherwydd oherwydd oedi o'r fath ar adeg eu defnyddio mae'n hawdd cael ymchwydd o 500 o wallau. Er enghraifft, gall gwall ddigwydd yn y cam o anfon cais i fyny'r afon, ond mae'r “oedi amser” o ryngweithio rhwng cydrannau yn eithaf byr - llai nag eiliad.

Felly Mewn Cyfanswm gyda'r gyfarwyddeb a grybwyllwyd eisoes process_control_timeout gallwch ddefnyddio'r adeiladwaith canlynol ar gyfer lifecycle:

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

Yn yr achos hwn, byddwn yn gwneud iawn am yr oedi gyda'r gorchymyn sleep a pheidiwch â chynyddu'r amser lleoli yn fawr: a oes gwahaniaeth amlwg rhwng 30 eiliad ac un?.. Mewn gwirionedd, dyma'r process_control_timeoutAc lifecycle yn cael ei ddefnyddio fel “rhwyd ​​ddiogelwch” yn unig rhag ofn oedi.

A siarad yn gyffredinol mae'r ymddygiad a ddisgrifir a'r ateb cyfatebol yn berthnasol nid yn unig i PHP-FPM. Gall sefyllfa debyg godi mewn rhyw ffordd neu'i gilydd wrth ddefnyddio ieithoedd/fframweithiau eraill. Os na allwch drwsio cau gosgeiddig mewn ffyrdd eraill - er enghraifft, trwy ailysgrifennu'r cod fel bod y rhaglen yn prosesu signalau terfynu yn gywir - gallwch ddefnyddio'r dull a ddisgrifir. Efallai nad dyma'r harddaf, ond mae'n gweithio.

Ymarfer. Profi llwyth i wirio gweithrediad y pod

Mae profi llwyth yn un o'r ffyrdd o wirio sut mae'r cynhwysydd yn gweithio, gan fod y weithdrefn hon yn dod ag ef yn agosach at amodau ymladd go iawn pan fydd defnyddwyr yn ymweld â'r wefan. I brofi'r argymhellion uchod, gallwch eu defnyddio Yandex.Tankom: Mae'n cwmpasu ein holl anghenion yn berffaith. Mae'r canlynol yn awgrymiadau ac argymhellion ar gyfer cynnal profion gydag enghraifft glir o'n profiad diolch i graffiau Grafana a Yandex.Tank ei hun.

Y peth pwysicaf yma gwirio newidiadau gam wrth gam. Ar ôl ychwanegu atgyweiriad newydd, rhedwch y prawf i weld a yw'r canlyniadau wedi newid o gymharu â'r rhediad diwethaf. Fel arall, bydd yn anodd nodi atebion aneffeithiol, ac yn y tymor hir dim ond niwed y gall ei wneud (er enghraifft, cynyddu amser defnyddio).

Naws arall yw edrych ar y logiau cynhwysydd yn ystod ei derfynu. A yw gwybodaeth am gau i lawr gosgeiddig yn cael ei chofnodi yno? A oes unrhyw wallau yn y logiau wrth gyrchu adnoddau eraill (er enghraifft, i gynhwysydd PHP-FPM cyfagos)? Gwallau yn y cais ei hun (fel yn achos NGINX a ddisgrifir uchod)? Rwy'n gobeithio y bydd y wybodaeth ragarweiniol o'r erthygl hon yn eich helpu i ddeall yn well beth sy'n digwydd i'r cynhwysydd yn ystod ei derfyniad.

Felly, cynhaliwyd y prawf cyntaf hebddo lifecycle a heb gyfarwyddebau ychwanegol ar gyfer gweinydd y cais (process_control_timeout yn PHP-FPM). Pwrpas y prawf hwn oedd nodi nifer bras y gwallau (ac a oes rhai). Hefyd, o wybodaeth ychwanegol, dylech wybod bod yr amser defnyddio cyfartalog ar gyfer pob pod tua 5-10 eiliad nes ei fod yn gwbl barod. Y canlyniadau yw:

Awgrymiadau a thriciau Kubernetes: nodweddion cau gosgeiddig yn NGINX a PHP-FPM

Mae panel gwybodaeth Yandex.Tank yn dangos cynnydd mawr o 502 o wallau, a ddigwyddodd ar adeg eu defnyddio ac a barhaodd ar gyfartaledd hyd at 5 eiliad. Mae'n debyg bod hyn oherwydd bod ceisiadau presennol i'r hen god yn cael eu terfynu pan oedd yn cael ei derfynu. Ar ôl hyn, ymddangosodd gwallau 503, a oedd yn ganlyniad i gynhwysydd NGINX a stopiwyd, a oedd hefyd yn gollwng cysylltiadau oherwydd y backend (a ataliodd Ingress rhag cysylltu ag ef).

Gawn ni weld sut process_control_timeout yn PHP-FPM yn ein helpu i aros i brosesau plant gael eu cwblhau, h.y. cywiro gwallau o'r fath. Ail-leoli gan ddefnyddio'r gyfarwyddeb hon:

Awgrymiadau a thriciau Kubernetes: nodweddion cau gosgeiddig yn NGINX a PHP-FPM

Nid oes mwy o wallau yn ystod y 500fed defnydd! Mae'r lleoliad yn waith cau i lawr llwyddiannus, gosgeiddig.

Fodd bynnag, mae'n werth cofio'r broblem gyda chynwysyddion Ingress, sef canran fach o wallau y gallwn eu derbyn oherwydd oedi. Er mwyn eu hosgoi, y cyfan sydd ar ôl yw ychwanegu strwythur gyda nhw sleep ac ailadrodd y defnydd. Fodd bynnag, yn ein hachos penodol ni, nid oedd unrhyw newidiadau i'w gweld (eto, dim gwallau).

Casgliad

I derfynu'r broses yn osgeiddig, rydym yn disgwyl yr ymddygiad canlynol o'r cais:

  1. Arhoswch ychydig eiliadau ac yna stopiwch dderbyn cysylltiadau newydd.
  2. Arhoswch i bob cais gwblhau a chau pob cysylltiad cadw'n fyw nad yw'n gweithredu ceisiadau.
  3. Gorffennwch eich proses.

Fodd bynnag, ni all pob cais weithio fel hyn. Un ateb i'r broblem yn realiti Kubernetes yw:

  • ychwanegu bachyn cyn-stop a fydd yn aros ychydig eiliadau;
  • astudio ffeil ffurfweddu ein backend ar gyfer y paramedrau priodol.

Mae'r enghraifft gyda NGINX yn ei gwneud yn glir efallai na fydd hyd yn oed cais a ddylai brosesu signalau terfynu yn gywir i ddechrau yn gwneud hynny, felly mae'n hanfodol gwirio am wallau 500 wrth ddefnyddio'r cais. Mae hyn hefyd yn caniatáu ichi edrych ar y broblem yn ehangach a pheidio â chanolbwyntio ar un pod neu gynhwysydd, ond edrych ar y seilwaith cyfan yn ei gyfanrwydd.

Fel offeryn profi, gallwch ddefnyddio Yandex.Tank ar y cyd ag unrhyw system fonitro (yn ein hachos ni, cymerwyd data o Grafana gyda chefnlen Prometheus ar gyfer y prawf). Mae problemau gyda chau gosgeiddig i'w gweld yn glir o dan lwythi trwm y gall y meincnod eu cynhyrchu, ac mae monitro yn helpu i ddadansoddi'r sefyllfa'n fanylach yn ystod neu ar ôl y prawf.

Mewn ymateb i adborth ar yr erthygl: mae'n werth nodi bod y problemau a'r atebion yn cael eu disgrifio yma mewn perthynas â NGINX Ingress. Ar gyfer achosion eraill, mae yna atebion eraill, y gallwn eu hystyried yn y deunyddiau canlynol o'r gyfres.

PS

Arall o gyfres awgrymiadau a thriciau K8s:

Ffynhonnell: hab.com

Ychwanegu sylw