博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Kebernetes 学习总结(8) statefulset
阅读量:6952 次
发布时间:2019-06-27

本文共 9536 字,大约阅读时间需要 31 分钟。

RC、Deployment、DaemonSet都是面向无状态的服务,它们所管理的Pod的IP、Hostname、启停顺序等都是随机的,被管理的Pod重建时,Pod的IP、Hostname都会有变化。而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列表。
以redis cluster为例,由于各redis container 的角色不一定相同(有master、slave之分),所以每个redis container被重建之后必须保持原有的hostname,必须挂载原有的volume,这样才能保证每个shard内是正常的。而且每个redis shard 所管理的slot不同,存储的数据不同,所以要求每个redis shard 所连接的存储不同,保证数据不会被覆盖或混乱。(注:在Deployment中 Pod template里定义的存储卷,所有副本集共用一个存储卷,数据是相同的,因为Pod创建时基于同一模板生成)
为了保证container所挂载的volume不会出错,k8s引入了volumeClaimTemplate。
所以具有以下特性的应用使用statefullSet
1)、稳定且唯一的网络标识符;
2)、稳定且持久的存储;
3)、有序、平滑地部署和扩展;
4)、有序、平滑的终止和删除;
5)、有序的滚动更新;

对于一个完整的StatefulSet应用由三个部分组成: headless service、StatefulSet controller、volumeClaimTemplate

例1:

由于本例中pv是静态提供,所以首先准备pv,如下:

[root@k8s-master-dev statefulset]# kubectl get pvNAME      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM     STORAGECLASS   REASON    AGEpv01      5Gi        RWO,RWX        Retain           Available                                      27mpv02      10Gi       RWO,RWX        Retain           Available                                      27mpv03      15Gi       RWO,RWX        Retain           Available                                      27m[root@k8s-master-dev statefulset]#

然后定义一个statefulset 应用,如下:

[root@k8s-master-dev statefulset]# vim statefulset-demo.yaml[root@k8s-master-dev statefulset]# cat statefulset-demo.yamlapiVersion: v1kind: Servicemetadata:  name: ngx-svc  labels:    app: ngx-svcspec:  ports:  - port: 80    name: web  clusterIP: None  selector:    app: ngx-pod---apiVersion: apps/v1kind: StatefulSetmetadata:  name: ngxspec:  serviceName: ngx-svc #声明它属于哪个Headless Service  replicas: 2  selector:    matchLabels:      app: ngx-pod  #has to match .spec.template.metadata.labels  template:    metadata:      labels:        app: ngx-pod #has to match .spec.selector.matchLabels    spec:      containers:      - name: ngx        image: nginx:1.15-alpine        imagePullPolicy: IfNotPresent        ports:        - containerPort: 80          name: web        volumeMounts:        - name: ngxvol          mountPath: /usr/share/nginx/html  volumeClaimTemplates:  - metadata:      name: ngxvol    spec:      accessModes: ["ReadWriteMany"]      resources:        requests:          storage: 5Gi[root@k8s-master-dev statefulset]# kubectl apply -f statefulset-demo.yamlservice/ngx-svc createdstatefulset.apps/ngx created[root@k8s-master-dev statefulset]# kubectl get svcNAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGEkubernetes   ClusterIP   10.96.0.1    
443/TCP 1dngx-svc ClusterIP None
80/TCP 15s[root@k8s-master-dev statefulset]# kubectl get stsNAME DESIRED CURRENT AGEngx 2 2 30s[root@k8s-master-dev statefulset]# kubectl get podsNAME READY STATUS RESTARTS AGEngx-0 1/1 Running 0 35sngx-1 1/1 Running 0 34s[root@k8s-master-dev statefulset]#

每个podname 被定义为pod.name-0、pod.name-1... 依次类推。而每个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之上。

[root@k8s-master-dev statefulset]# kubectl get pvNAME      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM                  STORAGECLASS   REASON    AGEpv01      5Gi        RWO,RWX        Retain           Bound       default/ngxvol-ngx-0                            35mpv02      10Gi       RWO,RWX        Retain           Bound       default/ngxvol-ngx-1                            35mpv03      15Gi       RWO,RWX        Retain           Available                                                   35m[root@k8s-master-dev statefulset]# kubectl get pvcNAME           STATUS    VOLUME    CAPACITY   ACCESS MODES   STORAGECLASS   AGEngxvol-ngx-0   Bound     pv01      5Gi        RWO,RWX                       5mngxvol-ngx-1   Bound     pv02      10Gi       RWO,RWX                       5m[root@k8s-master-dev statefulset]#[root@k8s-master-dev manifests]# kubectl exec -it ngx-0 -- /bin/sh/ # nslookup ngx-0.ngx-svc.default.svc.cluster.localnslookup: can't resolve '(null)': Name does not resolveName:      ngx-0.ngx-svc.default.svc.cluster.localAddress 1: 10.244.4.2 ngx-0.ngx-svc.default.svc.cluster.local/ #/ #/ # nslookup ngx-1.ngx-svc.default.svc.cluster.localnslookup: can't resolve '(null)': Name does not resolveName:      ngx-1.ngx-svc.default.svc.cluster.localAddress 1: 10.244.1.101 ngx-1.ngx-svc.default.svc.cluster.local/ #/ # [root@k8s-master-dev manifests]#[root@k8s-master-dev statefulset]# kubectl exec ngx-0 -- ls /usr/share/nginx/html[root@k8s-master-dev statefulset]# kubectl exec -it ngx-0 -- /bin/sh/ # echo ngx-0 > /usr/share/nginx/html/index.html/ # [root@k8s-master-dev statefulset]#[root@k8s-master-dev statefulset]# kubectl get pods -o wideNAME      READY     STATUS    RESTARTS   AGE       IP            NODE            NOMINATED NODEngx-0     1/1       Running   0          9m        10.244.1.98   k8s-node1-dev   
ngx-1 1/1 Running 0 9m 10.244.2.63 k8s-node2-dev
[root@k8s-master-dev statefulset]# curl http://10.244.1.98ngx-0[root@k8s-master-dev statefulset]# kubectl delete pod/ngx-0pod "ngx-0" deleted[root@k8s-master-dev statefulset]# kubectl get pods -o wideNAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODEngx-0 1/1 Running 0 8s 10.244.1.99 k8s-node1-dev
ngx-1 1/1 Running 0 10m 10.244.2.63 k8s-node2-dev
[root@k8s-master-dev statefulset]# curl http://10.244.1.99ngx-0[root@k8s-master-dev statefulset]#

pod的扩展、收缩都是按照顺序执行。如下所示:

[root@k8s-master-dev statefulset]# kubectl scale sts ngx --replicas=3statefulset.apps/ngx scaled[root@k8s-master-dev statefulset]# kubectl get podsNAME      READY     STATUS    RESTARTS   AGEngx-0     1/1       Running   0          8mngx-1     1/1       Running   0          18mngx-2     1/1       Running   0          3s[root@k8s-master-dev statefulset]# kubectl get pvcNAME           STATUS    VOLUME    CAPACITY   ACCESS MODES   STORAGECLASS   AGEngxvol-ngx-0   Bound     pv01      5Gi        RWO,RWX                       18mngxvol-ngx-1   Bound     pv02      10Gi       RWO,RWX                       18mngxvol-ngx-2   Bound     pv03      15Gi       RWO,RWX                       12s[root@k8s-master-dev statefulset]# kubectl get pvNAME      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS    CLAIM                  STORAGECLASS   REASON    AGEpv01      5Gi        RWO,RWX        Retain           Bound     default/ngxvol-ngx-0                            49mpv02      10Gi       RWO,RWX        Retain           Bound     default/ngxvol-ngx-1                            48mpv03      15Gi       RWO,RWX        Retain           Bound     default/ngxvol-ngx-2                            48m[root@k8s-master-dev statefulset]# kubectl patch sts ngx -p '{"spec":{"replicas":2}}'statefulset.apps/ngx patched[root@k8s-master-dev statefulset]# kubectl get pvcNAME           STATUS    VOLUME    CAPACITY   ACCESS MODES   STORAGECLASS   AGEngxvol-ngx-0   Bound     pv01      5Gi        RWO,RWX                       20mngxvol-ngx-1   Bound     pv02      10Gi       RWO,RWX                       20mngxvol-ngx-2   Bound     pv03      15Gi       RWO,RWX                       1m[root@k8s-master-dev statefulset]# kubectl get podsNAME      READY     STATUS    RESTARTS   AGEngx-0     1/1       Running   0          9mngx-1     1/1       Running   0          20m[root@k8s-master-dev statefulset]#[root@k8s-master-dev statefulset]# kubectl delete -f statefulset-demo.yamlservice "ngx-svc" deletedstatefulset.apps "ngx" deleted[root@k8s-master-dev statefulset]# kubectl delete pvc --allpersistentvolumeclaim "ngxvol-ngx-0" deletedpersistentvolumeclaim "ngxvol-ngx-1" deletedpersistentvolumeclaim "ngxvol-ngx-2" deleted[root@k8s-master-dev statefulset]# kubectl delete -f ../volumes/pv-vol-demo.yamlpersistentvolume "pv01" deletedpersistentvolume "pv02" deletedpersistentvolume "pv03" deleted[root@k8s-master-dev statefulset]#

更新策略

在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。在大多数情况下,不需要使用分区。
修改更新策略及更新image 例:

kubectl patch sts ngx -p '{"spec":{"updateStrategy":{"rollingUpdate":{"partition":4}}}}'kubectl set image sts/ngx ngx=nginx:latest

转载于:https://blog.51cto.com/caiyuanji/2359723

你可能感兴趣的文章
MD110查看所有号码如何走位
查看>>
top
查看>>
DHCP
查看>>
Mysql 删除表(Drop)后数据恢复成功
查看>>
我的友情链接
查看>>
python while循环和双层循环
查看>>
史上最全程序员资源分享
查看>>
[置顶] Jquery插件之信息弹出框showInfoDialog(成功、错误、警告、通知)...
查看>>
回顾2017,展望2018
查看>>
[转]DPM2012系列之四:配置邮件报警功能
查看>>
LINUX下搭建mail服务器
查看>>
手把手教你把你的网站改为https
查看>>
Rxjs入门
查看>>
静态路由管理距离问题
查看>>
汽车常识全面介绍 - 引擎概论
查看>>
Android源码个个击破之Activity的渲染过程深入剖析
查看>>
C# 免费发邮件
查看>>
final关键字
查看>>
《Java程序员面试宝典》学习笔记(数据结构部分)
查看>>
[转载] 中华典故故事(孙刚)——29 拍马屁
查看>>