KubernetesOpenShift

pod常用控制器介绍(deployment、StatefulSet、Job、CronJob、DaemonSet)

何为pod控制器


pod控制器,是用于管理、部署pod的一种k8s中重要的资源,确保pod资源符合预期的状态,pod的资源出现故障时,会尝试 进行重启,当根据重启策略无效,则会新建pod的资源。这样,当有了控制器来管理pod,我们就能轻松的通过配置控制器,让控制器来帮我们实现我们所期望的pod扩容、缩容,即使当pod出现异常挂掉,控制器也能立即重新启动一个pod,因为控制器的本质其实就是实时检查pod数量使其符合我们预先设定的值。

常用pod控制器


常用的pod控制器有一下几种:

ReplicationController: 比较原始的pod控制器,已经被废弃,了解即可,有ReplicaSet替代;

ReplicaSet: 保证指定数量的pod运行,并提供pod数据变更,镜像版本变更;

DaemonSet: 在集群每个node上都运行一个pod,确保全部Node 上运行一个 Pod 的副本,适用于每个node工作节点后台日志收集等场景;

CronJob: 用于执行周期性定时任务的pod,主要用于执行周期性计划,类似于Linux的crontab定时任务;

Job: 用于一次性计划任务的pod,执行完毕pod就立即退出,类似于Linux的at命令;

Deployment: 通过创建DaemonSet来创建pod,支持滚动升级,版本回退,Deployment是最常用的pod控制器;

Horizontal Pod Autoscaler: 可以根据集群负载自动调整pod的数量,实现自动扩容缩容,削峰填谷;

StatefulSet: 管理又状态的应用;

ReplicationController介绍(已废弃,基本不会用到这种控制器)


ReplicationController,简写rc,是k8s中一种pod控制器,在新版本中,rc已经被取代,所以这里了解rc即可;
ReplicationController会持续监控正在运行的pod列表,并保证相应标签类型的pod数量与期望的相符,如正在运行的pod太少,rc就会根据pod模板来创建新的副本,如果正在运行的pod太多,rc将会删除多余的pod。
总之,ReplicationController的工作就是确保pod数据始终与其定义的标签选择器选中的pod数量相匹配,如果不匹配,rc将会根据所需,采取适当的操作来协调pod数量。

rc的三大部分

  • 1、label selector,标签选择器,用于确定rc作用于哪些pod,反过来说哪些pod可以被rc管理;
  • 2、replica,副本数,指定运行的pod数量;
  • 3、pod template,pod模板,用于创建新的pod副本,pod就是根据模板来创建的。

rc的实现原理

rc与pod其实是通过标签和标签选择器来进行管联的,当改变一个pod的标签,那么该pod就会脱离rc的管理,而rc 发现少了一个pod,又会根据模板重新创建一个pod来满足副本数。如果先独立创建了pod并定义了标签,然后再创建rc,rc的标签筛选器和已存在的pod的标签相同,那么创建rc时,rc直接接管已存在的pod,rc根本不会创建新的pod,这就说明,rc与pod的根本就是通过标签和标签选择器来进行管联的。

更改rc的标签选择器和pod模板会怎样

更改rc的标签选择器和pod模板对正在运行的pod没有影响,更改标签选择器会使现有的pod脱离rc的范围,因此rc会停止关注它们,它们称为无人托管的pod。如果更改了pod模板,该模板仅影响由rc创建的新的pod。

创建一个ReplicationController

下面就来创建一个ReplicationController资源:

[root@master ~]# vim rc_nginx.yaml 
apiVersion: v1
kind: ReplicationController				#创建一个ReplicationController控制器
metadata:
  name: rc-nginx						#控制器名称
  namespace: default					#命名空间
spec:
  replicas: 3							#表示pod副本数
  selector:								#定义标签选择器,用于说明rc控制管理的是带有哪些标签的pod
     app: nginx							#标签app=nginx
  template:								#定义pod模板,pod模板就是用来创建pod
     metadata:
       labels:							#pod标签,注意:pod标签必须与上面标签选择器定义的标签相同,否者rc就不知道如何关联pod
         app: nginx
     spec:
         containers:
         - image: nginx:1.7.9
           name: nginx-container
           ports:
           - containerPort: 80
[root@master ~]# kubectl  apply  -f rc_nginx.yaml 								#应用yaml文件
[root@master ~]# kubectl  get rc,pod --show-labels 								#查看rc和pod
NAME                             DESIRED   CURRENT   READY   AGE   LABELS
replicationcontroller/rc-nginx   3         3         3       43m   app=nginx

NAME                 READY   STATUS    RESTARTS   AGE   LABELS
pod/rc-nginx-4drqr   1/1     Running   0          43m   app=nginx
pod/rc-nginx-cn8wv   1/1     Running   0          43m   app=nginx
pod/rc-nginx-qwk9j   1/1     Running   0          43m   app=nginx
[root@master ~]# 
  • 1、在创建replicationcontroller时,pod模板中的标签必须要与replicationcontroller的标签选择器匹配,否则rc将无休止的创建pod;
  • 2、可以不写标签选择器,但模板中必须写标签,这时replicationcontroller会根据pod模板中的标签自动匹配。

pod扩容、缩容

使用控制器管理的pod可以很方便的实现扩容和缩容,其原理就是通过变更控制器的副本数,如下所示:

1、通过kubectl scale 对rc控制器的pod进行扩容
[root@master ~]# kubectl scale rc rc-nginx --replicas=5			#通过kubectl scale命令对rc直接变更副本数实现扩容缩容
2、通过kubectl edit 命令直接rc的配置文件中的副本数
[root@master ~]# kubectl  edit rc rc-nginx						#直接编辑rc的定义中的副本数实现扩容缩容

删除replicationcontroller

当不在需要replicationcontroller时,可以删除replicationcontroller,删除replicationcontroller默认情况会把pod一起删掉,如果仅想删除replicationcontroller,仍想保留pod,可以使用–cascade=orphan,此时的pod就处于未托管状态;

[root@master ~]# kubectl delete rc rc-nginx						#replicationcontroller和pod会被一起删除
[root@master ~]# kubectl delete rc rc-nginx	--cascade=orphan	#仅删除replicationcontroller,pod保留


以上就是replicationcontroller,注意:replicationcontroller已经被淘汰,所以你在创建pod控制器时不应该选择创建replicationcontroller了,下面来介绍ReplicaSet。

ReplicaSet介绍(一般不会直接用到replicaset,一般是deployment创建replicaset)


ReplicaSet是Replication Controller的下一代副本控制器,目前两者只在标签选择器支持的查找方式有区别,在新版本的 Kubernetes 中使用 ReplicaSet(简称为RS )来取代 ReplicationController。ReplicaSet 跟 ReplicationController 没有本质的不同,语法定义都一样,但是 replicaset 支持标签选择器等式查找与集合查找两种方式。比如rs允许匹配缺少某个标签的pod,或包含特定标签名的pod而不管其标签值如何,ReplicationController就无法做到这些,rc进支持等值匹配的标签。

[root@master ~]# cat  rs_nginx.yaml 
apiVersion: apps/v1
kind: ReplicaSet
metadata: 
  name: rs-nginx
  namespace: default
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx-rs
    matchExpressions:
      - {key: env, operator: In, values: [dev]}
  template:
     metadata:
       labels:
         app: nginx-rs
         env: dev
     spec:
         containers:
         - image: nginx:1.7.9
           name: nginx-container
           ports:
           - containerPort: 80

以上只对ReplicaSet做了简单介绍,实际上kubernetes官方推荐不要直接使用ReplicaSet,用Deployments取而代之,Deployments是比ReplicaSet更高级的概念,它会管理ReplicaSet并提供很多其它有用的特性,最重要的是Deployments支持声明式更新,声明式更好相比于命令式更新的好处是不会丢失历史变更。总结起来就是:不要再直接使用ReplicaSet。

删除ReplicaSet

[root@master ~]# kubectl delete rs rs-nginx-http --cascade=orphan		#删除rs,保留pod
[root@master ~]# kubectl delete rs rs-nginx-http						#删除rs所有,含pod


DaemonSet介绍(DaemonSet用于确保每个节点都运行一个pod的场景)


DaemonSet 确保全部(或者一些)Node 上运行一个 Pod 的副本。当有 Node加入集群时,也会为他们新增一个 Pod 。当有 Node 从集群移除时,这些 Pod也会被回收。删除 DaemonSet将会删除它创建的所有 Pod。DaemonSet 简写为ds。
使用 DaemonSet 的一些典型用法:
运行集群存储 daemon,例如在每个 Node 上运行 glusterd 、 ceph
在每个 Node 上运行日志收集 daemon,例如 fluentd 、 logstash
在每个 Node 上运行监控 daemon,例如 Prometheus Node Exporter、 collectd 、Datadog 代理、New Relic 代理,或 Ganglia gmond

编写一个DaemonSet

[root@master ~]#  vim ds.yaml 
apiVersion: apps/v1
kind: DaemonSet
metadata: 
  name: nginx-ds
  namespace: default
spec:
  selector:
    matchLabels:
      app: nginx 
      release: stable
  template:
    metadata:
      labels:
        app: nginx 
        release: stable
    spec:
      containers:
      - name: nginx 
        image: nginx:1.14
        imagePullPolicy: IfNotPresent
        ports:
        - name: http
          containerPort: 80
    
[root@master ~]# kubectl apply -f ds.yaml 						#应用yaml文件创建资源
[root@master ~]# kubectl  get pod -o wide						#查看pod,发现已经有2个pod,分别位于各个节点上
NAME                  READY   STATUS    RESTARTS   AGE     IP            NODE    NOMINATED NODE   READINESS GATES
nginx-ds-5qnxs        1/1     Running   0          4m10s   10.244.2.22   node2   <none>           <none>
nginx-ds-l7kjk        1/1     Running   0          4m10s   10.244.1.40   node1   <none>           <none>

再次说明:DaemonSet创建的pod只会在每个节点运行1个,也就是说你不用在创建DaemonSet的yaml文件中指定副本数,没必要;当每个节点的DaemonSet管理的pod被删除或者pod异常退出时,DaemonSet控制器又会重新创建一个pod,因为DaemonSet会实时监管每个节点确保存在一个pod运行。

查看daemonset

[root@master ~]# kubectl  get daemonset -n default				#查看集群的DaemonSet
NAME       DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
nginx-ds   2         2         2       2            2           <none>          14m


删除daemonset

[root@master ~]# kubectl delete pod nginx-ds-5qnxs				#删除某个节点上的pod,ds又会重新创建一个pod
pod "nginx-ds-5qnxs" deleted
[root@master ~]# kubectl  delete daemonset nginx-ds				#删除ds,其创建的pod都被删除
daemonset.apps "nginx-ds" deleted
[root@master ~]#

Job介绍(一次性计划任务,类似于centos的at命令)


有时候我们可能需要一种这样的pod控制器,即该控制器能实现pod执行完任务就结束,不需要重启或重建pod,相当于一次性任务。这就可以使用job控制器。(可以简单的理解为,Job相当于Linux中的at一次性计划任务)

创建job

[root@master ~]# cat Job.yaml 								#编写一个job资源,任务为睡眠120s
apiVersion: batch/v1										#job属于batch API组,版本为v1
kind: Job													#资源类型
metadata: 							
  name: busybox-job											#job的名称叫busybox-job	
  namespace: default										#命名空间
spec:
  template:													#pod模板
    metadata:
      labels:												#pod标签
        app: busybox
        env: dev
    spec:
      restartPolicy: OnFailure								#pod重启策略,默认为Always,但一定不能是Always,因为job的策略就只是一次性执行,执行完不需要重启,可以设置为OnFailure或Never
      containers:
      - name: busybox
        image: busybox:latest
        imagePullPolicy: IfNotPresent						#镜像拉取策略,默认就是IfNotPresent,不存在才拉取
        command: ["/bin/sh","-c","sleep 120s"]				#容器的任务为睡眠120s
[root@master ~]# 
[root@master ~]# kubectl  create -f Job.yaml 					#创建job
job.batch/busybox-job created

查看job

[root@master ~]# kubectl get pod,job							#查看job和pod
NAME                       READY   STATUS    RESTARTS   AGE
pod/busybox-job--1-2q87r   1/1     Running   0          6s

NAME                    COMPLETIONS   DURATION   AGE
job.batch/busybox-job   0/1           6s         6s

#等待120s后再次查看pod,发现pod状态变成Completed,表示pod已经执行完成了
[root@master ~]# kubectl get pod								#pod状态变成Completed
NAME                   READY   STATUS      RESTARTS   AGE
busybox-job--1-2q87r   0/1     Completed   0          3m29s

job还可以设计为运行多个pod实例,换句话来说就是创建一个job,顺序或者并行的运行多个pod,如下演示:

顺序运行 Job pod

假设需要一个job顺序运行多次,那么可以指定completions参数来设置希望job的pod运行多少次,所下代码所示:

[root@master ~]# cat Job.yaml 
apiVersion: batch/v1
kind: Job
metadata: 
  name: busybox-job
  namespace: default
spec:
  completions: 3												#表示运行3次
  template:
    metadata:
      labels:
        app: busybox
        env: dev
    spec:
      restartPolicy: OnFailure
      containers:
      - name: busybox
        image: busybox:latest
        imagePullPolicy: IfNotPresent
        command: ["/bin/sh","-c","sleep 20s"]
[root@master ~]# 
[root@master ~]# kubectl get pod								#查看pod,是第一个运行完成之后才创建第2个,依次运行
NAME                   READY   STATUS      RESTARTS   AGE
busybox-job--1-9f7bs   0/1     Completed   0          4m39s
busybox-job--1-mdqkb   0/1     Completed   0          4m18s
busybox-job--1-s98wc   0/1     Completed   0          5m

并行运行 Job pod

不必一个接着一个运行单个Job pod,也可以让Job 并行运行多个pod,可以通过parallelism Job配置属性,指定允许多个pod并行执行,如下代码所示:

[root@master ~]# vim  Job.yaml 
apiVersion: batch/v1
kind: Job
metadata:
  name: busybox-job
  namespace: default
spec:
  completions: 4
  parallelism: 2													#指定可以并行运行多少个pod
  template:
    metadata:
      labels:
        app: busybox
        env: dev
    spec:
      restartPolicy: OnFailure
      containers:
      - name: busybox
        image: busybox:latest
        imagePullPolicy: IfNotPresent
        command: ["/bin/sh","-c","sleep 20s"]
[root@master ~]# kubectl  apply  -f Job.yaml && kubectl get pod		#查看job和pod,发现已经在并行运行2个pod了
job.batch/busybox-job created
NAME                   READY   STATUS              RESTARTS   AGE
busybox-job--1-c8jb5   0/1     ContainerCreating   0          0s
busybox-job--1-lsrbv   0/1     ContainerCreating   0          0s

注意:如果restartPolicy:设为OnFailure,就表示pod出现异常时可以重新创建pod,这就意味着completions定义为n次,但实际job创建的pod可能会大于n。

限制Job pod完成任务的时间

通过pod配置中设置activeDeadlineSeconds属性,可以限制pod的运行时间,如果pod运行时间超过次时间,系统将尝试终止pod,并将job标记为失败。
通过指定Job资源清单中的spec.backoffLimit字段,可以配置Job在被标记为失败之前可以重试的重试,如果为指定,默认为6次。

删除Job

默认执行完毕的Job 的pod为Completed 状态,k8s并不会删除pod,是为了可以让你查看日志,如果需要删除Job,直接kubectl delete job Job_name即可,如下所示:

[root@master ~]# kubectl  delete job busybox-job 			#删除job,其pod也会被删除
job.batch "busybox-job" deleted


CronJob介绍


如果说Job相当于Linux中的at一次性激活任务,那么CronJob就相当于Linux中的Crontab周期性定时任务。Job与CronJob的区别在于,Job在创建时就运行,而CronJob在创建后会定时的运行,在k8s集群中的cron任务就是通过CronJob资源进行实现的。
在配置的时间里,k8s将根据在CronJob对象中配置的Job模板创建Job资源。
cron表达式格式与Linux中cron的表达式一样,格式为:分 时 日 月 周

创建一个CronJob

[root@master ~]# vim CronJob.yaml 
apiVersion: batch/v1
kind: CronJob										#创建CronJob
metadata: 
  name: busyboy
  namespace: default
spec:
  schedule: "*/5 * * * *"							#schedule字段指定定时任务:分时日月周
  startingDeadlineSeconds: 15						#表示最迟在预定时间后15秒启动pod
  jobTemplate:										#任务模板,用来指定需要运行的任务
    spec:
      template:
        metadata:
         labels:
           app: CronJob
           env: dev
        spec:
          restartPolicy: OnFailure
          containers:
             - name: busybox
               image: busybox:latest
               imagePullPolicy: IfNotPresent
               command: ["/bin/sh","-c","sleep 20s"]
[root@master ~]#


查看CronJob、查看pod

[root@master ~]# kubectl get cronjob									#查看CronJob
NAME      SCHEDULE      SUSPEND   ACTIVE   LAST SCHEDULE   AGE
busyboy   */5 * * * *   False     0        4m12s           19m
[root@master ~]# 
[root@master ~]# kubectl  get pods										#每隔5分钟就会产生一个pod
NAME                        READY   STATUS      RESTARTS   AGE
busyboy-27416295--1-k5t5h   0/1     Completed   0          5m23s
busyboy-27416300--1-qs7mt   0/1     Completed   0          23s

删除CronJob

默认执行完毕的CronJob的pod为Completed 状态,k8s并不会删除pod,是为了可以让你查看日志,如果需要删除CronJob,直接kubectl delete cronjob cronjob_name即可,如下所示:

[root@master ~]# kubectl  delete cronjob busyboy 			#删除job,其pod也会被删除
cronjob.batch "busyboy" deleted