Skip to content

Mastering Deployments & Rolling Updates

Trong thế giới Kubernetes, Deployment là "Đấng sáng tạo" của các ứng dụng stateless. Nó không trực tiếp chạy containers, mà quản lý một chuỗi chỉ huy nghiêm ngặt để đảm bảo ứng dụng của bạn luôn sống sótcập nhật mượt mà (Zero Downtime).


1. The Hierarchy: Chain of Command

Hiểu rõ phân cấp quyền lực là chìa khóa để debug. Bạn không tạo Pod, bạn tạo Deployment.

👑 The Chain of Command

  1. Deployment: Định nghĩa WHAT (Chạy image gì? Bao nhiêu bản? Strategy update là gì?).
  2. ReplicaSet: Đảm bảo HOW MANY (Luôn duy trì đủ số lượng bản sao).
  3. Pod: Người lính thực thi WORK (Chạy container).

Tại sao cần lớp trung gian ReplicaSet? Để phục vụ Rolling Update. Khi bạn update code, Deployment sẽ tạo một ReplicaSet MỚI song song với ReplicaSet CŨ, và chuyển dần quân số sang bên mới.


2. The Magic of Reconciliation

Kubernetes hoạt động dựa trên cơ chế Desired State (Trạng thái mong muốn). Khi bạn khai báo replicas: 3, bạn đang ra lệnh: "Ta muốn luôn luôn có 3 bản sao của ứng dụng này đang chạy. Không hơn, không kém."

Scenario: Self-Healing in Action

  1. Bạn có 3 Pods đang chạy yên ổn.
  2. SỰ CỐ: Một Node vật lý bị cháy, kéo theo 1 Pod xuống mồ.
  3. Current State: 2 Pods.
  4. Desired State: 3 Pods.
  5. Reconciliation Loop: K8s phát hiện sự chênh lệch (Delta). ReplicaSet lập tức ra lệnh tạo thêm 1 Pod mới trên Node khác còn sống.
  6. Kết quả: Hệ thống tự phục hồi mà không cần bạn can thiệp lúc nửa đêm.

3. Rolling Updates: The Killer Feature 🚀

Đây là lý do chính khiến doanh nghiệp chuyển từ Docker Swarm/VM sang Kubernetes: Cập nhật ứng dụng mà KHÔNG CÓ DOWNTIME.

Khi bạn đổi Image từ v1 sang v2, K8s không "giết sạch rồi chạy lại". Nó thực hiện chiến thuật "Cuốn chiếu".

Cơ chế hoạt động

Mặc định dùng strategy RollingUpdate:

  1. Tạo 1 Pod mới (v2).
  2. Chờ Pod mới Sẵn sàng (Ready).
  3. Giết 1 Pod cũ (v1).
  4. Lặp lại cho đến khi hết Pod cũ.

Tinh chỉnh tốc độ (Fine-tuning)

Bạn kiểm soát tốc độ update qua 2 tham số:

  • maxSurge (Mặc định 25%): Được phép tạo lố bao nhiêu Pod?
    • Ví dụ replicas: 10, maxSurge: 2 -> Có thể chạy tối đa 12 Pods trong lúc update.
  • maxUnavailable (Mặc định 25%): Được phép chết bao nhiêu Pod?
    • Ví dụ replicas: 10, maxUnavailable: 0 -> Cực kỳ an toàn. Luôn đảm bảo đủ 10 Pod phục vụ khách hàng, chỉ giết Pod cũ khi Pod mới đã 100% Ready.

4. Deployment YAML Anatomy (Line-by-line)

Một file Deployment chuẩn Production trông như thế nào?

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend-api
  labels:
    app: backend   # Label của chính Deployment
spec:
  replicas: 3      # Số lượng bản sao mong muốn
  selector:
    matchLabels:
      app: backend # ⚠️ QUAN TRỌNG: Phải khớp với template.metadata.labels
  
  # Chiến thuật Update (Zero Downtime)
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0 # An toàn tuyệt đối: Không cho phép thiếu người
  
  # Khuôn mẫu để đúc ra Pod (Pod Template)
  template:
    metadata:
      labels:
        app: backend # 🏷️ Đây là Label để Selector tìm thấy Pod
    spec:
      containers:
      - name: api-server
        image: my-registry/backend:v1.2.0 # ❌ CẤM DÙNG :latest
        ports:
        - containerPort: 8080
        
        # Kiểm tra sức khỏe (Bắt buộc cho Production)
        readinessProbe:
          httpGet:
            path: /healthz
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 10
        
        resources: # Giới hạn tài nguyên (Tránh 1 Pod ăn hết RAM của Node)
          limits:
            memory: "512Mi"
            cpu: "500m"

🧩 The Glue: Selectors & Labels

Đây là khái niệm quan trọng nhất. Deployment không quản lý Pod theo "Tên", mà quản lý theo Labels.

  • spec.selector.matchLabels: "Ta quản lý tất cả những thằng nào có nhãn là app: backend".
  • spec.template.metadata.labels: "Khi ta đẻ ra Pod mới, dán cho nó cái nhãn app: backend".

Nếu hai giá trị này lệch nhau -> Deployment sẽ không tìm thấy Pod nó vừa tạo ra -> Và nó sẽ tạo vô hạn Pod mới (bom nguyên tử hệ thống).


⚠️ The Golden Rule: NO LATEST TAG

💀 DO NOT USE :latest IN PRODUCTION

Không bao giờ được sử dụng tag :latest (Ví dụ: nginx:latest, my-app:latest).

Lý do:

  1. Bất định (Non-deterministic): Hôm nay latest là v1, ngày mai đồng nghiệp push code mới, latest thành v2. Bạn deploy lại mà không biết mình đang chạy version nào.
  2. Không Rollback được: Nếu bản build mới bị lỗi, bạn không thể rollback về bản cũ vì cả hai đều tên là :latest.
  3. Caching Issue: K8s nodes thường cache image. Nếu vẫn là tag :latest, nó có thể không pull bản mới về.

👉 Luôn dùng Semantic Versioning hoặc SHA: nginx:1.21.6-alpine hoặc my-app:v2.0.1-rc3.