一、Statefulset控制器
StatefulSet是为了管理有状态服务的问题而设计的
pod名称是唯一不能更改的,或者pod中运行的服务需要做数据持久化,比如MySQL主从、redis集群等都可称为有状态的服务,而这种有状态服务的pod就需要使用
StatefulSet控制器进行管理。
Statefulset 字段详情可通过如下命令进行查看
kubectl explain sts (Statefulset 可简写为sts)
1.1 Statefulset编写yaml创建pod
使用Statefulset控制器进行yaml文件的编写,创建两个pod,并挂载存储pvc,使两个pod独享存储。
ps:下方yaml文件中使用的volumeClaimTemplates(存储卷申请模板)定义的nfs存储类,可根据如下链接中“4.2 ~ 4.2.6”标题中的步骤进行部署,然后引用即可(存储类的名称切记不要写错,要与下方yaml文件中storageClassName字段定义的要保持一致)
[root@k8s-master ~]# vim sts.yaml
apiVersion: v1 ###创建service
kind: Service
metadata:
name: svc-01 #定义servic的名称
labels: #定义service的标签
sevice: svc-02
spec:
ports:
- port: 80 #这里定义端口,要与关联的pod中容器运行的服务端口一致
name: nginx-web-01
clusterIP: None #表示创建的service没有IP(不定义该行,创建时会自动生成一个service的IP)
selector: #定义关联pod的标签
svc: nginx
--- ###分割:创建statefulset控制器管理pod服务
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: sts
spec:
replicas: 2 #定义管理的pod副本数
selector: #定义标签选择器
matchLabels:
svc: nginx #匹配模板的标签,与下方模板中定义的标签要匹配
serviceName: svc-01 #使用StatefulSet控制器时,必须要定义一个service,写上方需要关联的service的名称
template: #定义模板
metadata:
labels: #定义模板的标签
svc: nginx
spec:
containers: #定义运行容器的信息
- name: mynginx
image: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80 #声明容器的端口
name: nginx-web #定义端口的别名
volumeMounts: #定义存储卷挂载的路径(写挂载到容器内的路径)
- mountPath: /usr/share/nginx/html
name: volume #定义卷申请模板的名称(要匹配到它才能使用并挂载到容器内)
volumeClaimTemplates: #定义存储卷申请模板(在StatefulSet下创建可不用写apiversion及kind)
- metadata:
name: volume #定义卷申请模板名称
spec:
accessModes: #定义访问模式
- ReadWriteOnce #单路读写模式
storageClassName: nfs #定义存储类,这里写创建的存储类storageclass的名称(kubectl get storageclass 查看)
resources: #定义存储大小
requests:
storage: 1G
#创建
[root@k8s-master ~]# kubectl apply -f sts.yaml
service/svc-01 created
statefulset.apps/sts created
#查看创建pod信息,pod名称是以yaml文件中定义的statefulset控制器指定的名称命名,并有序命名(sts-0\sts-1)
[root@k8s-master ~]# kubectl get pods -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
mynfs-provisioner-7bbf59f87d-m2vtz 1/1 Running 1 (20h ago) 21h 10.244.126.1 k8s-worker2 <none> <none>
sts-0 1/1 Running 0 15s 10.244.194.66 k8s-worker1 <none> <none>
sts-1 1/1 Running 0 4s 10.244.126.4 k8s-worker2 <none> <none>
#查看pvc 创建了两个,以yaml文件中的指定的存储卷名称+pod名称命名
[root@k8s-master ~]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
test-pvc Bound pvc-e6f251e2-c8d5-4f7e-ba20-951ba0eaa1ff 1G RWX nfs 21h
volume-sts-0 Bound pvc-0a03784a-a584-40f8-b345-3390f52d9c09 1G RWO nfs 116s
volume-sts-1 Bound pvc-31da41f7-5601-4d22-89e5-e79de4b6e04a 1G RWO nfs 105s
#pv是自动生成的
[root@k8s-master ~]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-0a03784a-a584-40f8-b345-3390f52d9c09 1G RWO Delete Bound default/volume-sts-0 nfs 112s
pvc-31da41f7-5601-4d22-89e5-e79de4b6e04a 1G RWO Delete Bound default/volume-sts-1 nfs 107s
pvc-e6f251e2-c8d5-4f7e-ba20-951ba0eaa1ff 1G RWX Delete Bound default/test-pvc nfs 21h
#查看nfs共享目录(pv)是否生成(已生成)
[root@k8s-master ~]# ls /nfs/test001/
default-volume-sts-1-pvc-31da41f7-5601-4d22-89e5-e79de4b6e04a
default-volume-sts-0-pvc-0a03784a-a584-40f8-b345-3390f52d9c09
#查看servic信息,yaml文件中指定servic的IP为none,所以IP为空
[root@k8s-master ~]# kubectl get svc | grep svc
svc-01 ClusterIP None <none> 80/TCP 5m35s
#查看service的Endpoints,它所关联的两个ip就是sts-0 sts-1pod所在node节点的IP
[root@k8s-master ~]# kubectl describe svc svc-01
Name: svc-01
Namespace: default
Labels: sevice=svc-02
Annotations: <none>
Selector: svc=nginx
Type: ClusterIP
IP Family Policy: SingleStack
IP Families: IPv4
IP: None
IPs: None
Port: nginx-web-01 80/TCP
TargetPort: 80/TCP
Endpoints: 10.244.126.4:80,10.244.194.66:80
Session Affinity: None
Events: <none>
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72.
- 73.
- 74.
- 75.
- 76.
- 77.
- 78.
- 79.
- 80.
- 81.
- 82.
- 83.
- 84.
- 85.
- 86.
- 87.
- 88.
- 89.
- 90.
- 91.
- 92.
- 93.
- 94.
- 95.
- 96.
- 97.
- 98.
- 99.
- 100.
- 101.
- 102.
- 103.
- 104.
- 105.
1.2 测试pod独享数据目录
测试俩个pod独享的数据目录是否成功
#在sts-0的pv中创建一个文件并写入数据
[root@k8s-master ~]# echo test000 >> /nfs/test001/default-volume-sts-0-pvc-0a03784a-a584-40f8-b345-3390f52d9c09/test.txt
#进入sts-0 pod中查看
[root@k8s-master ~]# kubectl exec -it sts-0 -- /bin/bash
root@sts-0:/# cat /usr/share/nginx/html/test.txt //宿主机上绑定的pv已共享进pod容器中
test000
root@sts-0:/# exit
exit
#退出sts-0 进入sts-1 查看验证数据是否共享,无则创建一个并验证
[root@k8s-master ~]# kubectl exec -it sts-1 -- /bin/bash
root@sts-1:/# ls /usr/share/nginx/html/ //该路径下为空(sts-0的pv未共享到sts-1)
root@sts-1:/#
root@sts-1:/# touch /usr/share/nginx/html/test-01.txt //创建测试文件
root@sts-1:/# exit
exit
#退出sts-1 pod后查看宿主机上sts-1的pv路径下进行验证,(该pv与sts-1 pod中容器已完成共享)
[root@k8s-master ~]# ls /nfs/test001/default-volume-sts-1-pvc-31da41f7-5601-4d22-89e5-e79de4b6e04a/
test-01.txt
PS:与deploymen控制不同的是,使用Statefulset控制器进行管理创建的pod,
可以使用volumeClaimTemplates字段做到每个pod中的容器(服务)拥有独立存储,且pod名称是有序且唯一的,
也就是说sts-0 pod删除在由statefulset控制器重新自动创建后,pod名称还是sts-0
另外就是创建statefulset资源的时候,必须要先创建一个service
由statefulset控制器创建的pod是含有域名的(域名命名格式为:pod名称.servic名称.所在命名空间名称.svc.cluster.local)
如:sts-0.svc-01.default.svc.cluster.local
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
关于deployment控制器的使用可以参考如下链接:
1.3 Statefulset 扩容、缩容、更新
使用Statefulset控制器管理pod进行pod的扩容、缩容及更新
1.3.1 扩容
修改sts.yaml文件,将replicas字段指定的副本数修改为要扩容的目标数
#修改为3sts.yaml文件,将replicas字段指定的副本数修改为要扩容的目标数(我这里修改为3)
[root@k8s-master ~]# cat sts.yaml | grep replicas
replicas: 3 #定义管理的pod副本数
#创建(已成功创建一个pod,按照序号从小到大进行扩容创建)
[root@k8s-master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
mynfs-provisioner-7bbf59f87d-m2vtz 1/1 Running 3 (3m6s ago) 2d18h
sts-0 1/1 Running 0 7m
sts-1 1/1 Running 0 6m51s
sts-2 1/1 Running 0 106s
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
1.3.2 缩容
同理 修改replicas字段指定的副本数即可
#修改为2
[root@k8s-master ~]# cat sts.yaml | grep replicas
replicas: 2 #定义管理的pod副本数
#创建(已成功删除一个pod,按照序号从大到小进行缩容删除)
[root@k8s-master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
mynfs-provisioner-7bbf59f87d-m2vtz 1/1 Running 3 (7m18s ago) 2d18h
sts-0 1/1 Running 0 11m
sts-1 1/1 Running 0 11m
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
1.3.3 滚动更新
实现Statefulset的滚动更新需要使用到updateStrategy字段,该字段在sts.spec下,可以通过如下命令进行查看
该字段下有两种更新类型如:rollingUpdate及type类型的Ondelete
kubectl explain sts.spec.updateStrategy.rollingUpdate
kubectl explain sts.spec.updateStrategy.type
1.3.3.1 rollingUpdate 字段更新
#修改sts.yaml文件 在spec下方增加更新字段如下,更新pod还需要更新镜像(我这里将nginx镜像更新成为了httpd)
[root@k8s-master ~]# cat sts.yaml | grep -C 6 updateStrategy
--- ###分割:创建statefulset控制器管理pod服务
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: sts
spec:
updateStrategy: #定义pod更新策略
rollingUpdate: #定义更新字段
partition: 1 #这里定义的数字表示更新的pod根据序号选择大于的,如sts-1、sts-2 就是更新大于等于带1数字的pod
maxUnavailable: 0 #这里写0表示更新的时候最少要有1个pod
replicas: 2 #定义管理的pod副本数
selector: #定义标签选择器
matchLabels:
#更新镜像字段
[root@k8s-master ~]# cat sts.yaml | grep image:
image: httpd
#更新
[root@k8s-master ~]# kubectl get pods -w
NAME READY STATUS RESTARTS AGE
mynfs-provisioner-7bbf59f87d-m2vtz 1/1 Running 3 (20m ago) 2d18h
sts-0 1/1 Running 0 24m
sts-1 1/1 Running 0 24m
sts-1 1/1 Terminating 0 30m //更新时,这里删除了sts-1 pod
sts-1 1/1 Terminating 0 30m
sts-1 0/1 Terminating 0 30m
sts-1 0/1 Terminating 0 30m
sts-1 0/1 Terminating 0 30m
sts-1 0/1 Pending 0 0s
sts-1 0/1 Pending 0 0s
sts-1 0/1 ContainerCreating 0 0s //然后重新创建sts-1 pod
sts-1 0/1 ContainerCreating 0 1s
sts-1 1/1 Running 0 2s
sts-1 1/1 Running 0 49s
#查看所更新pod信息
[root@k8s-master ~]# kubectl get pods -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
mynfs-provisioner-7bbf59f87d-m2vtz 1/1 Running 3 (27m ago) 2d18h 10.244.126.1 k8s-worker2 <none> <none>
sts-0 1/1 Running 0 31m 10.244.194.66 k8s-worker1 <none> <none>
sts-1 1/1 Running 0 38s 10.244.126.4 k8s-worker2 <none> <none>
#创建完成之后 验证更新的pod中容器服务已变成了httpd的主页面
[root@k8s-master ~]# curl 10.244.126.4:80
<html><body><h1>It works!</h1></body></html>
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
1.3.3.2 Ondelete 字段更新
使用 该字段进行更新pod,需要删除原有的pod才会自动更新创建新的pod
#修改sts.yaml文件添加type更新字段并删除rollingUpdate的更新字段,且修改镜像httpd为nginx 如下:
[root@k8s-master ~]# cat sts.yaml | grep -B 7 type
--- ###分割:创建statefulset控制器管理pod服务
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: sts
spec:
updateStrategy: #定义pod更新策略
type: OnDelete
#修改镜像为nginx
[root@k8s-master ~]# cat sts.yaml | grep image:
image: nginx
#创建更新
[root@k8s-master ~]# kubectl apply -f sts.yaml
service/svc-01 unchanged
statefulset.apps/sts configured
#创建时动态查看pod更新信息
#使用ondelete字段进行更新时,不会直接进行更新 需要删除pod重新创建,如下:
[root@k8s-master ~]# kubectl get pods -w
NAME READY STATUS RESTARTS AGE
mynfs-provisioner-7bbf59f87d-m2vtz 1/1 Running 3 (48m ago) 2d19h
sts-0 1/1 Running 0 52m
sts-1 1/1 Running 0 21m
#删除pod 重新创建
[root@k8s-master ~]# kubectl delete pod sts-0
pod "sts-0" deleted
[root@k8s-master ~]# kubectl delete pod sts-1
pod "sts-1" deleted
#删除pod时同台查看pod状态信息
[root@k8s-master ~]# kubectl get pods -w
NAME READY STATUS RESTARTS AGE
mynfs-provisioner-7bbf59f87d-m2vtz 1/1 Running 3 (48m ago) 2d19h
sts-0 1/1 Running 0 52m
sts-1 1/1 Running 0 21m
sts-0 1/1 Terminating 0 59m //sts-0 删除
sts-0 1/1 Terminating 0 59m
sts-0 0/1 Terminating 0 59m
sts-0 0/1 Terminating 0 59m
sts-0 0/1 Terminating 0 59m
sts-0 0/1 Pending 0 0s
sts-0 0/1 Pending 0 0s
sts-0 0/1 ContainerCreating 0 0s //sts-0 创建
sts-0 0/1 ContainerCreating 0 1s
sts-0 1/1 Running 0 2s
sts-1 1/1 Terminating 0 28m //sts-1 删除
sts-1 0/1 Terminating 0 28m
sts-1 0/1 Terminating 0 28m
sts-1 0/1 Terminating 0 28m
sts-1 0/1 Pending 0 0s
sts-1 0/1 Pending 0 0s
sts-1 0/1 ContainerCreating 0 0s //sts-1 创建
sts-1 0/1 ContainerCreating 0 0s
sts-1 0/1 ContainerCreating 0 1s
sts-1 1/1 Running 0 2s
sts-0 1/1 Running 0 27s
#查看pod所在节点IP并验证
[root@k8s-master ~]# kubectl get pods -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
mynfs-provisioner-7bbf59f87d-m2vtz 1/1 Running 3 (57m ago) 2d19h 10.244.126.1 k8s-worker2 <none> <none>
sts-0 1/1 Running 0 2m3s 10.244.194.67 k8s-worker1 <none> <none>
sts-1 1/1 Running 0 117s 10.244.126.5 k8s-worker2 <none> <none>
#验证(宿主机共享了nfs的路径给到pod中nginx容器的首页路径下,写入内容访问测试)
[root@k8s-master ~]# echo How are you >> /nfs/test001/default-volume-sts-1-pvc-8f712ce4-712c-4a4e-8689-1af681269294/index.html
[root@k8s-master ~]# curl 10.244.126.5:80
How are you
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72.
- 73.
- 74.