和Deployment
一样StatefulSet也是中一种可以帮助我们部署和扩展Pod
的控制器,使用Deployment
时多数时候不需要在意Pod的调度方式。如果需要关心Pod
的部署顺序、对应持久化存储或者要求Pod
拥有固定的网络标识时,就需要StatefulSet
控制器来完成调度工作
每个由StatefulSet
创建出来的Pod
都拥有一个序号(从0开始,启动完成才会进行下一个)和固定的网络标识。并且可以在yaml中定义添加**VolumeClaimTemplate
**来声明Pod存储的PVC
。
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 # 使用标签选择器,筛选标签里有app等于nginx的pods
template:
metadata:
labels:
app: nginx # 创建一个带有标签app=nginx的pods
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
name: web
这里创建了一个StatefulSet对象,关联了带有app=nginx的pods,并且还指定了名为nginx
的service
为什么StatefulSet还需要指定service呢? service已经使用标签选择器选中了pods,StatefulSet通过关联 Service,可以为 StatefulSet 中的每个 Pod 分配一个稳定的网络标识(如 DNS 域名),使其可以从集群内和集群外进行访问。这种关联有助于实现有状态应用程序的可靠通信和外部访问。
比如想访问上面的pod可以使用, 格式为:pod名称.service名称.命名空间.svc.集群后缀
,但后面的可以简写,比如:
ping web-0.nginx
kubectl scale sts web --replicas=5
kubectl scale sts web --replicas=3
缩容完后再看日志
kubectl describe sts web
---------------------------------------------
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulCreate 29m statefulset-controller create Pod web-0 in StatefulSet web successful
Normal SuccessfulCreate 29m statefulset-controller create Pod web-1 in StatefulSet web successful
Normal SuccessfulCreate 4m28s statefulset-controller create Pod web-2 in StatefulSet web successful
Normal SuccessfulCreate 4m26s statefulset-controller create Pod web-3 in StatefulSet web successful
Normal SuccessfulCreate 4m24s statefulset-controller create Pod web-4 in StatefulSet web successful
Normal SuccessfulDelete 10s statefulset-controller delete Pod web-4 in StatefulSet web successful
Normal SuccessfulDelete 3s statefulset-controller delete Pod web-3 in StatefulSet web successful
从日志里可以看出,StatefulSet的pods管理是有顺序
先使用命令进行修改内容后保存
kubectl edit sts web
statefulSet与depolyment的更新区别在于,statefulSet是有序的,按照倒叙进行一个一个的更新,看如下日志
kubectl describe sts web
------------------------------------------
Type Reason Age Message
Normal SuccessfulDelete 19s delete Pod web-2 in StatefulSet web successful
Normal SuccessfulCreate 18s (x2 over 10m) create Pod web-2 in StatefulSet web successful
Normal SuccessfulDelete 16s delete Pod web-1 in StatefulSet web successful
Normal SuccessfulCreate 14s (x2 over 35m) create Pod web-1 in StatefulSet web successful
Normal SuccessfulDelete 12s delete Pod web-0 in StatefulSet web successful
Normal SuccessfulCreate 11s (x2 over 35m) create Pod web-0 in StatefulSet web successful
这是一种逐步升级 StatefulSet 的策略,它可以在不影响整个应用程序的情况下测试新版本的 Pod,并逐步将新版本的 Pod 逐步引入到应用程序中。
下面我们将操作一个场景,目前有三个nginx版本为1.9.1的pod,我们需要将这些pod切换成1.7.1的版本,但是不知道1.7.1版本是否有问题的情况下,我们需要先多扩展一个1.7.1的pod,如果这个1.7.1的没有问题了,我们就把另外所有的pod都换成这个版本
修改内容
kubectl edit sts web
修改部分
# 将镜像换成1.7.1
- image: nginx:1.7.1
# 把partition 设置为 3,那么此时滚动更新时,只会更新那些 序号 >= 3 的 pod
updateStrategy:
rollingUpdate:
partition: 3
在这里,我们将partition设置为 3,而我们现在最大的pod序号是2(从0开始),所以这次修改内容并不会影响到原来的pod版本
把更新模式设置为删除策略时,在更新 StatefulSet
配置文件时,不会触发pods的更新。相反,需要手动删除旧的pod,k8s才会创建一个新版本的Pod
spec:
updateStrategy:
type: OnDelete # 或 RollingUpdate
当我们使用普通删除sts的命令时,会把下面的pods也删除了,如果我们只是想删除sts,不删下面的pods可以使用非级联删除命令
kubectl delete sts web --cascade=false