Các Loại Workload: StatefulSet, DaemonSet, Job và CronJob

K
Kai··5 min read

Suốt series ta dùng Deployment — và đúng là nó lo phần lớn nhu cầu (app web, API không trạng thái). Nhưng Kubernetes có vài loại workload khác cho những bài toán Deployment không hợp. Biết chúng tồn tại và khi nào dùng giúp bạn chọn đúng công cụ thay vì gò ép Deployment cho mọi thứ.

   Deployment    →  app KHÔNG trạng thái, các pod như nhau, thay thế tự do  (web, API)
   StatefulSet   →  app CÓ trạng thái, mỗi pod một danh tính ổn định        (database)
   DaemonSet     →  một pod trên MỖI node                                    (agent log, monitoring)
   Job           →  chạy tới khi HOÀN THÀNH rồi dừng                         (batch, migration)
   CronJob       →  Job chạy theo LỊCH                                        (backup hằng đêm)

Job: chạy tới khi xong

Deployment giả định pod chạy mãi. Nhưng nhiều tác vụ có điểm kết thúc: chạy migration, xử lý một lô dữ liệu, gửi báo cáo. Job chạy pod tới khi hoàn thành thành công rồi dừng — không restart vô hạn.

apiVersion: batch/v1
kind: Job
metadata:
  name: pi
spec:
  template:
    spec:
      containers:
        - name: pi
          image: perl:5.40-slim
          command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(50)"]
      restartPolicy: Never
  backoffLimit: 2
kubectl apply -f job.yaml
kubectl get job pi
kubectl logs job/pi
NAME   STATUS     COMPLETIONS   DURATION   AGE
pi     Complete   1/1           17s        17s

3.1415926535897932384626433832795028841971693993751

Job chạy, tính 50 chữ số của số pi, rồi Complete (1/1). restartPolicy: NeverbackoffLimit: 2 (thử lại tối đa 2 lần nếu fail) là hai trường đặc trưng của Job. Job giữ lại pod sau khi xong để bạn đọc log — khác hẳn Deployment.

CronJob: Job theo lịch

CronJob là Job chạy định kỳ, theo cú pháp cron quen thuộc (nhớ series Linux):

apiVersion: batch/v1
kind: CronJob
metadata:
  name: hello
spec:
  schedule: "*/1 * * * *"        # mỗi phút (cú pháp cron)
  jobTemplate:
    spec:
      template:
        spec:
          containers:
            - name: hello
              image: busybox:1.36
              command: ["sh", "-c", "date; echo 'Xin chào từ CronJob'"]
          restartPolicy: OnFailure
kubectl get cronjob hello
NAME    SCHEDULE      SUSPEND   ACTIVE   LAST SCHEDULE   AGE
hello   */1 * * * *   False     0        <none>          0s

Mỗi phút (*/1 * * * *), CronJob tạo một Job mới chạy lệnh. Đây là cách Kubernetes-native để làm backup hằng đêm, dọn dẹp định kỳ, gửi báo cáo — thay cho crontab trên một máy đơn lẻ.

DaemonSet: một pod trên mỗi node

Có những thứ phải chạy trên mọi node, không phải "N bản sao đặt đâu cũng được": agent thu log, exporter giám sát, plugin mạng/lưu trữ. DaemonSet đảm bảo đúng một pod trên mỗi node — thêm node mới, nó tự thêm pod lên node đó.

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: node-logger
spec:
  selector:
    matchLabels: { app: node-logger }
  template:
    metadata:
      labels: { app: node-logger }
    spec:
      containers:
        - name: logger
          image: busybox:1.36
          command: ["sh", "-c", "while true; do sleep 3600; done"]
kubectl get daemonset node-logger
NAME          DESIRED   CURRENT   READY   NODE SELECTOR   AGE
node-logger   1         1         1       <none>          5s

DESIRED 1 vì minikube có một node. Trên cluster 10 node, DaemonSet sẽ tự có 10 pod — một trên mỗi node. Bạn không khai replicas; số pod luôn bằng số node. (Chính các thành phần như kube-proxy ở Bài 1 chạy dưới dạng DaemonSet.)

StatefulSet: cho app có trạng thái

Đây là loại tinh tế nhất. Với Deployment, các pod vô danh và thay thế được — tên ngẫu nhiên (web-5687-9n9j7), chết cái nào dựng cái khác cũng như nhau. Nhưng database thì khác: node 0 là primary, node 1–2 là replica; mỗi node cần danh tính ổn địnhđĩa riêng của nó. StatefulSet cung cấp đúng vậy.

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web-sts
spec:
  serviceName: nginx-sts
  replicas: 3
  selector:
    matchLabels: { app: nginx-sts }
  template:
    # ... như Deployment ...
  volumeClaimTemplates:               # mỗi pod tự có một PVC riêng
    - metadata: { name: data }
      spec:
        accessModes: ["ReadWriteOnce"]
        resources: { requests: { storage: 50Mi } }
kubectl get pods -l app=nginx-sts
kubectl get pvc -l app=nginx-sts
NAME        READY   STATUS    AGE
web-sts-0   1/1     Running   6s
web-sts-1   1/1     Running   4s
web-sts-2   1/1     Running   2s

NAME             STATUS   VOLUME            CAPACITY   STORAGECLASS
data-web-sts-0   Bound    pvc-a745d57d...   50Mi       standard
data-web-sts-1   Bound    pvc-c50a2045...   50Mi       standard
data-web-sts-2   Bound    pvc-f1eaa136...   50Mi       standard

Ba khác biệt cốt lõi so với Deployment hiện ra ngay:

  • Tên ổn định, có thứ tự: web-sts-0, web-sts-1, web-sts-2 — không phải hash ngẫu nhiên. Pod web-sts-0 chết và dựng lại vẫn tên đó, vẫn nối lại đúng đĩa của nó.
  • PVC riêng mỗi pod: volumeClaimTemplates tự tạo một PVC cho từng pod (data-web-sts-0/1/2) — dữ liệu của pod 0 không lẫn pod 1. Đây là điều database cần.
  • Tạo/xoá tuần tự: pod sinh theo thứ tự 0→1→2 (để ý AGE giảm dần), xoá theo chiều ngược. Quan trọng cho cụm có primary/replica.

Lưu ý StatefulSet thường đi với headless Service (clusterIP: None) để mỗi pod có một tên DNS riêng (web-sts-0.nginx-sts...) — cho phép gọi đích danh từng pod, thứ database cluster cần.

Thực tế, vận hành database trên Kubernetes thường dùng Operator (cài qua CRD) chứ ít khi tự viết StatefulSet trần, vì backup/failover phức tạp. Nhưng hiểu StatefulSet là nền để hiểu các Operator đó.

Tổng kết

Ngoài Deployment (app không trạng thái), Kubernetes có: Job (chạy tới hoàn thành rồi dừng — migration, batch), CronJob (Job theo lịch cron — backup hằng đêm), DaemonSet (đúng một pod trên mỗi node — agent log/giám sát, tự co giãn theo số node), và StatefulSet (cho app có trạng thái — tên ổn định có thứ tự, PVC riêng mỗi pod, tạo/xoá tuần tự, thường kèm headless Service). Chọn đúng loại theo bản chất tác vụ thay vì gò mọi thứ vào Deployment.

Ta đã có gần đủ công cụ. Bài 13 lùi lại một bước để rèn kỹ năng sống còn hằng ngày: quan sát và gỡ lỗi — đọc log, exec, describe, events, và dùng dashboard.