离线任务
“离线业务”可以分为两种。一种是“临时任务”,跑完就完事,下次有需求了说一声再重新安排;另一种是“定时任务”,可以按时按点周期运行,不需要过多干预。这分别对应了kubernetes中API对象中的Job和CronJob。
如何使用YAML描述Job
- apiVersion不是v1,而是batch/v1。
- kind是Job,这个和对象的名字是一致的。
- metadata里仍然要有name标记名字,也可以用labels添加任意的标签。
你可以使用kubectl explain job来看它的字段说明。不过想要生成YAML样板文件的话不能使用kubectl run,因为kubectl run只能创建Pod,要创建Pod以外的其他API对象,需要使用命令kubectl create,再加上对象的类型名。
export out="--dry-run=client -o yaml"
kubectl create job echo-job --image=busybox $out
会生成一个基本的YAML文件,保存之后做点修改,就有了一个Job对象
apiVersion: batch/v1
kind: Job
metadata:
name: echo-job
spec:
template:
spec:
restartPolicy: OnFailure
containers:
- image: busybox
name: echo-job
imagePullPolicy: IfNotPresent
command: ["/bin/echo"]
args: ["hello", "world"]
你可能注意到spec-template-spec这个结构。它其实就是在Job对象里应用了组合模式,template字段定义了一个“应用模板”,里面嵌入了一个Pod,这样Job就可以从这个模板来创建出Pod。
这个Pod受到Job的管理控制,不直接和apiserver交互,就没必要定义apiVersion等“头字段”,只需要定义好关键的spec,描述清楚容器相关的信息,是一个“无头”的Pod对象。
在spec中加一个字段的你restartPolicy,确定Pod运行失败时的策略,OnFailure是失败原地重启容器,而Never则是不重启容器,让Job去重新调度生成一个新的Pod。
# 创建
kubectl apply -f job.yml
# 查看job
kubectl get job
# 查看pod
kubectl get pod
Pod被Job管理,它不会反复重启报错,而是会显示为Completed表示任务完成,而Job里也会列出运行成功的作业数量。
Pod被自动关联了一个名字,用的是Job的名字再加上一个随机字符串。
列出几个控制离线作业的重要字段,其他更详细的信息可以参考Job文档:
- activeDeadlineSeconds:设置Pod运行的超时时间。
- backoffLimit:设置Pod的失败重试次数。
- completions:Job完成需要运行多少个Pod,默认是1个。
- parallelism:它与completions相关,表示允许并发运行的Pod数量,避免过多占用资源。
这四个字段在最外层spec下,所以属于Job级别的,用来控制模板里的Pod对象。
再创建一个Job对象,它的功能是:随机睡眠一段时间再退出,模拟运行时间较长的作业(MapReduce);Job的参数设置成15秒超时,最多重试2次,总共需要运行完4个Pod,但同一时刻最多并发2个Pod:
apiVersion: batch/v1
kind: Job
metadata:
name: sleep-job
spec:
activeDeadlineSeconds: 15
backoffLimit: 2
completions: 4
parallelism: 2
template:
spec:
restartPolicy: OnFailure
containers:
- image: busybox
name: echo-job
imagePullPolicy: IfNotPresent
command:
- sh
- -c
- sleep $(($RANDOM % 10 + 1)) && echo done
使用kubectl apply创建Job之后,我们可以用kubectl get pod -w来实现观察Pod的状态,看到Pod不断被排队、创建、运行的过程:
kubectl apply -f sleep-job.yml
kubectl get pod -w
等到4个Pod都运行完毕,我们再用kubectl get来看看Job和Pod的状态,看到Job的完成数量是4个,而4个Pod也都是完成状态。
如何使用YAML描述CronJob
注意
- CronJob的名字有点长,所以Kubernetes提供了简写的cj,这个简写也可以使用命令kubectl api-resources看到;
- CronJob需要定时运行,所以我们在命令行里还需要指定参数 --schedule。
export out="--dry-run=client -o yaml"
kubectl create cj echo-cj --image=busybox --schedule="" $out
生成CronJob对象
apiVersion: batch/v1
kind: CronJob
metadata:
name: echo-cj
spec:
schedule: '*/1 * * * *'
jobTemplate:
spec:
template:
spec:
restartPolicy: OnFailure
containers:
- image: busybox
name: echo-cj
imagePullPolicy: IfNotPresent
command: ["/bin/echo"]
args: ["hello", "world"]
这里有三个spec嵌套层次
- 第一个spec是从CronJob自己的对象规格声明
- 第二个spec从属于“jobTemplate”,它定义了一个Job对象
- 第三个spec从属于“template”,它定义了Job里运行的Pod。
除了定义Job对象的“jobTemplate”字段之外,CronJob还有一个新字段就是“schedule”,用来定义任务周期运行的规则。Cron语法和Linux上的crontab是一样的
除了名字不同,CronJob和Job的用法几乎是一样的,使用kubectl apply创建CronJob,使用kubectl get cj、kubectl get pod来查看状态:
kubeclt apply -f cronjob.yml
kubectl get cj
kubectl get pod
其他
- Job的关键字段是spec.template,里面定义了用来运行业务的Pod模板,其他的重要字段有completions、parallelism等
- CronJob的关键字段是spec.jobTemplate和spec.schedule,分别定义了Job模板和定时运行的规则。
- Job在运行结束后不会立即删除,这是为了方便获取计算结果,但如果积累过多的已完成Job也会消耗系统资源,可以使用字段“ttlSecondsAfterFinished”设置一个保留的时限。
- 一个学习cron时间设置语法的网站,crontab.guru
- 出于节约资源的考虑,CronJob不会无限地保留已经运行的Job,它默认只保留3个最近的执行结果,但可以用字段“successfulJobsHistoryLimit”改变。