当前位置: 首页 > news >正文

Kubernetes — StatefulSet 管理与使用

目录

一、使用StatefulSet

1. Deployment 的特征

2、“有状态”的应用

3、创建有状态应用的三步骤

4、创建PV 和 PVC

5、创建StatefulSet

6、创建结果

7、创建 Headless 服务

8、使用有状态的服务

9、StatefulSet 的故障处理

1. 与无状态服务不同,有状态的StatefulSet 中一个Pod出现故障之后,可以看到

2.以web-1为例,模拟故障 

10、扩缩容和升级

 11、Pod管理策略


一、使用StatefulSet

1. Deployment 的特征

回顾Deployment,可以发现它有一些很有趣的特征,比如,所有Pod地位都是平等的,当一个Pod因故障被替换后,新的容器与其余所有Pod依然相同,因此无论请求发送到哪个Pod,返回的结果都是一致的。又或者Pod被删除后,里面的数据也随之消失

这种特性一般称其为“无状态”

2、“有状态”的应用

1. 有些情况下希望运行一些和上述不同的应用,包括使用持久化的存储,稳定的网络标志,Pod与Pod之间并不是完全平等(即使它们用同一个镜像创建)。

    这类服务通常称为“有状态”的服务,

    它的实现不在依靠ReplicaSet,而是用StatefulSet,它具备以下特性(支持多副本):

        稳定的持久化存储,Pod重新调度后访问相同的持久化数据,使用PVC来实现

        稳定的网络标识,Pod重新调度后PodName 和 HostName不变,

             基于Headless Service 实现

        Pod都有一个“序号”,可以有序的进行扩展,部署等操作

3、创建有状态应用的三步骤

参考资料: StatefulSet | Kubernetes

4、创建PV 和 PVC

1. 创建一批 PV

$ sudo mkdir /etc/exports.d /nfs{1..3}
$ sudo tee /etc/exports.d/s.exports <<EOF
/nfs1 *(rw,no_root_squash)
/nfs2 *(rw,no_root_squash)
/nfs3 *(rw,no_root_squash)
EOF
$ sudo apt -y install nfs-kernel-server
$ sudo systemctl enable --now nfs-server.service
showmount -e
Export list for k8s-master:
/nfs3 *
/nfs2 *
/nfs1 *
$ kubectl apply -f- <<EOF
apiVersion: v1
kind: PersistentVolume
metadata:
  name: mypv1
spec:
  storageClassName: my-sc    #定义了存储类型
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  nfs:
    path: /nfs1
    server: 192.168.5.100
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: mypv2
spec:
  storageClassName: my-sc
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  nfs:
    path: /nfs2
    server: 192.168.5.100
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: mypv3
spec:
  storageClassName: my-sc
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  nfs:
    path: /nfs3
    server: 192.168.5.100
EOF
$ kubectl get pv
NAME    CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
mypv1   1Gi        RWO            Recycle          Available           my-sc                   8s
mypv2   1Gi        RWO            Recycle          Available           my-sc                   8s
mypv3   1Gi        RWO            Recycle          Available           my-sc                   8s

参考资料: 持久卷 | Kubernetes

2. 在yaml 文件中定义 PVC 的模板,使系统在创建statefulset 时自动创建PVC

5、创建StatefulSet

1. 创建StatefulSet 时需要注意,

    serviceName 这一项的值必须要和后面创建的headless Service的名称一致

2. 另外matchLabels 参数和pod 的标签一致,这与deployment 相同

3. 上一步关于 volumeClaimTemplates 的配置也需要添加进 StatefulSet 配置 yaml

$ kubectl apply -f- <<EOF
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  selector:
    matchLabels:
      app: nginx
  serviceName: nginx
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      terminationGracePeriodSeconds: 10    #删除pod的时间10s
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: stor
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: stor
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: "my-sc"
      resources:
        requests:
          storage: 1Gi
EOF

参考资料: StatefulSet 基础 | Kubernetes

6、创建结果

1. 创建完成后,可以看到Pod名称按序号排序。如果查看日志,可以发现Pod的创建顺序是第一个创建完成之后再创建第二个,依次完成

$ watch -n 1 kubectl get pod
NAME    READY   STATUS    RESTARTS   AGE
`web-0` 1/1     Running   0          79s
`web-1` 1/1     Running   0          55s
`web-2` 1/1     Running   0          30s
<Ctrl-C>

2. 创建了三个PVC,名称同样以序号排序,依次和PV 做绑定

$ kubectl get pv
NAME    CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                STORAGECLASS   REASON   AGE
mypv1   1Gi        RWO            Recycle          Bound    default/stor-web-0   my-sc                   27m
mypv2   1Gi        RWO            Recycle          Bound    default/stor-web-1   my-sc                   27m
mypv3   1Gi        RWO            Recycle          Bound    default/stor-web-2   my-sc                   27m

$ kubectl get pvc
NAME         STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
stor-web-0   Bound    mypv1    1Gi        RWO            my-sc          2m51s
stor-web-1   Bound    mypv2    1Gi        RWO            my-sc          2m28s
stor-web-2   Bound    mypv3    1Gi        RWO            my-sc          2m1s

7、创建 Headless 服务

1. 创建 headless 服务,注意以下几点:

        ① 服务名称和 statefulset 中的定义一致

        ② 选择器要指向正确的Pod 标签

        ③ 指定 clusterIP:None(没有指定,DNS解析的就是每一个pod的IP)

kubectl apply -f- <<EOF  
apiVersion: v1
kind: Service
metadata:
  name: nginx    #服务名要和statefulset名要一致
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None    #headless
  selector:
    app: nginx
EOF
$ kubectl get service nginx
NAME    TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
nginx   ClusterIP   None         <none>        80/TCP    17s
$ kubectl apply -f- <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: clientpod
spec:
  containers:
    - name: clientpod
      image: busybox:1.28.3
      args:
      - /bin/sh
      - -c
      - sleep 3h
EOF
    
$ kubectl get pod clientpod     #确认pod已经运行
NAME        READY   STATUS    RESTARTS   AGE
clientpod   1/1     Running   0          2m15s

8、使用有状态的服务

1. 使用nslookup 查看 DNS 记录,可以看到对该服务的访问直接指向Pod

$ kubectl exec -it clientpod -- /bin/sh    #进入pod
/ # nslookup nginx    #解析nginx
Server:    10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local

Name:      nginx
Address 1: 172.16.194.83 web-0.nginx.default.svc.cluster.local
Address 2: 172.16.126.19 web-1.nginx.default.svc.cluster.local
Address 3: 172.16.194.84 web-2.nginx.default.svc.cluster.local

2. 通过对稳定的名称访问也始终可以访问到固定的Pod

/ # nslookup web-0.nginx
Server:    10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local

Name:      web-0.nginx
Address 1: 172.16.194.83 web-0.nginx.default.svc.cluster.local

9、StatefulSet 的故障处理

1. 与无状态服务不同,有状态的StatefulSet 中一个Pod出现故障之后,可以看到

虽然Pod的IP地址变化了,但通过不变的域名,依然可以访问到重建后的Pod

即使经过了故障和重建,Pod中保持在持久化存储(卷)中的数据依然存在

2.以web-1为例,模拟故障 

$ kubectl describe pod web-1
...输出省略...
    ClaimName:  'stor-web-1'
...输出省略...
$ kubectl get pv | grep stor-web-1    #查询所在pv
'mypv2'   1Gi        RWO            Recycle          Bound    default/stor-web-1   my-sc                   70m
$ kubectl describe pv mypv2 | grep -i path    #查看对应的路径
    Path:      '/nfs2'
$ sudo touch /nfs2/newfile    #创建文件

$ kubectl exec -it web-1 -- /bin/sh
# ls /usr/share/nginx/html    #查看文件已生成
newfile
$ kubectl get pod -o wide
NAME                                READY   STATUS      RESTARTS        AGE     IP              NODE          NOMINATED NODE   READINESS GATES
web-0                               1/1     Running     0               59m     172.16.194.83   k8s-worker1   <none>           <none>
web-1                               1/1     Running     0               59m     172.16.126.19   k8s-worker2   <none>           <none>
web-2                               1/1     Running     0               58m     172.16.194.84   k8s-worker1   <none>           <none>
$ kubectl delete pod web-1    #删除web-1,后会重新创建()
pod "web-1" deleted '与deployment区别,statefulset是有状态'
$ kubectl get pod web-1 -o wide    #查看web-1的IP已经变化
NAME    READY   STATUS    RESTARTS   AGE     IP              NODE          NOMINATED NODE   READINESS GATES
web-1   1/1     Running   0          3m29s   172.16.126.21   k8s-worker2   <none>           <none>

$ kubectl exec -it clientpod -- nslookup web-1.nginx    #依旧可以继续解析
Server:    10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local

Name:      web-1.nginx
Address 1: 172.16.126.21 web-1.nginx.default.svc.cluster.local
$ k exec -it web-1 -- ls /usr/share/nginx/html
newfile

10、扩缩容和升级

1. 当扩容StatefulSet时,

    可以看到Pod停止的顺序为从序号最高的开始降序终止,

    并且只有在前一个pod被完全终止后,下一个pod才开始终止。

    升级时,也是以相同顺序处理

2. 试验

$ watch -n 1 kubectl get pod    #检测pod状态

新打开一个终端

$ kubectl scale statefulset web --replicas=1    #缩容;依次从2-1删除
$ kubectl scale statefulset web --replicas=3    #扩容;依次1-2增加

 11、Pod管理策略

1. 对于某些分布式系统,StatefulSet 的顺序性保证是不必要的,或者是不应该出现的

    为了解决这个问题,在Kubernetes 1.7 中引入了podManagementPolicy

        ① OrderedReady Pod 管理策略

                statefulSets 的默认选项,保证顺序性

        ② Parallel Pod 管理策略

                并行启动、终止、升级、弹性伸缩Pod

                在变更一个Pod时不必等前一个Pod完成

2. 案例

$ kubectl delete statefulsets web    #删除statefulset
$ kubectl delete pvc stor-web-0 stor-web-1 stor-web-2    #删除pvc
$ kubectl get service nginx    #服务还在
NAME    TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
nginx   ClusterIP   None         <none>        80/TCP    61m
kiosk@k8s-master:~$ kubectl get pv     #pv还在
NAME    CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS     CLAIM                STORAGECLASS   REASON   AGE
mypv1   1Gi        RWO            Recycle          Released   default/stor-web-0   my-sc                   115m
mypv2   1Gi        RWO            Recycle          Released   default/stor-web-1   my-sc                   115m
mypv3   1Gi        RWO            Recycle          Released   default/stor-web-2   my-sc                   115m
$ kubectl apply -f- <<EOF
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  selector:
    matchLabels:
      app: nginx
  serviceName: nginx
  # 增加 1 行
  podManagementPolicy: "Parallel" #平行
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      terminationGracePeriodSeconds: 10
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: stor
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: stor
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: "my-sc"
      resources:
        requests:
          storage: 1Gi
EOF

验证

$ watch -n 1 kubectl get pod    #动态查看pod状态

新打开终端

$ kubectl scale statefulset web --replicas=1
$ kubectl scale statefulset web --replicas=3

会发现扩缩容为同时进行

参考资料: StatefulSet 基础 | Kubernetes 

相关文章:

  • 想学习网络安全一定要学习web
  • 【leetcode刷题】数组篇
  • 基于VUE+Echarts大屏数据展示150套 (集合)
  • 【深度学习100例】—— 基于pytorch使用LSTM进行文本情感分析 | 第7例
  • 【基础巩固】详细总结对数组的理解
  • ⌈Linux_ 感受系统美学⌋ 剖释“Linux下一切皆文件” ,底层级操作增进Linux内功
  • 哪些是模糊用语-《软件方法》自测题解析020
  • 【设计模式】-创建型模式-第2章第5讲-【对象池模式】
  • 125款浪漫七夕表白网站源码【建议收藏】HTML+CSS+JavaScript
  • 基于JAVA忻府区饭中有豆粮油销售系统计算机毕业设计源码+系统+数据库+lw文档+部署
  • 毕业设计 基于单片机的风速测量系统 - 物联网 嵌入式 stm32 arduino
  • 【MSP430G2553】图形化开发笔记(4) Timer_A 定时器
  • 【老板要我啥都会】|前端升全栈之项目使用express重构项目(上篇)
  • SpringMVC之使用SpringMVC获取参数与返回数据
  • (附源码)spring boot车辆管理系统 毕业设计 031034
  • 【399天】跃迁之路——程序员高效学习方法论探索系列(实验阶段156-2018.03.11)...
  • 【MySQL经典案例分析】 Waiting for table metadata lock
  • Angular4 模板式表单用法以及验证
  • oldjun 检测网站的经验
  • Protobuf3语言指南
  • React 快速上手 - 07 前端路由 react-router
  • VUE es6技巧写法(持续更新中~~~)
  • vue-cli3搭建项目
  • Vultr 教程目录
  • 阿里云前端周刊 - 第 26 期
  • 仿天猫超市收藏抛物线动画工具库
  • 诡异!React stopPropagation失灵
  • 湖南卫视:中国白领因网络偷菜成当代最寂寞的人?
  • 区块链分支循环
  • 使用docker-compose进行多节点部署
  • 微信端页面使用-webkit-box和绝对定位时,元素上移的问题
  • 微信小程序--------语音识别(前端自己也能玩)
  • 项目实战-Api的解决方案
  • 小程序、APP Store 需要的 SSL 证书是个什么东西?
  • 一个完整Java Web项目背后的密码
  • 不要一棍子打翻所有黑盒模型,其实可以让它们发挥作用 ...
  • 交换综合实验一
  • ​Linux Ubuntu环境下使用docker构建spark运行环境(超级详细)
  • ​ssh免密码登录设置及问题总结
  • #Java第九次作业--输入输出流和文件操作
  • #WEB前端(HTML属性)
  • #宝哥教你#查看jquery绑定的事件函数
  • (3)nginx 配置(nginx.conf)
  • (LeetCode 49)Anagrams
  • (pytorch进阶之路)CLIP模型 实现图像多模态检索任务
  • (第8天)保姆级 PL/SQL Developer 安装与配置
  • (生成器)yield与(迭代器)generator
  • (十)【Jmeter】线程(Threads(Users))之jp@gc - Stepping Thread Group (deprecated)
  • (五)IO流之ByteArrayInput/OutputStream
  • (转载)在C#用WM_COPYDATA消息来实现两个进程之间传递数据
  • .NET CORE 第一节 创建基本的 asp.net core
  • .net core webapi 部署iis_一键部署VS插件:让.NET开发者更幸福
  • .Net8 Blazor 尝鲜
  • .NET和.COM和.CN域名区别
  • .NET开源项目介绍及资源推荐:数据持久层 (微软MVP写作)