0%

StatefulSet

StatefulSet是用于来管理有状态应用的对象。StatefulSet管理了一组Pod的部署和伸缩,并保证了这些Pod的顺序和唯一性。

像Deployment一样,StatefulSet管理基于相同容器规范的Pod。与Deployment不同,StatefulSet为其每个Pod维护一个粘性身份。这些Pod是根据相同的spec创建的,但不能互换,因为每个Pod都有一个永久性标识符,该标识符在任何重新计划中都会维护。

简单的示例

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
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 80
name: web-stateful-set
clusterIP: None
selector:
app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web-stateful-set
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: nginx:1.15
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 1Gi

上面的Service是一个Headless Service,用来控制网络域。

spec.serviceName: 必须字段。serviceName是管理此StatefulSet的服务名称。并且负责该集合的网络标识。Pod会遵循以下格式获取DNS/主机名:pod-specific-string.serviceName.default.svc.cluster.local,其中pod-specific-string由StatefulSet控制器管理。

该manifest已保存到Github:https://raw.githubusercontent.com/chengqing-su/kubernetes-learning/master/stateful-set%20/nginx-stateful-set.yaml

如何创建/更新/删除一个StatefulSet

创建

执行命令:

1
kubectl apply -f https://raw.githubusercontent.com/chengqing-su/kubernetes-learning/master/stateful-set%20/nginx-stateful-set.yaml

结果:
create

如何管理Pod

与 Deployment 不同的是, StatefulSet 是直接管理Pod的。下面展示的是web-stateful-set-0metadata

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
metadata:
creationTimestamp: "2020-02-20T12:52:31Z"
generateName: web-stateful-set-
labels:
app: nginx
controller-revision-hash: web-stateful-set-7579f5f4d9
statefulset.kubernetes.io/pod-name: web-stateful-set-0
name: web-stateful-set-0
namespace: default
ownerReferences:
- apiVersion: apps/v1
blockOwnerDeletion: true
controller: true
kind: StatefulSet
name: web-stateful-set
uid: c509a152-6096-44a9-aea9-b4b9f5168c86
resourceVersion: "2219083"
selfLink: /api/v1/namespaces/default/pods/web-stateful-set-0
uid: 5da1a0a6-a952-40c5-96d5-f32048f4e5a6

粘性身份

ReplicaSet 创建的Pod的名称是由ReplicaSet的名称和一个随机字符串组成,比如web-server-jqxfq。 Deployment 是通过ReplicaSet管理Pod,因此名称规则和 ReplicaSet 一致。

StatefulSet 有一个唯一的身份,它由一个序数、一个稳定的网络身份和稳定的存储组成。无论它(重新)调度在哪个节点上,标识都与Pod保持一致。

  • 其序数是从0到N-1(其中N为Pod的数量)。
  • 稳定的网络身份。StatefulSet中的每个Pod都从StatefulSet的名称和Pod的序数派生其主机名。 构造的主机名的模式为$(StatefulSet name)-$(序数)。 上面的示例了创建三个名为web-stateful-set-0web-stateful-set-1web-stateful-set-2的Pod。
  • 稳定的存储。Kubernetes为每个VolumeClaimTemplate创建一个PersistentVolume。将Pod调度(重新)到节点上时,其volumeMounts会安装与其PersistentVolume Claims关联的PersistentVolumes删除Pod或StatefulSet时,不会删除与Pods的PersistentVolume声明关联的PersistentVolumes,必须手动完成。

更新

将上述manifest中的nginx的版本升级到1.17,新的一份manifest:https://raw.githubusercontent.com/chengqing-su/kubernetes-learning/master/stateful-set%20/nginx-stateful-set-update.yaml

执行命令:

1
kubectl apply -f https://raw.githubusercontent.com/chengqing-su/kubernetes-learning/master/stateful-set%20/nginx-stateful-set-update.yaml

结果:

update

删除

执行命令:

1
kubectl delete -f https://raw.githubusercontent.com/chengqing-su/kubernetes-learning/master/stateful-set%20/nginx-stateful-set-update.yaml

或者

1
kubectl delete sts web-stateful-set

结果:

delete

部署和伸缩的保证

在上面的创建/更新/删除的操作中,能够更好的验证下述规则。

  • 对于具有N个副本的StatefulSet,在部署Pod时,将按{0..N-1}的顺序顺序创建它们。

  • 删除Pod时,它们以相反的顺序从{N-1..0}终止。

  • 在对Pod进行缩放操作之前,其所有前面的Pod必须处于“运行且就绪”状态。

  • 在终止Pod之前,必须完全关闭其所有后面所有的。

什么时候使用

StatefulSet对于需要以下一项或多项的应用程序非常有用。

  • 稳定的唯一网络标识符。

  • 稳定(跨Pod调度/重新计划的持久性),持久的存储。

  • 有序,顺畅的部署和扩展。

  • 有序的自动滚动更新。

有哪些局限

  • 给定Pod的存储必须由PersistentVolume提供者根据请求的存储类进行设置,或者由管理员预先设置。

  • 删除或缩小StatefulSet不会删除与StatefulSet关联的卷。这样做是为了确保数据安全,这通常比自动清除所有相关的StatefulSet资源有价值。

  • StatefulSet当前需要Headless Service来负责Pod的网络身份。

  • 删除StatefulSet时,StatefulSet不提供有关Pod终止的任何保证。为了实现StatefulSet中Pod的有序且正常的终止,可以在删除之前将StatefulSet缩小为0。

  • 如果将滚动更新与默认的Pod管理策略(OrderedReady)结合使用,则可能会陷入损坏状态,需要人工干预才能进行修复。