深入K8s:Kubernetes的任务调用Job与CronJob及源码分析

本文深入探讨Kubernetes中的Job和CronJob,包括它们的基本使用、参数说明和源码分析。通过示例展示了如何创建和配置Job与CronJob,以及并行任务处理、定时策略和失败处理。同时,文章通过源码分析揭示了K8s在任务调度和管理上的内在逻辑。
摘要由CSDN通过智能技术生成

推荐阅读:

在使用job中,我会结合源码进行一定的讲解,我们也可以从源码中一窥究竟,一些细节k8s是如何处理的,从而感受k8s的魅力。

Job

Job的基本使用

Job主要是用来任务调用,可以一个或多个 Pod,并确保指定数量的 Pod 可以成功执行到进程正常结束。

创建一个Job:

apiVersion: batch/v1
kind: Job
metadata:
  name: pi
spec:
  template:
    spec:
      containers:
      - name: pi
        image: perl
        command: ["perl",  "-Mbignum=bpi", "-wle", "print bpi(2000)"]
      restartPolicy: Never
  backoffLimit: 4

这个Job会创建一个容器,然后执行命令进行π的计算,

然后我们创建这个pod:

$ kubectl create -f job.yaml

$ kubectl describe jobs/pi

Name:           pi
Namespace:      default
Selector:       controller-uid=cf78ebe4-07f9-4234-b8f9-2fe92df352ea
Labels:         controller-uid=cf78ebe4-07f9-4234-b8f9-2fe92df352ea
                job-name=pi
Annotations:    Parallelism:  1
Completions:    1
...
Pods Statuses:  0 Running / 1 Succeeded / 0 Failed
Pod Template:
  Labels:  controller-uid=cf78ebe4-07f9-4234-b8f9-2fe92df352ea
           job-name=pi
  Containers:
   pi:
    Image:      resouer/ubuntu-bc
    ...
Events:
  Type    Reason            Age   From            Message
  ----    ------            ----  ----            -------
  Normal  SuccessfulCreate  29m   job-controller  Created pod: pi-g9fs4
  Normal  Completed         27m   job-controller  Job completed

可以看到创建对象后,Pod模板中,被自动加上了一个controller-uid=< 一个随机字符串 > 这样的 Label。而这个 Job 对象本身,则被自动加上了这个 Label 对应的 Selector,从而 保证了 Job 与它所管理的 Pod 之间的匹配关系。这个uid避免了不同Job对象的Pod不会重合。

$ kubectl get pod
NAME           READY   STATUS      RESTARTS   AGE
pi-g9fs4       0/1     Completed   0          33m

$ kubectl describe pod pi-g9fs4
...
Events:
  Type    Reason     Age   From                     Message
  ----    ------     ----  ----                     -------
  Normal  Scheduled  35m   default-scheduler        Successfully assigned default/pi-g9fs4 to 192.168.13.130
  Normal  Pulling    35m   kubelet, 192.168.13.130  Pulling image "resouer/ubuntu-bc"
  Normal  Pulled     35m   kubelet, 192.168.13.130  Successfully pulled image "resouer/ubuntu-bc"
  Normal  Created    35m   kubelet, 192.168.13.130  Created container pi
  Normal  Started    35m   kubelet, 192.168.13.130  Started container pi

我们可以看到Pod在创建好运行完毕之后会进入到Completed状态。上面的yaml定义中restartPolicy=Never也保证了这个Pod只会运行一次。

如果创建的Pod运行失败了,那么Job Controller会不断创建一个新的Pod:

$ kubectl get pods
NAME                                READY     STATUS              RESTARTS   AGE
pi-55h89                            0/1       ContainerCreating   0          2s
pi-tqbcz                            0/1       Error               0          5s
参数说明

spec.backoffLimit

我们在上面的字段中定义了为4,表示重试次数为4。

restartPolicy

在运行过程中,可能发生各种系统问题导致的Pod运行失败,如果设置restartPolicy为OnFailure,那么在运行中发生的失败后Job Controller会重启Pod里面的容器,而不是创建新的Pod。

还可以设置为Never,表示容器运行失败之后不会重启。

spec.activeDeadlineSeconds

表示最长运行时间,单位是秒。如:

spec:
 backoffLimit: 5
 activeDeadlineSeconds: 100

这样设置之后会进入pastActiveDeadline进行校验job.Spec.ActiveDeadlineSeconds是不是为空,不是空的话,会比较Pod的运行时间duration是否大于job.Spec.ActiveDeadlineSeconds设置的值,如果大于,那么会标记Pod终止的原因是DeadlineExceeded。

在job Controller的源码中,我们可以看到这部分的逻辑:

job Controller首先会去校验任务是不是处理次数是不是超过了BackoffLimit设置,如果没有超过的话就校验有没有设置ActiveDeadlineSeconds,如果设置了的话,就校验当前job运行时间是否超过了ActiveDeadlineSeconds设置的的时间,超过了那么会打上标记,表示这个job运行失败。

...
    jobHaveNewFailure := failed > job.Status.Failed

    exceedsBackoffLimit := jobHaveNewFailure && (active != *job.Spec.Parallelism) &&
        (int32(previousRetry)+1 > *job.Spec.BackoffLimit)

    if exceedsBackoffLimit || pastBackoffLimitOnFailure(&job, pods) {
        // check if the number of pod restart exceeds backoff (for restart OnFailure only)
        // OR if the number of failed jobs increased since the last syncJob
        jobFailed = true
        failureReason = "BackoffLimitExceeded"
        failureMessage = "Job has reached the specified backoff limit"
    } else if pastActiveDeadline(&job) {
        jobFailed = true
        failureReason = "DeadlineExceeded"
        failureMessage = "Job was active longer than specified deadline"
    }
...

func pastActiveDeadline(job *batch.Job) bool {
    if job.Spec.ActiveDeadlineSeconds == nil || job.Status.StartTime == nil {
        return false
    }
    now := metav1.Now()
    start := job.Status.StartTime.Time
    duration := now.Time.Sub(start)
    allowedDuration := time.Duration(*job.Spec.ActiveDeadlineSeconds) * time.Second
    return duration >= allowedDuration
}

Job的并行任务

在 Job 对象中,负责并行控制的参数有两个:

  1. spec.parallelism表示一个 Job 在任意时间最多可以启动多少个 Pod 同时运行;
  2. spec.completions表示Job 的最小完成数。

举例:

apiVersion: batch/v1
kind: Job
metadata:
  name: pi
spec:
  parallelism: 2
  completions: 4
  template:
    spec:
      containers:
      - name: pi
        image: perl
        command: ["perl&#
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值