何为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