一、Statefulset控制器
1.概念
StatefulSet 是用来管理有状态应用的工作负载 API 对象。
StatefulSet 用来管理某 Pod 集合的部署和扩缩, 并为这些 Pod 提供持久存储和持久标识符。
和 Deployment 类似, StatefulSet 管理基于相同容器规约的一组 Pod。但和 Deployment 不同的是, StatefulSet 为它们的每个 Pod 维护了一个有粘性的 ID。这些 Pod 是基于相同的规约来创建的, 但是不能相互替换:无论怎么调度,每个 Pod 都有一个永久不变的 ID。
如果希望使用存储卷为工作负载提供持久存储,可以使用 StatefulSet 作为解决方案的一部分。 尽管 StatefulSet 中的单个 Pod 仍可能出现故障, 但持久的 Pod 标识符使得将现有卷与替换已失败 Pod 的新 Pod 相匹配变得更加容易。
2.为什么使用 StatefulSet
在Kubernetes系统中,Pod的管理对象RC、Deployment、DaemonSet和Job都是面向无状态的服务。但现实中有很多服务是有状态的,特别是一些复杂的中间件集群,例如MySQL集群、MongoDB集群、Kafka集群、Zookeeper集群等。
这些应用集群有以下一些共同点:
- 每个节点都有固定的身份ID,通过这个ID,集群中的成员可以相互发现并且通信。
- 集群的规模是比较固定的,集群规模不能随意变动。
- 集群里的每个节点都是有状态的,通常会持久化数据到永久存储中。
- 如果磁盘损坏,则集群里的某个节点无法正常运行,集群功能受损。
如果用 RC/Deployment 控制 Pod 副本数的方式来实现上述有状态的集群,则我们会发现第一点是无法满足的,因为Pod的名字是随机产生的,Pod的IP地址也是在运行期才确定且可能有变动的,我们事先无法为每个Pod确定唯一不变的ID,为了能够在其他节点上恢复某个失败的节点,这种集群中的Pod需要挂接某种共享存储,为了解决这个问题,Kubernetes从v1.4版本开始引入了PetSet这个新的资源对象,并且在v1.5版本时更名为StatefulSet。
3.特性
StatefulSet从本质上来说,可以看作 Deployment/RC 的一个特殊变种,它有如下一些特性:
- StatefulSet里的每个Pod都有稳定、唯一的网络标识,可以用来发现集群内的其他成员。假设StatefulSet的名字叫kafka,那么第一个Pod叫kafak-0,第二个Pod叫kafak-1,第三个叫kafka-2,以此类推。
- StatefulSet控制的Pod副本的启停顺序是受控的,操作第n个Pod时,前n-1个Pod已经时运行且准备好的状态。
- StatefulSet里的Pod采用稳定的持久化存储卷,通过 PV/PVC来实现,删除Pod时默认不会删除与StatefulSet相关的存储卷(为了保证数据的安全)。
StatefulSet除了要与PV卷捆绑使用以存储Pod的状态数据,还要与Headless Service(无头服务)配合使用,即在每个StatefulSet的定义中要声明它属于哪个Headless Service。Headless Service与普通Service的关键区别在于,它没有Cluster IP,如果解析Headless Service的DNS域名,则返回的是该Service对应的全部Pod的Endpoint列表。StatefulSet在Headless Service的基础上又为StatefulSet控制的每个Pod实例创建了一个DNS域名,这个域名的格式为:
$(podname).$(headless service name)
比如一个3节点的 StatefulSet 集群,对应的 Headless Service 的名字为nginx,StatefulSet的名字为web,则 StatefulSet 里面的 3 个 Pod 的 DNS 名称分别为web-0.nginx、web-1.nginx、web-2.nginx,这些DNS名称可以直接在集群的配置文件中固定下来。
二、配置解读
1.yaml文件解读
apiVersion: v1 ## Service apiversion 版本
kind: Service ## Service资源类型
metadata: ## 元数据
name: nginx ## Service name
namespace: test ## 命名空间
labels: ## 标签
app: nginx
spec: ## 详情
ports: ## service要暴露的端口
- port: 80 ## 源端口
name: web ## 目标端口
clusterIP: None ## clusterIP为空,表示headless service
selector: ## 标签选择器
app: nginx
--- ## 多种资源类型配置写入同一文件时,需要用---来分割
apiVersion: apps/v1 ## StatefulSet apiVersion
kind: StatefulSet ## StatefulSet资源类型,简称sts
metadata: ## 元数据
name: web ## sts的名称
namespace: test ## 命名空间
spec: ## 详情
podManagementPolicy: OrderedReady ## pod管理策略
serviceName: "nginx" ## 绑定那个service
replicas: 3 ## 副本数
selector: ## 标签选择器
matchLabels:
app: nginx
template: ## Pod模板
metadata: ## pod元数据
labels:
app: nginx
spec: ## 详情
imagePullSecrets: ## 镜像拉取秘钥
- name: harbor-secret ## 秘钥名称
containers: ## 容器信息
- name: nginx ## 容器名称
image: core.harbor.domain/test/nginx-1.16.1:v1 #镜像名
ports: ## 容器端口
- containerPort: 80
name: web ## 端口名称
volumeMounts: ## 卷挂载信息
- name: www ## pvc名称
mountPath: /opt/web_app/nginx-1.16.1/html ##挂载位置
volumeClaimTemplates: ## 卷声明模板,只有sts有
- metadata:
name: www ## pvc名称
spec:
accessModes: [ "ReadWriteOnce" ] ## 读写模式
storageClassName: "nfs" ## storageclass
resources: ## 资源申请信息
requests: ## 请求资源
storage: 1Gi ## 1G存储
访问模式accessModes
1.ReadWriteOnce(RWO):卷可以被一个节点以读写方式挂载。 ReadWriteOnce 访问模式也允许运行在同一节点上的多个 Pod 访问卷。
2.ReadOnlyMany(ROX):卷可以被多个节点以只读方式挂载。
3.ReadWriteMany(RWX):卷可以被多个节点以读写方式挂载。
4.ReadWriteOncePod(RWOP):卷可以被单个 Pod 以读写方式挂载。 如果你想确保整个集群中只有一个 Pod 可以读取或写入该 PVC, 请使用 ReadWriteOncePod 访问模式。这只支持 CSI 卷以及需要 Kubernetes 1.22 以上版本。
2.卷声明模板
volumeClaimTemplates :从名字就可以看出来,它跟 Deployment 里 Pod 模板(PodTemplate)的作用类似。也就是说,凡是被这个 StatefulSet 管理的 Pod,都会声明一个对应的 PVC;而这个 PVC 的定义,就来自于 volumeClaimTemplates 这个模板字段。更重要的是,这个 PVC 的名字,会被分配一个与这个 Pod 完全一致的编号。PVC 其实就是一种特殊的 Volume。只不过一个 PVC 具体是什么类型的 Volume,要在跟某个 PV 绑定之后才知道。
- 当把一个 Pod,比如 web-0,删除之后,这个 Pod 对应的 PVC 和 PV,并不会被删除,而这个 Volume
里已经写入的数据,也依然会保存在远程存储服务里(比如,我们在这个例子里用到的 NFS 服务器)。 - 此时,StatefulSet 控制器发现,一个名叫 web-0 的 Pod 消失了。所以,控制器就会重新创建一个新的、名字还是叫作
web-0 的 Pod 来,“纠正”这个不一致的情况。 - 需要注意的是,在这个新的 Pod 对象的定义里,它声明使用的 PVC 的名字,还是叫作:www-web-0。这个 PVC
的定义,还是来自于 PVC 模板(volumeClaimTemplates),这是 StatefulSet 创建 Pod 的标准流程。 - 所以,在这个新的 web-0 Pod 被创建出来之后,Kubernetes 为它查找名叫 www-web-0 的 PVC
时,就会直接找到旧 Pod 遗留下来的同名的 PVC,进而找到跟这个 PVC 绑定在一起的 PV。 - 这样,新的 Pod 就可以挂载到旧 Pod 对应的那个 Volume,并且获取到保存在 Volume 里的数据。
三、演练
1.创建statefulset
用上面的yaml文件,顺序创建pod
[root@k8s-master sts]# kubectl apply -f web-sts.yaml && kubectl get pod -n test -w
service/nginx created
statefulset.apps/web created
NAME READY STATUS RESTARTS AGE
nginx-854d5f75db-skscn 1/1 Running 0 7d1h
web-0 0/1 ContainerCreating 0 0s
web-0 0/1 ContainerCreating 0 0s
web-0 1/1 Running 0 1s
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 1s
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 2s
如同 StatefulSet 概念中所提到的, StatefulSet 中的每个 Pod 拥有一个具有黏性的、独一无二的身份标志。 这个标志基于 StatefulSet 控制器分配给每个 Pod 的唯一顺序索引。 Pod 名称的格式为 <statefulset 名称>-<序号索引>。 web StatefulSet 拥有三个副本,所以它创建了三个 Pod:web-0 、web-1、web-2。
2.稳定的网络身份标识
每个 Pod 都拥有一个基于其顺序索引的稳定的主机名。使用 kubectl exec 在每个 Pod 中执行 hostname:
[root@k8s-master sts]# for i in 0 1 2; do kubectl exec "web-$i" -n test -- sh -c 'hostname'; done
web-0
web-1
web-2
查看pod ip
[root@k8s-master sts]# kubectl get pod -n test -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
web-0 1/1 Running 0 19m 10.244.107.216 k8s-node3 <none> <none>
web-1 1/1 Running 0 19m 10.244.107.217 k8s-node3 <none> <none>
web-2 1/1 Running 0 19m 10.244.107.218 k8s-node3 <none> <none>
重启pod
[root@k8s-master sts]# kubectl delete pod -l app=nginx -n test
pod "web-0" deleted
pod "web-1" deleted
pod "web-2" deleted
查看主机名
[root@k8s-master sts]# for i in `seq 0 2`; do kubectl exec web-$i -n test -- sh -c 'hostname'; done
web-0
web-1
web-2
查看pod ip
[root@k8s-master sts]# kubectl get pod -n test -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
web-0 1/1 Running 0 33s 10.244.107.219 k8s-node3 <none> <none>
web-1 1/1 Running 0 31s 10.244.107.220 k8s-node3 <none> <none>
web-2 1/1 Running 0 29s 10.244.107.221 k8s-node3 <none> <none>
查看servicename解析
[root@k8s-master sts]# kubectl run -i --tty --image busybox dns-test --restart=Never --rm -n test
If you don't see a command prompt, try pressing enter.
/ #
/ #
/ # nslookup nginx.test.svc.cluster.local
Server: 10.96.0.10
Address: 10.96.0.10:53
Name: nginx.test.svc.cluster.local
Address: 10.244.107.221
Name: nginx.test.svc.cluster.local
Address: 10.244.107.219
Name: nginx.test.svc.cluster.local
Address: 10.244.107.220
/ # nslookup web-0.nginx.test.svc.cluster.local
Server: 10.96.0.10
Address: 10.96.0.10:53
Name: web-0.nginx.test.svc.cluster.local
Address: 10.244.107.219
Pod 的序号、主机名、SRV 条目和记录名称没有改变,但和 Pod 相关联的 IP 地址可能发生了改变。 这就是为什么不要在其他应用中使用 StatefulSet 中 Pod 的 IP 地址进行连接,这点很重要。
3.稳定的存储
查看pvc
[root@k8s-master node-exporter]# kubectl get pvc -n test
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
www-web-0 Bound pvc-a815eb1b-8bcc-4090-8a98-399f8e112cff 1 RWX nfs 19h
www-web-1 Bound pvc-5c274327-9360-4227-8464-7866f7619079 1 RWX nfs 19h
www-web-2 Bound pvc-a9588a0d-a6c4-4af4-9369-2d7f772695f9 1 RWX nfs 19h
将 Pod 的主机名写入它们的 index.html 文件并验证 NginX Web 服务器使用该主机名提供服务:
[root@k8s-master data]# for i in `seq 0 2`; do kubectl exec "web-$i" -n test -- sh -c 'echo "$(hostname)" > /opt/web_app/nginx-1.16.1/html/index.html'; done
[root@k8s-master data]# for i in `seq 0 2`; do kubectl exec -i -t "web-$i" -n test -- curl http://localhost/; done
web-0
web-1
web-2
删除所有pod
[root@k8s-master data]# kubectl delete pod -l app=nginx -n test
pod "web-0" deleted
pod "web-1" deleted
pod "web-2" deleted
pod重新调度
[root@k8s-master data]# kubectl get pod -n test -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
web-0 1/1 Running 0 24s 10.244.36.78 k8s-node1 <none> <none>
web-1 1/1 Running 0 13s 10.244.36.79 k8s-node1 <none> <none>
web-2 1/1 Running 0 11s 10.244.169.149 k8s-node2 <none> <none>
验证卷是否被挂载,所有 Web 服务器在继续使用它们的主机名提供服务:
[root@k8s-master data]# for i in `seq 0 2`; do kubectl exec -i -t "web-$i" -n test -- curl http://localhost/; done
web-0
web-1
web-2
4.扩/缩容
4.1横向扩容
[root@k8s-master data]# kubectl scale sts/web -n test --replicas=6
statefulset.apps/web scaled
[root@k8s-master data]# kubectl get pod -n test
NAME READY STATUS RESTARTS AGE
dns-test 1/1 Running 0 16h
nginx-854d5f75db-skscn 1/1 Running 0 7d18h
web-0 1/1 Running 0 31m
web-1 1/1 Running 0 31m
web-2 1/1 Running 0 31m
web-3 1/1 Running 0 3s
web-4 0/1 Pending 0 1s
4.2缩容
[root@k8s-master data]# kubectl scale sts/web -n test --replicas=5
statefulset.apps/web scaled
[root@k8s-master data]# kubectl get pod -n test
NAME READY STATUS RESTARTS AGE
dns-test 1/1 Running 0 16h
nginx-854d5f75db-skscn 1/1 Running 0 7d18h
web-0 1/1 Running 0 32m
web-1 1/1 Running 0 32m
web-2 1/1 Running 0 32m
web-3 1/1 Running 0 80s
web-4 1/1 Running 0 78s
web-5 0/1 Terminating 0 75s
5.顺序停止
控制器会按照与 Pod 序号索引相反的顺序每次删除一个 Pod。在删除下一个 Pod 前会等待上一个被完全关闭。
[root@k8s-master ~]# kubectl scale sts/web -n test --replicas=0
statefulset.apps/web scaled
[root@k8s-master nfs]# kubectl get pod -n test -o wide -w
web-4 1/1 Terminating 0 3m47s 10.244.169.154 k8s-node2 <none> <none>
web-4 1/1 Terminating 0 3m47s 10.244.169.154 k8s-node2 <none> <none>
web-4 0/1 Terminating 0 3m48s 10.244.169.154 k8s-node2 <none> <none>
web-4 0/1 Terminating 0 4m 10.244.169.154 k8s-node2 <none> <none>
web-4 0/1 Terminating 0 4m 10.244.169.154 k8s-node2 <none> <none>
web-3 1/1 Terminating 0 4m1s 10.244.36.82 k8s-node1 <none> <none>
web-3 1/1 Terminating 0 4m1s 10.244.36.82 k8s-node1 <none> <none>
web-3 0/1 Terminating 0 4m1s 10.244.36.82 k8s-node1 <none> <none>
web-3 0/1 Terminating 0 4m5s 10.244.36.82 k8s-node1 <none> <none>
web-3 0/1 Terminating 0 4m5s 10.244.36.82 k8s-node1 <none> <none>
web-2 1/1 Terminating 0 4m6s 10.244.36.81 k8s-node1 <none> <none>
web-2 1/1 Terminating 0 4m6s 10.244.36.81 k8s-node1 <none> <none>
web-2 0/1 Terminating 0 4m7s 10.244.36.81 k8s-node1 <none> <none>
web-2 0/1 Terminating 0 4m8s 10.244.36.81 k8s-node1 <none> <none>
web-2 0/1 Terminating 0 4m8s 10.244.36.81 k8s-node1 <none> <none>
web-1 1/1 Terminating 0 4m10s 10.244.169.153 k8s-node2 <none> <none>
web-1 1/1 Terminating 0 4m10s 10.244.169.153 k8s-node2 <none> <none>
web-1 0/1 Terminating 0 4m12s 10.244.169.153 k8s-node2 <none> <none>
web-1 0/1 Terminating 0 4m24s 10.244.169.153 k8s-node2 <none> <none>
web-1 0/1 Terminating 0 4m24s 10.244.169.153 k8s-node2 <none> <none>
web-0 1/1 Terminating 0 4m26s 10.244.169.152 k8s-node2 <none> <none>
web-0 1/1 Terminating 0 4m26s 10.244.169.152 k8s-node2 <none> <none>
web-0 0/1 Terminating 0 4m27s 10.244.169.152 k8s-node2 <none> <none>
web-0 0/1 Terminating 0 4m28s 10.244.169.152 k8s-node2 <none> <none>
web-0 0/1 Terminating 0 4m28s 10.244.169.152 k8s-node2 <none> <none>
6.更新statefulset
6.1滚动更新
RollingUpdate 更新策略会更新一个 StatefulSet 中的所有 Pod,采用与序号索引相反的顺序并遵循 StatefulSet 的保证。
对 web StatefulSet 应用 Patch 操作来应用 RollingUpdate 更新策略:
[root@k8s-master sts]# kubectl patch statefulset web -p '{"spec":{"updateStrategy":{"type":"RollingUpdate"}}}'
statefulset.apps/web patched
修改镜像版本,触发更新
[root@k8s-master nfs]# kubectl set image sts/web nginx=core.harbor.domain/test/nginx-1.16.1:v2 -n test
statefulset.apps/web image updated
[root@k8s-master sts]# kubectl get pod -n test -w
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 93s
web-1 1/1 Running 0 91s
web-2 1/1 Running 0 89s
web-3 1/1 Running 0 88s
web-4 1/1 Running 0 86s
web-5 1/1 Running 0 85s
web-5 1/1 Terminating 0 110s
web-5 1/1 Terminating 0 110s
web-5 0/1 Terminating 0 110s
web-5 0/1 Terminating 0 113s
web-5 0/1 Terminating 0 113s
web-5 0/1 Pending 0 0s
web-5 0/1 Pending 0 0s
web-5 0/1 ContainerCreating 0 0s
web-5 0/1 ContainerCreating 0 1s
web-5 1/1 Running 0 2s
web-4 1/1 Terminating 0 116s
web-4 1/1 Terminating 0 116s
web-4 0/1 Terminating 0 117s
web-4 0/1 Terminating 0 118s
web-4 0/1 Terminating 0 118s
web-4 0/1 Pending 0 0s
web-4 0/1 Pending 0 0s
web-4 0/1 ContainerCreating 0 0s
web-4 0/1 ContainerCreating 0 1s
web-4 1/1 Running 0 2s
web-3 1/1 Terminating 0 2m2s
web-3 1/1 Terminating 0 2m2s
web-3 0/1 Terminating 0 2m3s
web-3 0/1 Terminating 0 2m4s
web-3 0/1 Terminating 0 2m4s
web-3 0/1 Pending 0 0s
web-3 0/1 Pending 0 0s
web-3 0/1 ContainerCreating 0 0s
web-3 0/1 ContainerCreating 0 1s
web-3 1/1 Running 0 1s
web-2 1/1 Terminating 0 2m6s
web-2 1/1 Terminating 0 2m6s
web-2 0/1 Terminating 0 2m7s
web-2 0/1 Terminating 0 2m17s
web-2 0/1 Terminating 0 2m17s
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 1s
web-1 1/1 Terminating 0 2m20s
web-1 1/1 Terminating 0 2m20s
web-1 0/1 Terminating 0 2m21s
web-1 0/1 Terminating 0 2m29s
web-1 0/1 Terminating 0 2m29s
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 1s
web-0 1/1 Terminating 0 2m32s
web-0 1/1 Terminating 0 2m32s
web-0 0/1 Terminating 0 2m33s
web-0 0/1 Terminating 0 2m37s
web-0 0/1 Terminating 0 2m37s
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 0s
web-0 1/1 Running 0 1s
StatefulSet 里的 Pod 采用和序号相反的顺序更新。在更新下一个 Pod 前,StatefulSet 控制器终止每个 Pod 并等待它们变成 Running 和 Ready。 请注意,虽然在顺序后继者变成 Running 和 Ready 之前 StatefulSet 控制器不会更新下一个 Pod,但它仍然会重建任何在更新过程中发生故障的 Pod,使用的是它们当前的版本。
已经接收到更新请求的 Pod 将会被恢复为更新的版本,没有收到请求的 Pod 则会被恢复为之前的版本。 像这样,控制器尝试继续使应用保持健康并在出现间歇性故障时保持更新的一致性。
6.2OnDelete 策略
OnDelete 更新策略实现了传统(1.7 之前)行为,它也是默认的更新策略。 当你选择这个更新策略并修改 StatefulSet 的 .spec.template 字段时,StatefulSet 控制器将不会自动更新 Pod。当删除pod后才会触发更新。
7.金丝雀发布
修改partition
[root@k8s-master nfs]# kubectl edit sts web -n test
...
updateStrategy:
rollingUpdate:
partition: 3
type: RollingUpdate
...
或者
kubectl patch statefulset web -p '{"spec":{"updateStrategy":{"type":"RollingUpdate","rollingUpdate":{"partition":3}}}}'
观察pod更新
[root@k8s-master nfs]# kubectl set image sts/web nginx=core.harbor.domain/test/nginx-1.16.1:v1 -n test
statefulset.apps/web image updated
[root@k8s-master sts]# kubectl get pod -n test -w
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 170m
web-1 1/1 Running 0 171m
web-2 1/1 Running 0 171m
web-3 1/1 Running 0 171m
web-4 1/1 Running 0 171m
web-5 1/1 Running 0 171m
web-5 1/1 Terminating 0 171m
web-5 1/1 Terminating 0 171m
web-5 0/1 Terminating 0 171m
web-5 0/1 Terminating 0 171m
web-5 0/1 Terminating 0 171m
web-5 0/1 Pending 0 0s
web-5 0/1 Pending 0 0s
web-5 0/1 ContainerCreating 0 0s
web-5 0/1 ContainerCreating 0 1s
web-5 1/1 Running 0 1s
web-4 1/1 Terminating 0 171m
web-4 1/1 Terminating 0 171m
web-4 0/1 Terminating 0 171m
web-4 0/1 Terminating 0 171m
web-4 0/1 Terminating 0 171m
web-4 0/1 Pending 0 0s
web-4 0/1 Pending 0 0s
web-4 0/1 ContainerCreating 0 0s
web-4 0/1 ContainerCreating 0 0s
web-4 1/1 Running 0 1s
web-3 1/1 Terminating 0 171m
web-3 1/1 Terminating 0 171m
web-3 0/1 Terminating 0 171m
web-3 0/1 Terminating 0 172m
web-3 0/1 Terminating 0 172m
web-3 0/1 Pending 0 0s
web-3 0/1 Pending 0 0s
web-3 0/1 ContainerCreating 0 0s
web-3 0/1 ContainerCreating 0 1s
web-3 1/1 Running 0 2s
可以看到 pod只更新到web-3,这里我们解释一下partition这个参数
statefulset资源可通过控制partition参数来分阶段发布、更新应用;statefulset的更新是倒序的,根据partition配置的值,所有序号大于或等于partition的 Pod 都将被更新; 如果一个序号小于partition的 Pod 被删除或者终止,它将被按照原来的配置恢复。
继续更新
将partition修改为0,statefulset将继续完成web-2,web-1,web-0的更新
[root@k8s-master nfs]# kubectl edit sts web -n test
...
updateStrategy:
rollingUpdate:
partition: 0
type: RollingUpdate
...
[root@k8s-master sts]# kubectl get pod -n test -w
NAME READY STATUS RESTARTS AGE
dns-test 1/1 Running 0 20h
nginx-854d5f75db-skscn 1/1 Running 0 7d22h
web-0 1/1 Running 0 170m
web-1 1/1 Running 0 171m
web-2 1/1 Running 0 171m
web-3 1/1 Running 0 171m
web-4 1/1 Running 0 171m
web-5 1/1 Running 0 171m
web-5 1/1 Terminating 0 171m
web-5 1/1 Terminating 0 171m
web-5 0/1 Terminating 0 171m
web-5 0/1 Terminating 0 171m
web-5 0/1 Terminating 0 171m
web-5 0/1 Pending 0 0s
web-5 0/1 Pending 0 0s
web-5 0/1 ContainerCreating 0 0s
web-5 0/1 ContainerCreating 0 1s
web-5 1/1 Running 0 1s
web-4 1/1 Terminating 0 171m
web-4 1/1 Terminating 0 171m
web-4 0/1 Terminating 0 171m
web-4 0/1 Terminating 0 171m
web-4 0/1 Terminating 0 171m
web-4 0/1 Pending 0 0s
web-4 0/1 Pending 0 0s
web-4 0/1 ContainerCreating 0 0s
web-4 0/1 ContainerCreating 0 0s
web-4 1/1 Running 0 1s
web-3 1/1 Terminating 0 171m
web-3 1/1 Terminating 0 171m
web-3 0/1 Terminating 0 171m
web-3 0/1 Terminating 0 172m
web-3 0/1 Terminating 0 172m
web-3 0/1 Pending 0 0s
web-3 0/1 Pending 0 0s
web-3 0/1 ContainerCreating 0 0s
web-3 0/1 ContainerCreating 0 1s
web-3 1/1 Running 0 2s
web-2 1/1 Terminating 0 3h25m
web-2 1/1 Terminating 0 3h25m
web-2 0/1 Terminating 0 3h25m
web-2 0/1 Terminating 0 3h25m
web-2 0/1 Terminating 0 3h25m
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 0s
web-2 1/1 Running 0 1s
web-1 1/1 Terminating 0 3h25m
web-1 1/1 Terminating 0 3h25m
web-1 0/1 Terminating 0 3h25m
web-1 0/1 Terminating 0 3h25m
web-1 0/1 Terminating 0 3h25m
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 1s
web-0 1/1 Terminating 0 3h25m
web-0 1/1 Terminating 0 3h25m
web-0 0/1 Terminating 0 3h25m
web-0 0/1 Terminating 0 3h25m
web-0 0/1 Terminating 0 3h25m
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 0s
web-0 1/1 Running 0 1s
8.删除 StatefulSet
8.1非级联删除
使用 kubectl delete 删除 StatefulSet。请确保提供了 --cascade=orphan 参数给命令。这个参数告诉 Kubernetes 只删除 StatefulSet 而不要删除它的任何 Pod。
[root@k8s-master nfs]# kubectl delete sts web -n test --cascade=orphan
statefulset.apps "web" deleted
[root@k8s-master nfs]# kubectl get sts -n test
No resources found in test namespace.
[root@k8s-master nfs]# kubectl get pod -n test
NAME READY STATUS RESTARTS AGE
dns-test 1/1 Running 0 21h
nginx-854d5f75db-skscn 1/1 Running 0 7d22h
web-0 1/1 Running 0 16m
web-1 1/1 Running 0 16m
web-2 1/1 Running 0 17m
web-3 1/1 Running 0 50m
web-4 1/1 Running 0 51m
web-5 1/1 Running 0 51m
这时手动删除pod,那么这个pod将被删掉,因为没有了控制器
[root@k8s-master sts]# kubectl delete pod web-0 -n test
pod "web-0" deleted
[root@k8s-master sts]# kubectl get pod -n test
NAME READY STATUS RESTARTS AGE
web-1 1/1 Running 0 20m
web-2 1/1 Running 0 20m
web-3 1/1 Running 0 54m
web-4 1/1 Running 0 54m
web-5 1/1 Running 0 54m
恢复部署,web-0又回来了,且卷挂载成功
[root@k8s-master sts]# kubectl apply -f web-sts.yaml
service/nginx unchanged
statefulset.apps/web created
[root@k8s-master sts]# kubectl get pod -n test
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 49s
web-1 1/1 Running 0 21m
web-2 1/1 Running 0 21m
web-3 1/1 Running 0 16s
web-4 1/1 Running 0 14s
web-5 1/1 Running 0 13s
[root@k8s-master sts]# for i in `seq 0 2`; do kubectl exec -i -t "web-$i" -n test -- curl http://localhost/; done
web-0
web-1
web-2
8.2级联删除
statefulset和pod一起删除
[root@k8s-master sts]# kubectl delete sts web -n test
statefulset.apps "web" deleted
[root@k8s-master sts]# kubectl get pod -l app=nginx -n test
No resources found in test namespace.
9.Pod管理策略
9.1OrderedReady Pod 管理策略
OrderedReady Pod 管理策略是 StatefulSet 的默认选项。它告诉 StatefulSet 控制器遵循上文展示的顺序性保证。StatefulSet 将按顺序逐个创建 Pod,并按逆序逐个终止 Pod。Statefulset创建之后不可修改。
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
serviceName: "nginx"
podManagementPolicy: "OrderedReady"
9.2Parallel Pod 管理策略
Parallel Pod 管理策略告诉 StatefulSet 控制器并行的终止所有 Pod, 在启动或终止另一个 Pod 前,不必等待这些 Pod 变成 Running 和 Ready 或者完全终止状态。
这通俗易懂的概念来自哪里?
点这:https://www.orchome.com/1338