1、简介
StatefulSet是Kubernetes的一个资源类型,用于管理有状态应用,例如数据库或消息队列。它为每个Pod分配一个唯一的标识符,通常是数字索引,以确保每个Pod具有稳定的网络标识和存储卷。StatefulSet 是为了管理有状态服务的问题而设计的,给定 Pod 的存储必须由 PersistentVolume 驱动基于所请求的 storage class
来提供,或者由管理员预先提供。删除或者收缩 StatefulSet 并不会删除它关联的存储卷。这样做是为了保证数据安全。
2、两种服务状态
有状态服务?
StatefulSet 是有状态的集合,管理有状态的服务,它所管理的 Pod 的名称不能随意变化。数据 持久化的目录也是不一样,每一个 Pod 都有自己独有的数据持久化存储目录。比如 MySQL 主 从、redis 集群等。
无状态服务?
RC、Deployment、DaemonSet 都是管理无状态的服务,它们所管理的 Pod 的 IP、名字,启 停顺序等都是随机的。个体对整体无影响,所有 pod 都是共用一个数据卷的,部署的 tomcat 就 是无状态的服务,tomcat 被删除,在启动一个新的 tomcat,加入到集群即可,跟 tomcat 的名 字无关。
3、为什么需要 StatefulSet滚动更新
维持稳定的标识符:有状态应用程序通常有稳定的网络标识符和存储标识符。StatefulSet 可以确保这些标识符在 Pod 更新过程中保持不变,以维护应用程序的稳定性。
有序部署和缩放:StatefulSet 可以按照有序的方式部署和扩展应用程序,确保每个 Pod 都有唯一的标识符,并按照顺序进行扩展或缩小,有助于应用程序的可用性和可维护性。
持久存储:有状态应用程序通常需要持久存储来保存数据。StatefulSet 可以管理 Pod 的 PVC(PersistentVolumeClaim),确保每个 Pod 有自己的持久存储。
有序滚动更新:滚动更新是一种控制 Pod 更新的方式,以确保应用程序的平稳过渡。StatefulSet 允许您控制 Pod 的滚动更新,确保旧 Pod 在新 Pod 启动之前正确终止。
数据迁移:StatefulSet 可以处理数据的迁移,例如在 Pod 更新期间将数据从旧 Pod 迁移到新 Pod。这对于有状态应用程序的数据迁移非常重要。
自动 Pod 缩减:StatefulSet 可以在不需要的情况下自动删除多余的 Pod,从而节省资源。这对于动态扩展和缩减有状态应用程序非常有用。
4、StatefulSet的特点
Statefulset 管理的 pod,pod 名字是有序的,由 statefulset 的名字-0、1、2 这种格式组成。
创建 statefulset 资源的时候,必须事先创建好一个 service,如果创建的 service 没有 ip,那 对这个 service 做 dns 解析,会找到它所关联的 pod ip,如果创建的 service 有 ip,那对这个 service 做 dns 解析,会解析到 service 本身 ip。版权声明,本文档全部内容及版权归韩先超所有,只可用于自己学习使用,禁止私自传阅,违者依法 追责。
statefulset 管理的 pod,删除 pod,新创建的 pod 名字跟删除的 pod 名字是一样的 。
statefulset 具有 volumeclaimtemplate 这个字段,这个是卷申请模板,会自动创建 pv, pvc 也会自动生成,跟 pv 进行绑定,那如果创建的 statefulset 使用了 volumeclaimtemplate 这个字段,那创建 pod,数据目录是独享的 。
ststefulset 创建的 pod,是域名的(域名组成:pod-name.svc-name.svcnamespace.svc.cluster.local),pod可以通过域名访问到。
[root@i-cd6217fb 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: webs
spec:
selector:
matchLabels:
app: nginx # has to match .spec.template.metadata.labels
serviceName: "nginx"
replicas: 3 # by default is 1
template:
metadata:
labels:
app: nginx # has to match .spec.selector.matchLabels
spec:
terminationGracePeriodSeconds: 10
containers:
- name: nginx
image: docker.io/library/nginx:latest
ports:
- containerPort: 80
name: web
[root@i-cd6217fb Statefulset]# kubectl get pod
NAME READY STATUS RESTARTS AGE
webs-0 1/1 Running 0 7m35s
webs-1 1/1 Running 0 7m32s
webs-2 1/1 Running 0 7m29s
[root@i-cd6217fb Statefulset]# kubectl get sts
NAME READY AGE
webs 3/3 9m27s
[root@i-cd6217fb Statefulset]# kubectl edit sts webs
statefulset.apps/webs edited
#修改副本数为4个
[root@i-cd6217fb Statefulset]# kubectl get pod
NAME READY STATUS RESTARTS AGE
webs-0 1/1 Running 0 10m
webs-1 1/1 Running 0 10m
webs-2 1/1 Running 0 10m
webs-3 1/1 Running 0 7s
5、StatefulSet的两种更新策略
RollingUpdate(滚动更新)
使用
RollingUpdate
更新策略时,StatefulSet 会自动按顺序一个一个地创建新的 Pod 副本,并等待它们处于就绪状态。一旦新的 Pod 就绪,StatefulSet 会逐个删除旧的 Pod 副本,确保更新过程平滑。
这意味着在更新期间,总是至少有一个旧 Pod 和一个新 Pod 同时存在,从而保持了应用程序的高可用性。
使用
RollingUpdate
策略时,您可以在spec.updateStrategy.type
中明确指定。这是推荐的更新策略,特别适用于大多数有状态应用程序,因为它保证了高可用性和平滑的过渡。
OnDelete(手动删除更新)
使用
OnDelete
更新策略时,StatefulSet 不会自动滚动更新 Pod。相反,它等待您手动删除旧的 Pod 副本,并创建新的 Pod 副本。这意味着您需要明确地删除每个 Pod 副本,以完成更新。您可以通过运行
kubectl delete pod <pod-name>
来手动删除 Pod。OnDelete
策略通常用于特定需求,例如当应用程序需要特殊的维护过程或数据迁移时,可以在更新期间手动介入。使用
OnDelete
策略时,您不需要在spec.updateStrategy.type
中指定任何内容,因为这是默认策略。
6、RollingUpdate更新
RollingUpdate更新策略对 StatefulSet 中的 Pod 执行自动的滚动更新。在没有声明.spec.updateStrategy时,RollingUpdate是默认配置。当 StatefulSet 的.spec.updateStrategy.type被设置为RollingUpdate时,StatefulSet 控制器会删除和重建 StatefulSet 中的每个 Pod。它将按照与 Pod 终止相同的顺序(从最大序号到最小序号)进行,每次更新一个 Pod。它会等到被更新的 Pod 进入 Running 和 Ready 状态,然后再更新其前身。
[root@i-cd6217fb 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: webs
spec:
#滚动更新策略---起始
updateStrategy:
rollingUpdate:
partition: 2
maxUnavailable: 0
#滚动更新策略---结束
selector:
matchLabels:
app: nginx # has to match .spec.template.metadata.labels
serviceName: "nginx"
replicas: 3 # by default is 1
template:
metadata:
labels:
app: nginx # has to match .spec.selector.matchLabels
spec:
terminationGracePeriodSeconds: 10
containers:
- name: nginx
image: docker.io/library/nginx:latest
ports:
- containerPort: 80
name: web
#我这里有3个pod,上面配置的为2,如果更新镜像,只会更新大于等于2的pod, webs-1、webs-2、webs-3三个pod。
[root@i-cd6217fb Statefulset]# kubectl get pod
NAME READY STATUS RESTARTS AGE
webs-0 1/1 Running 0 32m
webs-1 1/1 Running 0 32m
webs-2 1/1 Running 0 31m
7、OnDelete 更新
OnDelete 更新策略实现了 1.6 及以前版本的历史遗留行为。当 StatefulSet 的 .spec.updateStrategy.type 设置为 OnDelete 时,它的控制器将不会自动更新 StatefulSet 中的 Pod。用户必须手动删除 Pod 以便让控制器创建新的 Pod,以此来对 StatefulSet 的 .spec.template 的变动作出反应。
[root@i-cd6217fb 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: webs
spec:
#滚动更新策略---起始
updateStrategy:
type: OnDelete
#滚动更新策略---结束
selector:
matchLabels:
app: nginx # has to match .spec.template.metadata.labels
serviceName: "nginx"
replicas: 3 # by default is 1
template:
metadata:
labels:
app: nginx # has to match .spec.selector.matchLabels
spec:
terminationGracePeriodSeconds: 10
containers:
- name: nginx
image: docker.io/library/nginx:latest
ports:
- containerPort: 80
name: web
#我这里有3个pod,如果更新镜像,只能手动删除镜像才能更新,默认是这种策略。
[root@i-cd6217fb Statefulset]# kubectl get pod
NAME READY STATUS RESTARTS AGE
webs-0 1/1 Running 0 32m
webs-1 1/1 Running 0 32m
webs-2 1/1 Running 0 31m
欢迎大家扫码关注:

本公众号只写原创,不接广告、不接广告、不接广告。下期小伙伴想学习什么技术,可以私信发我吆。





