理解Job/CronJob

389 阅读2分钟

理解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

img

因为 Job 业务的特殊性,所以我们还要在 spec 里多加一个字段 restartPolicy,确定 Pod 运行失败时的策略,OnFailure 是失败原地重启容器,而 Never 则是不重启容器,让 Job 去重新调度生成一个新的 Pod。

操作Job

创建Job

 kubectl apply -f echo-job.yml

查看Job和其管理的Pod

 kubectl get job
 kubectl get pod

image-20230201184410127

因为Pod被Job管理,就不会反复重启报错了,而是会显示Completed,表示任务完成。

查看Job中某个Pod的运行日志

 kubectl logs echo-job-wlcj8

image-20230201184642437

几个控制离线作业的重要字段

  • 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

image-20230202175648231

等到4个Pod都运行完毕,使用kubectl get来查看Job和Pod的状态

image-20230202175759095

可以看出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嵌套层次:

  1. 第一个spec,是CronJob自己的对象规格说明
  2. 第二个spec,从属于jobTemplate,定义了一个Job对象
  3. 第三个spec,从属于template,定义了Job中运行的Pod

img

schedule字段

CronJob的schedule字段,遵循cron语法,指定分钟、小时、天、月、周

创建并查看cj

 kubectl apply -f cronjob.yml
 kubectl get cj
 kubectl get pod

image-20230202182919565

总结

Kubernetes 里的资源对象设计,它强调“职责单一”和“对象组合”,简单来说就是“对象套对象”

CronJob 使用定时规则控制 Job,Job 使用并发数量控制 Pod,Pod 再定义参数控制容器,容器再隔离控制进程,进程最终实现业务功能,层层递进的形式有点像设计模式里的 Decorator(装饰模式),链条里的每个环节都各司其职,在 Kubernetes 的统一指挥下完成任务。

  1. Pod 是 Kubernetes 的最小调度单元,但为了保持它的独立性,不应该向它添加多余的功能。
  2. Kubernetes 为离线业务提供了 Job 和 CronJob 两种 API 对象,分别处理“临时任务”和“定时任务”。
  3. Job 的关键字段是 spec.template,里面定义了用来运行业务的 Pod 模板,其他的重要字段有 completions、parallelism 等
  4. CronJob 的关键字段是 spec.jobTemplate 和 spec.schedule,分别定义了 Job 模板和定时运行的规则。

image.png

《极客时间-Kubernetes入门实战课》学习笔记 Day13 极客课程分享