今天要來介紹什麼是 Statefulset ,一般我們前面進行透過 Deployment 部署的 POD,他都是 stateless , statefulset 跟 Deployment 的差別就在於它對對每一個 POD 產生固定的識別資訊,不會因為 POD 重啟而有所變動,所掛載的硬碟也都可以持續使用。

那到底什麼時侯應該使用 Statefulset ?

  • 需要持久性儲存,不因為 POD 重啟而需要重新設定硬碟給它。

這邊先給一個標準的 redis statefulset 設置

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: redis
spec:
  selector:
    matchLabels:
      app: redis
  serviceName: "redis"
  replicas: 1
  template:
    metadata:
      labels:
        app: redis
    spec:
      containers:
      - name: redis
        image: redis:5.0.4
        command: ["redis-server", "--appendonly", "yes"]
        ports:
        - containerPort: 6379
          name: web
        volumeMounts:
        - name: redis-aof
          mountPath: /data
  volumeClaimTemplates:
  - metadata:
      name: redis-aof
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: "gp2"
      resources:
        requests:
          storage: 1Gi

目前筆者 local 環境 multipass + k3s ,暫時無法實作出 local pvc,所以暫時無操作示範

照上面的 yaml 去部署相關檔案,應該會出現如下所示

$ kubectl --kubeconfig ~/.kube/k3s.yaml get pods
NAME                               READY   STATUS    RESTARTS   AGE
redis-0                            1/1     Running   2          5d17h

那我們需要去部署一個 headless service,用來搭配 Statefulset,

apiVersion: v1
kind: Service
metadata:
  name: redis
  labels:
    app: redis
spec:
  ports:
  - port: 6379
    name: web
  # 這邊跟一般 service 不同的重點在這,要把 clusterIP 設定為 None
  clusterIP: None
  selector:
    app: redis

這樣就完成了一個有狀態的 redis 設定。

大家有興趣可以去嘗試看看,另外部署一個無狀態的 redis,然後分別對這兩個 redis 設定資料,然後去 delete pods,看看 pod 重啟後,資料是不是都還在。

下面附上無狀態的 redis 設定檔,讓大家嘗試看看。

apiVersion: apps/v1
# 這裡改回 Deployment
kind: Deployment
metadata:
  name: redis
spec:
  selector:
    matchLabels:
      app: redis
  serviceName: "redis"
  replicas: 1
  template:
    metadata:
      labels:
        app: redis
    spec:
      containers:
      - name: redis
        image: redis:5.0.4
        command: ["redis-server", "--appendonly", "yes"]
        ports:
        - containerPort: 6379
          name: web
---
kind: Service
apiVersion: v1
metadata:
  name: redis
spec:
  type: ClusterIP
  selector:
    app: redis
  ports:
  - protocol: TCP
    port: 6379
    targetPort: 6379