StatefulSet如何提供穩定的網路標識和狀態
ReplicaSet中的Pod都是無狀態,可隨意替代的。又因為ReplicaSet中的Pod是根據模板生成的多副本,無法對每個副本都指定單獨的PVC。
來看一下StatefulSet如何解決的。
提供穩定的網路標識
StatefulSet建立Pod都有一個從零開始的順序索引,這會體現在Pod的名稱和主機名上,同樣也會體現在Pod對應的固定儲存上。所以這些名字是可預先知道的,不同於ReplicaSet的隨機生成名字。
因為他們的名字都是固定的,而且彼此狀態都不同,通常會操作他們其中的一個。如此情況,一般都會建立一個與之對應的headless Service,通過這個Service,每個Pod將擁有獨立的DNS記錄。
擴容一個StatefulSet會使用下一個順序索引建立一個新的Pod,縮容會刪除索引值最高的。並且縮容任何時候只會操作一個Pod。
如何提供穩定的儲存
StatefulSet可以擁有一個或多個PVC模板,這些PVC會在建立Pod前建立出來,繫結到一個Pod例項上。
擴容的時候會建立一個Pod以及若干個PVC,刪除的時候只會刪除Pod。StatefulSet縮容時不會刪除PVC,擴容時會重新掛上。
使用StatefulSet
定義三個PV
定義pv-(a|b|c)
# stateful-pv-list.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-a
spec:
capacity:
storage: 1Mi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
hostPath:
path: /tmp/pva
---
apiVersion: v1
kind: PersistentVolume
# 以下忽略
headless的Service
# stateful-service-headless.yaml
apiVersion: v1
kind: Service
metadata:
name: rwfile
spec:
clusterIP: None
selector:
app: rwfile
ports:
- port: 80
定義StatefulSet
先建立兩個Pod副本。使用volumeClaimTemplates定義了PVC模板。
# stateful.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: rwfile
spec:
replicas: 2
serviceName: rwfile
selector:
matchLabels:
app: rwfile
template:
metadata:
labels:
app: rwfile
spec:
containers:
- image: registry.cn-hangzhou.aliyuncs.com/orzi/rwfile
name: rwfile
ports:
- containerPort: 8000
volumeMounts:
- name: data
mountPath: /tmp/data
volumeClaimTemplates:
- metadata:
name: data
spec:
resources:
requests:
storage: 1Mi
accessModes:
- ReadWriteOnce
建立三個PV,一個headless的Service,一個StatefulSet
-> [root@kube0.vm] [~] k create -f stateful-pv-list.yaml
persistentvolume/pv-a created
persistentvolume/pv-b created
persistentvolume/pv-c created
-> [root@kube0.vm] [~] k create -f stateful-service-headless.yaml
service/rwfile created
-> [root@kube0.vm] [~] k create -f stateful.yaml
statefulset.apps/rwfile created
檢視
-> [root@kube0.vm] [~] k get all -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/rwfile-0 1/1 Running 0 12s 10.244.1.52 kube1.vm <none> <none>
pod/rwfile-1 1/1 Running 0 8s 10.244.2.56 kube2.vm <none> <none>
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 81s <none>
service/rwfile ClusterIP None <none> 80/TCP 23s app=rwfile
NAME READY AGE CONTAINERS IMAGES
statefulset.apps/rwfile 2/2 12s rwfile registry.cn-hangzhou.aliyuncs.com/orzi/rwfile
檢視PV和PVC,可以看到已經有兩個PVC繫結了PV
-> [root@kube0.vm] [~] k get pv,pvc -o wide
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE VOLUMEMODE
persistentvolume/pv-a 1Mi RWO Recycle Bound default/data-rwfile-0 7m20s Filesystem
persistentvolume/pv-b 1Mi RWO Recycle Bound default/data-rwfile-1 7m20s Filesystem
persistentvolume/pv-c 1Mi RWO Recycle Available 7m20s Filesystem
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE VOLUMEMODE
persistentvolumeclaim/data-rwfile-0 Bound pv-a 1Mi RWO 6m55s Filesystem
persistentvolumeclaim/data-rwfile-1 Bound pv-b 1Mi RWO 6m51s Filesystem
請求Pod
啟動代理
-> [root@kube0.vm] [~] k proxy
Starting to serve on 127.0.0.1:8001
傳送請求
-> [root@kube0.vm] [~] curl http://localhost:8001/api/v1/namespaces/default/pods/rwfile-0/proxy/ -d "a=123"
data stored in : rwfile-0
-> [root@kube0.vm] [~] curl http://localhost:8001/api/v1/namespaces/default/pods/rwfile-0/proxy/
a=123
刪除測試
刪除rwfile-0,然後檢視,從時間上看確實是被刪除重建的。
-> [root@kube0.vm] [~] k delete po rwfile-0
pod "rwfile-0" deleted
-> [root@kube0.vm] [~] k get po
NAME READY STATUS RESTARTS AGE
rwfile-0 1/1 Running 0 7s
rwfile-1 1/1 Running 0 19m
看一下之前儲存的資料還在不在
-> [root@kube0.vm] [~] curl http://localhost:8001/api/v1/namespaces/default/pods/rwfile-0/proxy/
a=123
還是在的,此次測試實際上也證明了StatefulSet提供了穩定的網路標識和儲存。
發現StatefulSet的夥伴節點
使用DNS解析headless的Service的FQDN。
例子以後再寫吧。。
如何處理節點失效
除非確定節點無法執行或者不會在訪問,否則不要強制刪除有狀態的Pod
k delete pod rwfile-0 --force --grace-period 0
小結
- StatefulSet建立Pod都有一個從零開始的順序索引
- 通常會建立一個與StatefulSet對應的headless Service。
- 擴容一個StatefulSet會使用下一個順序索引建立一個新的Pod,縮容會刪除索引值最高的。
- 新建StatefulSet需要指定headless ServiceName和volumeClaimTemplates。
- 使用DNS發現StatefulSet的夥伴節點
- 強制刪除:
k delete pod rwfile-0 --force --grace-period 0