Кубернетес савети и трикови: карактеристике грациозног искључивања у НГИНКС-у и ПХП-ФПМ-у

Типичан услов за имплементацију ЦИ/ЦД-а у Кубернетес: апликација мора бити у стању да не прихвати нове клијентске захтеве пре него што се потпуно заустави, и што је најважније, успешно заврши постојеће.

Кубернетес савети и трикови: карактеристике грациозног искључивања у НГИНКС-у и ПХП-ФПМ-у

Усклађеност са овим условом омогућава вам да постигнете нула застоја током имплементације. Међутим, чак и када користите веома популарне пакете (као што су НГИНКС и ПХП-ФПМ), можете наићи на потешкоће које ће довести до налета грешака при сваком постављању...

Тхеори. Како под живи

Већ смо детаљно објавили о животном циклусу махуна овај чланак. У контексту теме која се разматра, интересује нас следеће: у тренутку када махуна улази у стање Терминатинг, нови захтеви престају да му се шаљу (под уклоњен са листе крајњих тачака за услугу). Дакле, да бисмо избегли застоје током имплементације, довољно је да правилно решимо проблем заустављања апликације.

Такође треба да запамтите да је подразумевани грејс период 30 секунди: након овога, под ће бити прекинут и апликација мора имати времена да обради све захтеве пре овог периода. Приметити: иако је сваки захтев који траје више од 5-10 секунди већ проблематичан, а грациозно гашење му више неће помоћи...

Да бисте боље разумели шта се дешава када се под заврши, само погледајте следећи дијаграм:

Кубернетес савети и трикови: карактеристике грациозног искључивања у НГИНКС-у и ПХП-ФПМ-у

А1, Б1 - Пријем промена о стању огњишта
А2 - Полазак СИГТЕРМ
Б2 – Уклањање капсуле са крајњих тачака
Б3 – Пријем промена (листа крајњих тачака је промењена)
Б4 - Ажурирајте иптаблес правила

Имајте на уму: брисање модула крајње тачке и слање СИГТЕРМ-а се не дешава секвенцијално, већ паралелно. А због чињенице да Ингресс не добије одмах ажурирану листу крајњих тачака, нови захтеви клијената ће бити послати у под, што ће изазвати грешку од 500 током завршетка под (за детаљнији материјал о овом питању, ми преведено). Овај проблем треба решити на следеће начине:

  • Пошаљи везу: затворите у заглављима одговора (ако се ради о ХТТП апликацији).
  • Ако није могуће извршити промене у коду, онда следећи чланак описује решење које ће вам омогућити да обрађујете захтеве до краја граце период.

Тхеори. Како НГИНКС и ПХП-ФПМ завршавају своје процесе

НГИНКС

Почнимо са НГИНКС-ом, пошто је са њим све мање-више очигледно. Урањајући у теорију, сазнајемо да НГИНКС има један главни процес и неколико „радника“ – то су подређени процеси који обрађују захтеве клијената. Предвиђена је погодна опција: коришћењем команде nginx -s <SIGNAL> завршите процесе у режиму брзог искључивања или грациозног искључивања. Очигледно нас занима ова друга опција.

Онда је све једноставно: потребно је додати преСтоп-хоок команда која ће послати грациозан сигнал за искључивање. Ово се може урадити у Деплоимент-у, у блоку контејнера:

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

Сада, када се под искључи, видећемо следеће у евиденцији НГИНКС контејнера:

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 -s quit процес се неисправно завршава.

И у овој фази смо завршили са НГИНКС-ом: барем из евиденције можете да разумете да све ради како треба.

Шта је са ПХП-ФПМ-ом? Како се носи са грациозним искључивањем? Хајде да то схватимо.

ПХП-ФПМ

У случају ПХП-ФПМ-а, има мало мање информација. Ако се фокусирате на званични приручник према ПХП-ФПМ-у, то ће рећи да су следећи ПОСИКС сигнали прихваћени:

  1. SIGINT, SIGTERM — брзо гашење;
  2. SIGQUIT — грациозно гашење (оно што нам треба).

Преостали сигнали нису потребни у овом задатку, па ћемо њихову анализу изоставити. Да бисте исправно прекинули процес, мораћете да напишете следећу преСтоп куку:

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

На први поглед, ово је све што је потребно да се изврши елегантно гашење у оба контејнера. Међутим, задатак је тежи него што се чини. Испод су два случаја у којима грациозно гашење није функционисало и изазвало је краткорочну недоступност пројекта током имплементације.

Вежбајте. Могући проблеми са грациозним искључивањем

НГИНКС

Пре свега, корисно је запамтити: поред извршавања команде nginx -s quit Постоји још једна фаза на коју вреди обратити пажњу. Наишли смо на проблем где би НГИНКС и даље слао СИГТЕРМ уместо СИГКУИТ сигнала, што је довело до тога да се захтеви не довршавају исправно. Слични случајеви се могу наћи, нпр. овде. Нажалост, нисмо успели да утврдимо конкретан разлог за овакво понашање: постојала је сумња у НГИНКС верзију, али није потврђена. Симптом је био да су поруке примећене у евиденцији НГИНКС контејнера: "отворена утичница #10 остала у вези 5", након чега је под стао.

Такав проблем можемо уочити, на пример, из одговора на Ингрессу који су нам потребни:

Кубернетес савети и трикови: карактеристике грациозног искључивања у НГИНКС-у и ПХП-ФПМ-у
Индикатори статусних кодова у тренутку распоређивања

У овом случају, добијамо само код грешке 503 од самог Ингресс-а: он не може да приступи НГИНКС контејнеру, пошто му више није доступан. Ако погледате дневнике контејнера са НГИНКС-ом, они садрже следеће:

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

Након промене сигнала за заустављање, контејнер почиње исправно да се зауставља: ​​то потврђује чињеница да се грешка 503 више не примећује.

Ако наиђете на сличан проблем, има смисла открити који се сигнал за заустављање користи у контејнеру и како тачно изгледа кука за заустављање. Сасвим је могуће да разлог лежи управо у томе.

ПХП-ФПМ... и више

Проблем са ПХП-ФПМ-ом је описан на тривијалан начин: он не чека завршетак подређених процеса, он их прекида, због чега се јављају грешке 502 током имплементације и других операција. Постоји неколико извештаја о грешкама на бугс.пхп.нет од 2005 (нпр овде и овде), који описује овај проблем. Али највероватније нећете видети ништа у евиденцији: ПХП-ФПМ ће објавити завршетак свог процеса без икаквих грешака или обавештења треће стране.

Вреди појаснити да сам проблем може зависити у мањој или већој мери од саме апликације и можда се неће манифестовати, на пример, у надгледању. Ако наиђете на то, прво вам пада на памет једноставно решење: додајте преСтоп куку са sleep(30). То ће вам омогућити да испуните све захтеве који су били раније (а ми не прихватамо нове, пошто под већ способан за Терминатинг), а након 30 секунди сама капсула ће се завршити сигналом SIGTERM.

Испоставило се да lifecycle за контејнер ће изгледати овако:

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

Међутим, због 30 сек sleep ми снажно продужићемо време распоређивања, пошто ће свака група бити прекинута минимум 30 секунди, што је лоше. Шта се може учинити поводом овога?

Хајде да се обратимо страни која је одговорна за директно извршење апликације. У нашем случају јесте ПХП-ФПМКоји подразумевано не надгледа извршавање својих подређених процеса: Главни процес се одмах прекида. Ово понашање можете променити помоћу директиве process_control_timeout, који специфицира временска ограничења за подређене процесе да чекају сигнале од мастера. Ако поставите вредност на 20 секунди, ово ће покрити већину упита који се извршавају у контејнеру и зауставиће главни процес када се заврше.

Са овим сазнањем, вратимо се на наш последњи проблем. Као што је поменуто, Кубернетес није монолитна платформа: комуникација између његових различитих компоненти траје неко време. Ово је посебно тачно када узмемо у обзир рад Ингрессес-а и других сродних компоненти, јер је због таквог кашњења у тренутку имплементације лако добити налет од 500 грешака. На пример, може доћи до грешке у фази слања захтева узводном, али је „временско кашњење“ интеракције између компоненти прилично кратко - мање од једне секунде.

Дакле, Укупно са већ поменутом директивом process_control_timeout можете користити следећу конструкцију за lifecycle:

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

У овом случају, кашњење ћемо надокнадити командом sleep и немојте много да повећавате време примене: да ли постоји приметна разлика између 30 секунди и једне?.. У ствари, то је process_control_timeoutИ lifecycle користи се само као „заштитна мрежа“ у случају заостајања.

Генерално говорећи описано понашање и одговарајуће решење не примењују се само на ПХП-ФПМ. Слична ситуација може на овај или онај начин настати када се користе други језици/оквири. Ако не можете да поправите грациозно искључивање на друге начине – на пример, поновним писањем кода тако да апликација исправно обрађује сигнале завршетка – можете користити описани метод. Можда није најлепши, али ради.

Вежбајте. Тестирање оптерећења за проверу рада капсуле

Тестирање оптерећења је један од начина да се провери како контејнер ради, јер га овај поступак приближава стварним борбеним условима када корисници посете сајт. Да бисте тестирали горе наведене препоруке, можете користити Иандек.Танком: Савршено покрива све наше потребе. Следе савети и препоруке за спровођење тестирања са јасним примером из нашег искуства захваљујући графиконима Графане и самог Иандек.Танк-а.

Овде је најважније проверите промене корак по корак. Након што додате нову исправку, покрените тест и погледајте да ли су се резултати променили у поређењу са последњим покретањем. У супротном, биће тешко идентификовати неефикасна решења, а дугорочно то може само да нашкоди (на пример, да продужи време примене).

Још једна нијанса је да погледате дневнике контејнера током његовог завршетка. Да ли су тамо забележене информације о грациозном гашењу? Има ли грешака у евиденцији приликом приступа другим ресурсима (на пример, суседном ПХП-ФПМ контејнеру)? Грешке у самој апликацији (као у горе описаном случају са НГИНКС-ом)? Надам се да ће вам уводне информације из овог чланка помоћи да боље разумете шта се дешава са контејнером током његовог прекида.

Дакле, прва пробна вожња је одржана без lifecycle и без додатних директива за сервер апликација (process_control_timeout у ПХП-ФПМ). Сврха овог теста је била да се идентификује приближан број грешака (и да ли их има). Такође, из додатних информација, требало би да знате да је просечно време постављања за сваку подлогу било око 5-10 секунди док није била потпуно спремна. Резултати су:

Кубернетес савети и трикови: карактеристике грациозног искључивања у НГИНКС-у и ПХП-ФПМ-у

Панел са информацијама Иандек.Танк показује нагли пораст од 502 грешке, које су се десиле у време примене и које су у просеку трајале до 5 секунди. Вероватно је то било зато што су постојећи захтеви према старој подлози били прекинути када је она била прекинута. Након овога, појавиле су се 503 грешке, што је резултат заустављеног НГИНКС контејнера, који је такође прекинуо везе због позадинског дела (који је спречио Ингресс да се повеже са њим).

Да видимо како process_control_timeout у ПХП-ФПМ ће нам помоћи да сачекамо завршетак подређених процеса, тј. исправити такве грешке. Поново примените помоћу ове директиве:

Кубернетес савети и трикови: карактеристике грациозног искључивања у НГИНКС-у и ПХП-ФПМ-у

Нема више грешака током 500. размештања! Примена је успешна, грациозно гашење функционише.

Међутим, вреди запамтити проблем са Ингресс контејнерима, мали проценат грешака које можемо добити због временског кашњења. Да бисте их избегли, остаје само да додате структуру са sleep и поновите распоређивање. Међутим, у нашем конкретном случају, никакве промене нису биле видљиве (опет, нема грешака).

Закључак

Да бисмо грациозно окончали процес, очекујемо следеће понашање од апликације:

  1. Сачекајте неколико секунди, а затим престаните да прихватате нове везе.
  2. Сачекајте да се сви захтеви заврше и затворите све активне везе које не извршавају захтеве.
  3. Завршите свој процес.

Међутим, не могу све апликације да раде на овај начин. Једно решење проблема у Кубернетес стварности је:

  • додавање пре-стоп куке која ће сачекати неколико секунди;
  • проучавајући конфигурациону датотеку нашег бекенда за одговарајуће параметре.

Пример са НГИНКС-ом јасно показује да чак и апликација која у почетку треба да правилно обрађује сигнале завршетка можда то неће учинити, тако да је кључно проверити 500 грешака током примене апликације. Ово вам такође омогућава да на проблем сагледате шире и да се не фокусирате на једну капсулу или контејнер, већ да погледате целу инфраструктуру у целини.

Као алат за тестирање, можете користити Иандек.Танк у комбинацији са било којим системом за праћење (у нашем случају, подаци су преузети из Графане са Прометхеус позадином за тестирање). Проблеми са грациозним искључивањем су јасно видљиви под великим оптерећењима која бенчмарк може да генерише, а праћење помаже да се ситуација детаљније анализира током или након теста.

Као одговор на повратне информације о чланку: вреди напоменути да су овде описани проблеми и решења у вези са НГИНКС Ингресс. За друге случајеве постоје и друга решења која ћемо размотрити у следећим материјалима серије.

ПС

Остало из К8с серије савета и трикова:

Извор: ввв.хабр.цом

Додај коментар