Statefulset控制器:概念、原理解讀
用于管理有狀態(tài)應(yīng)用程序的部署。與無狀態(tài)應(yīng)用程序不同,有狀態(tài)應(yīng)用程序在運(yùn)行時通常要求穩(wěn)定的網(wǎng)絡(luò)標(biāo)識和持久性存儲。
- 有狀態(tài)服務(wù):StatefulSet是有狀態(tài)的集合,管理有狀態(tài)的服務(wù),它所管理的Pod的名稱不能隨意變化。數(shù)據(jù)持久化的目錄也是不一樣,每一個Pod都有自己獨(dú)有的數(shù)據(jù)持久化存儲目錄。比如MySQL主從、redis集群等。
- 無狀態(tài)服務(wù):RC、Deployment、DaemonSet都是管理無狀態(tài)的服務(wù),它們所管理的Pod的IP、名字,啟停順序等都是隨機(jī)的。個體對整體無影響,所有pod都是共用一個數(shù)據(jù)卷的,部署的tomcat就是無狀態(tài)的服務(wù),tomcat被刪除,在啟動一個新的tomcat,加入到集群即可,跟tomcat的名字無關(guān)。
Statefulset 功能
- 穩(wěn)定的網(wǎng)絡(luò)標(biāo)識: 每個StatefulSet管理的Pod都被分配一個穩(wěn)定的網(wǎng)絡(luò)標(biāo)識,通常是一個有序的索引(例如,Pod名稱的后綴)。這使得有狀態(tài)應(yīng)用程序能夠保持網(wǎng)絡(luò)標(biāo)識的穩(wěn)定性,從而更容易與其他系統(tǒng)進(jìn)行集成。
- 有序部署和縮放: StatefulSet確保Pod以有序的方式啟動和停止。當(dāng)新的Pod加入集群時,它們按照定義的順序啟動。同樣,當(dāng)縮減副本數(shù)量時,Pod按相反的順序終止。這有助于確保數(shù)據(jù)存儲等有狀態(tài)資源在縮放時能夠正確處理。
- 持久性存儲: StatefulSet通常與持久性存儲卷結(jié)合使用,以確保有狀態(tài)應(yīng)用程序的數(shù)據(jù)在Pod重新調(diào)度、重啟或升級時得以保留。每個Pod都可以使用一個或多個持久性存儲卷,這有助于保持?jǐn)?shù)據(jù)的一致性和可用性。
- 頭銜服務(wù)(Headless Service): StatefulSet通常與一個頭銜服務(wù)關(guān)聯(lián)。頭銜服務(wù)為每個Pod提供唯一的DNS名稱,這有助于通過服務(wù)發(fā)現(xiàn)訪問有狀態(tài)應(yīng)用程序的各個實(shí)例。
Statefulset資源清單文件編寫技巧
查看定義Statefulset資源需要的字段
kubectl explain statefulset
KIND: StatefulSet
VERSION: apps/v1
DESCRIPTION:
StatefulSet represents a set of pods with consistent identities. Identities
are 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 to the same storage identity.
FIELDS:
apiVersion <string> #定義statefulset資源需要使用的api版本
kind <string> #定義的資源類型
metadata <Object> #元數(shù)據(jù)
spec <Object> #定義容器相關(guān)的信息
查看statefulset.spec字段如何定義?
kubectl explain statefulset.spec
KIND: StatefulSet
VERSION: apps/v1
RESOURCE: 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> #副本數(shù)
revisionHistoryLimit <integer> #保留的歷史版本
selector <Object> -required- #標(biāo)簽選擇器,選擇它所關(guān)聯(lián)的pod
serviceName <string> -required- #headless service的名字
template <Object> -required- #生成pod的模板
updateStrategy <Object> #更新策略
volumeClaimTemplates <[]Object> #存儲卷申請模板
查看statefulset的spec.template字段如何定義
對于template而言,其內(nèi)部定義的就是pod,pod模板是一個獨(dú)立的對象
kubectl explain statefulset.spec.template
KIND: StatefulSet
VERSION: apps/v1
RESOURCE: template <Object>
DESCRIPTION:
template is the object that describes the pod that will be created if
insufficient replicas are detected. Each pod stamped out by the StatefulSet
will fulfill this Template, but have a unique identity from the rest of the
StatefulSet.
PodTemplateSpec describes the data a pod should have when created from a
template
FIELDS:
metadata <Object>
spec <Object> #定義容器屬性的
通過上面可以看到,statefulset資源中有兩個spec字段。
第一個spec聲明的是statefulset定義多少個Pod副本(默認(rèn)將僅部署1個Pod)、匹配Pod標(biāo)簽的選擇器、創(chuàng)建pod的模板、存儲卷申請模板
第二個spec是spec.template.spec:主要用于Pod里的容器屬性等配置。
.spec.template里的內(nèi)容是聲明Pod對象時要定義的各種屬性,所以這部分也叫做PodTemplate(Pod模板)。
還有一個值得注意的地方是:在.spec.selector中定義的標(biāo)簽選擇器必須能夠匹配到spec.template.metadata.labels里定義的Pod標(biāo)簽,否則Kubernetes將不允許創(chuàng)建statefulset。
Statefulset使用案例:部署web站點(diǎn)
編寫一個Statefulset資源清單文件
cat statefulset.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: nginx
---
apiVersion: apps/v1
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
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: "nfs"
resources:
requests:
storage: 1Gi
kubectl apply -f statefulset.yaml
kubectl get statefulset
NAME READY AGE
web 2/2 42s
kubectl get pods -l app=nginx
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 2m17s
web-1 1/1 Running 0 115s
查看headless service
kubectl get svc -l app=nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx ClusterIP None <none> 80/TCP 3m19s
查看pvc
kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
www-web-0 Bound pvc-39a9755f-3248-49ff-8f9e-5b068b609c8f 1Gi RWO,RWX nfs-web 7m45s
www-web-1 Bound pvc-be93d4a3-1aca-44cc-802f-ddeb38c05018 1Gi RWO,RWX nfs-web 7m41s
查看pv
kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-39a9755f-3248-49ff-8f9e-5b068b609c8f 1Gi RWO,RWX Delete Bound default/www-web-0 nfs-web 8m3s
pvc-be93d4a3-1aca-44cc-802f-ddeb38c05018 1Gi RWO,RWX Delete Bound default/www-web-1 nfs-web 7m59s
查看pod主機(jī)名
for i in 0 1; do kubectl exec web-$i -- sh -c 'hostname';done
web-0
web-1
StatefulSet由以下幾個部分組成:
- Headless Service:用來定義pod網(wǎng)路標(biāo)識,生成可解析的DNS記錄
- volumeClaimTemplates:存儲卷申請模板,創(chuàng)建pvc,指定pvc名稱大小,自動創(chuàng)建pvc,且pvc由存儲類供應(yīng)。
- StatefulSet:管理pod的
什么是Headless service
- Headless service不分配clusterIP,headless service可以通過解析service的DNS,返回所有Pod的dns和ip地址 (statefulSet部署的Pod才有DNS),普通的service,只能通過解析service的DNS返回service的ClusterIP。
- headless service會為service分配一個域名
- .$.svc.cluster.local
K8s中資源的全局FQDN格式:
Service_NAME.NameSpace_NAME.Domain.LTD.
Domain.LTD.=svc.cluster.local. #這是默認(rèn)k8s集群的域名
FQDN 全稱 Fully Qualified Domain Name
即全限定域名:同時帶有主機(jī)名和域名的名稱
FQDN = Hostname + DomainName
主機(jī)名是 hahaha
域名是 baidu.com
FQDN= hahaha.baidu.com
StatefulSet
StatefulSet會為關(guān)聯(lián)的Pod保持一個不變的Pod Name
statefulset中Pod的名字格式為$(StatefulSet name)-$(pod序號)
StatefulSet會為關(guān)聯(lián)的Pod分配一個dnsName
$<Pod Name>.$<service name>.$<namespace name>.svc.cluster.local
volumeClaimTemplate
對于有狀態(tài)應(yīng)用都會用到持久化存儲,比如mysql主從,由于主從數(shù)據(jù)庫的數(shù)據(jù)是不能存放在一個目錄下的,每個mysql節(jié)點(diǎn)都需要有自己獨(dú)立的存儲空間。而在deployment中創(chuàng)建的存儲卷是一個共享的存儲卷,多個pod使用同一個存儲卷,它們數(shù)據(jù)是同步的,而statefulset定義中的每一個pod都不能使用同一個存儲卷,這就需要使用volumeClainTemplate,當(dāng)在使用statefulset創(chuàng)建pod時,volumeClainTemplate會自動生成一個PVC,從而請求綁定一個PV,每一個pod都有自己專用的存儲卷。Pod、PVC和PV對應(yīng)的關(guān)系圖如下:
使用kubectl run運(yùn)行一個提供nslookup命令的容器的,這個命令來自于dnsutils包,通過對pod主機(jī)名執(zhí)行nslookup,可以檢查它們在集群內(nèi)部的DNS地址:
kubectl run busybox --image docker.io/library/busybox:1.28 --image-pull-policy=IfNotPresent --restart=Never --rm -it busybox -- sh
root@web-1:/# nslookup web-0.nginx.default.svc.cluster.local
Server: 10.96.0.10
Address: 10.96.0.10#53
Name: web-0.nginx.default.svc.cluster.local
statefulset創(chuàng)建的pod也是有dns記錄的
Address: 10.244.209.154 #解析的是pod的ip地址
root@web-1:/# nslookup nginx.default.svc.cluster.local
Server: 10.96.0.10
Address: 10.96.0.10#53
Name: nginx.default.svc.cluster.local #查詢service dns,會把對應(yīng)的pod ip解析出來
Address: 10.244.209.139
Name: nginx.default.svc.cluster.local
Address: 10.244.209.140
dig的使用
dig -t A nginx.default.svc.cluster.local @10.96.0.10
格式如下:
@來指定域名服務(wù)器
A 為解析類型 ,A記錄
-t 指定要解析的類型
A記錄:
A記錄是解析域名到IP
Statefulset總結(jié)
- Statefulset管理的pod,pod名字是有序的,由statefulset的名字-0、1、2這種格式組成
- 創(chuàng)建statefulset資源的時候,必須事先創(chuàng)建好一個service,如果創(chuàng)建的service沒有ip,那對這個service做dns解析,會找到它所關(guān)聯(lián)的pod ip,如果創(chuàng)建的service有ip,那對這個service做dns解析,會解析到service本身ip。
- statefulset管理的pod,刪除pod,新創(chuàng)建的pod名字跟刪除的pod名字是一樣的
- statefulset具有volumeclaimtemplate這個字段,這個是卷申請模板,會自動創(chuàng)建pv,pvc也會自動生成,跟pv進(jìn)行綁定,那如果創(chuàng)建的statefulset使用了volumeclaimtemplate這個字段,那創(chuàng)建pod,數(shù)據(jù)目錄是獨(dú)享的
- ststefulset創(chuàng)建的pod,是域名的(域名組成:pod-name.svc-name.svc-namespace.svc.cluster.local)
舉例說明service 和headless service區(qū)別:
通過deployment創(chuàng)建pod,pod前端創(chuàng)建一個service
cat deploy-service.yaml
apiVersion: v1
kind: Service
metadata:
name: my-nginx
labels:
run: my-nginx
spec:
type: ClusterIP
ports:
- port: 80 #service的端口,暴露給k8s集群內(nèi)部服務(wù)訪問
protocol: TCP
targetPort: 80 #pod容器中定義的端口
selector:
run: my-nginx #選擇擁有run=my-nginx標(biāo)簽的pod
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
selector:
matchLabels:
run: my-nginx
replicas: 2
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- name: my-nginx
image: busybox
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
command:
- sleep
- "3600"
kubectl apply -f deploy-service.yaml
kubectl get svc -l run=my-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
my-nginx ClusterIP 10.100.89.90 <none> 80/TCP
kubectl get pods -l run=my-nginx
NAME READY STATUS RESTARTS AGE
my-nginx-58f74fc5b6-jzbvk 1/1 Running 0 70s
my-nginx-58f74fc5b6-n9lqv 1/1 Running 0 53s
#通過上面可以看到deployment創(chuàng)建的pod是隨機(jī)生成的
#進(jìn)入到web-1的pod
kubectl exec -it web-1 -- /bin/bash
root@web-1:/# nslookup my-nginx.default.svc.cluster.local
Server: 10.96.0.10
Address: 10.96.0.10#53
Name: my-nginx.default.svc.cluster.local
Address: 10.100.89.90 #解析的是service的ip地址
Statefulset管理pod:擴(kuò)容、縮容、更新
Statefulset實(shí)現(xiàn)pod的動態(tài)擴(kuò)容
如果我們覺得兩個副本太少了,想要增加,只需要修改配置文件statefulset.yaml里的replicas的值即可,原來replicas: 2,現(xiàn)在變成replicaset: 3,修改之后,執(zhí)行如下命令更新:
vim statefulset.yaml
kubectl apply -f statefulset.yaml
kubectl get sts
NAME READY AGE
web 3/3 60m
kubectl get pods -l app=nginx
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 61m
web-1 1/1 Running 0 60m
web-2 1/1 Running 0 79s
也可以直接編輯控制器實(shí)現(xiàn)擴(kuò)容
kubectl edit sts web
#這個是我們把請求提交給了apiserver,實(shí)時修改
把上面的spec下的replicas 后面的值改成4,保存退出
kubectl get pods -l app=nginx
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 62m
web-1 1/1 Running 0 62m
web-2 1/1 Running 0 3m13s
web-3 1/1 Running 0 26s
Statefulset實(shí)現(xiàn)pod的動態(tài)縮容
如果我們覺得4個Pod副本太多了,想要減少,只需要修改配置文件statefulset.yaml里的replicas的值即可,把replicaset:4變成replicas: 2,修改之后,執(zhí)行如下命令更新:
vim statefulset.yaml
kubectl apply -f statefulset.yaml
kubectl get pods -l app=nginx
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 64m
web-1 1/1 Running 0 64m
Statefulset實(shí)現(xiàn)pod的更新
kubectl explain sts.spec.updateStrategy
vim statefulset.yaml
在一個終端動態(tài)查看pod
kubectl get pods -l app=nginx -w
另一個終端執(zhí)行如下命令:文章來源:http://www.zghlxwxcb.cn/news/detail-742483.html
kubectl apply -f statefulset.yaml
kubectl get pods -l app=nginx -w
出現(xiàn)的結(jié)果如下:
web-0 1/1 Running 0 10m
web-1 1/1 Running 0 10m
web-1 1/1 Terminating 0 10m
web-1 1/1 Terminating 0 10m
web-1 0/1 Terminating 0 10m
web-1 0/1 Terminating 0 10m
web-1 0/1 Terminating 0 10m
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 1s
web-1 1/1 Running 0 2s
web-1 1/1 Running 0 11s
從上面結(jié)果可以看出來,pod在更新的時候,只是更新了web-1這個pod, partition: 1表示更新的時候會把pod序號大于等于1的進(jìn)行更新
如果更新策略是OnDelete,那不會自動更新pod,需要手動刪除,重新常見的pod才會實(shí)現(xiàn)更新文章來源地址http://www.zghlxwxcb.cn/news/detail-742483.html
到了這里,關(guān)于學(xué)習(xí)筆記二十七:K8S控制器Statefulset入門到企業(yè)實(shí)戰(zhàn)應(yīng)用的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!