注明:当前文档内容来源于51cto课堂‘宽哥’杜宽学习课程。
一、什么是StatefulSet
Statefulset(有状态集,缩写为sts)常用于部署有状态的且需要有序启动的应用程序,比如在进行SpringCloud 项目容器化时,Eureka的部署是比较适合用StatefulSet部署方式的,可以给每个Eureka实例创建一个唯一且固定的标识符,并且每个Eureka实例无需配置多余的Service,其余Spring Boot应用可以直接通过Eureka的Headless Service即可进行注册。
需要使用有状态的服务:
1.需要稳定的独一无二的网络标识符
2.MongoDB 、Redis、kafka、Eureka 集群
3.需要持久化数据
4.需要有序的、优雅的部署和扩展
5.需要有序的自动滚动更新
二、Headless Service
和Deployment类似,一个StatefulSet也同样管理着基于相同容器规范的pod。不同的是StatefulSet为每个pod维护了一个粘性标识。
而StatefulSet创建的Pod一般使用Headless Service(无头服务)进行Pod之前的通信,和普通的Service的区别在于Headless Service没有ClusterIP,它使用的是Endpoint进行互相通信。
Headless一般格式为:
statefulSetName-{0..N-1}.serviceName.namespace.svc.cluster.local
serviceName为Headless Service的名字,创建StatefulSet时,必须指定Headless Service名称。
0...N-1为pod所在的序号,从0开始到N-1
statefulSetName为StatefulSet的名字
namespace为服务所在的命名空间
.cluster.local 为cluster Domain(集群域)
三、定义一个简单的StatefulSet
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: nginx
---
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: nginx
ports:
- containerPort: 80
name: web
StatefulSet解释:
kind: Service 定义了一个名字为Nginx的Headless Service, 创建的Service格式为nginx-0.nginx.default.svc.cluster.local,其他的类似,因为没有指定Namespace(命名空间),所以默认部署在default;
kind:StatefulSet定义了一个名字web的StatefulSet, replicas表示部署Pod的副本数,本实例为2 副本。
在StatefulSet 中必须设置Pod选择器(.spec.selector) 用来匹配其他标签(.spec.template.metadata.labels) 在1.8 版本之前,如果未配置该字段(.spec.selector),将被设置为默认值,在1.8版本之后,如果未指定匹配Pod Selector,则会导致StatefulSet创建错误。
当StatefulSet控制器创建Pod 时,它会添加一个标签statefulset.kubernetes.io/pod-name, 该标签的值为Pod的名称,用于匹配Service。
四、StatefulSet创建pod流程
StatefulSet 管理的pod部署和扩展规则如下:
1.对于具有N个副本的StatefulSet,将按顺序从0到N-1开始创建pod
2.当删除pod时,将按照N-1到0的反顺序终止。
3.在缩放pod之前,必须保证当前的Pod是Running(运行中)或者Ready(就绪)
4.在终止pod之前,它所有的继任者必须是完全关闭的状态
5.StatefulSet的pod.Spec.TerminationGracePeriodSeconds(终止pod的等待时间) 不应该指定为0,设置为0对StatefulSet的pod是极其不安全的做法,优雅地删除StatefulSet的pod是非常有必要的,而且是安全的,因为它可以确保在kubectl 从APIserver 删除之前,让pod正常关闭。
6.当创建上面的nginx实例时,pod将按web-0、web-1、web-2的顺序部署的3个pod。在web-0 处于Running或者Ready之前,web-1 不会被部署,相同的 web-2在web-1未处于Running和Ready之前也不会被部署。如果在web-1处于Running和Ready状态时,web-0 变成Failed(失败)状态,那么web-2 将不会被启动,直到web-0恢复为Running和Ready状态
7.如果用户将StatefulSet的replicas设置为1, 那么web-2将首先被终止,在完全关闭删除web-2 之前,不会删除web-1。如果web-2 终止并且完全关闭后,web-0突然失败,那么在web-0 未恢复成Running或者Ready时,web-1不会被删除。