Job 负责批量处理短暂的一次性任务 (short lived one-off tasks),即仅执行一次的任务,它保证批处理任务的一个或多个 Pod 成功结束。容器中的进程在正常运行结束后不会对其进行重启,而是将Pod对象置于"Completed"(完成)状态,若容器中的进程因错误而终止,则需要按照重启策略配置确定是否重启,未运行完成的Pod对象因其所在的节点故障而意外终止后会被调度。Job控制器的Pod对象的状态转换如下图所示:
Kubernetes 支持以下几种 Job:
根据 .spec.completions 和 .spec.Parallelism 的设置,可以将 Job 划分为以下几种 pattern:
有的作业可能需要运行不止一次,用户可以配置它们以串行或者并行的方式运行。
所谓 Bare Pods 是指直接用 PodSpec 来创建的 Pod(即不在 ReplicaSets 或者 ReplicationCtroller 的管理之下的 Pods)。这些 Pod 在 Node 重启后不会自动重启,但 Job 则会创建新的 Pod 继续任务。所以,推荐使用 Job 来替代 Bare Pods,即便是应用只需要一个 Pod。
一个简单的例子:
apiVersion: batch/v1
kind: Job
metadata:
name: pi
spec:
template:
metadata:
name: pi
spec:
containers:
- name: pi
image: perl
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
restartPolicy: Never
Job控制器的spec字段内嵌的必要字段只有template,不需要定义标签选择器,控制器会自动关联,除了这一点与Deployment控制器不同,其它别无二致。
1.创建Job控制器配置清单
使用busybox镜像,然后沉睡120s,完成后即正常退出容器。
cat busybox-job.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: busybox-job
spec:
template:
spec:
containers:
- name: busybox
image: busybox:latest
command: [ "/bin/sh", "-c", "sleep 120s" ]
restartPolicy: Never
Pod模版中的spec.restartPolicy默认为"Always",这对Job控制器来说非常不适用,"Never"和"OnFeailure"才比较合适Job控制器。
2.创建Job控制器
kubectl apply -f busybox-job.yaml
3.查看Job控制器及Pod状态
kubectl get job -o wide
NAME COMPLETIONS DURATION AGE CONTAINERS IMAGES SELECTOR
busybox-job 0/1 36s 36s busybox busybox:latest controller-uid=8e85200f-43eb-4f24-ab6d-64c545287d51
kubectl get pods -o wide | grep
busybox busybox-job-wtdvf 1/1 Running 0 45s 10.244.3.150 k8s-node01
120s后,Job控制器创建的Pod对象完成了任务。
kubectl get pods -o wide | grep
busybox busybox-job-wtdvf 0/1 Completed 0 3m38s 10.244.3.150 k8s-node01
4.查看Job控制器的详细信息
如下Selector与Lables都是Job控制器自动生成后自动关联,控制器自动生成的controller-uid-随机字符串,控制器携带了后面的字符串是为了防止所管理的Pod发生重合。
下面可以看到Job运行成功后及完成了操作并没有进程重启,这得助于我们设置的restartPolicy。
将并行度属性job.spec.parallelism的值设置为1,并设置总任务数job.spec.completions属性便能够让Job控制器以串行方式运行多任务,下面是一个需要串行5此任务的Job控制器示例:
cat busybox-job.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: busybox-job
spec:
parallelism: 1
completions: 5
template:
spec:
containers:
- name: busybox
image: busybox:latest
command: [ "/bin/sh", "-c", "sleep 20s" ]
restartPolicy: OnFailure
创建Job控制器:
kubectl apply -f busybox-job.yaml
动态监控Pod对象作业的变化:
kubectl get pods -l job-name=busybox-job --watch
NAME READY STATUS RESTARTS AGE
busybox-job-q8wqr 0/1 Pending 0 0s
busybox-job-q8wqr 0/1 Pending 0 0s
busybox-job-q8wqr 0/1 ContainerCreating 0 0s
busybox-job-q8wqr 1/1 Running 0 20s
busybox-job-q8wqr 0/1 Completed 0 39s
busybox-job-lppcw 0/1 Pending 0 0s
busybox-job-lppcw 0/1 Pending 0 0s
busybox-job-lppcw 0/1 ContainerCreating 0 0s
busybox-job-lppcw 1/1 Running 0 19s
busybox-job-lppcw 0/1 Completed 0 39s
busybox-job-8jw2q 0/1 Pending 0 0s
busybox-job-8jw2q 0/1 Pending 0 0s
busybox-job-8jw2q 0/1 ContainerCreating 0 0s
busybox-job-8jw2q 1/1 Running 0 19s
busybox-job-8jw2q 0/1 Completed 0 40s
busybox-job-bcxpn 0/1 Pending 0 0s
busybox-job-bcxpn 0/1 Pending 0 0s
busybox-job-bcxpn 0/1 ContainerCreating 0 0s
busybox-job-bcxpn 1/1 Running 0 18s
busybox-job-bcxpn 0/1 Completed 0 38s
busybox-job-5t7xm 0/1 Pending 0 0s
busybox-job-5t7xm 0/1 Pending 0 0s
busybox-job-5t7xm 0/1 ContainerCreating 0 0s
busybox-job-5t7xm 1/1 Running 0 20s
busybox-job-5t7xm 0/1 Completed 0 41s
如上,Job控制器需要执行五次任务,每次一个Pod执行一个任务,依次执行,执行成功后的Pod即为完成状态:
kubectl get pods -l job-name=busybox-job
NAME READY STATUS RESTARTS AGE
busybox-job-5t7xm 0/1 Completed 0 4m22s
busybox-job-8jw2q 0/1 Completed 0 5m40s
busybox-job-bcxpn 0/1 Completed 0 5m
busybox-job-lppcw 0/1 Completed 0 6m19s
busybox-job-q8wqr 0/1 Completed 0 6m58s
并行式Job我们只需要修改job.spec.parallelism属性与job.spec.completions属性即可:
如下示例一个5个作业,同时启动5个队列进行作业。
cat busybox-job.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: busybox-job
spec:
parallelism: 5
completions: 5
template:
spec:
containers:
- name: busybox
image: busybox:latest
command: [ "/bin/sh", "-c", "sleep 20s" ]
restartPolicy: OnFailure
kubectl apply -f busybox-job.yaml
查看Job控制器运行状态,如下Job控制器中的Pod对象创建时间是一致的。
Job控制器中的Pod运行完成后,将不再占用系统资源,用户可以按照需求保留或使用资源删除命令将Pod删除,不过如果某控制器的容器应用总是无法正常结束运行,而其restartPolicy又设置为了重启,则它可能会一直处于不停地重启和错误的循环当中。所幸的是,Job控制器提供了两个属性用于抑制这种情况的发生,具体如下:
例如,下面的配置清单为,表示其失败重试次数为5此,并且如果超出100秒的时间仍然未运行完成,那么则将其终止:
cat busybox-job.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: busybox-job
spec:
backoffLimit: 5
activeDeadlineSeconds: 100
parallelism: 1
completions: 5
template:
spec:
containers:
- name: busybox
image: busybox:latest
command: [ "/bin/sh", "-c", "sleep 30s" ]
restartPolicy: OnFailure
```
Job用来创建1个或多个Pod,并保证指定数量(.spec.completions)的Pod成功完成。当一个Pod成功完成时(.status.phase=Succeeded),Job会记录已完成的Pod的数量,但完成的数量达到指定值时,这个Job就完成了。可以通过以下3种方式来判断一个Job是否已完成:
Pod的中的容器可能因为各种各样的原因失败,比如退出码不为0、超出内存限制被kill掉,容器失败分两种情况:
当Pod执行失败时,Job会不断创建一个新的Pod进行重试,直到失败次数达到.spec.backoffLimit指定的数值,整个Job的执行失败。可以通过判断.status.failed和.spec.backoffLimit是否相等,即已失败数是否已经达到上限,来判断Job是否已经执行失败。如下,当.spec.backoffLimit设置为3时,.status.failed已经达到3,Job失败,不会再尝试创建新的Pod:
kubectl get -n demo jobs j-centos-2020-08-01-15-19-55-w -oyaml |grep status -A 10
status:
conditions:
- lastProbeTime: "2020-08-01T07:21:04Z"
lastTransitionTime: "2020-08-01T07:21:04Z"
message: Job has reached the specified backoff limit
reason: BackoffLimitExceeded
status: "True"
type: Failed
failed: 3
startTime: "2020-08-01T07:19:55Z"
如果Pod在执行过程中被意外删除(如使用kubectl delete),Job会重新创建一个新的Pod。
适用场景
Job不是设计用来完成通信密集型的并行程序,如科学计算领域常见的场景。它支持并行地处理一组独立但相关的work item,如发送邮件,渲染帧,转码文件和扫描NoSql数据库中的key。
Job Controller 负责根据 Job Spec 创建 Pod,并持续监控 Pod 的状态,直至其成功结束。如果失败,则根据 restartPolicy(只支持 OnFailure 和 Never,不支持 Always)决定是否创建新的 Pod 再次重试任务。
Job · Kubernetes指南
k8s Job详解_祈晴小义的博客-CSDN博客_k8s的job
带你快速了解 K8S Job - 知乎
k8s 关于Job与Cronjob - 知乎
深入K8S Job(一):介绍 - UCloud云社区
Kubernetes(K8s)之Job控制器
深入K8S Job(一):介绍
kubernetes - 深入K8S Job(一):介绍_个人文章 - SegmentFault 思否
kubernetes Job讲解 - 尘叶心繁的专栏 - TNBLOG
Jobs | Kubernetes
深入K8S Job(二):job controller源码分析 - UCloud云社区
Kubernetes Job Controller 原理和源码分析(一) - 知乎
Job | Kubernetes