在 Kubernetes 的世界中,ReplicaSet 和 Deployment 主要用于处理无状态的服务,无状态服务的需求往往非常简单并且轻量,每一个无状态节点存储的数据在重启之后就会被删除,虽然这种服务虽然常见,但是我们仍然需要有状态的服务来实现一些特殊的需求,StatefulSet 就是 Kubernetes 为了运行有状态服务引入的资源,例如 Zookeeper、Kafka 等。
这篇文章会介绍 Kubernetes 如何在集群中运行有状态服务,同时会分析这些有状态服务 StatefulSet 的同步过程以及实现原理。
概述
StatefulSet 是用于管理有状态应用的工作负载对象,与 ReplicaSet 和 Deployment 这两个对象不同,StatefulSet 不仅能管理 Pod 的对象,还它能够保证这些 Pod 的顺序性和唯一性。
与 Deployment 一样,StatefulSet 也使用规格中声明的 template 模板来创建 Pod 资源,但是这些 Pod 相互之间是不能替换的;除此之外 StatefulSet 会为每个 Pod 设置一个单独的持久标识符,这些用于标识序列的标识符在发生调度时也不会丢失。
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
serviceName: "nginx"
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: k8s.gcr.io/nginx-slim:0.8
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 1Gi
如果我们在 Kubernetes 集群中创建如上所示的 StatefulSet 对象,会得到以下结果,Kubernetes 不仅会创建 StatefulSet 对象,还会自动创建两个 Pod 副本:
$ kubectl get statefulsets.apps
kNAME READY AGE
web 2/2 2m27s
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 2m31s
web-1 1/1 Running 0 105s
$ kubectl get persistentvolumes
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-19ef374f-39d1-11e9-b870-9efb418608da 1Gi RWO Delete Bound default/www-web-1 do-block-storage 21m
pvc-fe53d5f7-39d0-11e9-b870-9efb418608da 1Gi RWO Delete Bound default/www-web-0 do-block-storage 21m
$ kubectl get persistentvolumeclaims
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
www-web-0 Bound pvc-fe53d5f7-39d0-11e9-b870-9efb418608da 1Gi RWO do-block-storage 21m
www-web-1 Bound pvc-19ef374f-39d1-11e9-b870-9efb418608da 1Gi RWO do-block-storage 21m
除此之外,上述 YAML 文件中的 volumeClaimTemplates 配置还会创建持久卷PersistentVolume 和用于绑定持久卷和 Pod 的 PersistentVolumeClaim 资源;
两个 Pod 对象名中包含了它们的序列号,该序列号会在 StatefulSet 存在的时间内保持不变,哪怕 Pod 被重启或者重新调度,也不会出现任何的改变。
StatefulSet 的拓扑结构和其他用于部署的资源其实比较类似,比较大的区别在于 StatefulSet 引入了 PV 和 PVC 对象来持久存储服务产生的状态,这样所有的服务虽然可以被杀掉或者重启,但是其中的数据由于 PV 的原因不会丢失。
实现原理
与 ReplicaSet 和 Deployment 资源一样,StatefulSet 也使用控制器的方式实现,它主要由 StatefulSetController
、StatefulSetControl
和 StatefulPodControl
三个组件协作来完成 StatefulSet 的管理,StatefulSetController
会同时从 PodInformer
和 ReplicaSetInformer
中接受增删改事件并将事件推送到队列中:
控制器 StatefulSetController 会在 Run 方法中启动多个 Goroutine 协程,这些协程会从队列中获取待处理的 StatefulSet 资源进行同步,接下来我们会先介绍 Kubernetes 同步 StatefulSet 的过程。
原文
https://draveness.me/kubernetes-statefulset