Kubernetes技术详解-从理论到实践-(14)-控制器-Job
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和节点亲和性我们在后面章节将会讲到。
更多推荐


所有评论(0)