Sau bài này bạn làm được: deploy app lên cluster với zero-downtime rolling update; rollback phiên bản lỗi trong 10 giây; hiểu relationship Deployment → ReplicaSet → Pod.


Tại sao không tạo Pod trực tiếp

Pod chết = pod mất. Không ai tạo lại. Bạn cần:

  • ReplicaSet: đảm bảo luôn có N pod chạy.
  • Deployment: quản lý ReplicaSet + rollout/rollback.
Deployment (bạn tạo)
    └── ReplicaSet v2 (Deployment tạo)  ← current
    │       ├── Pod 1
    │       ├── Pod 2
    │       └── Pod 3
    └── ReplicaSet v1 (giữ lại để rollback, replicas=0)

Deployment spec

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-api
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-api
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1     # Tối đa 1 pod không sẵn sàng
      maxSurge: 1            # Tối đa 1 pod thêm (tổng có thể 4)
  template:
    metadata:
      labels:
        app: my-api
    spec:
      containers:
      - name: app
        image: my-api:1.2.0
        ports:
        - containerPort: 8080
        resources:
          requests:
            cpu: "100m"
            memory: "128Mi"
          limits:
            memory: "256Mi"
        readinessProbe:        # Quan trọng cho rolling update
          httpGet:
            path: /healthz
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 10

Rolling update — cơ chế

Khi bạn đổi image (hoặc bất kỳ field nào trong .spec.template):

1. Deployment controller tạo ReplicaSet mới (v2)
2. Scale up v2 theo maxSurge (thêm 1 pod)
3. Chờ pod v2 Ready (readiness probe pass)
4. Scale down v1 theo maxUnavailable (giảm 1 pod)
5. Lặp lại cho đến khi v2 = 3 pods, v1 = 0 pods
# Trigger update
kubectl set image deploy/my-api app=my-api:1.3.0

# Hoặc edit trực tiếp
kubectl edit deploy my-api

# Hoặc apply file YAML đã sửa
kubectl apply -f deploy.yaml

maxUnavailable và maxSurge

Tham sốGiá trịÝ nghĩa
maxUnavailable1 hoặc 25%Tối đa bao nhiêu pod dưới replicas mong muốn trong quá trình update
maxSurge1 hoặc 25%Tối đa bao nhiêu pod trên replicas mong muốn

Ví dụ: replicas=4, maxUnavailable=1, maxSurge=1:

  • Tại bất kỳ thời điểm: tối thiểu 3 pod ready, tối đa 5 pod tồn tại.

Chiến lược phổ biến:

Mục tiêumaxUnavailablemaxSurge
Zero-downtime (an toàn nhất)01 hoặc 25%
Nhanh nhất25%25%
Tiết kiệm resource10

Rollout commands

# Xem trạng thái rollout
kubectl rollout status deploy/my-api

# Lịch sử revision
kubectl rollout history deploy/my-api
kubectl rollout history deploy/my-api --revision=2   # Chi tiết revision

# Rollback về revision trước
kubectl rollout undo deploy/my-api

# Rollback về revision cụ thể
kubectl rollout undo deploy/my-api --to-revision=3

# Pause rollout (canary thủ công)
kubectl rollout pause deploy/my-api
# ... quan sát pod mới ...
kubectl rollout resume deploy/my-api

# Restart (trigger update mà không đổi image)
kubectl rollout restart deploy/my-api

Revision history

Deployment giữ lại ReplicaSet cũ (replicas=0) để rollback. Giới hạn bằng:

spec:
  revisionHistoryLimit: 10    # Mặc định 10, giữ 10 ReplicaSet cũ

Recreate strategy

Thay vì rolling, dùng Recreate khi app không chạy được 2 version cùng lúc (ví dụ: DB migration incompatible, singleton):

spec:
  strategy:
    type: Recreate    # Kill tất cả v1, rồi tạo v2 → có downtime

Deployment vs ReplicaSet — ai quản lý ai

LayerTrách nhiệm
DeploymentQuản lý ReplicaSet, rolling update, rollback, revision history
ReplicaSetĐảm bảo đúng N pod chạy (tạo mới nếu thiếu, xoá nếu thừa)
PodChạy container thực tế

Không nên tạo ReplicaSet trực tiếp — luôn dùng Deployment. Ngoại lệ duy nhất: khi bạn cần controller đặc biệt (StatefulSet, DaemonSet — bài 06).


Readiness probe và rolling update

Rolling update phụ thuộc vào readiness probe. Nếu không có readiness probe:

  • Pod mới start xong là coi như Ready → traffic tới ngay.
  • Nếu app cần warm-up (load cache, connect pool) → user gặp lỗi.
readinessProbe:
  httpGet:
    path: /healthz
    port: 8080
  initialDelaySeconds: 5    # Chờ 5s trước probe đầu tiên
  periodSeconds: 10          # Probe mỗi 10s
  failureThreshold: 3        # 3 lần fail → không Ready

Chi tiết probe → Bài 05.


minReadySeconds

Pod Ready chưa chắc đã “ổn”. minReadySeconds bắt Deployment chờ thêm sau khi pod Ready trước khi tiếp tục update:

spec:
  minReadySeconds: 30    # Chờ 30s sau khi Ready, nếu không crash → tiếp

Giúp phát hiện lỗi sớm: nếu pod crash trong 30s đầu, rollout dừng lại.


progressDeadlineSeconds

Nếu rollout không tiến triển trong khoảng thời gian này, Deployment báo ProgressDeadlineExceeded:

spec:
  progressDeadlineSeconds: 600    # Mặc định 600s (10 phút)
kubectl rollout status deploy/my-api
# error: deployment "my-api" exceeded its progress deadline

Nguyên nhân thường gặp: image không tồn tại, readiness probe luôn fail, resource không đủ.


Lab: rolling update trên kind

# Tạo deployment
kubectl create deployment web --image=nginx:1.25 --replicas=3

# Xem pod
kubectl get pods -l app=web -w

# Update image (terminal khác watch)
kubectl set image deploy/web nginx=nginx:1.26

# Xem rollout
kubectl rollout status deploy/web

# Xem ReplicaSet
kubectl get rs -l app=web

# Rollback
kubectl rollout undo deploy/web

# Xem history
kubectl rollout history deploy/web

Tóm tắt

  • Deployment → ReplicaSet → Pod. Luôn dùng Deployment, không tạo RS/Pod trực tiếp.
  • RollingUpdate thay pod cũ bằng pod mới dần dần. maxUnavailable + maxSurge điều khiển tốc độ.
  • Readiness probe là bắt buộc cho rolling update an toàn — không có = traffic tới pod chưa sẵn sàng.
  • rollout undo rollback ngay. revisionHistoryLimit giới hạn số revision giữ lại.
  • minReadySeconds + progressDeadlineSeconds là safety net cho deploy automation.

Câu hỏi hay gặp

Đổi label selector của Deployment có được không?

Trả lời: Không (từ K8s 1.x). .spec.selector là immutable sau khi tạo. Đổi label pattern → tạo Deployment mới, chuyển traffic dần, xoá cũ.

Rollback có phải “deploy lại image cũ” không?

Trả lời: Về cơ bản có — rollout undo scale lên ReplicaSet cũ (đã giữ sẵn, replicas=0). Nhanh hơn rebuild image vì ReplicaSet spec còn đó. Tuy nhiên image vẫn phải còn trên registry.

Deployment update mỗi khi kubectl apply dù không đổi gì?

Trả lời: Nếu .spec.template không đổi, apply chỉ update metadata (annotation kubectl.kubernetes.io/last-applied-configuration) — không trigger rollout. Rollout chỉ xảy ra khi template thay đổi.


Bài tiếp theo (Giai đoạn II): Probe health: liveness, readiness, startup — cấu hình đúng, sai cấu hình thì hậu quả gì.