Lesson 51 — Graceful Shutdown (Visualization)

Ba mô phỏng tương tác cho graceful shutdown: (1) chuỗi shutdown theo dependency với in-flight request được phục vụ nốt, (2) signal timeline Ctrl+C → SIGTERM → graceful → force kill, (3) K8s rolling update với readiness drain. Nhấn nút để chạy từng mô phỏng. Mở "📖 Đọc README" để xem lý thuyết đầy đủ.

1. Shutdown sequence theo dependency

Đóng theo chiều ngược dependency: chặn request mới trước, đóng DB sau cùng. Quan sát 5 in-flight request được phục vụ nốt trong lúc các bước shutdown chạy tuần tự. Bấm Force kill giữa chừng để thấy request bị cắt (broken pipe) khi vượt timeout.

1 readiness = false — /readyz trả 503, K8s gỡ pod khỏi endpoints
2 srv.Shutdown(ctx) — đóng listener, chờ in-flight handler done
3 stop worker + wg.Wait() — worker xử lý nốt job rồi exit
4 flush log / metric / trace — logger.Sync()
5 db.Close() — đóng pool SAU CÙNG (mọi thứ đã dùng xong)
Trạng thái: SERVING — đang nhận request bình thường
In-flight request (mỗi cái cần ~3s để xong):

2. Signal timeline: Ctrl+C → SIGTERM → graceful → force kill

Mô phỏng dòng thời gian một lần shutdown. Con trỏ chạy qua 3 vùng: xanh = đang serve / drain, cam = grace period đếm ngược tới hạn, đỏ = quá terminationGracePeriodSeconds → SIGKILL. Chọn handler dài hơn grace period để thấy bị force kill.

grace period = 10s
t=0 SIGTERMdraint=10 grace hếtSIGKILL
Sẵn sàng. Bấm để gửi SIGTERM.

3. K8s rolling update — readiness drain

K8s thay pod cũ (v1) bằng pod mới (v2). Quan sát: pod cũ chuyển sang readiness=false → LB ngừng route → drain → terminate, trong khi pod mới phải Ready trước khi nhận traffic. So sánh với checkbox "bỏ readiness drain" để thấy request rơi vào pod đang chết → 502.

Load Balancer
route → pod v1 (1 endpoint)

Pod v1 (cũ)

Running · Ready
trong Service endpoints ✓

Pod v2 (mới)

chưa tạo