K8S有狀態服務-StatefulSet使用最佳實踐

kanjunbao發表於2018-08-24

介紹

StatefulSet是一種給Pod提供唯一標誌的控制器,它可以保證部署和擴充套件的順序。

Pod一致性:包含次序(啟動、停止次序)、網路一致性。此一致性與Pod相關,與被排程到哪個node節點無關。

穩定的次序:對於N個副本的StatefulSet,每個Pod都在[0,N)的範圍內分配一個數字序號,且是唯一的。

穩定的網路:Pod的hostname模式為$(statefulset名稱)-$(序號)。

穩定的儲存:通過VolumeClaimTemplate為每個Pod建立一個PV。刪除、減少副本,不會刪除相關的卷。

阿里云云盤支援動態掛載的功能,可以通過VolumeClaimTemplate方式部署statefulset應用。

部署Statefulset服務

volumeClaimTemplates:表示一類PVC的模板,系統會根據Statefulset配置的replicas數量,建立相應數量的PVC。這些PVC除了名字不一樣之外其他配置都是一樣的。

下面storageClassName配置為alicloud-disk-ssd,表示使用阿里雲SSD型別雲盤。

apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: nginx
---
apiVersion: apps/v1beta2
kind: StatefulSet
metadata:
  name: web
spec:
  selector:
    matchLabels:
      app: nginx
  serviceName: "nginx"
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: disk-ssd
          mountPath: /data
  volumeClaimTemplates:
  - metadata:
      name: disk-ssd
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: "alicloud-disk-ssd"
      resources:
        requests:
          storage: 20Gi

驗證服務伸縮性

建立Statefulset服務:


# kubectl create -f statefulset.yaml

# kubectl get pod
NAME      READY     STATUS    RESTARTS   AGE
web-0     1/1       Running   0          21m
web-1     1/1       Running   0          20m

# kubectl get pvc
NAME             STATUS    VOLUME                   CAPACITY   ACCESS MODES   STORAGECLASS        AGE
disk-ssd-web-0   Bound     d-2ze9k2rrtcy92e97d3ie   20Gi       RWO            alicloud-disk-ssd   21m
disk-ssd-web-1   Bound     d-2ze5dwq6gyjnvdcrmtwg   20Gi       RWO            alicloud-disk-ssd   21m

擴容服務到3個Pod,顯示會建立新的雲盤卷:

# kubectl scale sts web --replicas=3
statefulset.apps "web" scaled

# kubectl get pod
NAME      READY     STATUS    RESTARTS   AGE
web-0     1/1       Running   0          24m
web-1     1/1       Running   0          23m
web-2     1/1       Running   0          2m

# kubectl get pvc
NAME             STATUS    VOLUME                   CAPACITY   ACCESS MODES   STORAGECLASS        AGE
disk-ssd-web-0   Bound     d-2ze9k2rrtcy92e97d3ie   20Gi       RWO            alicloud-disk-ssd   24m
disk-ssd-web-1   Bound     d-2ze5dwq6gyjnvdcrmtwg   20Gi       RWO            alicloud-disk-ssd   24m
disk-ssd-web-2   Bound     d-2zea5iul9f4vgt82hxjj   20Gi       RWO            alicloud-disk-ssd   2m

縮容服務到2個Pod,顯示pvc/pv並不會一同刪除:


# kubectl scale sts web --replicas=2
statefulset.apps "web" scaled

# kubectl get pod
NAME      READY     STATUS    RESTARTS   AGE
web-0     1/1       Running   0          25m
web-1     1/1       Running   0          25m

# kubectl get pvc
NAME             STATUS    VOLUME                   CAPACITY   ACCESS MODES   STORAGECLASS        AGE
disk-ssd-web-0   Bound     d-2ze9k2rrtcy92e97d3ie   20Gi       RWO            alicloud-disk-ssd   25m
disk-ssd-web-1   Bound     d-2ze5dwq6gyjnvdcrmtwg   20Gi       RWO            alicloud-disk-ssd   25m
disk-ssd-web-2   Bound     d-2zea5iul9f4vgt82hxjj   20Gi       RWO            alicloud-disk-ssd   3m

再次擴容到3個Pod,新的pod會複用原來的PVC/PV:

# kubectl scale sts web --replicas=3
statefulset.apps "web" scaled

# kubectl get pod
NAME      READY     STATUS    RESTARTS   AGE
web-0     1/1       Running   0          27m
web-1     1/1       Running   0          27m
web-2     1/1       Running   0          2m

# kubectl get pvc
NAME             STATUS    VOLUME                   CAPACITY   ACCESS MODES   STORAGECLASS        AGE
disk-ssd-web-0   Bound     d-2ze9k2rrtcy92e97d3ie   20Gi       RWO            alicloud-disk-ssd   27m
disk-ssd-web-1   Bound     d-2ze5dwq6gyjnvdcrmtwg   20Gi       RWO            alicloud-disk-ssd   27m
disk-ssd-web-2   Bound     d-2zea5iul9f4vgt82hxjj   20Gi       RWO            alicloud-disk-ssd   5m

刪除StatefulSet服務,PVC、PV並不會隨著刪除;

驗證服務穩定性

刪除一個Pod前,Pod引用PVC:disk-ssd-web-1

# kubectl describe pod web-1 | grep ClaimName
ClaimName:  disk-ssd-web-1

# kubectl delete pod web-1
pod "web-1" deleted

刪除Pod後,重新建立的Pod名字與刪除的一致,且使用同一個PVC:

# kubectl get pod
NAME      READY     STATUS    RESTARTS   AGE
web-0     1/1       Running   0          29m
web-1     1/1       Running   0          6s
web-2     1/1       Running   0          4m

# kubectl describe pod web-1 | grep ClaimName
ClaimName:  disk-ssd-web-1

驗證服務高可用性

雲盤中建立臨時檔案:

# kubectl exec web-1 ls /data
lost+found

# kubectl exec web-1 touch /data/statefulset
# kubectl exec web-1 ls /data
lost+found
statefulset

刪除Pod,驗證資料永續性:

# kubectl delete pod web-1
pod "web-1" deleted

# kubectl exec web-1 ls /data
lost+found
statefulset


相關文章