本篇將說明關於StatefulSet的基本概念,因為怕太長,所以關於部分測試再分成另一篇文章來說明。
本文將說明:
針對”有狀態”的服務使用,例如如果是使用了db cluster時,ReplicaSet會因為ID不固定(random)而無法使服務正常運行,並且由於要接回原本的volume,也必須要透過這種方式實現。
特性如下:
一般來說,K8S的Service可以再細分成以下二種:
mysvc.mynamespace.svc.cluster.local
就是透過DNS服務解析到的mysvc的cluster IPHeadless Service
:訪問mysvc.mynamespace.sve.cluster.local
時,直接解析到mysvc代理的某一個實體Pod IP,中間少了cluster IP轉發。Headless Service不需要分配一個VIP,kube-proxy不會處理它們,
平台也不會為它們進行load balancer和路由,而是直接以DNS record的方式解析到後面Pod IP
apiVersion: v1
kind: Service
metadata:
name: nginx
namespace: example
labels:
app: nginx
spec:
ports:
- name: http
port: 80
clusterIP: None <-- headless主要差別為None
selector:
app: nginx
=> 服務建立後,不會分配cluster ip, 要改用DNS recored的方式暴露所代理的Pod
Headless Service在資料庫集群等應用中非常有用,因為它允許應用程式直接連接到資料庫的各個實例,而無需通過代理或負載均衡器。
Headless Service也可用於服務發現,因為它提供了一個可靠的方式來查找和連接到後端Pod。這對於微服務架構中的動態服務發現非常有用。
預設的管理策略為OrderedReady(照上下文的順序)
。可以改成Parallel(讓controller 平行終止所有Pod)
,這種方式可以在啟動或終止另一個Pod之前,不用等其他Pod的狀態。
apiVersion: v1
kind: Service
metadata:
name: nginx-ordered
namespace: nginx-sts
labels:
app: nginx
spec:
ports:
- name: http
port: 80
clusterIP: None
selector:
app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web-sts
namespace: nginx-sts
spec:
podManagementPolicy: OrderedReady
serviceName: "nginx-ordered"
replicas: 6
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 1Gi
### 確認Pod建立順序
# kubectl get pod -l app=nginx -w -n nginx-sts
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 99s
web-1 1/1 Running 0 98s
web-2 1/1 Running 0 95s
### 確認Pod刪除順序
# kubectl delete -f nginx-sts-ordered.yaml -n nginx-sts
# kubectl get po -l app=nginx -w -n nginx-sts
接下來,進行StatefulSet controller部署有狀態服務套用Policy控制的測試(Policy: Parallel):
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web-sts
namespace: nginx-sts
spec:
podManagementPolicy: Parallel
serviceName: "nginx-parallel"
replicas: 6
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 1Gi
### 確認Pod建立順序
# kubectl create -f nginx-sts-parallel.yaml -n nginx-sts ; kubectl get pod -l app=nginx -w -n nginx-sts
### 確認Pod刪除順序
# kubectl delete -f nginx-sts-parallel.yaml -n nginx-sts ; kubectl get pod -l app=nginx -w -n nginx-sts
StatefulSet也支援2種升級策略:onDelete
、RollingUpdate
。
### RollingUpdate: 建立statefulset
# kubectl create -f nginx-sts-parallel.yaml -n nginx-sts; kubectl get pod -l app=nginx -w -n nginx-sts
statefulset.apps/web created
NAME READY STATUS RESTARTS AGE
web-0 0/1 ContainerCreating 0 0s
web-1 0/1 ContainerCreating 0 0s
web-2 0/1 ContainerCreating 0 0s
web-3 0/1 ContainerCreating 0 0s
web-4 0/1 ContainerCreating 0 0s
web-5 0/1 ContainerCreating 0 0s
web-3 0/1 ContainerCreating 0 1s
web-0 0/1 ContainerCreating 0 1s
web-2 0/1 ContainerCreating 0 1s
web-1 0/1 ContainerCreating 0 1s
web-4 0/1 ContainerCreating 0 2s
web-2 1/1 Running 0 2s
web-3 1/1 Running 0 2s
web-5 0/1 ContainerCreating 0 3s
web-0 1/1 Running 0 3s
web-1 1/1 Running 0 3s
web-4 1/1 Running 0 4s
web-5 1/1 Running 0 4s
### 使用edit, 修改容器image (or edit YAML)
# kubectl patch statefulset web -n nginx-sts --type='json' -p='[{"op": "replace", "path":"/spec/template/spec/containers/0/image", "value":"nginx:latest"}]'
### RollingUpdate: 確認變化
# kubectl get pod -l app=nginx -w -n nginx-sts### RollingUpdate:
### RollingUpdate: 查看滾動更新狀態
# kubectl rollout status sts web -n nginx-sts
partitioned roll out complete: 6 new pods have been updated...
以下說明利用上述更新方式實現應用服務的Partitions(分段更新):Pod序號大於或等於Partition的pod會在Statefulset template更新後進行rollingUpdate, 其他的則不變。
例如:web0~web-9, partition設為3,只會更新web3~web-9,web0~web2不會更新,實現灰度發佈
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
namespace: nginx-sts
spec:
podManagementPolicy: OrderedReady
serviceName: "nginx-partition"
replicas: 6
updateStrategy:
type: RollingUpdate
rollingUpdate:
partition: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
spec:
accessModes: [ "ReadWriteMany" ]
resources:
requests:
storage: 1Gi
### RollingUpdate: 確認目前狀態
# kubectl get pod -l app=nginx -w -n nginx-sts
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 110s
web-1 1/1 Running 0 109s
web-2 1/1 Running 0 108s
web-3 1/1 Running 0 107s
web-4 1/1 Running 0 105s
web-5 1/1 Running 0 104s
### RollingUpdate: 觸發更新image 版本,啟動rollingupdate
# kubectl get pod -l app=nginx -w -n nginx-sts
# kubectl patch statefulset web -n nginx-sts --type='json' -p='[{"op": "replace", "path":"/spec/template/spec/containers/0/image", "value":"nginx:latest"}]'
### RollingUpdate: 確認pod內的image版本, 因partition=2, 故應為web2~5會有變化
# kubectl get pod web-1 -o yaml -n nginx-sts |grep image
# kubectl get pod web-2 -o yaml -n nginx-sts |grep image