kubernetes有状态集合之statefulset
生产中常用的副本控制器如Deployment、DaemonSet、RS都是适用于无状态服务,其所管理的Pod的启停顺序、IP、Podname等都是随机的,被管理的Pod被更新掉时,都会变化。
Kubernetes中StatefulSet是专为有状态服务如redis、kafka、consul等集群准备的集合,管理所有有状态服务。
**PS:什么是有状态服务?**
简单来说,有状态服务与无状态服务主要有如下区别:
1.判断服务是否有状态,是指两个来自相同发起者(客户端)的请求在服务器端是否具备上下文关系;
2.有状态服务,一般服务器端都要保存与请求的相关信息,每个请求可以默认地使用之前的请求信息;
3.相反,无状态服务一般服务器端所能够处理的过程全部来自于请求所携带的信息或者其他服务器端自身所保存的、并且可以被所有请求所使用的公共信息。
StatefulSet管理的Pod拥有固定的Pod名称(一般是pod.name-0/-1/-2顺延)、启停顺序(从-0开始依次重启);在StatefulSet中,Pod名字称为网络标识(hostname),还必须要用到共享存储。
与Deployment对应的网络映射为service,而在StatefulSet中与之对应的headless service(无头服务),相较于services,headless service没有ClusterIP,解析它的名称时将返回该Headless Service对应的全部Pod的Endpoint列表。
一个完整的StatefulSet应用由三个部分组成: headless service、StatefulSet controller、volumeClaimTemplate。
kubernetes中选择使用statefullSet的服务所具有如下特点:
1)、稳定且唯一的网络标识符(如kfaka集群zookeeper的myid);
2)、稳定且持久的存储(如redis cluster模式下每个节点的shard);
3)、有序、平滑地部署扩展、终止和删除;
5)、有序的滚动更新;
首选创建pv,如下:
```bash
[[email protected] statefulset-test]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv-01 5Gi RWO,RWX Retain Available 1h
pv-02 10Gi RWO,RWX Retain Available 1h
pv-03 15Gi RWO,RWX Retain Available 1h
然后定义statefulset 应用,如下:
```bash
[[email protected] statefulset-test]# cat statefulset.yaml
apiVersion: v1
kind: Service
metadata:
name: ngx-svc
labels:
app: ngx-svc
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: ngx-sts
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: ngx-sts
spec:
serviceName: ngx-svc #声明它属于哪个Headless Service
replicas: 2
selector:
matchLabels:
app: ngx-sts #has to match .spec.template.metadata.labels
template:
metadata:
labels:
app: ngx-sts #has to match .spec.selector.matchLabels
spec:
containers:
- name: ngx-sts
image: nginx:latest
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
name: web
volumeMounts:
- name: ngxvol
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: ngx-volumes
spec:
accessModes: ["ReadWriteMany"]
resources:
requests:
storage: 5Gi
[[email protected] statefulset-test]# kubectl apply -f statefulset.yaml
[[email protected] statefulset-test]# kubectl get service |grep nginx-svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ngx-svc ClusterIP None <none> 80/TCP 56s
[[email protected] statefulset-test]# kubectl get statefulset
NAME DESIRED CURRENT AGE
ngx-sts 2 2 5m
[[email protected] statefulset-test]# kubectl get pods
NAME READY STATUS RESTARTS AGE
ngx-sts-0 1/1 Running 0 2m
ngx-sts-1 1/1 Running 0 2m
[[email protected] statefulset-test]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
ngx-volumes-ngx-sts-0 Bound pv01 5Gi RWO,RWX 12m
ngx-volumes-ngx-sts-1 Bound pv02 10Gi RWO,RWX 12m
#每个pod的FQDN(完全现定域名)被定义为:$(pod.name).(headless server name).namespace.svc.cluster.local
#每个PVC 的名称又由两个部分组成:$(volumeClaimTemplates.name)-(pod.name) ,代表该PVC由哪个volumeClaimTemplates申请创建,且永远被挂载到$(pod.name)上。当原Pod被删除之后,PVC保持不变,数据不会丢失(手动删除pvc将自动释放pv)。当新Pod被创建之后,原podname会被继承,也会再次挂载到原Volume之上。
pod的扩展、收缩都是按照顺序执行
[[email protected] statefulset-test]# kubectl scale statefulset ngx-sts --replicas=3
statefulset.apps/ngx-sts scaled
[[email protected] statefulset-test]# kubectl get pods
NAME READY STATUS RESTARTS AGE
ngx-sts-0 1/1 Running 0 1h
ngx-sts-1 1/1 Running 0 1h
ngx-sts-2 1/1 Running 0 1m
[[email protected] statefulset-test]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
ngx-volumes-ngx-sts-0 Bound pv01 5Gi RWO,RWX 30m
ngx-volumes-ngx-sts-1 Bound pv02 10Gi RWO,RWX 30m
ngx-volumes-ngx-sts-2 Bound pv03 15Gi RWO,RWX 1ms
[[email protected] statefulset-test]# kubectl patch statefulset ngx-sts -p '{"spec":{"replicas":2}}'
statefulset.apps/ngx-sts patched
[[email protected] statefulset-test]# kubectl get pods
NAME READY STATUS RESTARTS AGE
ngx-sts-0 1/1 Running 0 5m
ngx-sts-1 1/1 Running 0 6m
更新策略
在Kubernetes 1.7及更高版本中,通过.spec.updateStrategy字段允许配置或禁用Pod、labels、source request/limits、annotations自动滚动更新功能。
OnDelete(默认方式):通过.spec.updateStrategy.type 字段设置为OnDelete,StatefulSet控制器不会自动更新StatefulSet中的Pod。用户必须手动删除Pod,以使控制器创建新的Pod。
RollingUpdate:通过.spec.updateStrategy.type 字段设置为RollingUpdate,实现了Pod的自动滚动更新,如果.spec.updateStrategy未指定,则此为默认策略。
StatefulSet控制器将删除并重新创建StatefulSet中的每个Pod。它将以Pod终止(从最大序数到最小序数)的顺序进行,一次更新每个Pod。在更新下一个Pod之前,必须等待这个Pod Running and Ready。
Partitions:通过指定 .spec.updateStrategy.rollingUpdate.partition 来对 RollingUpdate 更新策略进行分区,如果指定了分区,则当 StatefulSet 的 .spec.template 更新时,具有大于或等于分区序数的所有 Pod 将被更新。
具有小于分区的序数的所有 Pod 将不会被更新,即使删除它们也将被重新创建。如果 StatefulSet 的 .spec.updateStrategy.rollingUpdate.partition 大于其 .spec.replicas,则其 .spec.template 的更新将不会传播到 Pod。在大多数情况下,不需要使用分区。
推荐阅读
-
kubernetes有状态集合之statefulset
-
Kubernetes数据持久化之StatefulSet(自动创建PVC)
-
Kubernetes 实战——有状态应用(StatefulSet)
-
kubernetes(k8s) 学习 (十四) k8s存储之 持久卷(PV) (动态pv+statefulset)
-
Kubernetes服务--简述运行单实例的有状态服务示例
-
Kubernetes服务--简述运行单实例的有状态服务示例
-
k8s StatefulSet 有状态应用编排
-
开发:异常收集之ibatis查询集合有多个对象,但是对象都为空
-
Kubernetes 实战——有状态应用(StatefulSet)