【k8s】7、pod控制器详解

一、Pod控制器介绍

Pod是kubernetes的最小管理单元,在kubernetes中,按照Pod的创建方式可以将其分为两类

  • 自主式Pod: kubernetes直接创建出来的Pod,这种Pod删除后就没有了,也不会重建
  • 控制器创建的Pod: kubernetes通过控制器创建的Pod,这种Pod删除之后还会自动重建。
#什么是Pod控制器?

Pod控制器是管理Pod的中间层,使用Pod控制器之后,只需要告诉Pod控制器,想要多少个什么样的Pod就可以了,它会创建出满足条件的Pod并确保每一个Pod资源处于用户期望的目标状态,如果Pod资源在运行中出现故障,它会基于指定策略重新编排Pod。

在kubernetes中,有很多类型的Pod控制器,每种都有自己的适合的场景,常见的有下面这些:

pod控制器 功能
Replication Controller 比较原始的Pod控制器,以及被废弃,由ReplicaSet替代
ReplicaSet ①保证副本数量一致维持在期望值
②支持Pod数量扩缩容
③镜像版本升级
Deployment 通过控制ReplicaSet来控制Pod,并支持滚动升级,回退版本
Horizontal Pod Autoscaler 可以根据集群负载自动水平调整Pod的数量,实现消峰填谷
DaemonSet 在集群中的指定Node上运行且运行一个副本,一般用于守护进程类的任务
Job 它创建出来的Pod只要完成任务就立即退出,不需要重启或重建,用于执行一次任务
Cronjob 它创建的Pod服务周期性任务控制,不需要持续后台运行
StatefulSet 管理有状态应用

二、ReplicasSet(RS)控制器

ReplicaSet的主要作用是保证一定数量的Pod正常运行,它会持续监听这些Pod的运行状态,一旦发生故障,就会重启或重建,同时它支持对Pod数量的扩缩容和镜像版本的升降级。

image-20221007164644537

ReplicaSet的资源清单文件

apiVersion: apps/v1   #版本号
kind: ReplicaSet      #类型
metadata:             #元数据
  name:               #资源名称
  namespace:          #所属命名空间
  labels:             #标签
    controller: rs    
spec:                 #其它属性
  replicas: 3         #副本数量
  selector:           #标签选择器
    matchLabels:      #Labels匹配规则
      app: nginx-pod
    matchExpressions: #Expressions匹配规则
      - {
    
    key: app,operator: In,values: [nginx-pod]}
  template:           #模板,当副本数量不足时,会根据下面的模板创建pod副本
    metadata:
      labels:
        app: nginx-pod
    spec:
      containers:
      - name: nginx
        image: nginx:1.17.1
        ports:
        - containerPort: 80
        
--------------------------------------------------------------
#上述新了解配置解释

replicas: 指定副本数量,其实就是当前rs创建出来的Pod数量,默认为1
selector: 选择器,它的作用是建立Pod控制器和Pod之间的关联关系,采用的Label Selector机制,在Pod模板上定义label,在控制器上定义选择器,就可以表明控制器能管理哪些Pod了。
template: 模板,就是的当前控制器创建Pod所使用的模板。

1、创建ReplicaSet

创建pc-replicaset.yaml文件

apiVersion: apps/v1
kind: ReplicaSet   
metadata:
  name: pc-replicaset
  namespace: dev
spec:
  replicas: 3
  selector: 
    matchLabels:
      app: nginx-pod
  template:
    metadata:
      labels:
        app: nginx-pod
    spec:
      containers:
      - name: nginx
        image: nginx:1.17.1

image-20221007170616888

kubect create -f pc-replicaset.yaml
#创建rs控制器

kubectl get rs pc-replicaset -n dev -o wide
#查看rc

kubectl get pod -n dev
#查看pod的状态

image-20221007171459479

2、扩缩容

方法一:直接edit在线编辑修改

kubectl edit rs pc-replicaset -n dev
#编辑rs的副本数量,修改里面的spec.replicas:6即可

image-20221007171821510

image-20221007171943929

方法二:命令行直接修改

kubectl scale rs pc-replicaset --replicas=2 -n dev
#使用cscale命令实现扩缩容,后面的replicas=n,直接指定目标数量即可

image-20221007172252068

3、镜像升级

方法一:在线编辑edit文件

kubectl edit rs pc-replicaset -n dev
#编辑rs的容器镜像

image-20221007172537433

image-20221007172719051

方法二:命令直接升级版本

kubectl set image rs pc-replicaset nginx=nginx:1.17.1 -n dev
#指定换成任何的版本

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dqyEoNIM-1668959407562)(C:\Users\Ydq\AppData\Roaming\Typora\typora-user-images\image-20221007173134861.png)]

4、删除replicaset

kubectl delete rs pc-replicaset -n dev
#直接删除replicaset控制器,所有pod都会删除。

//删除步骤: kubernetes删除RS之前,会将replicasclear调整为0,等待所有的Pod被删除后,再执行RS对象删除

kubectl delete -f pc-replicaset -n dev
#通过yaml文件删除(推荐使用)

kubectl delete rs pc-replicaset -n dev --cascade=false
#如果希望仅仅删除RS对象,保留Pod,可以模板添加对象命令

image-20221007173844556

三、Deployment控制器

为了更好的解决服务编排问题,kubernetes在V1.2版本开始,引入了Deployment控制器,值得一提的是,这种控制器并不直接管理Pod,而是通过管理ReplicaSet 来间接管理Pod。

  • 也就是说:Deployment管理ReplicaSet,ReplicaSet管理Pod,所以Deployment比ReplicaSet功能更加强大。

image-20221007184519576

Deployment主要功能有下面几个:

  • 支持ReplicaSet的所有功能
  • 支持发布的停止、继续
  • 支持滚动更新和回滚版本

Deployment的资源清单文件

apiVersion: apps/v1         # 版本号
kind: Deployment            # 类型       
metadata:                   # 元数据
  name:                     # deploy名称 
  namespace:                # 所属命名空间 
  labels:                   #标签
    controller: deploy
spec:                           # 详情描述
  replicas: 3                   # 副本数量
  revisionHistoryLimit: 3       # 保留历史版本(默认是3个)
  paused: false                 # 暂停部署,默认是false
  progressDeadlineSeconds: 600  # 部署超时时间(s),默认是600
  strategy:                      # 策略
    type: RollingUpdate          # 滚动更新策略
    rollingUpdate:                # 滚动更新
      maxSurge: 25%                # 最大额外可以存在的副本数,可以为百分比,也可以为整数
      maxUnavailable: 25%         # 最大不可用状态的 Pod 的最大值,可以为百分比,也可以为整数
  selector:           # 选择器,通过它指定该控制器管理哪些pod
    matchLabels:      # Labels匹配规则
      app: nginx-pod
    matchExpressions: # Expressions匹配规则
      - {
    
    key: app, operator: In, values: [nginx-pod]}
  template:     # 模板,当副本数量不足时,会根据下面的模板创建pod副本
    metadata:
      labels:
        app: nginx-pod
    spec:
      containers:
      - name: nginx
        image: nginx:1.17.1
        ports:
        - containerPort: 80

1、创建deployment

创建pc-deployment.yaml文件

apiVersion: apps/v1
kind: Deployment      
metadata:
  name: pc-deployment
  namespace: dev
spec: 
  replicas: 3
  selector:
    matchLabels:
      app: nginx-pod
  template:
    metadata:
      labels:
        app: nginx-pod
    spec:
      containers:
      - name: nginx
        image: nginx:1.17.1

image-20221007185917789

2、扩缩容

deployment控制器的扩缩容和replicaset的方法一样,都可以进行在线编辑和使用scale命令进行扩缩容。

使用edit进行扩容

kubectl edit deployment pc-deployment -n dev
#修改deployment的副本数量

image-20221007190535378

image-20221007190614369

使用scale命令缩容

kubectl scale deployment pc-deployment --replica=2 -n dev
#进行副本的减少

image-20221007190758443

3、镜像更新

deployment支持两种更新策略:重建更新滚动更新 ,可以通过 strategy 指定策略类型,支持两个属性。

  • deployment 默认就是滚动更新
strategy  #指定新的Pod替换旧的Pod的策略, 支持两个属性:
  type    #指定策略类型,支持两种策略
    Recreate  #在创建出新的Pod之前会先杀掉所有已存在的Pod
    RollingUpdate  #滚动更新,就是杀死一部分,就启动一部分,在更新过程中,存在两个版本Pod
------//如果配置了滚动更新,就需要配置下面的-----
  rollingUpdate   #当type为RollingUpdate时生效,用于为RollingUpdate设置参数,支持两个属性:
    maxUnavailable   #用来指定在升级过程中不可用Pod的最大数量,默认为25%。
    maxSurge       # 用来指定在升级过程中可以超过期望的Pod的最大数量,默认为25%

3.1 重建更新

重新编辑pc-deployment.yaml 文件,添加更新策略

sepc:
  strategy:  #策略
    type: Recreate   #重建更新

image-20221007192839311

进行升级版本测试验证

kubectl set image deployment pc-deployment -n dev nginx=nginx:latest
#将deployment下面的版本全部升级至最新

kubect get pods -n dev -w
#一开始先进行时实监控

image-20221007193550843

image-20221007193648281

3.2 滚动更新

重新编辑pc-deployment.yaml文件,添加滚动更新策略(这个为默认策略)

下面也可进行手动配置

spec:
  strategy:
    type: RollingUpdate
    rollingUpdate:
       maxSurge: 25%
       maxUnavailable: 25%

image-20221007194921819

升级版本测试

kubectl set image deployment pc-deployment nginx=nginx:latest -n dev
#升级新的版本

kubectl get pods -n dev -w
#提前时实监控

image-20221007194813390

image-20221007195159971

4、版本回退

当我们进行deployment版本升级时,因为它是操作replicaset控制器的,可以查看一下rs的变化。

image-20221007220205961

#为什么旧的RS依然存在呢?

//这就是deployment的特殊的功能,它管控这replicaset来进行版本回退的操作。

deployment支持版本升级过程中的暂停、继续功能以及版本回退等诸多功能,下面具体来看

kubectl rollout : 版本升级相关功能,支持下面的选项

  • status : 显示当前升级状态
  • history: 显示升级历史记录
  • pause: 暂停版本升级过程
  • resume: 继续已经暂停的版本升级过程
  • restart : 重启版本升级过程
  • undo: 回滚到上一级版本(可以使用 –to-revision 回滚到指定版本)

image-20221007220554349

版本回滚

kubectl rollout undo deployment pc-deployment -n dev
#返回到上一个版本

image-20221007221234073

kubectl rollout undo deployment pc-deployment -n dev --to-revision=3
#返回到指定的版本

image-20221007221831663

5、金丝雀发布

Deployment控制器支持控制更新过程中的控制,如“暂停(pause)”或“继续(resume)”更新操作。

比如有一批新的Pod资源创建完成后立即暂停更新过程,此时,仅存在一部分新版本的应用,主体部分还是旧的版本。然后,再筛选一小部分的用户请求路由到新版本的Pod应用,继续观察能否稳定地按期望的方式运行。确定没问题之后再继续完成余下的Pod资源滚动更新,否则立即回滚更新操作。这就是所谓的金丝雀发布。

升级,然后暂停

kubectl set image deployment pc-deployment nginx=nginx:1.17.2 -n dev && kubectl rollout pause deployment pc-deployment -n dev
#将版本升级至1.17.2版本,升级一个,然后暂停升级

kubectl rollout status deployment pc-deployment
#查看更新状态(新开一个终端,会占用前台)

//监控更新的过程,可以看到已经新增了一个资源,但是并未按照预期的状态去删除一个旧的资源,就是因为使用了pause暂停命令

kubectl get rs -n dev -o wide
#查看replicaset控制器的版本信息

image-20221007224230958

image-20221007224305866

新版本确认没问题,进行全部滚动升级

kubectl rollout resume deployment pc-deployment -n dev
#继续更新

kubectl get rs -n dev -owide
#查看replicaset的版本信息

image-20221007224807561

image-20221007224851248

6、删除deployment

kubectl delete deployment pc-deployment -n dev

或

kubectl delete -f pc-deployment 

##以上两种都可以删除
//删除deployment后,其下的rs和pod也被删除

image-20221007225337521

四、Horizontal Pod Autoscaler(HPA)

在kubernets中,我们可以对pod进行有效的扩容和缩容,但是所有的操作都是通过kuberctl scale 命令实现的,无法达到自动化的要求,kubernetes可以通过检测Pod的使用情况,实现Pod数量的自动调整,于是就产生了 Horizontal Pod Autoscaler(HPA)这种控制器。

HPA可以获取每个Pod的利用率,然后和HPA中定义的指标进行对比,同时计算出需要伸缩的具体值,最后实现Pod数量的调整,起始HPA与之前的Deployment一样,也是属于Kubernetes资源对象, 它通过追踪分析RC控制的所有目标Pod的负载变化情况,来确认是否需要针对性的调整Pod的副本数。这就是HPA的实现原理.

image-20221007234916237

1、安装metrics-server

  • metrics-server可以用来收集集群中的资源使用情况
yum -y install git
#下面git(用来从远程仓库克隆一个版本到本地)

git clone -b v0.3.6 https://github.com/kubernetes-incubator/metrics-server
#克隆版本v0.3.6到本地

cd metrics-server/deploy/1.8+/
vim metrics-server-deployment.yaml

hostNetwork: true   #24行后面,添加

image: registry.cn-hangzhou.aliyuncs.com/google_containers/metrics-server-amd64:v0.3.6   #33行,修改

args:   #34行后面,添加
- --kubelet-insecure-tls
- --kubelet-preferred-address-types=InternalIP,Hostname,InternalDNS,ExternalDNS,ExternalIP

image-20221007235338955

image-20221007235417525

image-20221007235906613

image-20221007235854195

kubectl apply -f ./
#安装metrics-server

kubectl get pod -n kube-system
#查看是否安装运行成功

kubectl top node
#查看资源使用情况

kubectl top pod -n kube-system

image-20221008000235469

image-20221008000426386

2、准备deployment和service

vim deployment-nginx.yaml

apiVersion: v1
kind: Deployment
metadata: 
  name: nginx
  namespace: dev
spec:
  selector:
    matchLabels:
      app: nginx-pod
  template:
    metadata:
      labels:
        app: nginx-pod
    spec:
      containers:
      - name: nginx
        image: nginx:1.17.1
        resources:
          limits:
            cpu: "1"
          requests:
            cpu: "100m"

image-20221008185412281

kubectl create -f deployment-nginx
#创建deplyment

kubectl expose deployment nginx --type=NodePort --port=80 -n dev
#创建service

kubectl get deployment,pod,svc -n dev
#查看个资源信息

image-20221008183417161

3、部署HPA

创建pc-hap.yaml 文件

apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
  name: pc-hpa
  namespace: dev
spec:
  minReplicas: 1      #最小pod数量
  maxReplicas: 10     #最大pod数量
  targetCPUUtilizationPercentage: 3 # CPU使用率指标
  scaleTargetRef:     # 指定要控制的nginx信息
    apiVersion: apps/v1
    kind: Deployment
    name: nginx

image-20221008194154962

4、测试

使用压测工具对service地址 20.0.0.55:32179 进行压测,然后通过控制台查看hpa和pod的变化

压测工具地址: https://zhuanlan.zhihu.com/p/41212281

#根据网站地址,进行安装postman,进行压测。

访问测试

image-20221008223220731

保存访问路径

image-20221008223307016

开始进行压测

image-20221008223343604

开始进行压测,压测到一定程度后,就关闭,查看hpa的监控数

image-20221008223435228

#下面进行监控各种资源,查看监控变化

查看hap的变化

image-20221008222605305

查看pod的变化

image-20221008222739515

查看deployment变化

image-20221008222913049

五、DaemonSet控制器(DS)

DaemonSet 类型的控制器可以保证在集群中的每一台(或指定)节点上都运行一个副本,一般适用于日志收集、节点监控等场景。 也就是说,如果一个Pod提供的功能时节点级别的(就是每个节点都需要且只需要一个),那么这类Pod就适合使用DaemonSet类型的控制器创建。

image-20221010154722042

DaemonSet控制器的特点:

  • 每当向集群中添加一个节点时,指定的Pod副本也将添加到该节点上。
  • 当节点从集群中移除时,Pod也就被垃圾回收了。

DaemonSet的资源清单

apiVersion: apps/v1    # 版本号
kind: DaemonSet        # 类型       
metadata:              # 元数据
  name:                # ds名称 
  namespace:           # 所属命名空间 
  labels:              #标签
    controller: daemonset
spec:                  # 详情描述
  revisionHistoryLimit: 3    # 保留历史版本
  updateStrategy:            # 更新策略
    type: RollingUpdate      # 滚动更新策略
    rollingUpdate:           # 滚动更新
      maxUnavailable: 1      # 最大不可用状态的 Pod 的最大值,可以为百分比,也可以为整数
  selector:           # 选择器,通过它指定该控制器管理哪些pod
    matchLabels:      # Labels匹配规则
      app: nginx-pod
    matchExpressions: # Expressions匹配规则
      - {
    
    key: app, operator: In, values: [nginx-pod]}
  template:    # 模板,当副本数量不足时,会根据下面的模板创建pod副本
    metadata:
      labels:
        app: nginx-pod
    spec:
      containers:
      - name: nginx
        image: nginx:1.17.1
        ports:
        - containerPort: 80

案例:

创建pc-daemonset.yaml 文件

apiVersion: apps/v1
kind: DaemonSet      
metadata:
  name: pc-daemonset
  namespace: dev
spec: 
  selector:
    matchLabels:
      app: nginx-pod
  template:
    metadata:
      labels:
        app: nginx-pod
    spec:
      containers:
      - name: nginx
        image: nginx:1.17.1

image-20221010161813612

下面创建pod,进行查看

kubectl create -f pc-daemonset.yaml

kubectl get ds -n dev -o wide

kubectl get pods -n dev -o wide

image-20221010160436857

六、Job控制器

job控制器主要负责批量处理(一次要处理指定数量任务) 短暂的一次性的任务。

也就是说,Job控制器就是相当于创建一个或多个pod。专门用来执行一次性的任务,执行完成之后,pod就会处于完成状态。

Job特点:

  • 当 Job 创建的Pod执行成功结束时,Job将记录成功结束的Pod数量
  • 当成功结束的Pod达到指定的数量时,Job将完成任务。

image-20221010160908120

Job的资源清单文件

apiVersion: batch/v1    # 版本号
kind: Job               # 类型       
metadata:               # 元数据
  name:                 # 名称 
  namespace:            # 所属命名空间 
  labels:               #标签
    controller: job
spec:                   # 详情描述
  completions: 1        # 指定job需要成功运行Pods的次数。默认值: 1 (就是说:pod成功运行的次数)
  parallelism: 1        # 指定job在任一时刻应该并发运行Pods的数量。默认值: 1(多少pod可以并行执行)
  activeDeadlineSeconds: 30     # 指定job可运行的时间期限,超过时间还未结束,系统将会尝试进行终止。
  backoffLimit: 6        # 指定job失败后进行重试的次数。默认是6
  manualSelector: true   # 是否可以使用selector选择器选择pod,默认是false
  selector:              # 选择器,通过它指定该控制器管理哪些pod
    matchLabels:         # Labels匹配规则
      app: counter-pod
    matchExpressions:    # Expressions匹配规则
      - {
    
    key: app, operator: In, values: [counter-pod]}
  template:              # 模板,当副本数量不足时,会根据下面的模板创建pod副本
    metadata:
      labels:
        app: counter-pod
    spec:
      restartPolicy: Never  # 重启策略只能设置为Never或者OnFailure
      containers:
      - name: counter
        image: busybox:1.30
        command: ["bin/sh","-c","for i in 9 8 7 6 5 4 3 2 1; do echo $i;sleep 2;done"]
        
------------------------------------------------------------------
#关于重启策略设置的说明:
如果指定为OnFailure,则job会在pod出现故障时重启容器,而不是创建pod,failed次数不变

如果指定为Never,则job会在pod出现故障时创建新的pod,并且故障pod不会消失,也不会重启,failed次数加1

如果指定为Always的话,就意味着一直重启,意味着job任务会重复去执行了,当然不对,所以不能设置为Always

案例:

创建pc-job.yaml

apiVersion: batch/v1
kind: Job      
metadata:
  name: pc-job
  namespace: dev
spec:
  manualSelector: true   #允许是使用标签
  selector:
    matchLabels:
      app: counter-pod
  template:
    metadata:
      labels:
        app: counter-pod
    spec:
      restartPolicy: Never
      containers:
      - name: counter
        image: busybox:1.30
        command: ["/bin/sh","-c","for i in 9 8 7 6 5 4 3 2 1; do echo $i;sleep 3;done"]
image-20221010163634250

下面创建pod查看执行结果

kubectl create -f pc-job.yaml
#创建pod

kubectl get job -n dev -o wide -w 
#提前监控job的资源

kubectl get pods -n dev -w 
#提前监控pod状态
image-20221010163024542 image-20221010163253480

下面修改Pod运行的总数量和并行数量

spec: 
  completions: 6
  parallelism: 3
  
然后重新运行job,观察效果,此时会发现,job会每次运行3个pod,总共运行6个pod
image-20221010171949559

下面创建并执行查看结果

image-20221010172402409 image-20221010213905252 image-20221010172604301

七、CronJob控制器(CJ)

CronJob 控制器以Job控制器资源为其管控对象,并借助它管理Pod资源对象,Job控制器定义的作业任务在其控制器资源创建之后便会立即执行,但是CronJob 可以以类似于Linux 操作系统的周期性任务作业计划的方式控制器运行的时间点及重复运行的方式。

也就是说,Crontab可以在特定的时间点(反复的)去运行Job任务。

image-20221010173128434

CronJab的资源清单文件

apiVersion: batch/v1beta1  # 版本号
kind: CronJob              # 类型       
metadata:                  # 元数据
  name:                    # CJ名称 
  namespace:               # 所属命名空间 
  labels:                  #标签
    controller: cronjob
spec:                       # 详情描述
  schedule:                 # cron格式的作业调度运行时间点,用于控制任务在什么时间执行
  concurrencyPolicy:           # 并发执行策略,用于定义前一次作业运行尚未完成时是否以及如何运行后一次的作业
  failedJobHistoryLimit:       # 为失败的任务执行保留的历史记录数,默认为1
  successfulJobHistoryLimit:   # 为成功的任务执行保留的历史记录数,默认为3
  startingDeadlineSeconds:     # 启动作业错误的超时时长
  jobTemplate:             # job控制器模板,用于为cronjob控制器生成job对象;下面其实就是job的定义
    metadata:
    spec:
      completions: 1
      parallelism: 1
      activeDeadlineSeconds: 30
      backoffLimit: 6
      manualSelector: true
      selector:
        matchLabels:
          app: counter-pod
        matchExpressions: 规则
          - {
    
    key: app, operator: In, values: [counter-pod]}
      template:
        metadata:
          labels:
            app: counter-pod
        spec:
          restartPolicy: Never 
          containers:
          - name: counter
            image: busybox:1.30
            command: ["bin/sh","-c","for i in 9 8 7 6 5 4 3 2 1; do echo $i;sleep 20;done"]
            
--------------------------------------------------------------
需要重点解释的几个选项:
schedule: cron表达式,用于指定任务的执行时间
    */1    *      *    *     *
    <分钟> <小时> <日> <月份> <星期>

    分钟: 值从 0 到 59.
    小时: 值从 0 到 23.
    : 值从 1 到 31.
    : 值从 1 到 12.
    星期: 值从 0 到 6, 0 代表星期日
    多个时间可以用逗号隔开; 范围可以用连字符给出;*可以作为通配符; /表示每...
    
concurrencyPolicy:
    Allow:   允许Jobs并发运行(默认)
    Forbid:  禁止并发运行,如果上一次运行尚未完成,则跳过下一次运行
    Replace: 替换,取消当前正在运行的作业并用新作业替换它

创建pc-cronjob.yaml 文件

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: pc-cronjob
  namespace: dev
  labels:
    controller: cronjob
spec:
  schedule: "*/1 * * * *"
  jobTemplate:
    metadata:
    spec:
      template:
        spec:
          restartPolicy: Never
          containers:
          - name: counter
            image: busybox:1.30
            command: ["bin/sh","-c","for i in 9 8 7 6 5 4 3 2 1; do echo $i;sleep 3;done"]

image-20221010215717923

下面进行创建pod,查看执行结果

kubectl create -f pc-cronjob.yaml

kubectl get cronjobs -n dev
#查看cronjob控制器

kubectl get jobs -n dev
#查看job控制器

kubectl get pods -n dev
#查看pod

image-20221010215823108

image-20221010215900441

image-20221010220004667

八、StatefulSet控制器

1、statefulset原理

部署有状态应用的控制器

  • 像前面所看到到控制器,比如ReplicaSet、Deployment、DaemonSet都是面向无状态的服务,他们所管理的Pod的IP、名字、启动顺序等都是随机的。

  • 而StatefulSet控制器是有状态的控制器,管理所有有状态的服务,比如mysql、mongodb等

##有状态服务和无状态服务怎么理解?

//无状态服务,也就是请求一次数据,没有上下文的关系,请求中包含所有需要的信息。例如:token令牌。

//有状态服务,他它会根据存储的内容上下文关联,需要依靠以前的数据来请求相应的数据内容,如http的session会话保持。

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

StatefulSet是为了解决有状态服务的问题(对应Deployments和ReplicaSets是为无状态服务而设计),其应用场景包括:

  • 稳定的持久化存储,即Pod重新调度后还是能访问到相同的持久化数据,基于PVC来实现稳
  • 定的网络标志,即Pod重新调度后其PodName和HostName不变,基于Headless Service(即没有Cluster IP的Service)来实现。
  • 有序部署,有序扩展,即Pod是有顺序的,在部署或者扩展的时候要依据定义的顺序依次进行(即从0到N-1,在下一个Pod运行之前所有之前的Pod必须都是Running和Ready状态),基于init containers来实现
  • 有序收缩,有序删除(即从N-1到0)

从上面的应用场景可以发现,statefulset由以下几个部分组成

  • Headless service: 无头服务,用于为pod资源标识符 生成可解析的DNS记录。
  • VolumeClaimTemplates: 存储卷的申请模板,基于静态或动态的pv供给方式,为pod资源提供专有的固定存储。
  • statefulset: 用于管控pod资源。

为什么要有headless service 无头服务?

  • 在用Deployment时,每一个Pod名称是没有顺序的,是随机字符串,因此是Pod名称是无序的,但是在statefulset中要求必须是有序 ,每一个pod不能被随意取代,pod重建后pod名称还是一样的。而pod IP是变化的,所以是以Pod名称来识别。pod名称是pod唯一性的标识符。

  • 为了实现标识符的稳定,这时候要用到无头服务,它可以给每个Pod一个唯一的名称 。

为什么需要volumeclaimtemplate?

  • 大部分有状态副本集都会用到持久存储,比如分布式系统来说,由于数据时不一样的,每个节点都需要自己专用的存储节点。而在deployment 中的pod模板中创建的存储卷是一个共享pod是不适应的,多个pod使用同一个存储卷,而statefulset定义中的每个pod都不能使用同一个存储卷,由此基于pod模板创建pod时不适应 的。

  • 这就需要引入volume Clain Template ,当在使用statefulset创建pod时,会自动生成一个PVC,从而请求绑定一个PV,从而请求绑定一个PV,从而有自己的专用的存储卷。

image-20221015203926464

2、创建statefulset控制器

目前服务器中已经创建好了storageclass 自动创建pv的功能。

下面进行创建statefulset控制器创建pod,在 volumeClaimTemplates 中定义好storageclass的名称,在创建statefulset后,它会自动创建pvc和pv。

vim statefulset.yaml

apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None     #不创建custerip,也就是无头服务的service
  selector:
    app: nginx
---
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   #10秒内pod没关闭,就强制杀死
      containers:
      - name: nginx
        image: nginx:1.14.1
        ports:
        - containerPort: 80
          name: web
        volumeMounts:   #容器内挂载
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:   #存储卷的申请模板
  - metadata:
      name: www
    spec:
      accessModes: [ "ReadWriteOnce" ]   #可读可写,仅能一个节点挂载
      storageClassName: "nfs-client-storageclass"  #使用动态创建的pv
      resources:   #设置请求的资源大小
        requests:
          storage: 2Gi

解析上面: 由于StatefulSet资源依赖于一个实现存在的Headless类型的Service资源,所以需要先定义一个名为nginx的Headless Service资源,用于为关联到每个Pod资源创建DNS资源记录。接着定义了一个名为web的StatefulSet资源,它通过Pod模板创建了3个Pod资源副本,并基于volumeClaimTemplates向存储类进行了请求大小为2Gi的专用存储卷。

下面开始创建

kubectl apply -f statefulset.yaml
#创建service和statefulset。

kubectl get pods -w 

kubectl get pvc -w 

kubectl get pv -w

image-20221015215941664

image-20221015220005922

image-20221015220038597

image-20221015220105457

3、扩缩容

kubectl scale statefulset web --replicas=5

kubectl scale statefulset web --replicas=2

image-20221015220819182

4、滚动更新

kubectl set image statefulset web nginx=nginx:1.17.1 
#升级版本

image-20221015221440015

九、总结

无状态:

  • deployment 认为所有的pod都是一样的
  • 不用考虑顺序的要求
  • 不用考虑在哪个node节点上运行
  • 可以随意扩容和缩容

有状态

  • 实例之间有差别,每个实例都有自己的独特性,元数据不同,例如etcd,zookeeper
  • 实例之间不对等的关系,以及依靠外部存储的应用。

常规service和无头服务区别
service: 一组Pod访问策略,提供cluster-IP群集之间通讯,还提供负载均衡和服务发现。
Headless service: 无头服务,不需要cluster-IP,而是直接以DNS记录的方式解析出被代理Pod的IP地址。

猜你喜欢

转载自blog.csdn.net/m0_57515995/article/details/127956564