StatefulSet
概念
- StatefulSet 是用来管理
有状态应用的工作负载 API 对象。管理某些 Pod 集合的部署和扩缩,并为这些 Pod 提供持久存储和持久标识符 - 每个 Pod 维护了一个有粘性的 ID。这些 Pod 是基于相同的规约来创建的,但是不能相互替换:
无论怎么调度,每个 Pod 都有一个永久不变的 ID - 修改 StatefulSet 的配置后并不会重新启动 Pod(删除 Pod 可以触发)
基于 PV 创建 StatefulSet
yaml
# 需要创建持久卷,statefulSet 里面几个副本就创建几个持久卷
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv
spec:
capacity:
storage: 200Mi
volumeMode: Filesystem # 默认值,或设置 Block(块设备)
accessModes:
- ReadWriteOnce # 被单个客户端挂载为读写模式
- ReadOnlyMany # 被多个客户端挂载为读模式
- ReadWriteMany # 被多个客户端挂载为读写模式
persistentVolumeReclaimPolicy: Recycle # 当 pvc 被释放后的操作,pv 被回收
local:
path: /opt # 本地磁盘的路径
nodeAffinity: # 设置 Node 的亲和性
required: # 使用此块 pv 的 node 必须在 k8s-node1 上
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- k8s-node1
---
# 需要先创建用于有状态 Pod 之间提供网络标识的 headless service
apiVersion: v1
kind: Service
metadata:
name: kubia-stateful
spec:
clusterIP: None # headless 核心
selector:
app: kubia
ports:
- name: http
port: 80
---
# StatefulSet
apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
name: kubia-stateful
spec:
serviceName: kubia
replicas: 2
selector:
matchLabels:
app: kubia
template:
metadata:
labels:
app: kubia
spec:
containers:
- name: kubia
image: luksa/kubia-pet
ports:
- name: http
containerPort: 8080
volumeMounts:
- name: data
mountPath: /var/data
volumeClaimTemplates:
- metadata:
name: data
spec:
resources:
requests:
storage: 1Mi
accessModes:
- ReadWriteOnce
StatefulSet会等到第一个 Pod 启动完毕后才会启动第二个 Pod。如果某个 Pod 被删除,那么 StatefulSet 会创建一个新的 Pod(标识符、存储相同的新 Pod,新旧 Pod 不一定会在一个 node 上)
我们可以通过
curl -X POST -d "Hey there! This greeting was submitted to kubia-0." localhost:8001/api/v1/namespaces/default/pods/kubia-stateful-0/proxy/前后访问两次来判断新旧 Pod 是否使用相同的存储空间和标识符如果我们需要对 StatefulSet 进行缩容,那么会
优先删除索引值高的 Pod
基于 SC 创建 StatefulSet
yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: mini-storage-class
namespace: helloworld
parameters:
server: 10.50.8.38
share: /opt/share
provisioner: nfs.csi.k8s.io
reclaimPolicy: Retain
volumeBindingMode: Immediate
---
apiVersion: v1
kind: Service
metadata:
name: nginx
namespace: helloworld
labels:
app: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None # 设置无头模式,不需要负载均衡
selector:
app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
namespace: helloworld
spec:
selector:
matchLabels:
app: nginx # 必须匹配 .spec.template.metadata.labels
serviceName: "nginx"
replicas: 1
podManagementPolicy: OrderReady # 默认
updateStrategy:
type: RollingUpdate # 滚动更新,遵循销毁和创建顺序,若值为 OnDelete 将不再自动更新 pod,需要手动删除和创建
rollingUpdate:
partition: 1 # 序号为>=1 的 pod 在 .spec.template 改动时滚动更新 pod
template:
metadata:
labels:
app: nginx # 必须匹配 .spec.selector.matchLabels
spec:
terminationGracePeriodSeconds: 10
containers:
- name: nginx
image: lowyard/nginx-slim
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: "mini-storage-class"
resources:
requests:
storage: 1GiStatefulSet 创建与销毁顺序
- N 个副本的 StatefulSet,创建顺序是
0, 1, 2...N-1 - N 个副本的 StatefulSet,销毁的顺序是
N-1...2, 1, 0 - 当第 a 个 Pod 部署前,第 a 个 Pod 前的所有 Pod 必须处于 Running 和 Ready 状态
- 当第 a-1 个 Pod 销毁前,第 a 个 Pod 必须已经被终止和删除
StatefulSet 参数
updateStrategy
podManagementPolicy
默认是 OrderReady,即上文默认的创建、销毁和扩缩顺序。如果设置为 Parallel,会导致 Pod 的 扩缩 过程中无需等待对应的 Pod 进入准备或销毁状态。
🎈🎈
