理解Job/CronJob
为什么要有Job/CronJob
Kubernetes里的业务分为两类:
- 在线业务,比如Nginx、Node.js、MySQL、Redis 等等,一旦运行起来基本上不会停,也就是永远在线。
- 离线业务,比如日志分析、数据建模、视频转码等等,虽然计算量很大,但只会运行一段时间,特点是必定会退出
离线业务也可分为两类:
- 临时任务,在Kubernetes中用Job表示
- 定时任务,在Kubernetes中用CornJob表示
使用YAML描述Job
创建Job的YAML模板
export out="--dry-run=client -o yaml" # 定义Shell变量
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"]
理解Job和Pod
Job中的spec.template中实际嵌入了一个Pod,这样Job就能从这个模板中创建出Pod
因为 Job 业务的特殊性,所以我们还要在 spec 里多加一个字段 restartPolicy,确定 Pod 运行失败时的策略,OnFailure 是失败原地重启容器,而 Never 则是不重启容器,让 Job 去重新调度生成一个新的 Pod。
操作Job
创建Job
kubectl apply -f echo-job.yml
查看Job和其管理的Pod
kubectl get job
kubectl get pod
因为Pod被Job管理,就不会反复重启报错了,而是会显示Completed,表示任务完成。
查看Job中某个Pod的运行日志
kubectl logs echo-job-wlcj8
几个控制离线作业的重要字段
- activeDeadlineSeconds,设置Job 运行的超时时间。
- backoffLimit,设置 Pod 的失败重试次数。
- completions,Job 完成需要运行多少个 Pod,默认是 1 个。
- parallelism,它与 completions 相关,表示允许并发运行的 Pod 数量,避免过多占用资源。
sleep-job
apiVersion: batch/v1
kind: Job
metadata:
name: sleep-job
spec:
activeDeadlineSeconds: 36
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
运行并实时观察Pod
kubectl apply -f sleep-job.yml
kubectl get pod -w
等到4个Pod都运行完毕,使用kubectl get来查看Job和Pod的状态
可以看出sleep-job的持续时间为25s,没超过设定的36s
“声明式”的 Job 对象让离线业务的描述变得非常直观,简单的几个字段就可以很好地控制作业的并行度和完成数量,不需要我们去人工监控干预,Kubernetes 把这些都自动化实现了。
使用YAML描述CronJob
创建CronJob的YAML模板
export out="--dry-run=client -o yaml" # 定义Shell变量
kubectl create cj echo-cj --image=busybox --schedule="" $out
注意,这里需要添加指定参数--schedule
编辑这个YAML模板,生成CronJob对象
apiVersion: batch/v1
kind: CronJob
metadata:
creationTimestamp: null
name: echo-cj
spec:
jobTemplate:
metadata:
creationTimestamp: null
name: echo-cj
spec:
template:
metadata:
creationTimestamp: null
spec:
containers:
- image: busybox
name: echo-cj
imagePullPolicy: IfNotPresent
command: ["/bin/echo"]
args: ["hello", "world"]
resources: {}
restartPolicy: OnFailure
schedule: "*/1 * * * *"
status: {}
重点关注spec字段,发现存在连续3个spec嵌套层次:
- 第一个
spec,是CronJob自己的对象规格说明 - 第二个
spec,从属于jobTemplate,定义了一个Job对象 - 第三个
spec,从属于template,定义了Job中运行的Pod
schedule字段
CronJob的schedule字段,遵循cron语法,指定分钟、小时、天、月、周
创建并查看cj
kubectl apply -f cronjob.yml
kubectl get cj
kubectl get pod
总结
Kubernetes 里的资源对象设计,它强调“职责单一”和“对象组合”,简单来说就是“对象套对象”
CronJob 使用定时规则控制 Job,Job 使用并发数量控制 Pod,Pod 再定义参数控制容器,容器再隔离控制进程,进程最终实现业务功能,层层递进的形式有点像设计模式里的 Decorator(装饰模式),链条里的每个环节都各司其职,在 Kubernetes 的统一指挥下完成任务。
- Pod 是 Kubernetes 的最小调度单元,但为了保持它的独立性,不应该向它添加多余的功能。
- Kubernetes 为离线业务提供了 Job 和 CronJob 两种 API 对象,分别处理“临时任务”和“定时任务”。
- Job 的关键字段是 spec.template,里面定义了用来运行业务的 Pod 模板,其他的重要字段有 completions、parallelism 等
- CronJob 的关键字段是 spec.jobTemplate 和 spec.schedule,分别定义了 Job 模板和定时运行的规则。
《极客时间-Kubernetes入门实战课》学习笔记 Day13