前言
默认读者有kubernetes基础概念的背景知识,因此基础概念例如有状态、pod、Replica Sets、Deployments等不在此文详细阐述。
可以看我之前的一些关于kubernetes的文章:
kubernetes pod&container生命周期浅析
本文主要介绍1.5版本以后新出现的概念StatefulSets的定义以及应用。
StatefulSets的概念
StatefulSets在kubernetes 1.5中作为beta特性出现,这个特性是用来取代1.4之前的PetSets的概念。
StatefulSets简而言之是一个用来给自己的pods提供特定唯一标识的控制器。它提供了有状态容器的顺序扩容以及部署的能力。
下面这张表给出一个直观的对1.3之前网易云基础服务中有状态容器与社区1.6有状态容器的对比。
1.3 有状态(网易云基础服务适配) | 1.6 有状态(社区) | |
---|---|---|
实现方式 | pod | StatefulSet |
副本数 | 1 | n(n为大于等于1的整数) |
是否可迁移 | 是(经适配产品后,系统盘保留数据) | 是,系统盘默认不保留数据 |
是否支持扩缩容 | 否 | 是 |
是否支持顺序部署 | 否(本身就1个pod,没有顺序的概念) | 是(自动顺序启动和销毁StatefuleSet中的pod) |
是否支持回收资源 | 否(需要适配产品做额外的回收逻辑) | 是(将副本数设成0,就自动回收pod资源) |
在1.3以前的版本中有状态的容器是不支持扩容以及动态部署的。有状态容器跟无状态最大的区别就是有状态可以持久化数据,无状态容器经过重新部署、扩缩容等操作,数据是不会保留持久化的。但是有状态容器通过挂载数据盘的方式可以做到持久化。需要注意的一点是StatefulSets的扩容以及动态部署不支持系统盘的数据保留。因此应用StatefulSets部署的程序需要确保尽量使用数据盘做数据的持久化。
如何做到数据盘的数据持久化呢?如果应用StatefulSets的话,当应用所在的node节点挂掉或者断链以后,node上面所在的pod可以被自动调度到其他node上,并且使用网络访问数据盘,以确保重新调度以后应用还是可以访问到它原有数据盘上的数据。
在1.3之前如果直接应用pod的话,需要自定义实现pod迁移以后,将原始的数据盘从老node上卸载后再挂载到新调度的node上的步骤。而使用StatefulSets后可以自动完成,因为不是以卸载挂载的方式来实现,而是直接走网络远程访问数据盘。
StatefulSets的约束
说了那么多StatefulSets的概念以及1.3跟现在社区1.6的实现对比以后,来看下StatefulSets本身的一些约束限制。
1.在社区1.5之前无法应用StatefulSets。
2.可以通过apiserver的启动参数--runtime-config来禁用StatefulSets特性。
3.pod上的存储需要以PersistentVolume的方式提供(基于Kubernetes StorageClass文档实现)。
4.对StatefulSets进行删除以及扩缩容操作不会删除StatefulSets上关联的卷。这样会确保数据持久化。
5.StatefulSets需要Headless Service来为Pods分配一个可靠的网络唯一标识符。
6.升级已有的StatefulSets需要手工运维。
约束里提到的两个概念:
1.PersistentVolume:简称PV,是一种可以由管理员分配提供的网络存储资源,跟Volumes类似,但是它的生命周期独立的所使用PV的Pod。kubenetes目前支持多种PV插件,例如AWSElasticBlockStore、NFS、iScsi、Ceph等。详情可以看github链接
2.Headless Service:是service的一种,用于不需要负载均衡以及单个serviceIP等场景。这时创建Headless Service时将spec.clusterIP标记为None即可。这样的service,由于clusterIP没有被分配,因此kube-proxy无法管理这些service。DNS如何自动分配依赖于service是否定义了selectors。
定义了selector的service:endpoints控制器可以创建endpoints记录,修改DNS配置返回一个指向service内pod的地址信息。 没有定义selector的service:endpoints不能被创建,然而可以通过ExternalName方式记录CNAME(ExternalName类型的service),例如foo.bar.example.com,用来作为服务发现的途径。
以下例子给出了StatefulSets的一些组成部分
1.一个headless service,命名为nginx,用来控制网络域。
2.一个StatefulSet,命名为web,描述了nginx容器的3个副本,会分配到特定的pod上。
3.volumeClainTemplates使用PV提供了稳定的存储资源。
service 的json描述如下,需要关注的是clusterIP是置为null的,是headless service的最重要的标志:
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: nginx
StatefuleSet 的json描述如下,关注副本数以及volumeClaimTemplates的配置。
apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
name: web
spec:
serviceName: "nginx"
replicas: 3
template:
metadata:
labels:
app: nginx
spec:
terminationGracePeriodSeconds: 10
containers:
- name: nginx
image: gcr.io/google_containers/nginx-slim:0.8
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
annotations:
volume.beta.kubernetes.io/storage-class: nfs
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 1Gi
Pod的唯一标识
上面的例子中名为web的StatefulSet定义为三副本以后,kubenetes就会自动创建3个pod,用来调度及启动容器。StatefulSet pods有一个包含序号、稳定网络标识、稳定存储的唯一标识。不管pod调度到哪个node,这个唯一标识是不变的。
web包含的三副本pod命名规则为:(statefulsetname)−(ordinal),即顺序命名为web-0,web-1,web-2,headless service管理pod的所在域,service域格式为:(servicename).(namespace).svc.cluster.local。pod生成后会得到一个DNS的子域,格式为:(podname).(governing service domain)。下面的图展示了pod的域跟cluster域、service命名之间的关系。
部署以及扩缩容保障
StatefulSet最大的特色就是提供了有状态容器的顺序扩容以及部署的能力,下面来看下机制上如何确保部署和扩缩容成功执行。
1.N个副本的StatefulSet,包含的Pods会从0~N-1顺序创建并部署。
2.Pods被删除回收时,终止的时候反序终止,从N-1~0。
3.在扩容操作执行之前,所有的Pod必须处于Running和Ready态。
4.在一个Pod终止之前,它的继承者们需要完全关闭。
不推荐将StatefulSet的参数pod.Spec.TerminationGracePeriodSeconds配置为0,这样代表强制删除里面的pod,不安全也不建议这样做。
当上面的例子中nginx service被创建以后,web StatefuleSet创建成功,三个Pods依次顺序部署(web-0,web-1,web-2)。web-1只有当web-0处于Running和Ready态以后才会进行部署。当web-0在web-1部署成功后再变成fail的话,除非web-0自己恢复重新拉起,否则web-2不会进行部署动作。
假如想把web这个StatefuleSet缩容成1副本,则将replicas=1。这样的话,web-2则首先会被终止,然后web-1再会终止。如果web-0在web-2终止以后先fail了,则web-1不会终止,直到web-0恢复成Running和Ready。
总结
StatefulSet使得有状态的应用扩缩容以及部署更加轻量级,更加便利,当然也会有它的一些限制,例如使用远端网络存储盘作为数据保持。总的来说社区建议使用这种资源去进行有状态的应用的部署和管理。在网易云基础服务中也会尝试使用1.6版本中的StatefulSets来进行有状态容器的管理。
网易云容器服务为用户提供了无服务器容器,让企业能够快速部署业务,轻松运维服务。容器服务支持弹性伸缩、垂直扩容、灰度升级、服务发现、服务编排、错误恢复及性能监测等功能。
本文来自网易实践者社区,经作者崔晓晴授权发布。