Konteynerlarda graceful shutdown: SIGTERM, drenaj va taymautlar
Chuqur3 daqInnovialabs tahririyati
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:
- signal haqiqatan jarayonga yetib boradi;
- jarayon yangi ulanishlar va vazifalarni qabul qilishni to‘xtatadi;
- boshlanganini tugatadi, baza bilan ulanishlarni yopadi va buferlarni bo‘shatadi;
- 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 -cni 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 skriptlardaexecyoki--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.