【Kubernetes】离线业务:Job与CronJob
Deployment、StatefulSet和DaemonSet这三个编排概念编排的对象主要都是在线业务(Long Running Task,这些应用一旦运行起来,除非出错或者停止,它的容器进程会一直保持在Running状态)。
但是对于离线业务(Batch Job,计算业务)在计算完成后就直接退出了,如果依然使用Deployment来管理,就会发现Pod会在计算结束后退出,然后被Deployment Controller不断重启。
在Kubernetes v1.4版本之后,设计出来一个用来描述离线业务的API对象:Job。
举个Job的栗子
apiVersion: batch/v1 kind: Job metadata:name: pi spec:template:spec:containers:- name: piimage: resouer/ubuntu-bc #安装了ba明了的Ubuntu镜像command: ["sh", "-c", "echo 'scale=10000; 4*a(1)' | bc -l "] #bc命令是Linux里的计算器,; -l表示使用标准数学课; a(1)调用arctangent函数,scale指定小数点后的位数restartPolicy: NeverbackoffLimit: 4
创建这个Pod
$ kubectl create -f job.yaml $ kubectl describe jobs/pi Name: pi Namespace: default Selector: controller-uid=c2db599a-2c9d-11e6-b324-0209dc45a495 Labels: controller-uid=c2db599a-2c9d-11e6-b324-0209dc45a495job-name=pi Annotations: <none> Parallelism: 1 Completions: 1 .. Pods Statuses: 0 Running / 1 Succeeded / 0 Failed Pod Template:Labels: controller-uid=c2db599a-2c9d-11e6-b324-0209dc45a495job-name=piContainers:...Volumes: <none> Events:FirstSeen LastSeen Count From SubobjectPath Type Reason Message--------- -------- ----- ---- ------------- -------- ------ -------1m 1m 1 {job-controller } Normal SuccessfulCreate Created pod: pi-rq5rl
可以看大这个Job对象在创建后,它的Pod模板被自动加上了一个Labels, controller-uid=<一个随机的字符串>。而Job对象本身,则被自动加上了这个Label对应的Selector,从而保证了Job与它所管理的Pod之间的匹配关系。
Job Controller之所以要使用这种携带了UID的Label,就是为了避免不同Job对象管理的Pod重合
### 接下来可以看到这个Job创建的Pod进入了Running状态,这意味着它正在计算Pi的值$ kubectl get pods NAME READY STATUS RESTARTS AGE pi-rq5rl 1/1 Running 0 10s###计算结束后,Pod会进入Completed状态,这也是需要在Pod模板中定义restartPolicy=Never的原因:离线计算的Pod永远不应该被重启$ kubectl get pods NAME READY STATUS RESTARTS AGE pi-rq5rl 0/1 Completed 0 4m ### 通过查看log可以看到计算的值
$ kubectl logs pi-rq5rl
3.141592653589793238462643383279...
那如果这个离线作业失败了怎么办?因为这个例子中定义了restartPolicy=Never,那离线作业失败后Job Controller就会不断地尝试创建一个新Pod
Job对象的spec.backoffLimit字段限制尝试的次数,在例子中定义为4,默认值为6。Job Controller重新创建Pod的间隔是呈倍数增加的,即下一次重新创建Pod的动作会分别发生在10s,20s,40s……
那如果定义的restartPolicy=OnFailure呢?离线作业失败后,Job Controller就不会去尝试创建新的Pod,但是它会不断尝试重启Pod里的容器。
那如果这个Pod一直不肯结束呢?spec.activeDeadlineSeconds字段可以设置最长运行时间
spec:backoffLimit: 5activeDeadlineSeconds: 100 # 运行超过100s,这个Job的所有Pod都会被终止
Job Controller 对并行作业的控制方法
在Job对象中,负责并行控制的参数有两个:
spec.parallelism:定义一个Job在任意时间最多可以启动多少个Pod同时运行
spec.completions:定义Job至少要玩的Pod的数目
再举个栗子
apiVersion: batch/v1 kind: Job metadata:name: pi spec:parallelism: 2completions: 4template:spec:containers:- name: piimage: resouer/ubuntu-bccommand: ["sh", "-c", "echo 'scale=5000; 4*a(1)' | bc -l "]restartPolicy: NeverbackoffLimit: 4
指定了最大并行数是2,最小完成数是4
### 创建Job对象 $ kubectl create -f job.yaml### Job维护两个字段,DESIRED即最小完成数 $ kubectl get job NAME DESIRED SUCCESSFUL AGE pi 4 0 3s### Job首先创建两个并行运行的Pod计算PI $ kubectl get pods NAME READY STATUS RESTARTS AGE pi-5mt88 1/1 Running 0 6s pi-gmcq5 1/1 Running 0 6s### 当一个Pod完成计算会进入Completed状态,就会有一个新的Pod被创建出来,并且快速地从Pending状态进入ContainerCreating状态,再到Running状态,最后完成 $ kubectl get pods NAME READY STATUS RESTARTS AGE pi-gmcq5 0/1 Completed 0 40s pi-84ww8 0/1 Pending 0 0s pi-5mt88 0/1 Completed 0 41s pi-62rbt 0/1 Pending 0 0s$ kubectl get pods NAME READY STATUS RESTARTS AGE pi-gmcq5 0/1 Completed 0 40s pi-84ww8 0/1 ContainerCreating 0 0s pi-5mt88 0/1 Completed 0 41s pi-62rbt 0/1 ContainerCreating 0 0s$ kubectl get pods NAME READY STATUS RESTARTS AGE pi-5mt88 0/1 Completed 0 54s pi-62rbt 1/1 Running 0 13s pi-84ww8 1/1 Running 0 14s pi-gmcq5 0/1 Completed 0 54s$ kubectl get pods NAME READY STATUS RESTARTS AGE pi-5mt88 0/1 Completed 0 5m pi-62rbt 0/1 Completed 0 4m pi-84ww8 0/1 Completed 0 4m pi-gmcq5 0/1 Completed 0 5m### 所有Pod均已成功退出,SUCCESSFUL字段值变成4 $ kubectl get job NAME DESIRED SUCCESSFUL AGE pi 4 4 5m
通过上述DESIRED和SUCCESSFUL字段的关系,可以看出Job Controller控制的直接对象是Pod,Job Controller在控制循环中进行的调谐(Reconcile)操作,是根据实际在Running状态Pod数目、已经成功推出的Pod数目,以及parallelism、completions参数的值共同计算在这个周期里,应该创建或删除的Pod数目,然后调用Kubernetes API来执行这个操作
Job对象使用方法
1、外部管理器 + Job模板
把Job的YAML文件定义为一个模板,然后用一个外部工具控制这些模板来生成Job 。Job的定义方式如下所示:
apiVersion: batch/v1 kind: Job metadata:name: process-item-$ITEMlabels:jobgroup: jobexample spec:template:metadata:name: jobexamplelabels:jobgroup: jobexamplespec:containers:- name: cimage: busyboxcommand: ["sh", "-c", "echo Processing item $ITEM && sleep 5"] ### 定义了$ITEM变量restartPolicy: Never
在控制这种Job时,只要注意如下两个方面即可
- 创建Job时,替换掉$ITEM这样的变量
- 所有来自同一个目标的Job,都有一个jobgroup: jobexample标签,也就是说这一组Job使用这样一个相同的标识
### 第一点可以通过shell把¥ITEM替换掉 $ mkdir ./jobs $ for i in apple banana cherry docat job-tmpl.yaml | sed "s/\$ITEM/$i/" > ./jobs/job-$i.yaml done### 创建Job $ kubectl create -f ./jobs $ kubectl get pods -l jobgroup=jobexample NAME READY STATUS RESTARTS AGE process-item-apple-kixwv 0/1 Completed 0 4m process-item-banana-wrsf7 0/1 Completed 0 4m process-item-cherry-dnfu9 0/1 Completed 0 4m
这种模式虽然看起很傻,但却很普遍,因为大多数用户在需要管理Batch Job时,都已经有自家的一套方案,需要做的往往就是集成工作。这时候Kubernetes对这些方案最有价值的就是Job这个API对象,因此只需要编写一个外部工具(如上面for循环)来管理这些Job即可。
这种模式下使用Job对象,completions和parallelism这两个字段都应该使用默认值1,作业Pod的并行控制,应该完全交由外部工具来进行管理
2、拥有固定任务数目的并行Job
只关心最后是否有指定数目(spec.completions)个任务成功推出,不关心执行时的并行度多少。
比如上面计算pi的例子,或者可以不指定parallelism
3、指定并行度(parallelism),不设置固定的completions的值
任务总数未知,需要决定什么时候启动Pod,什么时候Job才算执行完成。因此需要一个工作队列来负责任务分发,还需要能够判断工作队列已经为空(所有工作已经结束)
apiVersion: batch/v1 kind: Job metadata:name: job-wq-2 spec:parallelism: 2template:metadata:name: job-wq-2spec:containers:- name: cimage: gcr.io/myproject/job-wq-2env:- name: BROKER_URLvalue: amqp://guest:guest@rabbitmq-service:5672 ##工作队列采用RabbitMQ- name: QUEUEvalue: job2restartPolicy: OnFailure
这个Pod执行逻辑为
/* job-wq-2 的伪代码 */ for !queue.IsEmpty($BROKER_URL, $QUEUE) {task := queue.Pop()process(task) } print("Queue empty, exiting") exit
CronJob
CronJob描述的是定时任务,举个栗子
apiVersion: batch/v1beta1 kind: CronJob metadata:name: hello spec:schedule: "*/1 * * * *"jobTemplate:spec:template:spec:containers:- name: helloimage: busyboxargs:- /bin/sh- -c- date; echo Hello from the Kubernetes clusterrestartPolicy: OnFailure
在这个YAML文件中,最重要的关键词就是jobTemplate,即一个Job对象的控制器(Controller)。如Deployment和Pod的关系一样,CronJob是一个专门用来管理Job对象的控制器。
CronJob创建和删除Job的依据是schedule字段定义的、一个标准的Unix Cron格式的表达式
如,“*/1****”,这个Cron表达式里*/1中的*表示从0开始,/表示每,1表示偏移量,它的意思就是从零开始,每1个时间单位执行一次
那时间单位又是什么意思?Cron表达式中的五个部分分别代表:分钟、小时、日、月、星期。因此上面的意思就是每分钟执行一次。
$ kubectl create -f ./cronjob.yaml cronjob "hello" created# 一分钟后 $ kubectl get jobs NAME DESIRED SUCCESSFUL AGE hello-4111706356 1 1 2s##CronJob对象会记录下这次Job的执行时间 $ kubectl get cronjob hello NAME SCHEDULE SUSPEND ACTIVE LAST-SCHEDULE hello */1 * * * * False 0 Thu, 6 Sep 2018 14:34:00 -070
另外由于定时任务的特殊性,很可能某个Job还没有执行完,另外一个新的Job就产生了,这时候可以通过spec.concurrencyPolicy字段来定义具体的处理策略
- concurrencyPolicy=Allow:默认情况,Job可以同时存在;
- concurrencyPolicy=Forbid:不会创建新的Jod,该创建周期被跳过
- concurrencyPolicy=Replace:新产生的Job会替换旧的、没有执行完的Job
如果一个Job创建失败,这次创建就会被标记为“miss”,当在指定的时间窗口内,miss的数目达到100时,那么CronJob会停止创建这个Job。这个时间窗口可以由spec.startingDeadlineSeconds字段指定。
例如,startingDeadlineSeconds=200,意味着在过去的200s里,如果miss的数目到达了100次,那么这个Job就不会被创建执行了。
转载于:https://www.cnblogs.com/yuxiaoba/p/9797331.html
【Kubernetes】离线业务:Job与CronJob相关推荐
- Kubernetes-主要概念-CronJob
分享一个大牛的人工智能教程.零基础!通俗易懂!风趣幽默!希望你也加入到人工智能的队伍中来!请点击http://www.captainbed.net CronJob即定时任务,就类似于Linux系统的c ...
- kubernetes离线一键安装教程
前言 离线安装包中不包含docker,请先自行安装docker,适配版本1.11.1.1.12.1.1.13.1.17.03.17.09.18.06 docker 安装 # 设置docker repo ...
- kubeadm源码分析(kubernetes离线安装包,三步安装)
k8s离线安装包 三步安装,简单到难以置信 kubeadm源码分析 说句实在话,kubeadm的代码写的真心一般,质量不是很高. 几个关键点来先说一下kubeadm干的几个核心的事: kubeadm ...
- 【Kubernetes离线安装】
文章目录 离线安装Kubernetes 一.环境准备 二.配置ftp服务 三.Docker安装 四.部署Kubernetes 五.Kubernetes优化 六.配置kube-proxy ipvs 七. ...
- Kubernetes 的原理
kubernetes 已经成为容器编排领域的王者,它是基于容器的集群编排引擎,具备扩展集群.滚动升级回滚.弹性伸缩.自动治愈.服务发现等多种特性能力. 本文将带着大家快速了解 kubernetes , ...
- 容器开启数据服务之旅系列(四):Kubernetes QoS 助力在线运用与大数据离线运用的带宽控制和磁盘控制...
容器开启数据服务之旅系列(四) Kubernetes QoS 助力在线运用与大数据离线运用的带宽控制和磁盘控制 概述 本文是2018年大数据峰会上的一些分享,关于在线业务,离线业务在ACK(阿里云容器 ...
- 灵魂拷问,上 Kubernetes 有什么业务价值?
本文整理自 2020 年 7 月 22 日<基于 Kubernetes 与 OAM 构建统一.标准化的应用管理平台>主题线上网络研讨会.文章共分为上下两篇,本文为上篇,主要和大家介绍上 K ...
- 【带你上手云原生体系】第四部分:Kubernetes 圣经 【完整生态、生产必备、一文精通、无需再学】大量图文请慎入
[带你上手云原生体系]第一部分:文章简介 及 云原生思维概览 [带你上手云原生体系]第二部分:Go语言从入门到精通 [带你上手云原生体系]第三部分:Docker从入门到精通 [带你上手云原生体系]第四 ...
- kubernetes 降本增效标准指南| 资源利用率提升工具大全
背景 公有云的发展为业务的稳定性.可拓展性.便利性带来了极大帮助.这种用租代替买.并且提供完善的技术支持和保障的服务,理应为业务带来降本增效的效果.但实际上业务上云并不意味着成本一定较少,还需适配云上 ...
最新文章
- 使用正则表达式进行高效的测试
- for vue 一行2列_awk 处理文本:行转列,列转行
- ajax状态码--转他人的
- VLAD教程和资料 All about VLAD
- JMS中queue和topic区别
- 6-3 递增的整数序列链表的插入 (10 分)
- 1. 请简述mysql数据库的锁机制_【MySQL入门】之MySQL数据库的锁机制(二)
- 从MVC到前后端分离(REST-个人也认为是目前比较流行和比较好的方式)
- pytorch ResNet结构代码实现
- select、poll、epoll区别总结
- 20200727每日一句
- LNMP架构搭建编译安装详细部署
- 微信公众号 Markdown 编辑器
- 2019最新升级【超能版】 vbox硬件级虚拟机系统 去虚拟化去vm标识 支持批量启动 批量克隆 CPA网赚挂机电商 virtualbox
- 股民误将向日葵当成农业股
- 【C指针】初识指针,轻松了解指针
- 如何用python处理pdf_用Python处理PDF
- 2021-07-25
- Visual Studio2015安装步骤详解
- 微信or支付宝交易限额