1 Job任务控制器简介

Kubernetes的Job是一种一次性任务控制器,它保证指定数量的Pod成功退出(返回码0)后,任务即视为完成并停止重试。Job适合批处理、数据迁移、离线计算等跑完就结束的场景。

2 Job的核心特征

  • 一次性:Pod正常结束即Job完成,不会无限重启。
  • 可并行:通过completions/parallelism字段让多个Pod同时跑。
  • 重试策略:失败时按backoffLimit(默认6)重新创建新Pod。
  • 完成计数:可要求N个Pod都成功才算整体完成。

3 Job与Deployment 的区别

维度 Job Deployment
目标 一次性任务完成 长期运行服务
Pod结束 期望成功退出 期望永远运行
重启策略 Never/OnFailure Always
完成状态 有Complete/Failed 无完成概念

4 一个典型的Job控制器资源清单文件

下面这个Job资源清单,利用busybox镜像+hostPath挂载,在宿主机/root/k8s-test/data/time-job.log追加写入一行带时间戳的日志,运行一次即完成,所有字段共同保证了一次性任务 + 数据落盘 + 失败重试的需求。

[root@master 14-job]# cat busybox-job.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: time-writer-job
spec:
  template:
    spec:
      containers:
      - name: writer
        image: busybox:1.34.1
        command:
        - /bin/sh
        - -c
        - |
          echo "$(date '+%F %T') - hello from busybox (one-shot)" >> /opt/cronjob/time-job.log
        volumeMounts:
        - name: hostdir
          mountPath: /opt/cronjob
      restartPolicy: OnFailure
      volumes:
      - name: hostdir
        hostPath:
          path: /root/k8s-test/data
          type: DirectoryOrCreate

下面是对这个资源清单的具体解释。
(1) 顶层字段

apiVersion: batch/v1        # 资源组/版本:Job属于batch组,v1是当前稳定版
kind: Job                   # 资源类型:Job控制器
metadata:
  name: time-writer-job     # Job对象名称,集群内唯一;Pod名会以此作为前缀

(2) Job规约(spec)
Job本身只有模板级字段;真正描述“跑什么”的内容全在template里。

(3) Pod模板(spec.template)

spec:
  template:                      # Pod模板,Job根据它生成Pod
    spec:                        # Pod规约
      restartPolicy: OnFailure   # 必须写!Job不支持Always;失败才重启容器

(4) 容器(spec.template.spec.containers[0])

containers:
- name: writer              # 容器名称,可随意;日志/排障时会看到
  image: busybox:1.34.1     # 轻量级工具镜像,内置/bin/sh、date、echo等命令
  command:                  # 覆盖镜像默认入口,实现“一次性写文件”
  - /bin/sh
  - -c
  - |
    echo "$(date '+%F %T') - hello from busybox (one-shot)" >> /opt/cronjob/time-job.log
  # 说明:
  #   $(date '+%F %T')  → 2024-06-25 14:32:45
  #   >> 追加写入,多次运行Job不会覆盖旧内容

(5) 挂载(volumeMounts + volumes)

volumeMounts:
- name: hostdir             # 对应下方volumes名称
  mountPath: /opt/cronjob   # 容器里看到的目录;若不存在会自动创建

volumes:
- name: hostdir
  hostPath:                        # 直接把节点宿主机目录挂进来
    path: /root/k8s-test/data      # 宿主机绝对路径
    type: DirectoryOrCreate        # 若宿主机上不存在,则先自动创建

5 Job控制器示例

下面的示例是在有一个控制平面节点和两个工作节点的集群内,运行一个Job,向宿主机/root/k8s-test/data/time-job.log追加写入一行带时间戳的日志。
操作步骤如下:

(1) 查看集群信息

有一个master节点和两个worker节点
[root@master 14-job]# kubectl get node -o wide
NAME      STATUS   ROLES                  AGE     VERSION        INTERNAL-IP      EXTERNAL-IP   OS-IMAGE              KERNEL-VERSION                    CONTAINER-RUNTIME
master    Ready    control-plane,master   10m     v1.29.6+k3s1   192.168.88.132   <none>        openEuler 22.03 LTS   5.10.0-60.18.0.50.oe2203.x86_64   docker://20.10.0
worker1   Ready    <none>                 9m58s   v1.29.6+k3s1   192.168.88.134   <none>        openEuler 22.03 LTS   5.10.0-60.18.0.50.oe2203.x86_64   docker://20.10.0
worker2   Ready    <none>                 9m6s    v1.29.6+k3s1   192.168.88.135   <none>        openEuler 22.03 LTS   5.10.0-60.18.0.50.oe2203.x86_64   docker://20.10.0
默认命名空间下没有pod
[root@master 14-job]# kubectl get pod -o wide
No resources found in default namespace.

(2) 编写Job资源配置文件清单

# Job配置文件
[root@master 14-job]# cat busybox-job.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: time-writer-job
spec:
  template:
    spec:
      containers:
      - name: writer
        image: busybox:1.34.1
        command:
        - /bin/sh
        - -c
        - |
          echo "$(date '+%F %T') - hello from busybox (one-shot)" >> /opt/cronjob/time-job.log
        volumeMounts:
        - name: hostdir
          mountPath: /opt/cronjob
      restartPolicy: OnFailure
      volumes:
      - name: hostdir
        hostPath:
          path: /root/k8s-test/data
          type: DirectoryOrCreate

(3) 创建Job资源

# job已创建,已执行完毕
[root@master 14-job]# kubectl apply -f busybox-job.yaml
job.batch/time-writer-job created

(4) 查看Job详情

# Job已运行完毕,COMPLETIONS字段1/1,前面的1表示已经完成的Pod数量,后面的1表示当前Job需要完成的总Pod数量
[root@master 14-job]# kubectl get job
NAME              COMPLETIONS   DURATION   AGE
time-writer-job   1/1           3s         7s
# Job被调度到worker1节点执行。
[root@master 14-job]# kubectl get pod -o wide
NAME                    READY   STATUS      RESTARTS   AGE   IP          NODE      NOMINATED NODE   READINESS GATES
time-writer-job-cxr4c   0/1     Completed   0          13s   10.42.1.2   worker1   <none>           <none>

(5) 查看Job写入的log文件
【此步骤需要在worker1节点虚拟机执行】
上一步骤,查看Job详情,看到Job被调度到worker1节点,所以需要在worker1节点查看文件写入情况。

# 进入worker1宿主机目录
[root@worker1 install-k3s]# cd /root/k8s-test/data/
[root@worker1 data]# ls
time-job.log
# 查看Job写入的带时间戳的日志文件
[root@worker1 data]# cat time-job.log
2025-08-09 21:45:06 - hello from busybox (one-shot)

Job默认只创建"spec.completions"个Pod(本示例里缺省为1),调度器把它们随机分配到当前可用的任意节点上。除非显式指定了.spec.parallelism>1或与节点亲和性/DaemonSet机制配合使用,否则不会出现“每个节点都跑一份Job”的情况,也不会自动扩散到全部节点。想让Job在所有节点上各跑一次,需要用到DaemonSet或在Job模板里加nodeAffinity手动拆成多份。DaemonSet和节点亲和性我们在后面章节将会讲到。

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐