Asosiy kontentga o‘tish
Innovialabs

Konteynerlarda graceful shutdown: SIGTERM, drenaj va taymautlar

Chuqur3 daq

Qisqacha

SIGTERM kelganda ilova yangi ishni qabul qilishni to‘xtatishi, joriy so‘rovlarni tugatishi va grace period tugashidan oldin chiqishi kerak; signal jarayonga PID 1 sifatida yetib borishini ta’minlang va Kubernetes’da qisqa preStop qo‘shing.

Qisqacha javob

Har bir deploy, replikalarni kamaytirish yoki node drain konteynerlarni to‘xtatadi. Agar ilova bir zumda o‘lsa, joriy so‘rovlar xato bilan tugaydi, fon vazifalari esa yarmida uziladi. Graceful shutdown quyidagini anglatadi:

  1. signal haqiqatan jarayonga yetib boradi;
  2. jarayon yangi ulanishlar va vazifalarni qabul qilishni to‘xtatadi;
  3. boshlanganini tugatadi, baza bilan ulanishlarni yopadi va buferlarni bo‘shatadi;
  4. platforma sabri tugab SIGKILL yuborishidan oldin chiqadi.

Docker va Kubernetes konteynerlarni qanday to‘xtatadi

Docker: docker stop konteynerning PID 1 jarayoniga SIGTERM (yoki STOPSIGNAL dagi signal) yuboradi, taymautni kutadi (standart 10 soniya, --stop-timeout yoki -t orqali o‘zgaradi), so‘ng SIGKILL yuboradi.

Kubernetes ko‘proq ish qiladi, bunda qisman parallel:

  • pod Terminating deb belgilanadi va servis endpoints’idan olib tashlanadi;
  • agar berilgan bo‘lsa, preStop hook bajariladi;
  • so‘ng konteyner SIGTERM oladi;
  • terminationGracePeriodSeconds (standart 30) tugaganda u hali tirik bo‘lsa, SIGKILL keladi. preStop vaqti shu davrga kiradi.

Muhim tafsilot: endpoints’dan olib tashlash kube-proxy, ingress-kontrollerlar va balanserlarga asinxron yetib boradi. SIGTERM’dan keyin bir necha lahza trafik hali kelishi mumkin. Listener’ni darhol yopadigan ilova bu so‘rovlarni rad etadi.

PID 1 va signallarni uzatish

Konteynerda PID 1 bo‘lgan jarayon o‘ziga xos ishlaydi: yadro unga signallarning standart amallarini qo‘llamaydi. Agar PID 1’da SIGTERM ishlovchisi bo‘lmasa, signal shunchaki e’tiborsiz qoldiriladi va konteyner SIGKILL’ni kutadi.

Odatiy tuzoqlar:

  • Shell form CMD npm start /bin/sh -c ni ishga tushiradi, u PID 1 bo‘ladi va signallarni ilovaga uzatmaydi.
  • npm, yarn va shunga o‘xshash o‘ramlar signallarni ishonchsiz uzatishi mumkin. Runtime’ni to‘g‘ridan-to‘g‘ri ishga tushiring.
  • Entrypoint skriptlari exec "$@" bilan tugashi kerak, shunda ilova shell o‘rnini egallaydi.
# exec form: PID 1 — node’ning o‘zi
CMD ["node", "server.js"]

Agar jarayon signallarni ishlay olmasa yoki bola jarayonlar yaratsa, kichik init’dan foydalaning: docker run --init yoki entrypoint’da tini. U signallarni uzatadi va zombi jarayonlarni tozalaydi.

Kodda SIGTERM’ni ushlash

Node.js: HTTP serverni to‘xtatamiz, ochiq so‘rovlarni kutamiz, resurslarni yopamiz. Qattiq taymaut osilib qolgan keep-alive ulanishlardan himoya qiladi.

process.on("SIGTERM", () => {
  server.close(async () => {
    await db.end();
    process.exit(0);
  });
  setTimeout(() => process.exit(1), 25000).unref();
});

Python: Gunicorn va Uvicorn kabi serverlar SIGTERM’ni allaqachon to‘g‘ri ishlaydi — asosiysi, ular PID 1 bo‘lsin. O‘z worker siklingizda bayroq qo‘yamiz va joriy vazifani tugatamiz:

import signal

stopping = False

def on_sigterm(signum, frame):
    global stopping
    stopping = True

signal.signal(signal.SIGTERM, on_sigterm)

while not stopping:
    process_next_job()
close_connections()

Go: http.Server.Shutdown listener’larni yopadi va kontekst tugaguncha faol so‘rovlarni kutadi.

ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGTERM, os.Interrupt)
defer stop()

go srv.ListenAndServe()
<-ctx.Done()

shutdownCtx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
defer cancel()
srv.Shutdown(shutdownCtx)

Kubernetes’da preStop va taymautlar

Endpoints yangilanishi bilan bog‘liq poygani yopish uchun SIGTERM’dan oldin qisqa pauza qo‘shing:

spec:
  terminationGracePeriodSeconds: 45
  containers:
    - name: api
      lifecycle:
        preStop:
          exec:
            command: ["sleep", "5"]

exec uchun image’da sleep binar fayli kerak; Kubernetes’ning yangi versiyalarida preStop uchun o‘rnatilgan sleep amali ham bor. Vaqt byudjeti tuzing: preStop pauzasi + eng uzun oddiy so‘rov + tozalash terminationGracePeriodSeconds ichiga sig‘ishi, ilova ichidagi qattiq taymaut esa Kubernetes SIGKILL yuborishidan oldin ishlashi kerak.

Cheklist

  • CMD/ENTRYPOINT’da exec form, shell skriptlarda exec yoki --init.
  • SIGTERM ishlovchisi: qabulni to‘xtatish, drenaj, 0 kodi bilan chiqish.
  • To‘xtash boshlanishi bilan readiness probe muvaffaqiyatsiz javob bera boshlaydi.
  • Endpoints tarqalishi uchun preStop’da pauza.
  • Grace period drenaj vaqtidan uzunroq.
  • Navbat iste’molchilari xabarni faqat ishlov berilgandan keyin tasdiqlaydi, shunda uzilgan vazifa qayta keladi.
  • Uzoq ulanishlar (WebSocket, striming) yopilish xabarini oladi, shunda mijozlar boshqa nusxaga qayta ulanadi.

Ko‘p beriladigan savollar

Servisga doimiy yuklama bering va bir vaqtda rolling deploy qiling. Chiqarish paytidagi har qanday 5xx yoki ulanish uzilishi bo‘shliqni ko‘rsatadi: ishlovchi yo‘q, PID 1 bilan muammo yoki preStop juda qisqa.

Bunda yordam beramiz

O‘zingiz shug‘ullanmasdan natija olishni istasangiz — biz har kuni shu bilan shug‘ullanamiz.

Loyihani muhokama qilish

Yana o‘qing

G‘oya yoki vazifangiz bormi? Bizga aytib bering

Ish kuni davomida javob beramiz va yechim taklif qilamiz. Konsultatsiya bepul.