Rolling deploy, không downtime nhưng có rủi ro
Kubernetes rolling update thay Pod theo từng batch:
[1] v1: 3/3 running
│
▼
[2] Deploy v2 bắt đầu
│
▼
[3] v1: 2/3 | v2: 1/3 — LB gửi traffic tới cả v1 và v2
│
▼
[4] v1: 1/3 | v2: 2/3
│
▼
[5] v1: 0/3 | v2: 3/3 — hoàn thànhNguyên nhân 502 hay gặp khi rolling deploy:
Lỗi 1: readiness probe chưa sẵn sàng nhưng traffic đã tới
spec:
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 10 # chờ 10s trước probe đầu tiên
periodSeconds: 5
failureThreshold: 3
Nếu initialDelaySeconds quá ngắn, LB gửi traffic vào Pod chưa sẵn sàng → 502.
Lỗi 2: Pod cũ bị terminate giữa chừng (thiếu graceful shutdown)
Xem lại bài 12: Pod phải handle SIGTERM và hoàn thành request đang xử lý trước khi exit.
spec:
terminationGracePeriodSeconds: 60 # cho Pod 60s để graceful shutdown
containers:
- lifecycle:
preStop:
exec:
command: ["sh", "-c", "sleep 5"] # chờ LB cập nhật endpoints
preStop sleep nhỏ (5–10s) đảm bảo LB đã remove Pod khỏi backend trước khi Pod bắt đầu shutdown.
Canary và blue-green
Canary, tăng dần traffic cho phiên bản mới
# Hai Deployment: v1 (9 replica) và v2 (1 replica)
# Cùng label selector trên Service → 10% traffic tới v2
# Tăng dần replica v2, giảm v1
# Hoặc dùng Ingress weight (NGINX Ingress Controller)
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "10" # 10% traffic
Blue-Green, switch toàn bộ
Load Balancer
│ 100% traffic
▼
Service (selector: app=blue)
│
▼
Blue deployment v1 (nhận toàn bộ traffic)DNS TTL strategy khi đổi endpoint
Tình huống: di chuyển service từ LB cũ sang LB mới, cần đổi DNS.
Sai (TTL cao):
api.example.com → LB cũ (TTL 3600s = 1h)
Đổi record → LB mới
→ 1h sau một số user mới dùng LB mới; user cũ còn LB cũ 1h nữa
→ Nếu LB cũ đã tắt → 502 cho user còn cache
Đúng (hạ TTL trước):
Trước 1 ngày: đặt TTL = 60s
Chờ 24h (TTL cũ expire hết)
Đổi record → LB mới
→ Sau tối đa 60s, mọi user đã dùng LB mới
Sau khi ổn: nâng TTL lại về 300–3600s
CDN và cache invalidation
Khi dùng CDN (Cloudflare, CloudFront, Fastly) trước origin:
User
│ request
▼
CDN edge
│ forward nếu cache miss (ví dụ Cache-Control: public, max-age=300)
▼
Origin (app)Chiến lược:
- API dynamic:
Cache-Control: no-storehoặcprivate(không cache CDN). - Static asset: đổi URL theo version hash (
/app.v2.js), max-age dài. - Cần invalidate nhanh: dùng CDN purge API, hoặc tăng version path.
Checklist incident mạng
Khi nhận alert hoặc escalation “service không vào được”:
T+0: Xác nhận scope
□ Tất cả user hay một nhóm cụ thể?
□ Tất cả region hay một AZ?
□ Mọi endpoint hay một path cụ thể?
□ Bắt đầu từ khi nào? Có deploy gần đây không?
T+5: Kiểm tra nhanh (theo thứ tự tầng)
□ DNS: dig +short A api.example.com
□ TCP: nc -vz api.example.com 443
□ HTTP: curl -sv https://api.example.com/health
□ LB: kiểm tra healthy target count
T+10: Scope hẹp hơn
□ LB log: có pattern 5xx nào không?
□ App log: có exception cụ thể không?
□ Infra: CPU, memory, connection count bình thường không?
T+15: Quyết định
□ Rollback deploy? (nếu gần đây có deploy)
□ Scale up? (nếu traffic tăng đột biến)
□ Failover AZ? (nếu một AZ có vấn đề)
□ Escalate? (nếu không xác định được nguyên nhân)
Post-mortem: tập trung nguyên nhân gốc rễ
Sau incident, viết post-mortem có cấu trúc:
## Incident: 502 sau deploy v2.3.1 (14:30–15:45 UTC)
### Timeline
- 14:30: Deploy v2.3.1 bắt đầu
- 14:35: Alert rate(5xx) > 5% trigger
- 14:42: Xác nhận readiness probe sai path (/health vs /ready)
- 14:45: Rollback về v2.3.0
- 15:00: Metric về normal
- 15:45: Deploy lại v2.3.1 với probe đúng
### Nguyên nhân gốc rễ
readinessProbe path trong v2.3.1 đổi từ /health sang /ready
nhưng endpoint /ready chỉ được thêm ở v2.3.2 (chưa merge lúc deploy).
Pod báo Not Ready → LB loại nhưng không đủ nhanh → 502 trong ~5 phút.
### Hành động khắc phục
1. [DONE] Rollback về v2.3.0
2. [TODO] Thêm CI test kiểm tra readiness probe endpoint tồn tại trước deploy
3. [TODO] Tăng initialDelaySeconds để buffer tốt hơn
4. [TODO] Alert sớm hơn: readiness probe fail > 30s trong rolling deploy
Nguyên tắc post-mortem tốt: không blame người, tập trung vào hệ thống và quy trình.
Tóm tắt
- Graceful shutdown + readiness probe là bộ đôi bắt buộc để rolling deploy không 502.
- Hạ TTL trước 24–48h khi plan đổi DNS endpoint.
- CDN cache và DNS TTL là hai lý do user thấy phiên bản cũ dù deploy đã xong.
- Incident checklist: DNS → TCP → HTTP → LB → App, cùng thứ tự như debug bình thường.
Câu hỏi hay gặp
Grace 30s, request dài 20s, có cần preStop không?
Trả lời: Về lý thuyết đủ nếu app shutdown nhanh. preStop hữu ích khi cần chờ LB gỡ backend (sleep vài giây) hoặc drain trước SIGTERM, tránh race với kube-proxy.
Đổi DNS lúc 14:00, TTL 3600s, 15:00 vẫn user trỏ LB cũ, vì sao? LB cũ xóa thì sao?
Trả lời: Resolver/client vẫn cache tới 1h. LB cũ xóa → user đó lỗi/timeout cho đến khi cache hết. Giảm TTL trước migration.
Post-mortem: lỗi do quên cập nhật probe, “ai chịu trách nhiệm”?
Trả lời: Nguyên tắc blameless: tìm thiếu sót hệ thống (CI không validate probe, checklist deploy). Trách nhiệm cá nhân không để “kỷ luật” trong doc, mà để cải quy trình.
Bạn đã hoàn thành nhánh vận hành chính của loạt bài (Giai đoạn I → IV).
Ôn lại lộ trình:
- Giai đoạn I (01–04): Bản đồ giao thức, tầng, IP, TCP, DNS.
- Giai đoạn II (05–07): HTTP stack, HTTPS, TLS, debug checklist.
- Giai đoạn III (08–10): Nơi workload chạy, Linux, Docker, Kubernetes.
- Giai đoạn IV (11–16): Hạ tầng và vòng đời, cloud, LB, cert, observability, IaC, release.
Bài tuỳ chọn nâng cao: Service mesh và mTLS, nếu hệ thống đã đủ lớn để quan tâm east-west traffic, retry mesh-level và zero-trust giữa service.
Xem lại mục lục loạt bài hoặc tiếp tục với các bài spin-off: tcpdump thực chiến, eBPF observability, hoặc đa cloud VPC.