pod 控制器

在K8s 中,按照pod 的创建方式,可以将其分为两类:

  • 自主式pod : K8s 直接创建出来的pod,这种pod 删除了也就没有了,也不会重建。
  • 控制器创建的pod : 通过控制器创建的pod,这种pod 删除了之后还会自动重建。

什么是pod 控制器

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

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

  • ReplicationController : 比较原始的pod 控制器,已被废弃,由ReplicaSet 替代
  • ReplicaSet : 保证指定数量的pod 运行,并支持pod 数量变更,镜像版本变更。
  • Deployment: 通过控制ReplicaSet 来控制pod,并支持滚动升级,版本回退。
  • Horizontal Pod Autoscaler : 可以根据负载自动调节pod 数量,实现削峰填谷
  • DaemonSet: 在集群中指定Node上 都运行一个副本,一般用于守护进程类任务
  • Job: 它创建出的pod 只要完成任务就立即退出,用于执行一次性任务。
  • Cronjob: 它创建的pod 会周期性执行,用于执行周期性任务。
  • StatefulSet : 管理有状态的应用。
ReplicaSet(RS)

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

在这里插入图片描述

RelocaSet 的资源清单文件

在这里插入图片描述

apiVersion: v1
kind: ReplicaSet
metadata:
  name: pod-podaffinity-target
  namespace: dev  
spec:
  containers:
  -  name: nginx
     image: nginx:1.17.1
  affinity: #亲和性设置
    nodeAffinity: # 设置node 亲和性
      requiredDuringSchedulingIgnoredDuringExecution: #硬限制
      - labelSelector:
          matchExpressions: #匹配env的值在["pro","yyy"中的标签
          - key: podenv
            operator: In
            values: ["pro","yyy"]
         topologyKey:  kubernetes.io/hostname  
Deployment

为了更好的解决服务编排的问题, K8s 从V1.2 版本开始引进了Deployment 控制器,但是Deploument 控制器并不直接管理pod,而是通过管理ReplicaSet 来间接管理pod,Deployment 比ReplicaSet 功能更加强大。

在这里插入图片描述

Deployment 主要功能有下面几个:

  • 支持Replicate 的所有功能
  • 支持发布的停止,继续
  • 支持版本滚动升级和版本回退

Deployment 的资源清单文件:

整体的资源清单:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bBUBN3s4-1638588064560)(D:\java workstation\笔记\浪潮\images\image-20211126193712268.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mV6GhOZM-1638588064562)(D:\java workstation\笔记\浪潮\images\image-20211126193512798.png)]

第一部分,Deployment 自己的一部分信息。

在这里插入图片描述

revisionHistoryLimit: Deployment 是支持镜像更新的,每更新一次就产生一个版本。revisionHistoryLimit 来记录保留的版本的次数,保留版本是为了进行版本的回退。

在这里插入图片描述

控制的pod 的信息。

创建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

使用命令

 kubectl create -f pc-deployment.yaml --record=true

在这里插入图片描述

kubectl get deploy -n dev -o wide
查看启动的deploy 容器

在这里插入图片描述

UP-TO-DATE : 最新版本的pod 数量

AVAILABLE: 当前可用的pod 数量

使用命令查看deployment 对应的rs

 kubectl get rs -n dev -o wide

在这里插入图片描述

rs 的名字是在原来的deployment 名字之后添加一个随机串

查看pod

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-waw4sghe-1638588064586)(D:\java workstation\笔记\浪潮\images\image-20211126200435796.png)]

发现pod 的名字就是在rs 名字之后再加上一个随机串。

deployment 扩缩容

目前有三个pod 在运行,调整成5个:

1 使用下列命令:

kubectl scale deploy pc-deployment --replicas=5 -n dev

在这里插入图片描述

新增到5个pod

2 编辑deployment 实现

kubectl  edit deploy pc-deployment -n dev

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0OPakCWb-1638588064591)(D:\java workstation\笔记\浪潮\images\image-20211126201618266.png)]

使用命令replicas 变为了5,将其改为3,保存退出。(一保存就会调整)

在这里插入图片描述

变为3个

deployment 镜像更新

Deployment 支持两种镜像更新策略: 重建更新滚动更新(默认),可以通过stragety选项进行配置。

在这里插入图片描述

重建更新

一次性删掉所有老版本的pod , 然后立即重建同等数量新版本的pod 。

1 编辑pc-deployment.yaml,在spce 节点下添加更新策略

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

进行应用

 kubectl apply -f pc-deployment.yaml

启动另外一个中断进行监视,使用命令:

kubectl get pods -n dev -w

在这里插入图片描述

进行镜像的变更的命令

kubectl set image deploy pc-deployment  nginx=nginx:1.17.2 -n dev

结果:

在这里插入图片描述

可以所有pod 都是在一起行动,先Terminating-> Pending-> CointainerCreating -> Runing

滚动更新

先杀掉一部分老版本的pod,就启动一部分,在更新过程中,存在两个版本的pod。

滚动更新

spec:
  strategy: # 策略
    type: RollingUpdate # 滚动重建更新策略
    rollingUpdate:
      maxUnavailable: 25%
      maxSurge: 25%
apiVersion: apps/v1
kind: Deployment
metadata:
  name: pc-deployment
  namespace: dev
spec:
  strategy: # 策略
    type: RollingUpdate # 滚动重建更新策略
    rollingUpdate:
      maxUnavailable: 25%
      maxSurge: 25%
  replicas: 3
  selector:
    matchLabels:
      app: nginx-pod
  template:
    metadata:
      labels:
        app: nginx-pod
    spec:
      containers:
      - name: nginx
        image: nginx:1.17.1

剩下操作与重建更新一致

运行结果

观察先启动新的,然后再关闭旧的,只操作一部分。

deployment版本回退

删除之前的的pc-deployment

kubectl delete -f pc-deployment.yaml

重新创建

kubectl create -f pc-deployment.yaml --record

–record 会记录整个deploy 的更新过程

启动两个监听窗口去监听Pod 和RS 的更新操作

kubectl get rs -n dev -w
kubectl get pods -n dev -w 

镜像更新

kubectl set image deploy pc-deployment   nginx=nginx:1.17.2 (容器名=镜像版本) -n dev

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

可以看到新创建的RS 和之前的是不一样的。
在这里插入图片描述

可以看到老的RS 中没有了Pod。 老RS没有被删除的原因在于要用老RS 进行版本的回退

在这里插入图片描述

deployment 支持版本升级过程中的暂停,继续功能,以及版本回退等功能。

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

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

1 查看指定deploy升级的状态:

kubectl rollout  status deploy pc-deployment -n dev

在这里插入图片描述

2 查看指定 deploy 升级的历史:

kubectl rollout  history deploy pc-deployment -n dev

在这里插入图片描述

3 版本进行回退

kubectl rollout  undo  deploy pc-deployment --to-revision=1 -n dev

回退到1 版本

在这里插入图片描述

在这里插入图片描述

可以看到nginx 的版本回退到了1.17.1 版本

金丝雀发布

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

金丝雀发布: 一批新Pod 资源创建之后,立即暂停。 筛选一小部分请求路由到新版本的Pod 应用上。观察是否能够正常相应。如果不正常进行回退,正常继续更新操作。

发布一个点,没有问题才继续发布

1 更新版本,并配置暂停deployment

kubectl set image deploy pc-deployment nginx=nginx:1.17.4 -n dev && kubectl rollout pause deployment pc-deployment -n dev

在这里插入图片描述

2 观察更新状态

kubectl rollout status deploy pc-deployment -n dev

在这里插入图片描述

有三个需要更新,现在已经更新了一个了。

在这里插入图片描述

3 没有问题,继续更新

kubectl rollout resume deploy pc-deployment -n dev

4 有问题进行回退

kubectl rollout  undo  deploy pc-deployment --to-revision=1 -n dev
Horizontal Pod Autoscaler (HPA)

之前,我们可以通过手工执行 kubectl scale 实现pod 扩容,但这不符合K8s 的定位目标–自动化,智能化。K8s 期望监控Pod 的使用情况,实现pod 数量的自动调整。于是就产生了HPA 这种控制器。

HPA 可以获取每个Pod 的利用率,然后和HPA 中定义的指标进行对比。同时计算出需要伸缩的具体值。最后实现Pod 数量的调整。HPA 通过追踪分析目标的pod 的负载变化情况,来确定是否需要针对性地调整目标pod 的副本数。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R0iMV1lT-1638588064717)(D:\java workstation\笔记\浪潮\images\image-20211202215651867.png)]

1 安装 metrics-server

metrics-server 用来收集集群中资源的使用情况

1 安装git

apt install git

2 获取metrics-server

git clone -b v0.3.6 https://github.com/kubernetes-incubator/metrics-server

3 修改 deployment,修改镜像和初始化参数

cd metrics-server/deploy/1.8+

vim metrics-server-deployment.yaml

在这里插入图片描述

添加hostNetwork 为true,调整仓库的位置。

调整镜像参数为阿里云

registry.cn-hangzhou.aliyuncs.com/google_containers/metrics-server-amd64:v0.3.6  

增加启动参数

- --kubelet-preferred-address types=InternalIP,Hostname,InternalDNS,ExternalDNS,ExternalIP            

- --kubelet-insecure-tls  
---
apiVersion: v1
kind: ServiceAccount
metadata:
 name: metrics-server
 namespace: kube-system
---
apiVersion: apps/v1
kind: Deployment
metadata:
 name: metrics-server
 namespace: kube-system
 labels:
   k8s-app: metrics-server
spec:
 selector:
   matchLabels:
     k8s-app: metrics-server
 template:
   metadata:
     name: metrics-server
     labels:
       k8s-app: metrics-server
   spec:
     hostNetwork: true
     serviceAccountName: metrics-server
     volumes:
       # mount in tmp so we can safely use from-scratch images and/or read-only containers
       - name: tmp-dir
         emptyDir: {}
     containers:
       - name: metrics-server
         image: registry.cn-hangzhou.aliyuncs.com/google_containers/metrics-server-amd64:v0.3.6
         imagePullPolicy: Always
         volumeMounts:
           - name: tmp-dir
             mountPath: /tmp
         args:
         - --kubelet-preferred-address-types=InternalIP,Hostname,InternalDNS,ExternalDNS,ExternalIP
         - --kubelet-insecure-tls

4 使用apply 部署当前文件下的所有yaml

​ kubectl apply -f ./

在这里插入图片描述

5 查看pod 的运行状态

kubectl get pod -n kube-system

6 使用 kubectl top 资源 查看资源使用情况

​ 查看pod 资源: kubectl top pod

在这里插入图片描述

2 准备deployment 和service

1 创建deployment

kubectl create nginx1 --image=nginx:1.17.1 --requests=cpu=100m -n dev

2 创建service

kubectl expose pod nginx --type=NodePort  --port=80 -n dev

在这里插入图片描述

3 部署HPA

创建pc-hpa.yaml

apiVersion: autoscaling/v1 #固定的,可以查看
kind: HorizontalPodAutoscaler
metadata:
  name: pc-hpa
  namespace: dev
spec:
  minReplicas: 1 #最小pod数
  maxReplicas: 10 #最大pod 数
  targetCPUUtilizationPercentage: 3 #cpu 使用率指标 3 代表百分之三
  scaleTargetRef: # 指定要控制的nginx 信息
    apiVersion: apps/v1
    kind: Deployment
    name: nginx

在这里插入图片描述

查看hpa:

	kubectl get hpa -n dev

在这里插入图片描述

开启两个窗口监听pod 和hpa

kubectl get pod -n dev -w

kubectl get hpa -n dev -w

快速发送一万条请求,查看变换。

for i in {1..10000}; do curl 172.17.0.51:31964; done

pod 数量随着cpu 的使用率上升而增加。

DaemonSet(DS):

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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LJHgpaau-1638588064739)(D:\java workstation\笔记\浪潮\images\image-20211202221215767.png)]

DaemonSet 控制器特点

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

Job 主要用于负责批量处理(一次要处理指定数量的任务)短暂的一次性任务,Job 特点如下:

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

Job 控制器创建的pod 运行一次后就停止。

在这里插入图片描述

Job 资源清单

apiVersion: batch/v1
kind: Job
metadata: 
  name:
  namespace:
  labels:
    controller: job
spec:
  completions: 1  #指定job需要成功运行pods的次数,默认值为1
  parallelism: 1  #指定job在任一时刻应该并发运行pods的数量,默认值为1
  activeDeadlineSeconds: 30  #指定job可运行的时间期限,超过时间还未结束,系统将会尝试进行终止
  backoffLimit: 6  #指定job失败后进行重试的次数,默认值是6
  manualSelector: true  #是否可以使用selector选择器选择pod,默认是false
  selector: #选择器,通过它指定该控制器管理哪些pod
    matchLabels:  #Labels匹配规则
      app: counter-pod
    matchExpressions:  #Expression匹配规则
      - {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次数加一
  • 如果指定为Always,就意味着一直重启,意味着job任务会重复去执行,当然不对,所以不能设置为Always

创建pc-job.yaml 文件

apiVersion: batch/v1
kind: Job
metadata: 
  name: pc-job
  namespace: dev
spec:
  completions: 6  #指定job需要成功运行pods的次数,默认值为1
  parallelism: 3  #指定job在任一时刻应该并发运行pods的数量,默认值为1
  manualSelector: true  #是否可以使用selector选择器选择pod,默认是false
  selector: #选择器,通过它指定该控制器管理哪些pod
    matchLabels:  #Labels匹配规则
      app: 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 3;done"]

在这里插入图片描述

COMPLETIONS : 1(任务成功执行的数量)/1(总的任务数量)

completions: 6 #指定6个pod 运行comand 中的命令
parallelism: 3 # 每次最多有3个pod 在同时运行

一个 comand 命令会运行30秒

在这里插入图片描述

可以看到最后运行了60秒

Cronjob(CJ)

Cronjob 控制器以job 控制器资源为其管控对象,并凭借它管理pod 资源对象。Job 控制器定义的作业任务在其控制器资源创建之后就会立即执行,但Cronjob 类似与Linux 操作系统的周期性任务作业计划的方式去控制其运行时间点及重复运行的方式,也就是说Cronjob 可以在特定的时间点(反复的)去运行job 任务。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WLLRY7hd-1638588064780)(D:\java workstation\笔记\浪潮\images\image-20211204094220990.png)]

Cronjob 资源清单

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name:
  namespace:
  labels:
    controller: cronjob
spec:
  schedule: #cron格式的作业调度运行时间点,用于控制任务在什么时间执行
  concurrencyPolicy: #并发执行策略,用于定义前一次作业运行尚未完成时是否以及如何运行后一次的作业
  failedJobHistoryLimit: #为失败的任务执行保留的历史记录数,默认为1
  successfulJobHistoryLimit: #为成功的任务执行保留的历史记录数,默认为3
  startingDeadlineSeconds: #启动作业错误的超时时长
  jobTemplate: #job控制器模板,用于为cronjob控制器生成job对象,下面其实就是job的定义
    metadata:
    spec:
      completions: 1  #指定job需要成功运行pods的次数,默认值为1
      parallelism: 1  #指定job在任一时刻应该并发运行pods的数量,默认值为1
      activeDeadlineSeconds: 30  #指定job可运行的时间期限,超过时间还未结束,系统将会尝试进行终止
      backoffLimit: 6  #指定job失败后进行重试的次数,默认值是6
      manualSelector: true  #是否可以使用selector选择器选择pod,默认是false
      selector: #选择器,通过它指定该控制器管理哪些pod
        matchLabels:  #Labels匹配规则
          app: counter-pod
        matchExpressions:  #Expression匹配规则
          - {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"]

Cronjob 是通过Job 来控制管理pod 的。

在这里插入图片描述

创建 pc-cronjob.yaml 内容如下

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: pc-cronjob
  namespace: dev
  labels:
    controller: cronjob
spec:
  schedule: "*/1 * * * *"  #表明每一分钟都会执行这个任务
  jobTemplate: #job控制器模板,用于为cronjob控制器生成job对象,下面其实就是job的定义
    metadata:
    spec:
      template:  #模板,当副本数量不足时,会根据下面的模板创建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 3;done"]

在这里插入图片描述

每分钟运行一次。

在这里插入图片描述

StatefulSet

RS,Deployment ,DaemonSet 都是面向无状态的服务,它们所管理的Pod 的IP,名字,启动顺序都是随机的,StatfulSet 是一种给Pod 提供唯一标志的控制器,它可以保证部署和扩展的顺序。

在StatefulSet中,Pod名字称为网络标识(hostname),还必须要用到共享存储。

StatefulSet 解决问题

1 Pod 之间并非相同的副本,每个Pod 有一个独立标识

2 Pod 独立标识能够对应一个固定的网络标识,并在发布升级后继续保持

3 每个Pod 有一块独立的存储盘,并且发布升级后还能继续挂载原有的盘(保留数据)

4 应用发布时,按照固定顺序升级Pod

Stateless: 无需将它的状态持久化到容器或本地存储

Stateful: 有状态的运行环境,需要将运行过程中的数据持久化到本地pod 对应的Volume 中,

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GXXzipqY-1638588064788)(D:\java workstation\笔记\浪潮\images\image-20211204104138408.png)]

有很多应用 mysql, mongdb,redis 可以在K8s 的集群中去运行。

2 特点

Pod一致性:包含次序(启动、停止次序)、网络一致性。此一致性与Pod相关,与被调度到哪个node节点无关;
稳定的次序:对于N个副本的StatefulSet,每个Pod都在[0,N)的范围内分配一个数字序号,且是唯一的;
稳定的网络:Pod的hostname模式为( s t a t e f u l s e t 名 称 ) − (statefulset名称)-(statefulset名称)−(序号);
稳定的存储:通过VolumeClaimTemplate为每个Pod创建一个PV。删除、减少副本,不会删除相关的卷。

3 组成部分

Headless Service:用来定义Pod网络标识( DNS domain);
volumeClaimTemplates :存储卷申请模板,创建PVC,指定pvc名称大小,将自动创建pvc,且pvc必须由存储类供应;
StatefulSet :定义具体应用,名为Nginx,有三个Pod副本,并为每个Pod定义了一个域名部署statefulset。

Redis 的StatefulSet 案例

创建 redis-sfs.yaml

apiVersion: apps/v1
kind: StatefulSet  # 类型为 statefulset
metadata:
  name: redis-sfs  # app 名称
spec:
  serviceName: redis-sfs  # 这里的 service 下面解释
  replicas: 2      # 定义了两个副本
  selector:
    matchLabels:
      app: redis-sfs
  template:
    metadata:
      labels:
        app: redis-sfs
    spec:
      containers:
      - name: redis-sfs 
        image: redis  # 镜像版本
        command:
          - bash
          - "-c"
          - |
            set -ex
            ordinal=`hostname | awk -F '-' '{print $NF}'`   # 使用 hostname 获取序列
            if [[ $ordinal -eq 0 ]]; then     # 如果是 0,作为主
              echo > /tmp/redis.conf
            else
              echo "slaveof redis-sfs-0.redis-sfs 6379" > /tmp/redis.conf # 如果是 1,作为备
            fi
            redis-server /tmp/redis.conf

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t5tDaEEP-1638588064791)(D:\java workstation\笔记\浪潮\images\image-20211204111404508.png)]

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐