概述
概念
StatefulSet 是为了解决有状态服务的问题(对应 Deployments 和 ReplicaSets 是为无状态服务而设计),其应用场景包括
- 稳定的持久化存储,即 Pod 重新调度后还是能访问到相同的持久化数据,基于 PVC 来实现
- 稳定的网络标志,即 Pod 重新调度后其 PodName 和 HostName 不变,基于 Headless Service(即没有 Cluster IP 的 Service)来实现
- 有序部署,有序扩展,即 Pod 是有顺序的,在部署或者扩展的时候要依据定义的顺序依次依序进行(即从 0 到 N-1,在下一个 Pod 运行之前所有之前的 Pod 必须都是 Running 和 Ready 状态),基于 init containers 来实现
- 有序收缩,有序删除(即从 N-1 到 0)
从上面的应用场景可以发现,StatefulSet 由以下几个部分组成:
- 用于定义网络标志(DNS domain)的 Headless Service
- 用于创建 PersistentVolumes 的 volumeClaimTemplates
- 定义具体应用的 StatefulSet
StatefulSet 中每个 Pod 的 DNS 格式为 statefulSetName-{0..N-1}.serviceName.namespace.svc.cluster.local,其中
- serviceName 为 Headless Service 的名字
- 0..N-1 为 Pod 所在的序号,从 0 开始到 N-1
- statefulSetName 为 StatefulSet 的名字
- namespace 为服务所在的 namespace,Headless Service 和 StatefulSet 必须在相同的 namespace
- .cluster.local 为 Cluster Domain
限制
- 给定 Pod 的存储必须由 PersistentVolume Provisioner 根据请求的 storage class 进行配置,或由管理员预先配置。
- 删除或 scale StatefulSet 将不会删除与 StatefulSet 相关联的 volume。 这样做是为了确保数据安全性,这通常比自动清除所有相关 StatefulSet 资源更有价值。
- StatefulSets 目前要求 Headless Service 负责 Pod 的网络身份。 您有责任创建此服务。
部署Statefulset服务
首先我们下面使用的是用前面博文中使用到的NFS做动态供给PVC作为持久化存储。那么他的创建步骤这里不在赘述,我们在编排yaml文件中申请即可。
获取动态卷信息
1 | $ kubectl describe storageclass managed-nfs-storage |
编写service
一个名为 nginx 的 headless service,用于控制网络域。
1 | $ cat >> statefulset_service.yaml << EOF |
编写statefulset yaml
- 一个名为 web 的 StatefulSet,它的 Spec 中指定在有 2 个运行 nginx 容器的 Pod。
volumeClaimTemplates
使用 PersistentVolume Provisioner 提供的PersistentVolumes
作为稳定存储。
volumeClaimTemplates: 表示一类PVC的模板,系统会根据Statefulset配置的replicas数量,创建相应数量的PVC。这些PVC除了名字不一样之外其他配置都是一样的。
下面storageClassName配置为我之前通过NFS创建的。
1 | $ cat >> statefulset.yaml << EOF |
验证服务伸缩性
创建Statefulset服务:
1 | # 执行创建 |
扩容服务到3个Pod,显示会创建新的云盘卷:
1 | $ kubectl scale sts web --replicas=3 |
缩容服务到1个Pod,显示pvc/pv并不会一同删除:
1 | $ kubectl scale sts web --replicas=1 |
再次扩容到3个Pod,新的pod会复用原来的PVC/PV:
1 | $ kubectl scale sts web --replicas=3 |
删除一个pod/web0前,Pod引用PVC:www-disk-web-0
1 | kubectl describe pod/web-0 | grep ClaimName |
删除Pod后,重新创建的Pod名字与删除的一致,且使用同一个PVC:
1 | $ kubectl delete pod/web-0 |
验证服务高可用性
共享持久卷中新建文件
1 | $ kubectl exec web-1 ls /usr/share/nginx/html |
删除Pod,验证数据持久性:
1 | $ kubectl delete pod web-1 |
数据保存:
上面也说啦, 删除或 scale StatefulSet 将不会删除与 StatefulSet 相关联的 volume。 这样做是为了确保数据安全性,这通常比自动清除所有相关 StatefulSet 资源更有价值。
所以我到NFS Server上面check一下:
可见 我们在pod/web-1上创建的文件还是保存着的。
附:
该yaml为华为云那边的PV申请,以及StatefulSet应用的创建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
# PVC存储申请
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-evs-auto-example
namespace: default
annotations:
volume.beta.kubernetes.io/storage-class: sata
volume.beta.kubernetes.io/storage-provisioner: flexvolume-huawei.com/fuxivol
labels:
failure-domain.beta.kubernetes.io/region: cn-north-1
failure-domain.beta.kubernetes.io/zone: cn-north-1a
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 10Gi
# StatefulSet应用创建
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: cce21days-app11-guomaoqiu
namespace: default
spec:
podManagementPolicy: OrderedReady
serviceName: cce21days-app11-guomaoqiu
replicas: 3
revisionHistoryLimit: 10
selector:
matchLabels:
app: cce21days-app11-guomaoqiu
failure-domain.beta.kubernetes.io/region: cn-north-1
failure-domain.beta.kubernetes.io/zone: cn-north-1a
template:
metadata:
labels:
app: cce21days-app11-guomaoqiu
failure-domain.beta.kubernetes.io/region: cn-north-1
failure-domain.beta.kubernetes.io/zone: cn-north-1a
spec:
affinity: {}
containers:
- image: 100.125.0.198:20202/guomaoqiu/tank:1.0.1
imagePullPolicy: IfNotPresent
name: container-0
resources: {}
volumeMounts:
- mountPath: /tmp
name: pvc-evs-example
dnsPolicy: ClusterFirst
imagePullSecrets:
- name: default-secret
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
volumes:
- name: pvc-evs-example
persistentVolumeClaim:
claimName: pvc-evs-auto-example
updateStrategy:
type: RollingUpdate