傲视Kubernetes(六):Pod管理及控制器

本文主要内容:

1、Kubernetes如何管理Pod?

2、Kubernetes Control Plane组件有哪几种?作用效果是什么?

一、Kubernetes如何管理Pod

Kubernetes中的Pod根据创建方式的不同,可以分为两种:一种是直接创建的Pod,比如自己写了一个Pod的yaml文件,通过kubectl create命令创建的Pod;一种是通过控制器,也就是Control Plane创建的Pod。

对于第一种Pod,也就是自己创建的Pod,创建完成之后由它所在的Node节点上的Kubelet管理。第二种Pod由控制器Control Plane管理。

Kubelet管理Pod

Kubelet管理Pod的手段很简单,就是重启大法。每个Pod创建时,都可以给配置存活探针,如下所示,创建Pod之后Kubernetes会每隔一段时间调用一次这个存活探针,也就是请求,如果执行失败或者没有响应,Kubelet则重启Pod

...
spec:
  containers:
  -  image:xxx
     livenessProbe:
       httpGet: /
       port: 8080

Kubernetes提供了三种探针类型,上面示例中的是httpGet(返回的状态码是2xx或3xx则会被认定成功),还有两种是TCP套接字探针和Exec探针。常用的一般都是HttpGet类型。

注意,如果不设置存活探针,kubelet只会根据容器进程是否存在来判断进程是否健康,也就是没有了健康检查应有的效果(因为比如OOM这样的异常发生时,JVM进程仍然运行),所以存活探针基本是一个必须的配置项。

在存活探针的配置项livenessProbe的同一级,还可以配置探针的其他属性,比如delay、timeout、period等,还有一个参数叫初始延迟initialDelaySeconds一般来说也需要配置上。如果不配置初始延迟参数,探针将在容器启动时就探测容器,这很容易失败,因为应用还没完成启动。配置这个参数就能有效避免这种情况的发生。

到此为止,都是在讲Pod出异常之后的重启处理,但如果Pod所在的Node节点出异常导致宕机呢?此时Node节点上的kubelet也就挂了,从而那些我们自己创建的依赖于Kubelet管理的Pod也就彻底GG了。

遇到这种情况该怎么办呢?这时候Kubernetes Control Plane就可以发挥作用了。

Control Plane管理Pod

 Kubernetes的控制器,也就是Control Plane组件,有很多种,比如ReplicationController、ReplicationSet、DaemonSet、Job等。

在创建这些控制器的时候,会指定对应非副本数,控制器创建完成之后就会检测实际运行的pod数是否跟副本数一致,如果实际运行的少了(Pod出异常挂掉了或者Pod所在的节点挂了),控制器会根据配置的模板创建新的Pod;如果实际运行的多了,则会删掉多余的Pod。总之控制器会控制实际运行的Pod数与配置的副本数目一致

当然,如果这些控制器所属Pod的探针存活检测异常,还是由Pod所在节点的kubelet来重启容器。即kubelet负责重启,控制器负责创建/删除

二、Kubernetes Control Plane的组件有哪些?作用各是什么?

下面分别对五种Control Plane的作用进行说明,其实除此之外还有两种最常用的Deployment和StatefulSet,这两种会在后面着重学习。

1、ReplicationController

ReplicationController顾名思义,副本的控制器。它主要由三部分组成: 标签选择器(label selector)、副本个数(replica count)、pod模板(pod template)。ReplicationController的yaml配置示例如下:

apiVersion: v1
kind: ReplicationController
metadata:
   name: kubia
spec:
   replicas: 3  # 副本数
   selector:  # 标签选择器
      app: kubia
   template: # pod模板
      metadata:
         labels:
            app: kubia
      spec:
         containers:
         -  name: kubia
            image: xxx/kubia
            port:
            -  containerPort:8080

标签选择器用户查询并监控所有拥有这个标签的Pod;而副本数则用户控制跟标签选择器匹配上的Pod的数量;如果Pod数量少于副本数,则会按照Pod模板创建新的Pod。所以这里的标签选择器必须要与pod模板中的标签一致,当然也可以不指定标签选择器,此时会默认按照pod模板中的标签来选择。

从上面就可以知道很重要的一点:Kubernetes是通过标签与标签选择器实现的控制器与Pod的归属关系

具体操作的指令如下,很多操作跟操作其他对象没什么差别:

kubectl create -f kubia-rc.yaml  # 根据yaml文件创建ReplicationController

kubectl get rc   # 查看ReplicationController

kubectl delete pod kubia-xxx # 删掉一个pod后再用get pod会看到正在创建新pod

kubectl delete rc kubia # 删除kubia这个rc,此时连它所对应的Pod也都会被删掉

kubectl delete rc kubia --cascade=false # 删除kubia这个rc,但它所对应的Pod会被保留下来 kubectl describe rc kubia # 查看ReplicationController的详细信息

kubectl label pod kubia-xxx app=kulet --overwrite # 改变pod的标签,此时rs会创建一个新Pod来达到3个的副本数

kubectl get pods -L app # 查看pod的标签

kubectl edit rc kubia # 进入修改名为kubia的rc的页面,修改后会立即生效,如果改了pod模板,只会对从此以后新创建的pod有效,不会影响已有pod

kubectl scale rc kubia --replicas=4 # 将副本数置为4,此时如果实际pod数少了则会新建

注意,如果是一个Node节点不可用导致的Pod失效,Kubernetes会等待一段时间(几分钟)来等待Node的恢复,如果几分钟后仍未恢复,才会创建新Pod来代替之前失效的Pod。

 

2、ReplicationSet

 ReplicationSet是ReplicationController的升级版,前者rs拥有rc所有的功能,而且还有更富表达力的标签选择器,所以后者现在完全可以弃之不用。

ReplicationSet的yaml示例:

apiVersion: apps/v1beta2
kind: ReplicationSet
metadata:
   name: kubia
spec:
   replicas: 3  # 副本数
   selector:  # 标签选择器
      matchLabels:
         app: kubia
   template: # pod模板
      metadata:
         labels:
            app: kubia
      spec:
         containers:
         -  name: kubia
            image: xxx/kubia
            port:
            -  containerPort:8080

对比ReplicationController可以看到有两处有区别:一是apiVersion不再是v1了(此处的apps是api组,后面的v1beta2是实际的api版本),二是选择器那里中间又加了一级matchLabels。

上面所有对ReplicationController的指令都可以用于ReplicationSet,只需将rc替换为rs即可。

 下面着重看看ReplicationSet对于标签选择器的升级:

1)、matchLabels

具体用法已经在上面的yaml示例中体现了,它的作用跟ReplicationController中的标签选择器相同,即完全匹配key和value(允许有其他的标签)。

2)matchExpressions

使用方式如下:

selector:
   matchExpressions:
     - key: app 
       operator: In
       values:
         - kubia   # 表示标签的值必须是kubia

matchExpressions下面必须有key和operator标签,而value标签有还是无取决于operator的值。operator有如下几种:

In: 此时需要有values标签,表示pod必须有与其中一个指定的values匹配的标签

NotIn:此时需要有values标签,表示pod必须的标签与任何指定的values不匹配

Exists:不需要values标签,表示pod必须包含指定key的标签,不关注value

DoesNotExist:不需要values标签,表示pod不得包含有指定key的标签

需要注意的是,selector下面可以指定多个标签表达式,即matchLabels和matchExpressions可以有一个也可以有多个也可以混合,此时这多个match的关系是与的关系,即都为true的pod才满足要求。一般不建议设置多个。

 

3、DaemonSet

 该控制器可以达到一种效果,即在每个Node节点上创建一个Pod。如果Node有增加或减少,相应的Pod也增加减少。DaemonSet的yaml配置如下所示:

apiVersion: apps/v1beta2
kind: DaemonSet
metadata:
   name: kubia-monitor
spec:
   selector:  # 标签选择器
      matchLabels:
         app: kubia-monitor
   template: # pod模板
      metadata:
         labels:
            app: kubia-monitor
      spec:
         nodeSelector: # 节点选择器
            disk: ssd
         containers:
         -  name: kubia-monitor
            image: xxx/kubia-monitor
            port:
            -  containerPort:8080

可以看到,DaemonSet不需要设置副本数,因为每个Node节点只有一个Pod。在上面的配置中,还多了一个节点选择器nodeSelector,它是用于控制只在满足节点选择器的节点上创建Pod,即对节点做一个过滤。注意,DaemonSet对Pod的创建是绕过了调度器的,所以即使对节点设置了不可调度,只要满足DaemonSet的节点选择器,则仍然可以在上面创建一个Pod

对DaemonSet的create、get、describe、delete等操作与其他控制器相同,就不在此赘述了,只需将对应的描述改成ds即可。

 

4、Job

上面介绍的三种控制器都是启动后一直运行的,而Job是用于执行一次性任务的,执行完之后就会被自动删掉。Job的yaml文件示例如下:

apiVersion: batch/v1  #Job属于batch API组,版本为v1
kind: Job
metadata:
   name: kubia-job
spec:
   template: # pod模板
      metadata:
         labels:
            app: kubia-job
      spec:
         restartPolicy: OnFailure  # 设置重启策略
         containers:
         -  name: main
            image: xxx/kubia-job
            port:
            -  containerPort:8080

着重看一下重启策略 restartPolicy。重启策略一共有三种:Always(总是重启,即执行完成之后会再次启动,一直这样进行下去)、OnFailure(失败重启)、Never(不重启,即使执行失败)。一般来说只会用

后两者,不会用Always。

Job执行完之后,通过kubectl get pod是无法查看到它的,需要用 kubectl get pod -a ,状态是Completed。

Job还支持运行多次和并行执行,配置方式如下:

apiVersion: batch/v1  
kind: Job
metadata:
   name: kubia-job
spec:
   completions: 5
   parallelism: 2
   template: # pod模板
       ...

completions配置的数目,表示要执行多少次。如果未配置parallelism,则默认并行度是1,即同一时间只有一个Pod在运行,运行完这个Pod再创建第二个,一直运行完5个为止。

若如上所示,配置了parallelism=2,则同一时间会有两个Pod在运行,其中一个执行完之后再创建一个,一直执行完5个为止。

在Job运行时更改parallelism的指令:

kubectl scale job kubia-job --replicas=3

可以看到,跟扩容指令相同。

为应对异常情况,Job还有两个属性配置:

spec.activeDeadlineSeconds: 设置超时时间,Job实例运行时间超过这个配置时间,会被标记为失败,pod被终止运行。

spec.backoffLimit:重试次数,未配置时默认为6次。

 

5、CronJob

 熟悉定时任务的,应该不难猜到,该类型的控制器用于精确控制Pod定期执行的。配置的yaml如下所示:

apiVersion: batch/v1beta1
kind: CronJob
metadata:
   name: kubia-cronjob
spec:
   schedule: "0,15,30,45 * * * *"
   startingDeadlineSeconds: 15  #表示如果离预定时间15s后还未启动Job,则本次任务不会执行
   jobTemplate: 
      metadata:
         labels:
            app: kubia-cronjob
      spec:
         restartPolicy: OnFailure  # 设置重启策略
         containers:
         -  name: main
            image: xxx/kubia-cronjob
            port:
            -  containerPort:8080

CronJob创建后,会在每个指定的cron表达式时间点创建一个新的Job。但有点坑的地方在于,它可能一下子创建两个Job,也可能一个不创建。所以需要在业务侧进行兼容,一方面是可以幂等,另一方面后面运行的任务需将前面未运行的任务未做的事情给做了。

 

本文到这里就结束了,下一节将一起学习Kubernetes中的服务。

posted on 2021-01-25 23:00  淡墨痕  阅读(406)  评论(0编辑  收藏  举报