Statefulset控制器
- 一、概念
- 二、Statefulset資源清單文件編寫技巧
- 2.1、查看定義Statefulset資源需要的字段
- 2.2、查看statefulset.spec字段如何定義
- 2.3、查看statefulset的spec.template字段如何定義
- 三、Statefulset使用案例:部署web站點
- 3.1、編寫一個Statefulset資源清單文件
- 3.2、更新資源清單文件
- 3.3、查看相關資源
- 四、StatefulSet組成部分
- 4.1、 Headless Service
- 【1】headless service會為service分配一個域名
- 【2】StatefulSet會為關聯的Pod保持一個不變的Pod Name
- 【3】StatefulSet會為關聯的Pod分配一個dnsName
- 4.2、volumeClaimTemplates
- 4.3、總結
- 五、Statefulset管理pod:擴容、縮容、更新
- 5.1、動態擴縮容
- 5.2、滾動更新
一、概念
StatefulSet是為了管理有狀態服務的問題而設計的.
擴展:
有狀態服務?
StatefulSet是有狀態的集合,管理有狀態的服務,它所管理的Pod的名稱不能隨意變化。數據持久化的目錄也是不一樣,每一個Pod都有自己獨有的數據持久化存儲目錄。比如MySQL主從、redis集群等。
無狀態服務?
RC、Deployment、DaemonSet都是管理無狀態的服務,它們所管理的Pod的IP、名字,啟停順序等都是隨機的。個體對整體無影響,所有pod都是共用一個數據卷的,部署的tomcat就是無狀態的服務,tomcat被刪除,在啟動一個新的tomcat,加入到集群即可,跟tomcat的名字無關。
二、Statefulset資源清單文件編寫技巧
2.1、查看定義Statefulset資源需要的字段
[root@master ~]# kubectl explain statefulset
KIND: StatefulSet
VERSION: apps/v1DESCRIPTION:StatefulSet represents a set of pods with consistent identities. Identitiesare defined as:- Network: A single stable DNS and hostname.- Storage: As many VolumeClaims as requested.The StatefulSet guarantees that a given network identity will always map tothe same storage identity.FIELDS:apiVersion <string> # 定義資源需要使用的api版本kind <string> # 定義資源類型metadata <Object> # 定義元數據spec <Object> # 定義容器相關的信息
2.2、查看statefulset.spec字段如何定義
[root@master ~]# kubectl explain statefulset.spec
KIND: StatefulSet
VERSION: apps/v1RESOURCE: spec <Object>DESCRIPTION:Spec defines the desired identities of pods in this set.A StatefulSetSpec is the specification of a StatefulSet.FIELDS:podManagementPolicy <string> # POD管理策略replicas <integer> # 副本數revisionHistoryLimit <integer> # 保留的歷史版本selector <Object> -required- # 標簽選擇器,選擇它所關聯的podserviceName <string> -required- # headless service的名字template <Object> -required- # 生成pod的模板updateStrategy <Object> # 更新策略volumeClaimTemplates <[]Object> # 存儲卷申請模板
2.3、查看statefulset的spec.template字段如何定義
對于template而言,其內部定義的就是pod,pod模板是一個獨立的對象。
.spec.template里的內容是聲明Pod對象時要定義的各種屬性,所以這部分也叫做PodTemplate(Pod模板)
[root@master ~]# kubectl explain statefulset.spec.template
KIND: StatefulSet
VERSION: apps/v1RESOURCE: template <Object>
DESCRIPTION:......
FIELDS:metadata <Object> # 定義多少個Pod副本(默認將僅部署1個Pod)、匹配Pod標簽的選擇器、創建pod的模板、存儲卷申請模板 spec <Object> # Pod里的容器屬性等配置 # 在spec.template.spec.selector中定義的標簽選擇器必須能夠匹配到spec.template.metadata.labels里定義的Pod標簽,否則Kubernetes將不允許創建statefulset。
三、Statefulset使用案例:部署web站點
3.1、編寫一個Statefulset資源清單文件
[root@master 12]# cat statefulset.yaml
apiVersion: v1 # 定義api版本
kind: Service # 定義要創建的資源:service
metadata:name: nginx # 定義service的名字labels: app: nginx # service的標簽
spec:ports:- port: 80name: webclusterIP: None # 創建一個沒有ip的serviceselector:app: nginx # 選擇擁有app=nginx標簽的pod
---
apiVersion: apps/v1
kind: StatefulSet
metadata:name: web
spec:selector:matchLabels:app: nginxserviceName: "nginx" # headless service的名字replicas: 2 # 副本數template:metadata: # 定義pod的模板labels:app: nginxspec:containers:- name: nginximage: nginxports:- containerPort: 80 # 容器服務的端口name: web # 端口別名volumeMounts:- name: wwwmountPath: /usr/share/nginx/htmlvolumeClaimTemplates: # 存儲卷申請模板- metadata:name: wwwspec:accessModes: ["ReadWriteOnce"] # 訪問模式:單路讀寫storageClassName: "nfs" # 指定從哪個存儲類申請pvresources:requests:storage: 1Gi # 需要1G的pvc,會自動跟符合條件的pv綁定
3.2、更新資源清單文件
[root@master 12]# kubectl apply -f statefulset.yaml
service/nginx created
statefulset.apps/web created
# 查看statefulset是否創建成功
[root@master 12]# kubectl get statefulset
NAME READY AGE
web 2/2 2m7s
# 查看pod
[root@master 12]# kubectl get pods -l app=nginx
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 2m50s
web-1 1/1 Running 0 2m8s
# 通過上面可以看到創建的pod是有序的
3.3、查看相關資源
[root@master 12]# kubectl get svc -l app=nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx ClusterIP None <none> 80/TCP 3m50s
[root@master 12]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
www-web-0 Bound pvc-223fc042-1b1b-4516-a1b5-a5572434d3ee 1Gi RWO nfs 4m8s
www-web-1 Bound pvc-b4f026b2-4984-4302-b45d-00c57a74a162 1Gi RWO nfs 3m26s
[root@master 12]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-223fc042-1b1b-4516-a1b5-a5572434d3ee 1Gi RWO Delete Bound default/www-web-0 nfs 4m39s
pvc-b4f026b2-4984-4302-b45d-00c57a74a162 1Gi RWO Delete Bound default/www-web-1 nfs 3m56s
[root@master 12]# for i in 0 1; do kubectl exec web-$i -- sh -c 'hostname';done
web-0
web-1
四、StatefulSet組成部分
4.1、 Headless Service
用來定義pod網路標識,生成可解析的DNS記錄
Headless service不分配clusterIP,headless service可以通過解析service的DNS,返回所有Pod的dns和ip地址 (statefulSet部署的Pod才有DNS),普通的service,只能通過解析service的DNS返回service的ClusterIP。
【1】headless service會為service分配一個域名
<service name>.$<namespace name>.svc.cluster.local
K8s中資源的全局FQDN格式:
Service_NAME.NameSpace_NAME.Domain.LTD.
Domain.LTD.=svc.cluster.local #這是默認k8s集群的域名。
擴展:FQDN
FQDN 全稱 Fully Qualified Domain Name
即全限定域名:同時帶有主機名和域名的名稱
FQDN = Hostname + DomainName
如 主機名是 xianchao 域名是 baidu.com
FQDN= xianchao.baidu.com
【2】StatefulSet會為關聯的Pod保持一個不變的Pod Name
statefulset中Pod的名字格式為$(StatefulSet name)-$(pod序號)
【3】StatefulSet會為關聯的Pod分配一個dnsName
$<Pod Name>.$<service name>.$<namespace name>.svc.cluster.local
4.2、volumeClaimTemplates
為什么要用volumeClaimTemplate?
對于有狀態應用都會用到持久化存儲,比如mysql主從,由于主從數據庫的數據是不能存放在一個目錄下的,每個mysql節點都需要有自己獨立的存儲空間。
而在deployment中創建的存儲卷是一個共享的存儲卷,多個pod使用同一個存儲卷,它們數據是同步的,而statefulset定義中的每一個pod都不能使用同一個存儲卷,這就需要使用volumeClainTemplate。
當在使用statefulset創建pod時,volumeClainTemplate會自動生成一個PVC,從而請求綁定一個PV,每一個pod都有自己專用的存儲卷。
Pod、PVC和PV對應的關系圖如下:
使用kubectl run運行一個提供nslookup命令的容器,這個命令來自于dnsutils包,通過對pod主機名執行nslookup,可以檢查它們在集群內部的DNS地址
kubectl run busybox --image docker.io/library/busybox:1.28 --image-pull-policy=IfNotPresent --restart=Never --rm -it busybox -- sh
If you don't see a command prompt, try pressing enter.
/ # nslookup web-0.nginx.default.svc.cluster.local
Server: 10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.localName: web-0.nginx.default.svc.cluster.local # 查詢service dns,會把對應的pod ip解析出來
Address 1: 10.244.196.144 web-0.nginx.default.svc.cluster.local
4.3、總結
- 1、Statefulset管理的pod,pod名字是有序的,由statefulset的名字-0、1、2這種格式組成
- 2、創建statefulset資源的時候,必須事先創建好一個service,如果創建的service沒有ip,那對這個service做dns解析,會找到它所關聯的pod ip,如果創建的service有ip,那對這個service做dns解析,會解析到service本身ip。
- 3、statefulset管理的pod,刪除pod,新創建的pod名字跟刪除的pod名字是一樣的
- 4、statefulset具有volumeclaimtemplate這個字段,這個是卷申請模板,會自動創建pv,pvc也會自動生成,跟pv進行綁定,那如果創建的statefulset使用了volumeclaimtemplate這個字段,那創建pod,數據目錄是獨享的
- 5、ststefulset創建的pod,是有域名的(域名組成:pod-name.svc-name.svc-namespace.svc.cluster.local)
五、Statefulset管理pod:擴容、縮容、更新
5.1、動態擴縮容
如果我們覺得兩個副本太少了,想要增加,只需要修改配置文件statefulset.yaml里的replicas的值即可,原來replicas: 2,現在變成replicaset: 3,修改之后,執行如下命令更新:
[root@master 12]# kubectl apply -f statefulset.yaml
service/nginx unchanged
statefulset.apps/web configured
[root@master 12]# kubectl get sts
NAME READY AGE
web 3/3 80m
[root@master 12]# kubectl get pods -l app=nginx
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 81m
web-1 1/1 Running 0 80m
web-2 1/1 Running 0 28s
也可以直接編輯控制器實現擴容,這個是我們把請求提交給了apiserver,實時修改
[root@master 12]# kubectl edit sts web # 副本改成4
statefulset.apps/web edited
[root@master 12]# kubectl get pods -l app=nginx
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 82m
web-1 1/1 Running 0 81m
web-2 1/1 Running 0 90s
web-3 1/1 Running 0 7s
5.2、滾動更新
kubectl explain sts.spec.updateStrategy
[root@master 12]# kubectl explain sts.spec.updateStrategy
KIND: StatefulSet
VERSION: apps/v1RESOURCE: updateStrategy <Object>DESCRIPTION:updateStrategy indicates the StatefulSetUpdateStrategy that will beemployed to update Pods in the StatefulSet when a revision is made toTemplate.StatefulSetUpdateStrategy indicates the strategy that the StatefulSetcontroller will use to perform updates. It includes any additionalparameters necessary to perform the update for the indicated strategy.FIELDS:rollingUpdate <Object>RollingUpdate is used to communicate parameters when Type isRollingUpdateStatefulSetStrategyType.type <string>Type indicates the type of the StatefulSetUpdateStrategy. Default isRollingUpdatePossible enum values:- `"OnDelete"` - `"RollingUpdate"`
[root@master 12]# cat statefulset.yaml
apiVersion: v1
kind: Service
metadata:name: nginxlabels:app: nginx
spec:ports:- port: 80name: webclusterIP: Noneselector:app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:name: web
spec:updateStrategy: # 1、添加更新策略rollingUpdate:partition: 1 # 序號大于等于1的pod做更新maxUnavailable: 0 # 滾動更新時允許不可用 Pod 的最大數量selector:matchLabels:app: nginxserviceName: "nginx"replicas: 3template:metadata:labels:app: nginxspec:containers:- name: nginximage: ikubernetes/myapp:v2 # 2、修改鏡像:容器才會更新imagePullPolicy: IfNotPresentports:- containerPort: 80name: webvolumeMounts:- name: wwwmountPath: /usr/share/nginx/htmlvolumeClaimTemplates:- metadata:name: wwwspec:accessModes: ["ReadWriteOnce"]storageClassName: "nfs"resources:requests:storage: 1Gi
# 在一個終端執行如下命令:kubectl apply -f statefulset.yaml
# 在另一個終端動態查看pod
[root@master ~]# kubectl get pods -l app=nginx -w
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 102m
web-1 1/1 Running 0 101m
web-2 1/1 Running 0 22m
web-3 1/1 Running 0 20m
web-3 1/1 Terminating 0 20m
web-3 1/1 Terminating 0 20m
web-3 0/1 Terminating 0 20m
web-3 0/1 Terminating 0 20m
web-3 0/1 Terminating 0 20m
web-2 1/1 Terminating 0 22m
web-2 1/1 Terminating 0 22m
web-2 0/1 Terminating 0 22m
web-2 0/1 Terminating 0 22m
web-2 0/1 Terminating 0 22m
web-2 0/1 Pending 0 0s
web-2 0/1 Pending 0 0s
web-2 0/1 ContainerCreating 0 0s
web-2 0/1 ContainerCreating 0 1s
web-2 1/1 Running 0 10s
web-1 1/1 Terminating 0 102m
web-1 1/1 Terminating 0 102m
web-1 0/1 Terminating 0 102m
web-1 0/1 Terminating 0 102m
web-1 0/1 Terminating 0 102m
web-1 0/1 Pending 0 0s
web-1 0/1 Pending 0 0s
web-1 0/1 ContainerCreating 0 0s
web-1 0/1 ContainerCreating 0 0s
web-1 1/1 Running 0 9s
web-2 1/1 Running 0 42s
web-1 1/1 Running 0 52s# 從上面結果可以看出來,pod在更新的時候,只是更新了web-1、2、3
# partition: 1表示更新的時候會把pod序號大于等于1的進行更新
如果更新策略是OnDelete,那不會自動更新pod,需要手動刪除,重新常見的pod才會實現更新
修改策略:
updateStrategy:type: OnDelete# rollingUpdate:# partition: 1# maxUnavailable: 0
[root@master 12]# kubectl apply -f statefulset.yaml
service/nginx unchanged
statefulset.apps/web configured
[root@master 12]# kubectl get pod -l app=nginx
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 121m
web-1 1/1 Running 0 18m
web-2 1/1 Running 0 18m
[root@master 12]# kubectl delete pod web-0
pod "web-0" deleted
# 在另一種終端動態查看
[root@master ~]# kubectl get pod -w
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 122m
web-1 1/1 Running 0 19m
web-2 1/1 Running 0 19m
web-0 1/1 Terminating 0 122m
web-0 1/1 Terminating 0 122m
web-0 0/1 Terminating 0 122m
web-0 0/1 Terminating 0 122m
web-0 0/1 Terminating 0 122m
web-0 0/1 Pending 0 0s
web-0 0/1 Pending 0 0s
web-0 0/1 ContainerCreating 0 0s
web-0 0/1 ContainerCreating 0 1s
web-0 1/1 Running 0 2s