Chiến lược triển khai (Deployment Strategies)
| Chiến lược | Downtime | Tài nguyên thêm | v1 và v2 chạy cùng lúc? | Có sẵn trong Deployment? |
|---|---|---|---|---|
| Recreate | Có | Không | Không | ✅ type: Recreate |
| RollingUpdate | Không | Ít (maxSurge) | Có, trong lúc update | ✅ mặc định |
| Blue/Green | Không | Gấp đôi | Không (chuyển tức thì) | ❌ tự làm bằng 2 Deployment + Service |
| Canary | Không | Ít | Có, theo tỉ lệ | ❌ tự làm hoặc dùng công cụ |
1. Recreate
- Scale RS cũ về 0 – xóa hết Pod v1.
- Đợi Pod v1 tắt xong.
- Scale RS mới lên N – tạo Pod v2.
spec:
replicas: 4
strategy:
type: Recreate
- ✅ Đơn giản nhất, không bao giờ có v1 và v2 cùng chạy, không tốn thêm tài nguyên.
- ❌ Có downtime; rollback cũng downtime lần nữa.
2. RollingUpdate (mặc định)
Vừa tăng RS mới vừa giảm RS cũ theo từng đợt. Tốc độ do 2 tham số quyết định:
spec:
replicas: 4
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 25% # mặc định
maxUnavailable: 25% # mặc định
| Tham số | Ý nghĩa | Ví von |
|---|---|---|
maxSurge | Được tạo thêm tối đa bao nhiêu Pod vượt replicas | Thuê thêm tối đa bao nhiêu nhân viên tạm |
maxUnavailable | Được thiếu tối đa bao nhiêu Pod sẵn sàng | Cho tạm đóng tối đa bao nhiêu quầy |
Trong suốt quá trình update:
- Số Pod tối đa =
replicas + maxSurge - Số Pod sẵn sàng tối thiểu =
replicas − maxUnavailable
⚠️ Quy tắc làm tròn khi dùng %
maxSurge→ làm tròn lên.maxUnavailable→ làm tròn xuống.
| replicas | maxSurge 25% | maxUnavailable 25% | Ý nghĩa |
|---|---|---|---|
| 1 | ⌈0.25⌉ = 1 | ⌊0.25⌋ = 0 | Tạo Pod mới trước rồi mới xóa Pod cũ |
| 3 | ⌈0.75⌉ = 1 | ⌊0.75⌋ = 0 | Như trên |
| 4 | 1 | 1 | Tối đa 5 Pod, tối thiểu 3 Pod sẵn sàng |
| 10 | ⌈2.5⌉ = 3 | ⌊2.5⌋ = 2 | Tối đa 13 Pod, tối thiểu 8 Pod sẵn sàng |
💡
maxSurge và maxUnavailable không được cùng bằng 0 – không được thêm, cũng không được bớt thì rollout không bắt đầu được, Kubernetes từ chối ngay.
Tham số liên quan
| Tham số | Ý nghĩa |
|---|---|
minReadySeconds | Pod mới phải Ready liên tục bao nhiêu giây mới được tính là "available" |
progressDeadlineSeconds | Quá thời gian này (mặc định 600s) mà rollout không tiến triển → đánh dấu thất bại |
3. Blue/Green
- Blue = bản đang chạy (v1). Green = bản mới (v2), dựng đầy đủ song song.
- Test Green xong → đổi selector của Service từ blue sang green. Toàn bộ traffic chuyển gần như ngay lập tức.
apiVersion: v1
kind: Service
metadata:
name: myapp
spec:
selector:
app: myapp
version: blue # đổi thành green để chuyển traffic
ports:
- port: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-green
spec:
replicas: 3
selector:
matchLabels: {app: myapp, version: green}
template:
metadata:
labels: {app: myapp, version: green}
spec:
containers:
- name: web
image: nginx:1.27
# chuyển sang v2
kubectl patch svc myapp -p '{"spec":{"selector":{"app":"myapp","version":"green"}}}'
# rollback
kubectl patch svc myapp -p '{"spec":{"selector":{"app":"myapp","version":"blue"}}}'
- ✅ Chuyển 100% tức thì; rollback trong vài giây; test được v2 thật trước khi chuyển.
- ❌ Tốn gấp đôi tài nguyên; kết nối đang mở tới v1 có thể bị cắt; database phải hỗ trợ cả 2 phiên bản.
4. Canary
- 2 Deployment dùng chung một label mà Service chọn.
- kube-proxy chia traffic ngẫu nhiên giữa các Pod → tỉ lệ traffic ≈ tỉ lệ số Pod.
# stable: 9 Pod v1
metadata: {name: myapp-stable}
spec:
replicas: 9
selector: {matchLabels: {app: myapp, track: stable}}
template:
metadata: {labels: {app: myapp, track: stable}}
spec: {containers: [{name: web, image: nginx:1.26}]}
---
# canary: 1 Pod v2
metadata: {name: myapp-canary}
spec:
replicas: 1
selector: {matchLabels: {app: myapp, track: canary}}
template:
metadata: {labels: {app: myapp, track: canary}}
spec: {containers: [{name: web, image: nginx:1.27}]}
# Service chỉ chọn app: myapp → trúng cả hai Deployment
Các bước thường làm:
- Canary nhận khoảng 10% traffic.
- Theo dõi lỗi và độ trễ.
- Tăng dần canary, giảm dần stable.
- Cập nhật image của stable lên v2, xóa canary.
Chia theo trọng số (chuẩn hơn)
Với Gateway API (có trong đề CKA từ 2025):
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata: {name: myapp}
spec:
parentRefs: [{name: my-gateway}]
rules:
- backendRefs:
- {name: myapp-stable, port: 80, weight: 90} # 2 Service riêng
- {name: myapp-canary, port: 80, weight: 10}
Cách này cho đúng 10% dù mỗi bên chỉ có 1 Pod. Công cụ tự động hóa canary: Argo Rollouts, Flagger, Istio. Trên EKS còn có ALB weighted target groups.
5. A/B testing và Shadow
| Chiến lược | Cách chia | Mục đích |
|---|---|---|
| A/B | Theo thuộc tính request (header, cookie, vùng) | Thử tính năng với nhóm người dùng cụ thể |
| Shadow | Nhân bản traffic thật sang v2, bỏ qua phản hồi của v2 | Kiểm tra v2 với tải thật mà người dùng không bị ảnh hưởng |
Cả hai cần tầng định tuyến L7 (Ingress, Gateway API, service mesh).
6. StatefulSet và DaemonSet
| Workload | Trường | Gi á trị | Ghi chú |
|---|---|---|---|
| Deployment | spec.strategy.type | RollingUpdate / Recreate | |
| StatefulSet | spec.updateStrategy.type | RollingUpdate / OnDelete | Update theo thứ tự ngược (Pod số lớn nhất trước). partition: N chỉ update Pod có số thứ tự ≥ N – dùng như canary |
| DaemonSet | spec.updateStrategy.type | RollingUpdate / OnDelete | OnDelete: chỉ khi bạn tự xóa Pod thì Pod mới theo template mới |