Kubernetes maslahatlari va fokuslari: NGINX va PHP-FPM-da oqlangan o'chirish xususiyatlari

Kubernetes-da CI/CD-ni amalga oshirishning odatiy sharti: dastur to'liq to'xtamasdan oldin yangi mijoz so'rovlarini qabul qila olmasligi va eng muhimi, mavjudlarini muvaffaqiyatli bajarishi kerak.

Kubernetes maslahatlari va fokuslari: NGINX va PHP-FPM-da oqlangan o'chirish xususiyatlari

Ushbu shartga rioya qilish sizga joylashtirish vaqtida nol ishlamay qolishga erishish imkonini beradi. Biroq, juda mashhur to'plamlardan (masalan, NGINX va PHP-FPM) foydalanganda ham, har bir joylashtirishda xatolarning ko'payishiga olib keladigan qiyinchiliklarga duch kelishingiz mumkin...

Nazariya. Pod qanday yashaydi

Biz allaqachon podaning hayot aylanishi haqida batafsil nashr qildik Ushbu maqola. Ko'rib chiqilayotgan mavzu kontekstida bizni quyidagilar qiziqtiradi: pod davlatga kirgan paytda Bekor qilish, unga yangi so'rovlar yuborilmaydi (pod olib tashlandi xizmat uchun so'nggi nuqtalar ro'yxatidan). Shunday qilib, joylashtirish paytida ishlamay qolishning oldini olish uchun dasturni to'xtatish muammosini to'g'ri hal qilish kifoya.

Bundan tashqari, standart imtiyozli davr ekanligini unutmasligingiz kerak 30 soniya: shundan so'ng, podkast tugatiladi va ilova ushbu muddatgacha barcha so'rovlarni ko'rib chiqish uchun vaqtga ega bo'lishi kerak. nota: 5-10 soniyadan ko'proq vaqt talab qiladigan har qanday so'rov allaqachon muammoli bo'lsa-da va oqlangan o'chirish endi yordam bermaydi...

Pod tugashi bilan nima sodir bo'lishini yaxshiroq tushunish uchun quyidagi diagrammaga qarang:

Kubernetes maslahatlari va fokuslari: NGINX va PHP-FPM-da oqlangan o'chirish xususiyatlari

A1, B1 - o'choq holati haqida o'zgarishlarni qabul qilish
A2 - ketish SIGTERM
B2 - so'nggi nuqtalardan podani olib tashlash
B3 - O'zgarishlarni qabul qilish (so'nggi nuqtalar ro'yxati o'zgartirildi)
B4 - iptables qoidalarini yangilang

E'tibor bering: so'nggi nuqtani o'chirish va SIGTERMni yuborish ketma-ket emas, balki parallel ravishda amalga oshiriladi. Va Ingress oxirgi nuqtalarning yangilangan ro'yxatini darhol olmaganligi sababli, mijozlardan yangi so'rovlar podkaga yuboriladi, bu pod to'xtatish paytida 500 xatoga olib keladi. (ushbu masala bo'yicha batafsilroq material uchun biz tarjima qilingan). Ushbu muammoni quyidagi yo'llar bilan hal qilish kerak:

  • Ulanishni yuborish: javob sarlavhalarini yoping (agar bu HTTP ilovasiga tegishli bo'lsa).
  • Agar kodga o'zgartirish kiritish imkoni bo'lmasa, keyingi maqolada so'rovlarni imtiyozli davr oxirigacha ko'rib chiqishga imkon beradigan yechim tasvirlangan.

Nazariya. NGINX va PHP-FPM qanday jarayonlarni tugatadi

NGINX

NGINX dan boshlaylik, chunki u bilan hamma narsa ko'proq yoki kamroq aniq. Nazariyaga kirib, biz NGINX-da bitta asosiy jarayon va bir nechta "ishchilar" borligini bilib olamiz - bular mijoz so'rovlarini qayta ishlaydigan bolalar jarayonlari. Qulay variant taqdim etiladi: buyruq yordamida nginx -s <SIGNAL> jarayonlarni tez o'chirish yoki oqlangan o'chirish rejimida tugatish. Shubhasiz, bizni qiziqtirgan oxirgi variant.

Keyin hamma narsa oddiy: siz qo'shishingiz kerak prestop kancasi oqlangan o'chirish signalini yuboradigan buyruq. Buni Deployment-da, konteyner blokida qilish mumkin:

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

Endi, pod yopilganda, biz NGINX konteyner jurnallarida quyidagilarni ko'ramiz:

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

Va bu bizga kerak bo'lgan narsani anglatadi: NGINX so'rovlarning bajarilishini kutadi va keyin jarayonni o'ldiradi. Biroq, quyida biz buyruq bilan ham keng tarqalgan muammoni ko'rib chiqamiz nginx -s quit jarayon noto'g'ri tugaydi.

Va bu bosqichda biz NGINX bilan tugatdik: hech bo'lmaganda jurnallardan hamma narsa kerakli darajada ishlayotganini tushunishingiz mumkin.

PHP-FPM bilan qanday kelishuv bor? U oqlangan o'chirishni qanday boshqaradi? Keling, buni aniqlaylik.

PHP-FPM

PHP-FPM holatida ma'lumotlar biroz kamroq. Agar e'tiboringizni qaratsangiz rasmiy qo'llanma PHP-FPM ga ko'ra, u quyidagi POSIX signallari qabul qilinganligini aytadi:

  1. SIGINT, SIGTERM - tez o'chirish;
  2. SIGQUIT - oqlangan o'chirish (bizga kerak bo'lgan narsa).

Qolgan signallar bu vazifada talab qilinmaydi, shuning uchun biz ularning tahlilini o'tkazib yuboramiz. Jarayonni to'g'ri tugatish uchun siz quyidagi preStop kancasini yozishingiz kerak bo'ladi:

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

Bir qarashda, bu ikkala konteynerda ham oqlangan o'chirishni amalga oshirish uchun zarur bo'lgan narsadir. Biroq, vazifa ko'rinadiganidan ko'ra qiyinroq. Quyida oqlangan o'chirish ishlamagan va joylashtirish paytida loyihaning qisqa muddatli ishlamay qolishiga olib kelgan ikkita holat keltirilgan.

Amaliyot. Chiroyli o'chirish bilan bog'liq mumkin bo'lgan muammolar

NGINX

Avvalo, eslash foydalidir: buyruqni bajarishdan tashqari nginx -s quit E'tibor berishga arziydigan yana bir bosqich bor. NGINX hali ham SIGQUIT signali o‘rniga SIGTERM ni yuboradigan muammoga duch keldik, bu esa so‘rovlarning to‘g‘ri bajarilmasligiga olib keldi. Shunga o'xshash holatlarni topish mumkin, masalan, shu yerda. Afsuski, biz bu xatti-harakatning aniq sababini aniqlay olmadik: NGINX versiyasi haqida shubha bor edi, lekin u tasdiqlanmadi. Alomat shundan iboratki, xabarlar NGINX konteyner jurnallarida kuzatilgan: "10-ulanishda qolgan №5 rozetkani oching", shundan keyin pod to'xtadi.

Biz bunday muammoni, masalan, bizga kerak bo'lgan kirish haqidagi javoblardan ko'rishimiz mumkin:

Kubernetes maslahatlari va fokuslari: NGINX va PHP-FPM-da oqlangan o'chirish xususiyatlari
Joylashtirish vaqtidagi holat kodlari ko'rsatkichlari

Bunday holda, biz Ingressning o'zidan atigi 503 xato kodini olamiz: u NGINX konteyneriga kira olmaydi, chunki u endi mavjud emas. NGINX bilan konteyner jurnallariga qarasangiz, ular quyidagilarni o'z ichiga oladi:

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

To'xtash signalini o'zgartirgandan so'ng, konteyner to'g'ri to'xtashni boshlaydi: bu 503 xatosi endi kuzatilmaganligi bilan tasdiqlanadi.

Agar siz shunga o'xshash muammoga duch kelsangiz, konteynerda qanday to'xtash signali ishlatilishini va preStop kancasi qanday ko'rinishini aniqlash mantiqan. Buning sababi aynan shu yerda bo'lishi mumkin.

PHP-FPM... va boshqalar

PHP-FPM bilan bog'liq muammo arzimas tarzda tasvirlangan: u bolalar jarayonlarining tugashini kutmaydi, ularni tugatadi, shuning uchun joylashtirish va boshqa operatsiyalarda 502 xatolik yuzaga keladi. 2005 yildan beri bugs.php.net saytida bir nechta xato hisobotlari mavjud (masalan shu yerda и shu yerda), bu muammoni tavsiflaydi. Ammo, ehtimol, siz jurnallarda hech narsani ko'rmaysiz: PHP-FPM hech qanday xato yoki uchinchi tomon bildirishnomalarisiz o'z jarayoni tugaganligini e'lon qiladi.

Muammoning o'zi ozroq yoki ko'p darajada dasturning o'ziga bog'liq bo'lishi va, masalan, monitoringda o'zini namoyon qilmasligi mumkinligini aniqlashtirish kerak. Agar siz bunga duch kelsangiz, avval aqlga oddiy vaqtinchalik yechim keladi: preStop kancasini qo'shing sleep(30). Bu sizga ilgari bo'lgan barcha so'rovlarni bajarishga imkon beradi (va biz yangilarini qabul qilmaymiz, chunki pod allaqachon holatida Bekor qilish), va 30 soniyadan so'ng podning o'zi signal bilan tugaydi SIGTERM.

Bu chiqadi lifecycle uchun konteyner quyidagicha ko'rinadi:

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

Biroq, 30 soniya tufayli sleep bizmiz kuchli biz joylashtirish vaqtini oshiramiz, chunki har bir pod to'xtatiladi eng kam 30 soniya, bu yomon. Bu borada nima qilish mumkin?

Keling, arizaning to'g'ridan-to'g'ri bajarilishi uchun mas'ul bo'lgan tomonga murojaat qilaylik. Bizning holatlarimizda shunday PHP-FPM, bu sukut bo'yicha o'zining asosiy jarayonlarining bajarilishini nazorat qilmaydi: Asosiy jarayon darhol tugatiladi. Direktiv yordamida bu xatti-harakatni o'zgartirishingiz mumkin process_control_timeout, bu ustadan signallarni kutish uchun bolalar jarayonlari uchun vaqt chegaralarini belgilaydi. Agar siz qiymatni 20 soniyaga o'rnatsangiz, bu konteynerda ishlaydigan so'rovlarning ko'p qismini qamrab oladi va ular tugallangandan so'ng asosiy jarayonni to'xtatadi.

Ushbu bilim bilan, keling, oxirgi muammomizga qaytaylik. Yuqorida aytib o'tilganidek, Kubernetes monolit platforma emas: uning turli komponentlari o'rtasidagi aloqa biroz vaqt talab etadi. Bu, ayniqsa, Ingresses va boshqa tegishli komponentlarning ishlashini ko'rib chiqsak, to'g'ri keladi, chunki joylashtirish vaqtidagi bunday kechikish tufayli 500 ta xatoni olish oson. Masalan, yuqori oqimga so'rov yuborish bosqichida xatolik yuz berishi mumkin, ammo komponentlar o'rtasidagi o'zaro ta'sirning "vaqt kechikishi" juda qisqa - bir soniyadan kamroq.

Shuning uchun, Jami allaqachon aytib o'tilgan direktiva bilan process_control_timeout uchun quyidagi qurilishdan foydalanishingiz mumkin lifecycle:

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

Bunday holda, biz kechikishni buyruq bilan qoplaymiz sleep va joylashtirish vaqtini sezilarli darajada oshirmang: 30 soniya va bir soniya o'rtasida sezilarli farq bormi?.. Aslida, bu process_control_timeoutva lifecycle kechikish holatlarida faqat "xavfsizlik tarmog'i" sifatida ishlatiladi.

Odatda, tasvirlangan xatti-harakatlar va tegishli vaqtinchalik yechim nafaqat PHP-FPM uchun amal qiladi. Shunga o'xshash vaziyat boshqa tillardan/ramkalardan foydalanganda u yoki bu tarzda yuzaga kelishi mumkin. Agar siz oqlangan o'chirishni boshqa yo'llar bilan tuzata olmasangiz - masalan, dastur tugatish signallarini to'g'ri ishlashi uchun kodni qayta yozish orqali - siz tasvirlangan usuldan foydalanishingiz mumkin. Bu eng chiroyli bo'lmasligi mumkin, lekin u ishlaydi.

Amaliyot. Podning ishlashini tekshirish uchun sinovni yuklang

Yukni sinovdan o'tkazish konteyner qanday ishlashini tekshirish usullaridan biridir, chunki bu protsedura foydalanuvchilar saytga tashrif buyurganlarida uni haqiqiy jangovar sharoitlarga yaqinlashtiradi. Yuqoridagi tavsiyalarni sinab ko'rish uchun siz foydalanishingiz mumkin Yandex.Tankom: U bizning barcha ehtiyojlarimizni mukammal darajada qoplaydi. Quyida Grafana va Yandex.Tank grafiklari tufayli tajribamizdan aniq misol bilan test o'tkazish bo'yicha maslahatlar va tavsiyalar keltirilgan.

Bu erda eng muhimi o'zgarishlarni bosqichma-bosqich tekshiring. Yangi tuzatish qo'shgandan so'ng, sinovni o'tkazing va natijalar oxirgi ish bilan solishtirganda o'zgarganligini tekshiring. Aks holda, samarasiz echimlarni aniqlash qiyin bo'ladi va uzoq muddatda u faqat zarar etkazishi mumkin (masalan, joylashtirish vaqtini oshirish).

Yana bir nuance - uni tugatish paytida konteyner jurnallariga qarash. U erda oqlangan o'chirish haqida ma'lumot yozilganmi? Boshqa resurslarga (masalan, qo'shni PHP-FPM konteyneriga) kirishda jurnallarda xatolar bormi? Ilovaning o'zida xatolar (yuqorida tavsiflangan NGINX bilan bo'lgani kabi)? Umid qilamanki, ushbu maqoladagi kirish ma'lumotlari konteynerni tugatish paytida nima sodir bo'lishini yaxshiroq tushunishga yordam beradi.

Shunday qilib, birinchi sinov yugurishsiz bo'lib o'tdi lifecycle va dastur serveri uchun qo'shimcha ko'rsatmalarsiz (process_control_timeout PHP-FPM da). Ushbu testning maqsadi xatolarning taxminiy sonini (va bor yoki yo'qligini) aniqlash edi. Bundan tashqari, qo'shimcha ma'lumotlardan shuni bilishingiz kerakki, har bir pod uchun o'rtacha o'rnatish vaqti to'liq tayyor bo'lgunga qadar taxminan 5-10 soniya edi. Natijalar:

Kubernetes maslahatlari va fokuslari: NGINX va PHP-FPM-da oqlangan o'chirish xususiyatlari

Yandex.Tank ma'lumot panelida 502 ta xatolik ko'rsatkichi ko'rsatilgan, ular joylashtirish vaqtida yuzaga kelgan va o'rtacha 5 soniyagacha davom etgan. Ehtimol, bu eski podkastga mavjud so'rovlar tugatilayotganda to'xtatilganligi sababli bo'lgan. Shundan so'ng, 503 xatolik paydo bo'ldi, bu to'xtatilgan NGINX konteynerining natijasi bo'lib, u ham backend tufayli ulanishlarni to'xtatdi (bu Ingressning unga ulanishiga to'sqinlik qildi).

Keling, qanday qilib process_control_timeout PHP-FPM da bizga bolalar jarayonlarining tugashini kutishga yordam beradi, ya'ni. bunday xatolarni tuzatish. Ushbu direktiv yordamida qayta o'rnating:

Kubernetes maslahatlari va fokuslari: NGINX va PHP-FPM-da oqlangan o'chirish xususiyatlari

500-joylashtirishda boshqa xatolik yo'q! Joylashtirish muvaffaqiyatli, oqlangan o'chirish ishlari.

Biroq, Ingress konteynerlari bilan bog'liq muammoni esga olish kerak, bu vaqt oralig'i tufayli biz olishimiz mumkin bo'lgan xatolarning kichik foizi. Ularning oldini olish uchun faqat strukturani qo'shish qoladi sleep va joylashtirishni takrorlang. Biroq, bizning alohida holatimizda hech qanday o'zgarishlar ko'rinmadi (yana xatoliklar yo'q).

xulosa

Jarayonni oqilona tugatish uchun biz ilovadan quyidagi xatti-harakatlarni kutamiz:

  1. Bir necha soniya kuting va keyin yangi ulanishlarni qabul qilishni to'xtating.
  2. Barcha so'rovlar bajarilishini kuting va so'rovlarni bajarmayotgan barcha doimiy ulanishlarni yoping.
  3. Jarayoningizni tugating.

Biroq, barcha ilovalar bu tarzda ishlay olmaydi. Kubernetes voqeliklarida muammoning yechimlaridan biri:

  • bir necha soniya kutadigan oldindan to'xtash kancasini qo'shish;
  • tegishli parametrlar uchun bizning backend konfiguratsiya faylini o'rganish.

NGINX bilan misol, hatto dastlab tugatish signallarini to'g'ri qayta ishlashi kerak bo'lgan dastur ham buni amalga oshira olmasligini aniq ko'rsatib turibdi, shuning uchun dasturni joylashtirish paytida 500 ta xatoni tekshirish juda muhimdir. Bu, shuningdek, muammoni kengroq ko'rib chiqish va bitta pod yoki konteynerga e'tibor qaratmasdan, balki butun infratuzilmani bir butun sifatida ko'rib chiqish imkonini beradi.

Sinov vositasi sifatida siz Yandex.Tank-dan har qanday monitoring tizimi bilan birgalikda foydalanishingiz mumkin (bizning holatlarimizda ma'lumotlar Grafana'dan sinov uchun Prometheus backend bilan olingan). Nafis o'chirish bilan bog'liq muammolar benchmark yaratishi mumkin bo'lgan og'ir yuklar ostida aniq ko'rinadi va monitoring sinov paytida yoki undan keyin vaziyatni batafsilroq tahlil qilishga yordam beradi.

Maqola bo'yicha fikr-mulohazalarga javoban: NGINX Ingress bilan bog'liq muammolar va echimlar bu erda tasvirlanganligini ta'kidlash kerak. Boshqa holatlar uchun biz seriyaning quyidagi materiallarida ko'rib chiqishimiz mumkin bo'lgan boshqa echimlar mavjud.

PS

K8s maslahatlar va fokuslar seriyasidan boshqa:

Manba: www.habr.com

a Izoh qo'shish