Kubernetes кеңештери жана амалдары: NGINX жана PHP-FPMде кооз өчүрүү өзгөчөлүктөрү

Kubernetes'те CI/CDди ишке ашыруунун типтүү шарты: колдонмо толугу менен токтоп калганга чейин жаңы кардарлардын суроо-талаптарын кабыл албашы керек, эң негизгиси, учурдагыларды ийгиликтүү аякташы керек.

Kubernetes кеңештери жана амалдары: NGINX жана PHP-FPMде кооз өчүрүү өзгөчөлүктөрү

Бул шартты сактоо жайылтуу учурунда нөлдүк токтоп калууга жетишүүгө мүмкүндүк берет. Бирок, абдан популярдуу таңгактарды (NGINX жана PHP-FPM сыяктуу) колдонуп жатканда да, ар бир жайылтууда каталардын көбөйүшүнө алып келе турган кыйынчылыктарга туш болушуңуз мүмкүн...

Теория. Кантип жашашат

Биз буга чейин чөптүн жашоо цикли жөнүндө кеңири жарыялаганбыз бул макалада. Каралып жаткан теманын контекстинде бизди төмөндөгүлөр кызыктырат: поп мамлекетке кирген учурда токтотуу, ага жаңы сурамдар жөнөтүлбөйт (под жок кылынды кызмат үчүн акыркы чекиттердин тизмесинен). Ошентип, жайгаштыруу учурунда токтоп калуудан качуу үчүн, тиркемени токтотуу маселесин туура чечишибиз жетиштүү.

Сиз ошондой эле демейки жеңилдик мөөнөтү экенин унутпашыбыз керек 30 секунд: ушундан кийин, подкаст токтотулат жана колдонмо ушул мезгилге чейин бардык суроо-талаптарды иштеп чыгууга үлгүрүшү керек. пикир: 5-10 секунддан ашык убакыт талап кылынган суроо-талап мурунтан эле көйгөйлүү болсо да, жакшылап өчүрүү мындан ары ага жардам бербейт...

Капчык токтогондо эмне болорун жакшыраак түшүнүү үчүн төмөнкү диаграмманы караңыз:

Kubernetes кеңештери жана амалдары: NGINX жана PHP-FPMде кооз өчүрүү өзгөчөлүктөрү

A1, B1 - очоктун абалы жөнүндө өзгөртүүлөрдү кабыл алуу
A2 - кетүү SIGTERM
B2 - Капчыгы акыркы чекиттерден алып салуу
B3 - Өзгөртүүлөрдү кабыл алуу (акыркы чекиттердин тизмеси өзгөрдү)
B4 - iptables эрежелерин жаңыртуу

Көңүл буруңуз: акыркы чекти жок кылуу жана SIGTERM жөнөтүү ырааттуу эмес, параллелдүү болот. Жана Ingress акыркы чекиттердин жаңыртылган тизмесин дароо албагандыгына байланыштуу, кардарлардын жаңы суроо-талаптары подрядга жөнөтүлөт, бул подкушту токтотуу учурунда 500 катага алып келет (бул маселе боюнча кененирээк материал үчүн, биз которулган). Бул көйгөй төмөнкү жолдор менен чечилиши керек:

  • Туташуу жөнөтүү: жооп аталыштарын жабуу (эгер бул HTTP тиркемесин тиешелүү болсо).
  • Эгер кодго өзгөртүүлөрдү киргизүү мүмкүн болбосо, анда кийинки макалада сизге суроо-талаптарды жагымдуу мезгилдин аягына чейин иштетүүгө мүмкүндүк берүүчү чечим сүрөттөлөт.

Теория. NGINX жана PHP-FPM процесстерин кантип токтотот

жөргөмүш

NGINX менен баштайлы, анткени аны менен баары аздыр-көптүр айкын. Теорияга сүңгүп, биз NGINXтин бир башкы процесси жана бир нече “жумушчулары” бар экенин билебиз - булар кардардын суроо-талаптарын иштеп чыгуучу бала процесстер. Ыңгайлуу вариант каралган: буйрукту колдонуу nginx -s <SIGNAL> процесстерди тез өчүрүү же кооз өчүрүү режиминде токтотуу. Албетте, бул бизди кызыктырган акыркы вариант.

Ошондо баары жөнөкөй: сиз кошуу керек алдын ала токтотуу илгич көрктүү өчүрүү сигналын жөнөтө турган буйрук. Бул контейнер блогунда, жайылтууда жасалышы мүмкүн:

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

Эми, поддон өчкөндө, биз 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

Жана бул бизге эмне керек дегенди билдирет: NGINX сурамдардын аткарылышын күтөт, анан процессти жок кылат. Бирок, төмөндө биз жалпы көйгөйдү карап чыгабыз, ал тургай, буйрук менен nginx -s quit процесс туура эмес аяктайт.

Ал эми бул этапта биз NGINX менен бүттүк: жок дегенде журналдардан сиз баары каалагандай иштеп жатканын түшүнө аласыз.

PHP-FPM менен кандай келишим бар? Ал кооз өчүрүүнү кантип чечет? Келгиле, аны аныктап көрөлү.

PHP-FPM

PHP-FPM учурда, бир аз азыраак маалымат бар. Эгер көңүл бурсаңыз расмий колдонмо PHP-FPM ылайык, ал төмөнкү POSIX сигналдар кабыл алынган деп айтылат:

  1. SIGINT, SIGTERM — тез өчүрүү;
  2. SIGQUIT — кооз өчүрүү (бизге эмне керек).

Калган сигналдар бул тапшырмада талап кылынбайт, ошондуктан биз алардын анализин өткөрүп жиберебиз. Процессти туура токтотуу үчүн, сиз төмөнкү preStop илгичин жазышыңыз керек:

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

Бир караганда, бул эки контейнерде жакшы өчүрүү үчүн зарыл болгон нерсе. Бирок, иш көрүнгөндөн да татаал. Төмөндө көрктүү өчүрүү иштебей калган жана жайылтуу учурунда долбоордун кыска мөөнөттүү жеткиликтүү болбой калышына алып келген эки учур келтирилген.

Машыгуу. Кереметтүү өчүрүү менен мүмкүн болгон көйгөйлөр

жөргөмүш

Биринчиден, бул эстен чыгарбоо пайдалуу: буйрукту аткаруудан тышкары nginx -s quit Көңүл бурууга арзырлык дагы бир этап бар. NGINX дагы эле SIGQUIT сигналынын ордуна SIGTERMди жөнөтө турган маселеге туш болдук, андыктан сурамдар туура эмес аяктады. Окшош учурларды табууга болот, мисалы, бул жерде. Тилекке каршы, биз бул жүрүм-турумдун конкреттүү себебин аныктай алган жокпуз: NGINX версиясы боюнча шектенүү бар болчу, бирок ал тастыкталган жок. Симптом NGINX контейнер журналдарында билдирүүлөр байкалган: "10-туташууда калган №5 розетка ачык", андан кийин подвод токтоп калды.

Биз мындай көйгөйдү байкай алабыз, мисалы, бизге керектүү Ingress боюнча жооптор:

Kubernetes кеңештери жана амалдары: NGINX жана PHP-FPMде кооз өчүрүү өзгөчөлүктөрү
Жайгаштыруу учурундагы абал коддорунун көрсөткүчтөрү

Бул учурда, биз Ingress өзүнөн эле 503 ката кодун алабыз: ал NGINX контейнерине кире албайт, анткени ал мындан ары жеткиликтүү эмес. NGINX менен контейнер журналдарын карасаңыз, алар төмөнкүлөрдү камтыйт:

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

Токтотуу сигналын өзгөрткөндөн кийин, контейнер туура токтой баштайт: бул 503 катасы байкалбай калгандыгы менен тастыкталат.

Эгер сиз дагы ушундай көйгөйгө туш болсоңуз, контейнерде кандай токтотуу сигналы колдонуларын жана preStop илгичинин так кандай экенин түшүнүү керек. Мунун себеби так ушул жерде болушу толук мүмкүн.

PHP-FPM... жана башкалар

PHP-FPM көйгөйү майда-чүйдөсүнө чейин сүрөттөлгөн: ал бала процесстеринин аякташын күтпөйт, аларды токтотот, ошондуктан жайылтууда жана башка операцияларда 502 ката пайда болот. 2005-жылдан бери bugs.php.net сайтында бир нече ката отчеттору бар (мис бул жерде и бул жерде), бул көйгөйдү сүрөттөйт. Бирок, балким, сиз журналдардан эч нерсе көрбөйсүз: PHP-FPM эч кандай катасыз же үчүнчү тараптын эскертмелерисиз процессинин аяктаганын жарыялайт.

Көйгөйдүн өзү аздыр-көптүр тиркеменин өзүнөн көз каранды болушу мүмкүн жана, мисалы, мониторингде көрүнбөй калышы мүмкүн экенин тактоо керек. Эгер сиз ага жолуксаңыз, биринчи кезекте жөнөкөй чечүү жолу келет: PreStop илгичти кошуңуз sleep(30). Бул сизге мурда болгон бардык сурамдарды аткарууга мүмкүндүк берет (жана биз жаңыларын кабыл албайбыз, анткени pod буга чейин абалда токтотуу), жана 30 секунддан кийин подконун өзү сигнал менен аяктайт SIGTERM.

Ал экен lifecycle үчүн контейнер төмөнкүдөй болот:

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

Бирок, 30 секунддан улам sleep биз күчтүү биз жайылтуу убактысын көбөйтөбүз, анткени ар бир поддон токтотулат минималдуу 30 секунд, бул жаман. Бул жөнүндө эмне кылсак болот?

Арыздын тузден-туз аткарылышына жооптуу тарапка кайрылалы. Биздин учурда ушундай PHP-FPMошол демейки боюнча, анын бала процесстеринин аткарылышын көзөмөлдөбөйт: Башкы процесс дароо токтотулат. Бул жүрүм-турумду директива аркылуу өзгөртө аласыз process_control_timeout, ал бала процесстеринин кожоюндан сигналдарды күтүү мөөнөттөрүн аныктайт. Эгер сиз маанини 20 секундага орнотсоңуз, бул контейнерде иштеген сурамдардын көбүн камтыйт жана алар аяктагандан кийин башкы процессти токтотот.

Ушул билим менен акыркы маселебизге кайрылалы. Жогоруда айтылгандай, Kubernetes монолиттүү платформа эмес: анын ар кандай компоненттеринин ортосундагы байланыш бир аз убакытты талап кылат. Бул, өзгөчө, биз Ingresses жана башка ага байланыштуу компоненттердин иштешин эске алганда туура болот, анткени жайылтуу учурундагы мындай кечигүүдөн улам 500 катанын өсүшү оңой. Мисалы, жогорку агымга суроо-талапты жөнөтүү стадиясында ката пайда болушу мүмкүн, бирок компоненттердин ортосундагы өз ара аракеттенүүнүн "убакыт кечигүү" абдан кыска - бир секунддан аз.

Ошондуктан, Жалпысынан буга чейин айтылган директива менен process_control_timeout үчүн төмөнкү курулушту колдоно аласыз lifecycle:

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

Бул учурда биз команда менен кечиктирүүнүн ордун толтурабыз sleep жана жайгаштыруу убактысын чоңойтпоңуз: 30 секунд менен бир секунданын ортосунда байкаларлык айырма барбы?.. Чынында, бул process_control_timeoutжана lifecycle артта калган учурда «коопсуздук тор» катары гана колдонулат.

Жалпылап айтканда, сүрөттөлгөн жүрүм-турум жана тиешелүү убактылуу чечүү PHP-FPM үчүн гана эмес. Окшош жагдай тигил же бул жол менен башка тилдерди/алкактарды колдонууда пайда болушу мүмкүн. Эгерде сиз көрктүү өчүрүүнү башка жолдор менен оңдой албасаңыз - мисалы, колдонмо токтотуу сигналдарын туура иштетиши үчүн кодду кайра жазуу менен - ​​сүрөттөлгөн ыкманы колдонсоңуз болот. Бул эң сулуу болушу мүмкүн эмес, бирок ал иштейт.

Машыгуу. Подгондун иштешин текшерүү үчүн тестти жүктөңүз

Жүктөөнү тестирлөө - бул контейнердин иштешин текшерүүнүн жолдорунун бири, анткени бул процедура колдонуучулар сайтка киргенде аны чыныгы согуштук шарттарга жакындатат. Жогорудагы сунуштарды сыноо үчүн, сиз колдоно аласыз Yandex.Tankom: Бул биздин бардык муктаждыктарыбызды кемчиликсиз камтыйт. Төмөндө Grafana жана Яндекс.Танктын графиктеринин аркасында биздин тажрыйбабыздан айкын мисал менен тестирлөө жүргүзүү боюнча кеңештер жана сунуштар келтирилген.

Бул жерде эң негизгиси этап-этабы менен өзгөрүүлөрдү текшерүү. Жаңы оңдоону кошкондон кийин, тестти иштетиңиз жана жыйынтыктар акыркы иштетүүгө салыштырмалуу өзгөргөнүн көрүңүз. Болбосо, натыйжасыз чечимдерди аныктоо кыйынга турат, жана узак мөөнөттүү келечекте ал зыян гана алып келиши мүмкүн (мисалы, жайылтуу убактысын көбөйтүү).

Дагы бир нюанс - аны токтотуу учурунда контейнер журналдарын карап көрүү. Ашыкча өчүрүү тууралуу маалымат ал жерде жазылганбы? Башка ресурстарга (мисалы, коңшу PHP-FPM контейнерине) кирүүдө журналдарда каталар барбы? Колдонмонун өзүндөгү каталар (жогоруда сүрөттөлгөн NGINX менен болгон окуядай)? Бул макаладагы кириш маалымат контейнерди токтотуу учурунда эмне болорун жакшыраак түшүнүүгө жардам берет деп үмүттөнөм.

Ошентип, биринчи тестирлөө жок болуп өттү lifecycle жана колдонмо сервери үчүн кошумча директиваларсыз (process_control_timeout PHP-FPMде). Бул тесттин максаты каталардын болжолдуу санын (жана бар-жогун) аныктоо болгон. Ошондой эле, кошумча маалымат боюнча, сиз ар бир подъезддин орточо жайылтуу убактысы ал толугу менен даяр болгонго чейин болжол менен 5-10 секунд болгонун билишиңиз керек. натыйжалары болуп саналат:

Kubernetes кеңештери жана амалдары: NGINX жана PHP-FPMде кооз өчүрүү өзгөчөлүктөрү

Yandex.Tank маалымат панели жайгаштыруу учурунда пайда болгон жана орто эсеп менен 502 секундага чейин созулган 5 катаны көрсөтөт. Кыязы, бул эски подкастка болгон суроо-талаптар ал токтотулуп жатканда токтотулуп жаткандыктан болду. Андан кийин, NGINX контейнеринин токтоп калышынын натыйжасы болгон 503 ката пайда болду, ал ошондой эле бэкендинин (Ingress ага туташуусуна тоскоол болгон) улам байланыштарды токтотту.

Келгиле, кантип карап көрөлү process_control_timeout PHP-FPMде бизге бала процесстеринин аякташын күтүүгө жардам берет, б.а. мындай каталарды оңдоо. Бул директиваны колдонуп кайра жайгаштырыңыз:

Kubernetes кеңештери жана амалдары: NGINX жана PHP-FPMде кооз өчүрүү өзгөчөлүктөрү

500-жайгаштыруу учурунда дагы каталар жок! Жайгаштыруу ийгиликтүү, көрктүү өчүрүү иштери.

Бирок, Ingress контейнерлери менен байланышкан маселени эстен чыгарбоо абзел, бул каталардын бир аз пайызы бизде убакыттын кечигүүсүнөн улам келип чыгышы мүмкүн. Аларды болтурбоо үчүн, структураны кошуу гана калды sleep жана жайгаштырууну кайталаңыз. Бирок, биздин өзгөчө учурда, эч кандай өзгөртүүлөр көрүнгөн жок (кайра, эч кандай каталар).

жыйынтыктоо

Процессти акырындык менен токтотуу үчүн, биз колдонмодон төмөнкү аракеттерди күтөбүз:

  1. Бир нече секунд күтө туруңуз, анан жаңы байланыштарды кабыл алууну токтотуңуз.
  2. Бардык сурамдардын аткарылышын күтүңүз жана сурамдарды аткарбаган бардык туруктуу байланыштарды жабыңыз.
  3. Процессиңизди бүтүрүңүз.

Бирок, бардык колдонмолор ушундай иштей албайт. Kubernetes реалиясындагы маселенин бир чечими:

  • бир нече секунд күтө турган алдын ала токтотуу илгичти кошуу;
  • тиешелүү параметрлер үчүн биздин сервердин конфигурация файлын изилдөө.

NGINX менен болгон мисал, адегенде токтотуу сигналдарын туура иштетиши керек болгон тиркеме да андай кылбашы мүмкүн экенин ачык көрсөтүп турат, андыктан тиркемени жайылтуу учурунда 500 катаны текшерүү өтө маанилүү. Бул ошондой эле көйгөйдү кененирээк кароого жана бир подъездге же контейнерге көңүл бурбастан, бүтүндөй инфраструктураны кароого мүмкүндүк берет.

Тестирлөө куралы катары, сиз Yandex.Tankты каалаган мониторинг системасы менен бирге колдоно аласыз (биздин учурда, маалыматтар Grafanaдан Prometheus бэкэнди менен тесттен алынган). Сыноочу өчүрүү көйгөйлөрү эталон түзө турган оор жүктөрдө даана көрүнүп турат жана мониторинг сыноо учурунда же андан кийин кырдаалды деталдуу талдап чыгууга жардам берет.

Макала боюнча пикирлерге жооп катары: NGINX Ingress менен байланыштуу көйгөйлөр жана чечимдер бул жерде сүрөттөлгөндүгүн белгилей кетүү керек. Башка учурларда, башка чечимдер бар, аларды биз сериянын төмөнкү материалдарында карап чыгабыз.

PS

K8s кеңештер жана ыкмалар сериясынан башка:

Source: www.habr.com

Комментарий кошуу