k8s之statefulSet-有状态应用副本集控制器

时间:2022-06-01 18:15:45

1.概述

无状态应用更关注群体,任何一个成员都可以被取代,有状态应用关注的是个体。用deployment控制器管理的nginx、myapp等都属于无状态应用,像mysql、redis、zookeeper等都属于有状态应用,他们有的还有主从之分、先后顺序之分.

statefulset控制器能实现有状态应用的管理,但实现起来也是非常麻烦,需要把运维管理过程写成脚本并注入到statefulset中才能使用,虽然互联网上有人做好了stateful的脚本,但是还是建议大家不要轻易的把redis、mysql等这样有状态的应用迁移到k8s上.

在k8s中,statefulset管理的应用有以下特效:

a).每一个Pod稳定且有唯一的网络标识符;
b).稳定且持久的存储设备;
c).要求有序、平滑的部署和扩展;
d).要求有序、平滑的终止和删除;
e).有序的滚动更新,应该先更新从节点,再更新主节点;

statefulset由三个组件组成:

a).headless service(无头的服务,即没名字);
b).statefulset控制器;
c).volumeClaimTemplate(存储卷申请模板,因为每个pod要有专用存储卷,而不能共用存储卷)

2.创建StatefulSet控制器

kubectl explain sts

cat stateful-demo.yaml
apiVersion: v1
kind: Service
metadata:
name: myapp-svc
labels:
app: myapp-svc
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: myapp-pod
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: myapp
spec:
serviceName: myapp-svc
replicas: 2
selector:
matchLabels:
app: myapp-pod
template:
metadata:
labels:
app: myapp-pod
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
ports:
- containerPort: 80
name: web
volumeMounts:
- name: myappdata
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: myappdata
spec:
accessModes: ["ReadWriteOnce"]
#storageClassName: "gluster-dynamic"
resources:
requests:
storage: 5Gi

volumeClaimTemplates:存储卷申请模板,为每个pod定义volume;为pod所在的名称空间自动创建pvc.

kubectl apply -f stateful-demo.yaml
kubectl get pods
NAME READY STATUS RESTARTS AGE
myapp-0 1/1 Running 0 4m
myapp-1 1/1 Running 0 4m # pod和service会被删除,但是pvc不会被删,所以还能恢复.
kubectl delete -f stateful-demo.yaml # 解析pod时的格式:pod名.svc名.namespace名.svc.cluster.local
kubectl exec -it myapp-0 -- /bin/sh
/ # nslookup myapp-0.myapp-svc.default.svc.cluster.local
nslookup: can't resolve '(null)': Name does not resolve
Name: myapp-0.myapp-svc.default.svc.cluster.local
Address 1: 10.244.1.110 myapp-0.myapp-svc.default.svc.cluster.local # 将pod为5个
kubectl scale sts myapp --replicas=5
# 也可以用patch打补丁的方法来进行扩容和缩容
kubectl patch sts myapp -p '{"spec":{"replicas":2}}'
# 更新策略
kubectl explain sts.spec.updateStrategy.rollingUpdate
假设有4个pod(pod0,pod1,pod2,pod3),如果设置partition为5,那么说明大于等于5的pod更新,四个Pod就都不更新;
如果partition为4,那么说明大于等于4的pod更新,即pod3更新,其他pod都不更新;
如果partiton为3,那么说明大于等于3的pod更新,那么就是pod2和pod3更新,其他pod都不更新.
kubectl patch sts myapp -p '{"spec":{"updateStrategy":{"rollingUpdate":{"partition":4}}}}'
kubectl describe sts myapp
Update Strategy: RollingUpdate
Partition: 4
# 把myapp升级为v2版本
kubectl set image sts/myapp myapp=ikubernetes/myapp:v2
kubectl get pods myapp-4 -o yaml
containerStatuses:
image: ikubernetes/myapp:v2

可以参考github上别人做好的有状态应用:github k8s statefulSet redis|mysql

参考博客:http://blog.itpub.net/28916011/viewspace-2215046/