Kubernetes(五) Pod控制器详解

Pod控制器详解

本章主要介绍Pod控制器的详细使用

 

1. Pod控制器介绍

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

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

 

什么是Pod控制器?

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

 

在kubernetes中,有很多种类型的pod控制器,每种都有它适合的场景,常见有:

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

 

2. ReplicaSet

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

 

ReplicaSet 如下图所示:

常规配置:

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name:
  namespace:
  labels:
     controller: rs
spec:
  replicas: 3                 #副本数量
  selector:                   #选择器,通过它指定控制器管理哪些 pod 
     matchLabels:
        app: nginx-pod
     matchExpressions:
        - {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

这里需要了解的配置就是spec下面的几个选项:

  • replicas:

指定副本数量,也就是当前rs创建出来的pod数量,默认为1

  • selector:

选择器,它的作用是建立pod控制器和pod之间的关联关系,采用的Label Selector机制。在pod模板上也需要定义label,这样在控制器上定义选择器,就可以表明当前控制器能管理哪些pod了

  • template:模板,当前控制器创建pod所使用的模板,里面是pod定义

 

部署

示例:

$ cat yamls/pc-replicaset.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: pc-replicaset
  namespace: dev
  labels:
     controller: rs
spec:
  replicas: 3                 #副本数量
  selector:
     matchLabels:
        app: nginx-pod
     matchExpressions:
        - {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

 

查看创建的rs:

$ kubectl get rs -n dev -o wide
NAME            DESIRED   CURRENT   READY   AGE    CONTAINERS   IMAGES         SELECTOR
pc-replicaset     3                    3               3       115s        nginx        nginx:1.17.1   app=nginx-pod,app in (nginx-pod)

 

扩缩容

有2种方法:

1. 直接编辑

$ kubectl edit rs -n dev
replicaset.apps/pc-replicaset edited

 

2. kubescale rs 命令

$ kubectl scale rs pc-replicaset --replicas=4 -n dev
replicaset.apps/pc-replicaset scaled

 

镜像版本升降级

同样

1. 直接编辑

$ kubectl edit rs -n dev
replicaset.apps/pc-replicaset edited

$ kubectl get rs pc-replicaset -n dev -o wide
NAME            DESIRED   CURRENT   READY   AGE     CONTAINERS   IMAGES         SELECTOR
pc-replicaset   4         4         4       5m39s   nginx        nginx:1.17.2   app=nginx-pod,app in (nginx-pod)

 

2. kubect set image 命令

$ kubectl set image rs pc-replicaset nginx=nginx:1.17.1 -n dev
replicaset.apps/pc-replicaset image updated

 

删除

使用kubectl delete 命令可以删除rs以及它管理的pod。Kubernetes在删除rs前,会将rs的replicascaler调整为0,等待所有pod被删除后,再执行rs对象的删除。

如果希望仅仅删除rs对象(保留pod),可以使用kubectl delete 命令时添加 --cascade=false(不推荐)

当然,删除yaml的形式也是可以的

 

3. Deployment

为了更好地解决服务编排的问题,kubernetes在V1.2 版本开始,引入了Deployment控制器。这种控制器并不直接管理pod,而是通过管理ReplicaSet来间接管理Pod。即:Deployment管理ReplicaSet,ReplicaSet管理Pod。所以Deployment比ReplicaSet功能更强大。

Deployment主要功能有:

  1. 支持ReplicaSet的所有功能
  2. 支持发布的停止、继续
  3. 支持版本滚动升级和版本回退

Deployment资源主要配置:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: 
  namespace:
  labels:
    controller: deploy
spec:
  replicas: 3
  revisionHistoryLimit: 3                      # 保留历史版本,默认为10
  paused: false                                       # 暂停部署,默认是false
  progressDeadlineSeconds: 600       # 部署超时时间(s),默认是600
  strategy:                                              # 策略
    type: RollingUpdate                         # 滚动更新策略
    rollingUpdate:                                  # 滚动更新
      maxSurge: 30%                               # 最大额外可以存在的副本数,可以为百分比或整数
      maxUnavailable: 30%                    # 最大不可用状态的Pod的最大值,可以为百分比或整数
  selector:
    matchLabels:
      app: nginx-pod
    matchExpressions:
      - {key: app, operator: In, values: [nginx-pod]}
  template:
    metadata:
      labels:
        app: nginx-pod
    spec:
      containers:
      - name: nginx
        image: nginx:1.17.1
        ports:
        - containerPort: 80
    

 

扩缩容

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

2. kubectl edit deploy pc-deployment -n dev

 

镜像更新

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

重建更新就是一次性删除所有老版本pod,然后重建。滚动就是先删一部分,启动一部分,中间状态是新版本与老版本pod均存在,最终只有新版本pod存在。

strategy:       # 指定新的pod替换旧pod的策略,支持2个属性
type:            # 支持2个属性
    Recreate:    # 在创建出新的Pod之前会kill掉所有已存在的pod
    RollingUpdate:     # 滚动更新,kill一部分启动一部分,在更新过程中,存在2个版本的pod
 rollingUpdate:     # 当type为RollingUpdate时生效,用于设置它的参数
     maxUnavailable:    # 用来指定在升级过程中不可用 Pod 的最大数量,默认为25%
     maxSurge:        # 用来指定在升级过程中可以超过期望的Pod的最大数量,默认为 25%

 

1. 重建更新

测试配置项:

$ cat yamls/pc-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
   name: pc-deployment
   namespace: dev
   labels:
      controller: deploy
spec:
   replicas: 3
   strategy:
      type: Recreate
   selector:
      matchLabels:
          app: nginx-pod
   template:
      metadata:
         labels:
            app: nginx-pod
      spec:
         containers:
         - name: nginx
           image: nginx:1.17.1
           ports:
           - containerPort: 80

 

变更镜像:

$ kubectl set image deployment pc-deployment nginx=nginx:1.17.2 -n dev
deployment.apps/pc-deployment image updated

$ kubectl get pods -n dev -o wide –w


NAME                             READY   STATUS    R
pc-deployment-7d7dd5499b-5wdlc   1/1     Running   0
pc-deployment-7d7dd5499b-czpzs   1/1     Running   0
pc-deployment-7d7dd5499b-dgvp5   1/1     Running   0
…
pc-deployment-7d7dd5499b-5wdlc   1/1     Terminating
pc-deployment-7d7dd5499b-dgvp5   1/1     Terminating
pc-deployment-7d7dd5499b-czpzs   1/1     Terminating
….
pc-deployment-7bbbd589d5-kkdcs   0/1     Pending    
pc-deployment-7bbbd589d5-kkdcs   0/1     Pending    
pc-deployment-7bbbd589d5-xtw4l   0/1     Pending    
…
pc-deployment-7bbbd589d5-kkdcs   0/1     ContainerCreating
pc-deployment-7bbbd589d5-xtw4l   0/1     ContainerCreating
pc-deployment-7bbbd589d5-ztfbw   0/1     ContainerCreating
…
pc-deployment-7bbbd589d5-xtw4l   1/1     Running    
pc-deployment-7bbbd589d5-ztfbw   1/1     Running    
pc-deployment-7bbbd589d5-kkdcs   1/1     Running    

从这个部署记录可以看到,recreate 的策略是一次性全部terminate,然后启动新版本pod

 

2. 滚动更新

更改配置:

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

 

变更 image 后打印的输出:

$ kubectl get pods -n dev -o wide -w
NAME                                                    READY   STATUS     
pc-deployment-866fdcbd54-9xwrb   0/1     Pending           
pc-deployment-866fdcbd54-9xwrb   0/1     Pending      
pc-deployment-866fdcbd54-9xwrb   0/1     ContainerCreating  
pc-deployment-866fdcbd54-9xwrb   1/1     Running            
pc-deployment-7bbbd589d5-xbnmw   1/1     Terminating        
pc-deployment-866fdcbd54-wjs8n   0/1     Pending            
pc-deployment-866fdcbd54-wjs8n   0/1     Pending            
pc-deployment-866fdcbd54-wjs8n   0/1     ContainerCreating  
pc-deployment-7bbbd589d5-xbnmw   0/1     Terminating        
pc-deployment-7bbbd589d5-xbnmw   0/1     Terminating        
pc-deployment-7bbbd589d5-xbnmw   0/1     Terminating        
pc-deployment-866fdcbd54-wjs8n   1/1     Running            
pc-deployment-7bbbd589d5-2cjvp   1/1     Terminating        
pc-deployment-866fdcbd54-ls9b8   0/1     Pending            
pc-deployment-866fdcbd54-ls9b8   0/1     Pending            
pc-deployment-866fdcbd54-ls9b8   0/1     ContainerCreating  
pc-deployment-7bbbd589d5-2cjvp   0/1     Terminating        
pc-deployment-866fdcbd54-ls9b8   1/1     Running            
pc-deployment-7bbbd589d5-f44sx   1/1     Terminating        
pc-deployment-7bbbd589d5-f44sx   0/1     Terminating        
pc-deployment-7bbbd589d5-2cjvp   0/1     Terminating        
pc-deployment-7bbbd589d5-2cjvp   0/1     Terminating        
pc-deployment-7bbbd589d5-f44sx   0/1     Terminating        
pc-deployment-7bbbd589d5-f44sx   0/1     Terminating        

可以看到在过程中是启动一个停止一个。

滚动更新其实是通过2ReplicaSet 完成的,新版本pod全在新的rs中启动。旧版本pod在旧rs中陆续关闭。旧版本的ReplicaSet 不会被删掉,这是为版本回退而做的设计。

查看rs数量,可以看到第二次实验有2rs

$ kubectl get rs -n dev
NAME                       DESIRED   CURRENT   READY   AGE
pc-deployment-7bbbd589d5   0         0         0       32m
pc-deployment-7d7dd5499b   0         0         0       32m
pc-deployment-866fdcbd54   3         3         3       30m

 

3. 版本回退

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

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

  • status:显示当前升级状态
  • history:显示升级历史记录
  • pause:暂停版本升级过程
  • resume:继续已经暂停的版本升级过程
  • restart:重启版本升级过程
  • undo:回滚到上一版本(可以使用--to-version回滚到指定版本)
#查看deployment 升级的当前状态
$ kubectl rollout status deploy pc-deployment -n dev
deployment "pc-deployment" successfully rolled out

# 查看版本升级历史
$ kubectl rollout history deploy pc-deployment -n dev
deployment.apps/pc-deployment
REVISION  CHANGE-CAUSE
1         <none>
2         <none>
3         <none>

这里change-cause为<none> 是因为我们在部署 deployment的时候未添加--record的选项

加上 kubectl apply -f yamls/pc-deployment.yaml --record 后再次尝试的结果:
$ kubectl rollout history deploy pc-deployment -n dev
deployment.apps/pc-deployment
REVISION  CHANGE-CAUSE
1         kubectl apply --filename=yamls/pc-deployment.yaml --record=true
2         kubectl apply --filename=yamls/pc-deployment.yaml --record=true

# 版本回退,若未指定版本号,默认回退到上一版本
$ kubectl rollout undo deploy pc-deployment -n dev
deployment.apps/pc-deployment rolled back

# 其实这个回退版本另一方面又是一个新版本(版本1 现在变为了版本4):
$ kubectl rollout history deploy pc-deployment -n dev
deployment.apps/pc-deployment
REVISION  CHANGE-CAUSE
2         kubectl apply --filename=yamls/pc-deployment.yaml --record=true
3         kubectl apply --filename=yamls/pc-deployment.yaml --record=true

 

金丝雀发布

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

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

# 更新deployment版本,并配置暂停deployment
$ kubectl set image deploy pc-deployment nginx=nginx:1.17.4 -n dev && kubectl rollout pause deployment pc-deployment -n dev
deployment.apps/pc-deployment image updated
deployment.apps/pc-deployment paused

# 查看 rs
$ kubectl get rs -n dev
NAME                       DESIRED   CURRENT   READY   AGE
pc-deployment-56f77b8695   1         1         1       18s
pc-deployment-7d7dd5499b   3         3         3       35m

可以看到老版本是仍有3个,新版本仅有1个

# 查看 deployment status
$ kubectl rollout status deploy pc-deployment -n dev
Waiting for deployment "pc-deployment" rollout to finish: 1 out of 3 new replicas have been updated...

后续可以将部分流量先导入到新的rs中进行测试,最终没有任何问题后,可以继续rollout的流程:
$ kubectl rollout resume deployment pc-deployment -n dev
deployment.apps/pc-deployment resumed

$ kubectl rollout status deploy pc-deployment -n dev
Waiting for deployment "pc-deployment" rollout to finish: 1 out of 3 new replicas have been updated...

Waiting for deployment spec update to be observed...
Waiting for deployment spec update to be observed...
Waiting for deployment "pc-deployment" rollout to finish: 1 out of 3 new replicas have been updated...
Waiting for deployment "pc-deployment" rollout to finish: 1 out of 3 new replicas have been updated...
Waiting for deployment "pc-deployment" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "pc-deployment" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "pc-deployment" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "pc-deployment" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "pc-deployment" rollout to finish: 1 old replicas are pending termination...
deployment "pc-deployment" successfully rolled out

 

4. Horizontal Pod AutoscalerHPA

前面都是通过kubectl scale进行的手动扩容,在生产中更多的是自动化扩展。通过HPA可以实现此续期。

HPA可以获取每个pod利用率,然后和HPA中定义的指标进行对比,同时计算需要伸缩的具体指,最后实现pod数量调整。

HPA与之前的Deployment一样,也属于一种kubernetes 资源对象,它通过追踪分析目标pod的负载变化情况,来确定是否需要针对性地调整目标pod的副本数。

4.1. 安装metrics-server

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

$ git clone -b v0.3.6 https://github.com/kubernetes-incubator/metrics-server
$ cd metrics-server/deploy/1.8+/

# 修改metrics-server-deployment.yaml 文件以下内容
    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-insecure-tls
        - --kubelet-preferred-address-types=InternalIP,Hostname,InternalDNS,ExternalDNS,ExternalIP

# 部署
kubectl apply -f ./

# 验证
$ kubectl get pods -n kube-system
metrics-server-5f55b696bd-xmgkp   1/1     Running   0          2m2s

 

部署完成后即可查看资源使用情况

# 查看资源使用情况
$ kubectl top node
NAME                                                                     CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%
ip-10-0-1-217.cn-north-1.compute.internal    51m                2%            657Mi                  19%
ip-10-0-2-30.cn-north-1.compute.internal      42m                2%            565Mi                  16%

 

4.2. 准备deploymentservice

# 创建deployment
$ kubectl get deploy,pod -n dev
NAME                        READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx-dep   1/1     1            1           61s

NAME                             READY   STATUS    RESTARTS   AGE
pod/nginx-dep-755c49cf64-9hrfn   1/1     Running   0          61s

# 准备service
$ kubectl expose deploy nginx-dep --type=NodePort --port 80 --target-port=80 -n dev
service/nginx-dep exposed

 

4.3. 部署HPA

$ cat yamls/pc-hpa.yaml
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
    name: pc-hpa
    namespace: dev
spec:
    minReplicas: 1
    maxReplicas: 10
    targetCPUUtilizationPercentage: 3       # 此处用3仅是为了测试
    scaleTargetRef:                                         # 指定要扩展的target deployment
        apiVersion: apps/v1
        kind: Deployment
        name: nginx-dep

# 部署后
$ kubectl get hpa -n dev
NAME     REFERENCE                       TARGETS        MINPODS   MAXPODS   REPLICAS   AGE
pc-hpa   Deployment/nginx-dep   <unknown>/3%   1               10                  0              11s

=> 这里 unknown 表示当前的使用情况,仍在计算中,需要等待一会儿出数据
$ kubectl get hpa -n dev
NAME     REFERENCE              TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
pc-hpa   Deployment/nginx-dep   0%/3%     1         10        1          21m

如果hpa一直报invalid metrics (1 invalid out of 1), first error is: failed to get cpu utilization: missing request for cpu,说明 deploy中没有配置 CPU requests。需要执行下面的命令:
kubectl patch deployment nginx-dep -p='{"spec":{"template":{"spec":{"containers":[{"name":"nginx","resources":{"requests":{"cpu":"200m"}}}]}}}}' -n dev

 

开始压测,并观察hpadeploy的结果:

$ kubectl get hpa -n dev -o wide -w
NAME     REFERENCE              TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
pc-hpa   Deployment/nginx-dep   0%/3%     1         10        1          32m
pc-hpa   Deployment/nginx-dep   3%/3%     1         10        1          32m
pc-hpa   Deployment/nginx-dep   9%/3%     1         10        1          33m

$ kubectl get deploy -n dev
NAME        READY   UP-TO-DATE   AVAILABLE   AGE
nginx-dep   3/3     3            3           51m

# 停掉一段时间后
$ kubectl get deploy -n dev
NAME        READY   UP-TO-DATE   AVAILABLE   AGE
nginx-dep   1/1     1            1           63m

 

5. DaemonSet

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

DaemonSet控制器的特点:

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

 

6. Job

Job主要用于负责批量处理(一次处理多个任务)、短暂的、一次性任务。有以下2个特点:

  1. 当job创建的pod执行成功结束时,job将记录成功结束后的pod数量
  2. 当成功结束的pod达到指定的数量时,job将完成执行

 

主要属性有:

spec:
  completions: 1                          # 指定job需要成功运行Pods的数量。默认为1
  parallelism: 1                            # 指定job在任一时刻应该并发运行Pods的数量
  activeDeadlineSeconds: 30    # job可运行的时间期限,若是超时仍未结束,则系统会尝试终止
  backoffLimit: 6                          # job失败后重试次数,默认为6 
  manualSelector: true              # 是否使用selector选择器选择pod,默认false
  selector:                        
    matchLabels:
    app: counter-pod
    matchExpressions:
      - {key: app, operator: In, values: [counter-pod]}

 

7. CronJobCJ

Cronjob控制器以Job控制器资源为其管控对象,并借助它管理pod资源对象,Job控制器定义的作业任务在其控制器资源创建之后便立即执行。但CronJob可以以类似于Linux操作系统的方式实现周期性地在某时间点运行。

主要属性有:

spec:
  schedule:                                        # cron格式的作业调度运行时间点,控制任务什么时间执行
    concurrencyPolicy:                     # 并发执行策略,定义前一次作业未完成时是否运行后一次
    failedJobHistoryLimit:                # 为失败的任务执行那个保留的历史记录数,默认为1
    successfulJobHistoryLimit:        # 为成功的任务执行保留的历史记录数,默认为3
    startingDeadlineSeconds:         # 启动作业错误的超时时长
    jobTemplate:                               # job控制器模板,用于为cronjob控制器生成job对象
      metadata:
        spec:
          completions: 1
          parallelism: 1
          activeDeadlineSeconds: 30
          ...
          template:
            metadata:
              labels:
                app: counter-pod
            spec:
              restartPolicy: Never
            containers:
            - name: counter
              ...
      

 

 

posted @ 2021-03-13 13:45  ZacksTang  阅读(629)  评论(0编辑  收藏  举报