众所周知,在运维工作中想要管理有状态的应用是非常困难的一件事,StatefulSet就是一种用来管理有状态应用的工作负载,他和其他几种控制器不同的是,他为每个Pod都提供了一个固定的ID,这些Pod都是基于相同的声明创建而来的,但是无论将他调度到哪个节点,Pod ID是永久不变的。
特点:
- 能为Pod提供稳定的唯一标识
顺序标识、稳定的网络标识,这个标识是和Pod绑定的 - 能提供持久化的存储
删除或者收缩StatefulSet的时候,为了保证数据的安全,不会删除他关联的存储卷。要删除必须由手动删除。当删除StatefulSet的时候并不能保证删除其Pod,为了能将Pod有序终止,通常将StatefulSet缩放为0后再删除。 - 有序的部署和缩放
默认的Pod管理策略是OrderedReady
例如通过yaml文件创建3个pod,分别命名为web-0、web-1、web-2,那么在web-0没有进入Running和Ready状态的时候是不会部署web-1的,同理在web-1没有部署完成的时候是不会部署web-2的。收缩的时候也是同理,如果要收缩到replicas=1的话,首先先关闭web-2,但是当web-1还没有被终止的时候web-0发生了故障,这时候web-1不会被终止,必须等web-0就绪后web-1再终止。
如果将.spec.podManagementPolicy
设置为Parallel
,这种管理模式是允许并行的终止所有Pod,无需等待Running完全停止。 - 有序的滚动更新
默认的.spec.updateStrategy.type
是RollingUpdate
他将按照序号从大到小的顺序进行更新,每次更新一个pod,被更新的Pod进入Running状态后才会更新下一个Pod。
另外还有一种叫分区更新,.spec.updateStrategy.rollingUpdate.partition
他可以实现分区更新,即指定一个序号,大于该序号的都会被更新,小于该序号的则不会被更新,这种在金丝雀部署的时候可能会使用,但一般情境下不会使用。
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 # 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: k8s.gcr.io/nginx-slim:0.8
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "my-storage-class"
resources:
requests:
storage: 1Gi