云原生技术之job-运行离线业务

举报
tea_year 发表于 2024/11/22 11:03:28 2024/11/22
【摘要】 job-运行离线业务 “离线业务”类型的应用一般不直接服务于外部用户,只对内部用户有意义,比如日志分析、数据建模、视频转码等等,虽然计算量很大,但只会运行一段时间。“离线业务”的特点是必定会退出,不会无期限地运行下去,所以它的调度策略也就与“在线业务”存在很大的不同,需要考虑运行超时、状态检查、失败重试、获取计算结果等管理事项。“离线业务”可以分为两种。一种是“临时任务”,跑完就完事了,下次...

job-运行离线业务

离线业务类型的应用一般不直接服务于外部用户,只对内部用户有意义,比如日志分析、数据建模、视频转码等等,虽然计算量很大,但只会运行一段时间。离线业务的特点是必定会退出,不会无期限地运行下去,所以它的调度策略也就与在线业务存在很大的不同,需要考虑运行超时、状态检查、失败重试、获取计算结果等管理事项。

离线业务可以分为两种。一种是临时任务,跑完就完事了,下次有需求了说一声再重新安排;另一种是定时任务,可以按时按点周期运行,不需要过多干预。

对应到 Kubernetes 里,临时任务就是 API 对象 Job定时任务就是 API 对象 CronJob,使用这两个对象你就能够在 Kubernetes 里调度管理任意的离线业务了。

 

使用 YAML 描述 Job  

Job YAML“文件头部分还是那几个必备字段:  

  • apiVersion 不是 v1,而是 batch/v1
  • kind Job,这个和对象的名字是一致的。
  • metadata 里仍然要有 name 标记名字,也可以用 labels 添加任意的标签。

使用以下命令可以生成一下 job 对象模板

比如用 busybox 创建一个“echo-job”,命令就是这样的:  

Bash
export out="--dry-run=client -o yaml "
kubectl create job echo-job --image=busybox $out

会生成一个基本的 YAML 文件,保存之后做点修改,就有了一个 Job 对象:  

 

YAML
apiVersion: batch/v1
kind: Job
metadata:
  name: echo-job
spec:
  template:
    metadata:
    spec:
      restartPolicy: Never
      containers:
      - name: echo-job
        image: busybox:latest
        imagePullPolicy: IfNotPresent
        command: ["/bin/echo"]
        args: ["hello", "world"]      

你会注意到 Job 的描述与 Pod 很像,但又有些不一样,主要的区别就在“spec”字段里,多了一个 template 字段,然后又是一个“spec”,显得有点怪。  

为了辅助你理解,我把 Job 对象重新组织了一下,用不同的颜色来区分字段,这样你就能够很容易看出来,其实这个“echo-job”里并没有太多额外的功能,只是把 Pod 做了个简单的包装:

 

 

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

创建 Job  

现在让我们来创建 Job 对象,运行这个简单的离线作业,用的命令还是 kubectl apply:  

Bash
kubectl apply -f job.yaml

创建之后 Kubernetes 就会从 YAML 的模板定义中提取 Pod,在 Job 的控制下运行 Pod,你可以用 kubectl get jobkubectl get pod 来分别查看 Job Pod 的状态:  

Bash
kubectl get job
kubectl get pod

 

显示为 Completed 表示任务完成,而 Job 里也会列出运行成功的作业数量,这里只有一个作业,所以就是 1/1

你还可以看到,Pod 被自动关联了一个名字,用的是 Job 的名字(echo-job)再加上一个随机字符串(4w9fj),这当然也是 Job 管理的功劳,免去了我们手工定义的麻烦,这样我们就可以使用命令 kubectl logs 来获取 Pod 的运行结果:

 

 

这里列出几个控制离线作业的重要字段,其他更详细的信息可以参考 Job 文档:

  • activeDeadlineSeconds,设置 job 运行的超时时间。
  • backoffLimit,设置 Pod 的失败重试次数。
  • completionsJob 完成需要运行多少个 Pod,默认是 1 个。
  • parallelism,它与 completions 相关,表示允许并发运行的 Pod 数量,避免过多占用资源。

要注意这 4 个字段是属于 Job 级别的,用来控制模板里的 Pod 对象。  

下面我再创建一个 Job 对象,名字叫“sleep-job”,它随机睡眠一段时间再退出,模拟运行时间较长的作业。Job 的参数设置成 15 秒超时,最多重试 2 次,总共需要运行完 4 Pod,但同一时刻最多并发 2 Pod:  

YAML
apiVersion: batch/v1
kind: Job
metadata:
  name: sleep-job
spec:
  activeDeadlineSeconds: 15
  backoffLimit: 2
  completions: 4
  parallelism: 2
  template:
    spec:
      restartPolicy: OnFailure
      containers:
      - name: echo-job
        image: busybox:latest
        imagePullPolicy: IfNotPresent
        command:
          - sh
          - -c
          - sleep $(($RANDOM % 10 + 1)) && echo done

使用 kubectl apply 创建 Job 之后,我们可以用 kubectl get pod -w 来实时观察 Pod 的状态,看到 Pod 不断被排队、创建、运行的过程:  

YAML
kubectl apply -f sleep-job.yaml
kubectl get pod -w

 

 

等到 4 Pod 都运行完毕,我们再用 kubectl get 来看看 Job Pod 的状态:  

 

 

就会看到 Job 的完成数量如同我们预期的是 4,而 4 Pod 也都是完成状态。

显然,声明式Job 对象让离线业务的描述变得非常直观,简单的几个字段就可以很好地控制作业的并行度和完成数量,不需要我们去人工监控干预,Kubernetes 把这些都自动化实现了。

 

使用 YAML 描述 CronJob  

使用命令 kubectl create 来创建 CronJob 的样板。

要注意两点。第一,因为 CronJob 的名字有点长,所以 Kubernetes 提供了简写 cj,这个简写也可以使用命令 kubectl api-resources 看到;第二,CronJob 需要定时运行,所以我们在命令行里还需要指定参数 --schedule

YAML
export out="--dry-run=client -o yaml "
kubectl create cj echo-cj --image=busybox --schedule=""  $out

然后我们编辑这个 YAML 样板,生成 CronJob 对象:  

YAML
apiVersion: batch/v1
kind: CronJob
metadata:
  name: echo-cj
spec:
  schedule: "*/1 * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          restartPolicy: OnFailure
          containers:
          - name: echo-cj
            image: busybox:latest
            imagePullPolicy: IfNotPresent
            command: ["/bin/echo"]
            args: ["hello", "world"]   

我们还是重点关注它的 spec 字段,你会发现它居然连续有三个 spec 嵌套层次:  

  • 第一个 spec CronJob 自己的对象规格声明
  • 第二个 spec 从属于“jobTemplate”,它定义了一个 Job 对象。
  • 第三个 spec 从属于“template”,它定义了 Job 里运行的 Pod

所以,CronJob 其实是又组合了 Job 而生成的新对象,我还是画了一张图,方便你理解它的套娃结构:  

 

 

除了定义 Job 对象的“jobTemplate”字段之外,CronJob 还有一个新字段就是“schedule”,用来定义任务周期运行的规则。它使用的是标准的 Cron 语法,指定分钟、小时、日、月、周,和 Linux 上的 crontab 是一样的。像在这里我就指定每分钟运行一次。

除了名字不同,CronJob Job 的用法几乎是一样的,使用 kubectl apply 创建 CronJob,使用 kubectl get cjkubectl get pod 来查看状态:  

Bash
kubectl apply -f cj-job.yaml
kubectl get cj
kubectl get pod

 

 

 

总结

单一职责  组合优于继承  


通过这种嵌套方式,Kubernetes 里的这些 API 对象就形成了一个控制链CronJob 使用定时规则控制 JobJob 使用并发数量控制 PodPod 再定义参数控制容器,容器再隔离控制进程,进程最终实现业务功能,链条里的每个环节都各司其职,在 Kubernetes 的统一指挥下完成任务。  

 

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

 

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。