iT邦幫忙

2026 iThome 鐵人賽

DAY 17
0
Kubernetes

從零開始的雲端實戰:30 天 Kubernetes 核心觀念與部署指南系列 第 17

【Day 17】有狀態應用:StatefulSet 如何管理 MySQL / Redis 等資料庫?

  • 分享至 

  • xImage
  •  

今日目標

  • 理解「無狀態(Stateless)」與「有狀態(Stateful)」應用在分散式架構下的根本差異。
  • 搞懂為什麼 Deployment 不適合用來跑多副本的 MySQL、Redis 或 Kafka。
  • 掌握 StatefulSet 的三大核心特徵:固定序號名稱、專屬持久化儲存(VolumeClaimTemplates)與 Headless Service。
  • 實戰操作:部署一個 StatefulSet 並觀察有序建立、專屬 PVC 綁定與固定 DNS 解析。

痛點場景:為什麼不能用 Deployment 跑資料庫集群?

在 Day 08 中學到的 Deployment 是專門為「無狀態應用(如 Web 前端、無狀態 REST API)」設計的:

  • Pod 彼此完全等價:每個 Pod 名字帶有隨機亂碼(如 nginx-75675f5897-abcde),死掉重建後會換一個全新的隨機名字。
  • 無序啟動與銷毀:3 個 Pod 同時並行建立,沒有先後順序。
  • 無法綁定專屬硬碟:如果 Deployment 掛載 PVC,3 個副本會搶同一個 PVC(容易造成檔案鎖定與寫入衝突)。

但分散式資料庫(如 MySQL 主從複製、Redis 集群、Kafka)有嚴格的「身分認同」需求:

  1. 角色分工:必須明確區分誰是 Master(主節點,負責寫入)、誰是 Slave(從節點,負責同步與讀取)。
  2. 固定識別碼與順序:Master 必須先啟動,Slave 才能連進來同步;Pod 重啟後必須保有原來的名字與網路位置。
  3. 專屬獨立磁碟:每個節點必須擁有專屬於自己的獨立數據庫檔案目錄,不能共用。

為了解決這些問題,Kubernetes 推出了專門管理有狀態服務的控制器——StatefulSet


StatefulSet 的三大核心武器

特性 Deployment (無狀態) StatefulSet (有狀態)
Pod 命名 隨機後綴(如 web-a1b2c 確定性有序編號(如 db-0, db-1, db-2
啟動/銷毀順序 同時並行(Parallel) 嚴格依序建立(0➔1➔2),倒序銷毀(2➔1➔0)
儲存綁定 多副本共享同一份 PVC volumeClaimTemplates 為每個 Pod 自動建立專屬獨立 PVC
網路識別 透過一般 Service 負載平衡隨機轉發 搭配 Headless Service 提供穩定的單獨 Pod DNS

關鍵配角:Headless Service(無頭服務)

一般 Service 會配置一個虛擬 IP(ClusterIP),將流量隨機負載平衡轉發給後端 Pod。

但有狀態應用需要直接連線到「特定的某一個節點」(例如應用程式必須明確連線到 db-0 進行寫入)。
Headless Service 就是將 clusterIP: None 的 Service:

  • 不分配任何 ClusterIP
  • CoreDNS 會直接為每一個 Pod 建立一組固定的內部域名:
    $(pod-name).$(service-name).$(namespace).svc.cluster.local
    (例如:db-0.db-service.default.svc.cluster.local

實戰演練:建立 StatefulSet 集群

步驟 1:建立 Headless Service 與 StatefulSet

建立 statefulset-demo.yaml,包含一個無頭服務與一個 3 副本的 StatefulSet:

apiVersion: v1
kind: Service
metadata:
  name: db-headless-service
spec:
  clusterIP: None
  selector:
    app: stateful-db
  ports:
    - port: 80
      name: web
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: stateful-db
spec:
  serviceName: "db-headless-service" # 綁定 Headless Service
  replicas: 3
  selector:
    matchLabels:
      app: stateful-db
  template:
    metadata:
      labels:
        app: stateful-db
    spec:
      containers:
        - name: app
          image: nginx:1.25
          ports:
            - containerPort: 80
              name: web
          volumeMounts:
            - name: db-data
              mountPath: /usr/share/nginx/html
  # 為每個副本自動動態產生獨立的 PVC
  volumeClaimTemplates:
    - metadata:
        name: db-data
      spec:
        accessModes: ["ReadWriteOnce"]
        resources:
          requests:
            storage: 1Gi

套用配置:

kubectl apply -f statefulset-demo.yaml

步驟 2:觀察有序啟動過程

打開另一個終端機觀察 Pod 建立的順序:

kubectl get pods -l app=stateful-db -w

你會看到嚴格的循序漸進過程:

  1. stateful-db-0 先進入 ContainerCreatingRunning
  2. 確認 0 號健康後,stateful-db-1 才開始建立。
  3. 最後才建立 stateful-db-2

步驟 3:驗證專屬獨立 PVC

查看系統中的 PVC:

kubectl get pvc

預期輸出:

NAME                    STATUS   VOLUME                                     CAPACITY   ACCESS MODES   AGE
db-data-stateful-db-0   Bound    pvc-11111111-2222-3333-4444-555555555555   1Gi        RWO            1m
db-data-stateful-db-1   Bound    pvc-22222222-3333-4444-5555-666666666666   1Gi        RWO            1m
db-data-stateful-db-2   Bound    pvc-33333333-4444-5555-6666-777777777777   1Gi        RWO            1m

Kubernetes 根據 volumeClaimTemplates,自動為 012 各自建立了一顆完全隔離的專屬磁碟!


步驟 4:測試固定網域名稱連線

我們臨時起一個測試容器,驗證是否可以直接透過域名精準指定存取 stateful-db-0

kubectl run dns-test --image=curlimages/curl --rm -it -- restart=Never -- nslookup stateful-db-0.db-headless-service

CoreDNS 會直接解析出 stateful-db-0 的專屬 IP 位址!即使 stateful-db-0 被刪除重建,新生的 Pod 依然會繼承這個域名與原本的 PVC 磁碟。


本日小結

今天我們搞懂了專門處理有狀態應用的 StatefulSet

  • 透過有序編號(0, 1, 2)倒序銷毀確保分散式應用的啟動安全。
  • 搭配 Headless Service 獲得固定唯一的 Pod 網域名稱。
  • 透過 volumeClaimTemplates 讓每個 Pod 都享有自己專屬、不共用的持久化磁碟。

到目前為止,我們學到的 Deployment 與 StatefulSet 都是「長時間持續運行(Long-running)」的服務。但有些工作只需要跑一次就結束(例如資料庫遷移、批次報表計算、定時備份腳本)。

明天 Day 18,我們將學習排程與一次性任務的利器:「排程與一次性任務:Job 與 CronJob 自動化執行腳本」


上一篇
【Day 16】資料持久化:PersistentVolume (PV) 與 PersistentVolumeClaim (PVC)
下一篇
【Day 18】排程與一次性任務:Job 與 CronJob 自動化執行腳本
系列文
從零開始的雲端實戰:30 天 Kubernetes 核心觀念與部署指南30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言