目录html
RC、Deployment、DaemonSet都是面向无状态的服务,它们所管理的Pod的IP、名字,启停顺序等都是随机的,而StatefulSet是什么?顾名思义,有状态的集合,管理全部有状态的服务,好比MySQL、MongoDB集群等。 StatefulSet本质上是Deployment的一种变体,在v1.9版本中已成为GA版本,它为了解决有状态服务的问题,它所管理的Pod拥有固定的Pod名称,启停顺序,在StatefulSet中,Pod名字称为网络标识(hostname),还必需要用到共享存储。 在Deployment中,与之对应的服务是service,而在StatefulSet中与之对应的headless service,headless service,即无头服务,与service的区别就是它没有Cluster IP,解析它的名称时将返回该Headless Service对应的所有Pod的Endpoint列表。 除此以外,StatefulSet在Headless Service的基础上又为StatefulSet控制的每一个Pod副本建立了一个DNS域名,这个域名的格式为: |
$(podname).(headless server name) FQDN: $(podname).(headless server name).namespace.svc.cluster.local
稳定且惟一的网络标识符;nginx
如: Redis集群, 在Redis集群中,它是经过槽位来存储数据的,假如:第一个节点是0~1000,第二个节点是1001~2000,第三个节点2001~3000...等等,这就使得Redis集群中每一个节点要经过ID来标识本身,如: 第二个节点宕机了,重建后它必须还叫第二个节点,或者说第二个节点叫R2,它必须还叫R2,这样在获取1001~2000槽位的数据时,才能找到数据,不然Redis集群将没法找到这段数据。web
稳定且持久的存储api
有序、平滑的部署和扩展安全
如 MySQL集群,要先启动主节点, 若从节点没有要求,则可一块儿启动,若从节点有启动顺序要求,可先启动第一个从节点,接着第二从节点等;这个过程就是有顺序,平滑安全的启动。网络
有序、平滑的终止和删除app
即: 咱们先终止从节点,若从节点是有启动顺序的,那么关闭时,也要按照逆序终止,即启动时是从S1~S4以此启动,则关闭时,则是先关闭S4,而后时S3,依次关闭,最后在关闭主节点。less
有序的滚动更新ide
MySQL在更新时,应该先更新从节点,所有的从节点都更新完了,最后在更新主节点,由于新版本通常可兼容老版本,可是必定要注意,若新版本不兼容老版本就很很麻烦spa
apiVersion: v1 kind: Service metadata: name: myapp-sts labels: app: myapp-sts spec: ports: - port: 80 name: web clusterIP: "None" selector: app: myapp-pod --- apiVersion: apps/v1 kind: StatefulSet metadata: name: myapp spec: serviceName: myapp-sts #声明它属于哪一个Headless Service. 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: "rook-ceph-block" resources: requests: storage: 1Gi
能够正确解析到ip
[root@master statfulset]# nslookup myapp-1.myapp-sts.default.svc.cluster.local 10.96.0.10 Server: 10.96.0.10 Address: 10.96.0.10#53 Name: myapp-1.myapp-sts.default.svc.cluster.local Address: 10.244.1.30 [root@master statfulset]# nslookup myapp-0.myapp-sts.default.svc.cluster.local 10.96.0.10 Server: 10.96.0.10 Address: 10.96.0.10#53 Name: myapp-0.myapp-sts.default.svc.cluster.local Address: 10.244.1.29
#扩容至三个pod kubectl scale sts myapp --replicas=3 #而后从新缩容至两个pod kubectl scale sts myapp --replicas=2
扩容当中出现了一个问题, 新建立的pod处于pending状态, describe看到是mount的问题, 原来是以前pod挂载的pv变成了released状态, 并无变成available状态, 通过查找发现最关键的是PV的
spec.claimRef
字段,该字段记录着原来PVC的绑定信息,删除绑定信息,便可从新释放PV从而达到Available。
OrderedReady:上述的启停顺序,默认设置。
spec: podManagementPolicy: OrderedReady
Parallel:告诉StatefulSet控制器并行启动或终止全部Pod,而且在启动或终止另外一个Pod以前不等待前一个Pod变为Running and Ready或彻底终止。
spec: podManagementPolicy: Parallel
kubectl explain sts.spec.updateStrategy.rollingUpdate
partition: 这种更新策略的含义是, 若当前statefulSet的副本数为5个,则Pod名为pod-0~pod-4,那么此时定义partition=4, 就意味着我要更新大于等于4的Pod,而只有pod-4的ID 4 是大于等于4的,因此只有pod-4会被更新,其它不会,这就是金丝雀更新。若后期发现pod-4更新后,工做一切正常,那么就能够调整partition=0,这样只要大于等于0的pod ID都将被更新。
修改滚动更新策略,查看效果
kubectl patch sts myapp -p '{"spec":{"updateStrategy":{"rollingUpdate":{"partition":2}}}}'
#修改statefulset的image kubectl set image sts/myapp myapp=ikubernetes/myapp:v2 #查看已经修改为功了 [root@master statfulset]# kubectl get sts myapp -o wide NAME READY AGE CONTAINERS IMAGES myapp 4/4 16h myapp ikubernetes/myapp:v2
由于策略写的是从第二个容器开始更新
经过命令
kubectl get pod myapp-1 -o yaml
能够看到2
以前的image没有改变经过命令
kubectl get pod myapp-2 -o yaml
能够看到2
以后的image都已经改变了
#再从新把partition改成0, 则把以前的pod的image都修改生效了 kubectl patch sts myapp -p '{"spec":{"updateStrategy":{"rollingUpdate":{"partition":0}}}}'
这种方式就能够模拟金丝雀发布 |
[root@master statfulset]# kubectl get pods -l app=myapp-pod -o custom-columns=NAME:metadata.name,IMAGE:spec.containers[0].image NAME IMAGE myapp-0 ikubernetes/myapp:v2 myapp-1 ikubernetes/myapp:v2 myapp-2 ikubernetes/myapp:v2 myapp-3 ikubernetes/myapp:v2
分区更新操做
将spec.updateStrategy.rollingUpdate.partition设置为Pod副本数量时,即意味着全部Pod资源都不会处于可直接更新的分区内,直到partition小于Pod数时,才会开始更新
此时,即使删除某Pod,也会按旧版本进行重建,即暂存状态的更新对全部Pod资源均不产生影响
go-template
自定义资源输出信息kubectl get pod myapp-1 -o go-template --template='{{.status.podIP}}'
[root@master statfulset]# kubectl get pod myapp-1 -o go-template --template='{{range .spec.containers}}{{.image}}{{end}}' ikubernetes/myapp:v2
由于这里查看containers的image信息是一个列表信息, 因此要用到range
关于更多的go-template
的使用方法, 能够参考这位老哥写的博客: https://www.bbsmax.com/A/gAJGgjX3JZ/
https://www.cnblogs.com/wn1m/p/11289079.html
https://www.cnblogs.com/tylerzhou/p/11027559.html
https://www.cnblogs.com/xzkzzz/p/9871837.html
https://pdf.us/2019/03/15/3013.html