8-4、Job Controller 一次性任务

文章介绍了K8s中用于一次性任务的工作类容器——Job和定时任务CronJob。Job的重启策略包括Never和OnFailure,以及失败回退次数和活跃期限设置。CronJob则允许定时执行Job,文章还提到了如何启用和配置CronJob以及如何管理Job的历史记录。
k8s 关于Job与Cronjob - 知乎  k8s 关于Job与Cronjob
   
容器按照持续运行的时间分为两类:
  • 服务类容器:提供持续服务,如http server、daemon、kubernetes的Deployment、ReplicaSet等;
  • 作类容器:一次性任务,比如批处理程序,完成后容器退出。

一、Job要点

1.1、Job重启与失败认定

重启策略(restartPolicy):
  • Never:pod启动失败时不会重启,而是通过job-controller重新创建pod供节点调度。
  • OnFailure:pod将会在节点重启执行任务。
失败回退策略(backoffLimit):
    当Job pod 经过多次重启无果,显然我们应该认定这个Job是一个失败任务,默认失败认定重启次数为6,我们可以通过在spec中添加backoffLimit来改变这一认定。

1.2、Job期限与清理

除了Job执行结束与重启失败认定的Job 终止外还可以通过配置活跃期限(activeDeadlineSeconds)来自动停止Job任务。
spec.activeDeadlineSeconds 设置一个秒数值。 该值适用于 Job 的整个生命期,无论 Job 创建了多少个 Pod。
一旦 Job 运行时间达到 activeDeadlineSeconds 秒,其所有运行中的 Pod 都会被终止,并且 Job 的状态更新为 type: Failed 及 reason: DeadlineExceeded。
   
添加spec.ttlSecondsAfterFinished使Job在任务完成后一段时间内被清理。
  

二、一个简单的Job配置文件 myjob.yaml

apiVersion: batch/v1    # 当前JobapiVersion, 根据kubectl api-resources查到
kind: Job
metadata:
  name: myjob
spec:
  template:
    metadata:
       name: myjob
    spec:
      containers:
      - name: hello
        image: busybox
        command: ["echo", "hell k8s"]
      restartPolicy: Never   # 指定什么情况下需要重启容器;对于Job只能设置为Never或者OnFailure,Job就相当于来执行一个批处理任务,执行完就结束了,如果支持Always的话会陷入了死循环了。对于其他Controller可设为Always
执行 kubectl apply -f myjob.yaml
kubectl get job查看Job的状态、 kubectl get pod查看你Pod的状态:
COMPLETIONS为1/1,表示按照预期启动了一个Pod,并且已经成功执行。
STATUS为Completed,表示任务已经完成。
  

三、Job运行失败会怎样?

apiVersion: batch/v1   # 当前JobapiVersion
kind: Job
metadata:
    name: myjob
spec:
    template:
        metadata:
            name: myjob
        spec:
            containers:
            - name: hello
              image: busybox
              command: ["invalid-command", "hello k8s job!"]
            restartPolicy: Never   # 指定什么情况下需要重启容器;对于Job只能设置为Never或者OnFailure。对于其他Controller可设为Always
kubectl apply -f myjob.yaml 创建Job
kubectl get job查看Job的状态:
  • 若restartPolicy取值 Never,Job失败,SUCCESSFUL的Pod个数为0。 kubectl get pods查看Pod的状态,看到有多个Pod( 默认 6个),状态均不正常。
       Never 下存在多个失败的Pod的原因:当第一个Pod启动时,容器失败退出,根据 restartPolicy:Never,此容器失败后不会被重启,但Job DESIRED的Pod是1,目前SUCCESSFUL为0,不满足,故 J ob Controller会启动新的Pod,直至SUCCESSFUL为1( k8s为Job提供spec.bakcofflimits来限制重试次数,默认值为6)。
kubectl edit job myjob:
  • 若restartPolicy取值 OnFailure,Job失败,SUCCESSFUL的Pod个数为0, kubectl get job --show-all查看Pod只有1个,RESTARTS为4,而且不断增加,说明OnFailure生效,容器失败后会自动重启。
kubectl describe pod  myjob--1-gxbhb  查看错误原因:
   

四、并行执行Job

有时希望同时运行多个Pod,提高Job的执行效率。可以通过 parallelism设置。
apiVersion: batch/v1   # 当前JobapiVersion
kind: Job
metadata:
    name: myjob
spec:
    parallelism: 2 # 将并行的pod数量设为2
    template:
        metadata:
            name: myjob
        spec:
            containers:
            - name: hello
              image: busybox
              command: ["echo", "hello k8s job!"]
            restartPolicy: OnFailure  # 指定什么情况下需要重启容器;对于Job只能设置为Never或者OnFailure。对于其他Controller可设为Always
Job一共启动了两个pod,在同一时间创建和结束:
  
通过 completions设置Job成功完成Pod的总数:
apiVersion: batch/v1   # 当前JobapiVersion
kind: Job
metadata:
    name: myjob
spec:
    completions: 6
    parallelism: 2     # 这两行的含义:每次运行两个Pod,直至有6pod成功完成
    template:
        metadata:
            name: myjob
        spec:
            containers:
            - name: hello
              image: busybox
              command: ["echo", "hello k8s job!"]
            restartPolicy: OnFailure    # 指定什么情况下需要重启容器;对于Job只能设置为Never或者OnFailure。对于其他Controller可设为Always
每次运行两个Pod,直至有6个pod成功完成:
  

五、定时执行Job

Kubernetes的 CronJob提供了定时执行Job。
apiVersion: batch/v1          # 当前CronJobapiVersion
kind: CronJob
metadata:
    name: hello
spec:
    schedule: "*/1 * * * *"     # 格式与linux cron一致
    jobTemplate:                 # 定义job模板
        spec:
            template:
                spec:
                    containers:
                    - name: hello           
                      image: busybox
                      imagePullPolicy: IfNotPresent
                      command: ["echo", "hello k8s job!"]
                    restartPolicy: Never  # 指定什么情况下需要重启容器;对于Job只能设置为Never或者OnFailure。对于其他Controller可设为Always
直接 kubectl apply -f cronjob.yaml会失败:
因为 kubernetes默认没有enable cronjob功能,需要在kube-apiserver中加入 这个功能,方法如下:
修改kube-apiserver的配置文件/etc/kubernetes/manifests/kube-apiserver.yaml
kube-apiserver 本身也是个 Pod,在启动参数中加上 --runtime-config=batch/v2alpha1=true 即可。
然后重启 kubelet 服务:systemctl restart kubelet.service
kubelet 会重启 kube-apiserver Pod。通过 kubectl api-versions 确认 kube-apiserver 现在已经支持 batch/v2alpha1
再次 kubectl apply -f cronjob.yaml,ok。通过 kubectl get cronjob 查看 CronJob 的状态:
等待几分钟后,通过 kubectl get jobs查看Job的执行情况:cronjob可以自动清理任务, 默认保留3次成功的任务
每隔1分钟就启动一个Job。执行kubectl logs查看某个Job的运行日志: hello k8s job!
   
spec.successfulJobsHistoryLimit:3, 每次限制启动的cronjob的个数为3个:可以修改这个参数改变保留历史任务信息
### Kubernetes Job BackoffLimitExceeded 错误的原因及解决方案 在 Kubernetes 中,Job 是一种控制器资源,用于管理短暂任务的执行。当 Job 控制的 Pod 在运行过程中多次失败时,Kubernetes 会尝试重启这些 Pod,直到达到一定的重试限制(即 `backoffLimit`)。如果达到了这个限制,Job 将停止进一步的重试,并报告 `BackoffLimitExceeded` 错误。 #### 原因分析 1. **Pod 失败次数超过 `backoffLimit`** `backoffLimit` 是一个配置选项,用于指定在 Job 被标记为失败之前,Pod 可以失败和重试的次数。默认情况下,该值为 6。如果 Job 的 Pod 在短时间内多次失败并达到此限制,则 Job 不会再尝试重启 Pod,而是直接标记为失败状态 [^3]。 2. **Pod 启动后立即失败** 如果 Pod 在启动后迅速失败,可能会导致无法及时获取日志信息。由于 KubernetesJob 控制器会在达到 `backoffLimit` 后删除 Pod,因此可能无法通过 `kubectl logs` 获取到完整的日志内容,从而难以定位问题的根本原因 [^1]。 3. **资源不足或配置错误** Pod 可能由于资源不足(如 CPU 或内存不足)或配置错误(如镜像拉取失败、环境变量缺失等)而频繁失败。这种情况下,Pod 会不断进入重启循环,最终触发 `BackoffLimitExceeded` 错误 [^2]。 4. **健康检查失败** 如果 Pod 配置了 `livenessProbe` 或 `readinessProbe` 探针,并且这些探针未能通过检查,Pod 也会被终止并重新启动。如果探针配置不当或应用本身存在问题,可能导致 Pod 频繁重启 [^2]。 #### 解决方案 1. **增加 `backoffLimit` 值** 如果任务较为复杂,或者需要更多时间来完成,可以适当增加 `backoffLimit` 的值,以允许更多的重试机会。例如,在 Job 的 YAML 文件中设置 `backoffLimit: 10`,这样 Job 会在 10 次失败后才停止 [^3]。 2. **延长 `initialDelaySeconds` 和 `failureThreshold`** 对于依赖外部服务或初始化时间较长的任务,可以通过调整 `livenessProbe` 和 `readinessProbe` 的参数来避免过早的失败判定。例如,增加 `initialDelaySeconds` 以给予应用更多时间启动,同时调整 `failureThreshold` 以容忍短期的失败 [^2]。 3. **检查 Pod 日志和事件** 在 Job 达到 `backoffLimit` 之前,应尽快使用 `kubectl describe pod <pod-name>` 和 `kubectl logs <pod-name>` 来查看 Pod 的详细状态和日志信息。这有助于快速定位问题的根本原因。如果无法及时获取日志,可以考虑启用 Kubernetes 的日志收集机制(如 Fluentd、Logstash 等)或将日志持久化存储 [^1]。 4. **优化资源分配** 确保 Pod 请求的资源(CPU 和内存)足够支持其正常运行。可以通过 `kubectl describe node` 查看节点资源使用情况,并根据实际需求调整 Pod 的资源请求和限制。此外,确保集群中有足够的可用节点来调度 Pod [^2]。 5. **验证镜像和配置** 检查 Pod 使用的容器镜像是否正确且可访问,确保所有必要的环境变量、卷挂载和命令参数都已正确配置。可以通过手动运行相同的容器镜像进行测试,以排除镜像本身的问题 [^2]。 6. **使用调试工具和服务** 如果问题仍然无法解决,可以使用 Kubernetes 提供的调试工具(如 `kubectl debug`)或第三方监控工具(如 Prometheus、Grafana)来深入分析 Pod 的行为和性能瓶颈 [^2]。 7. **启用 Job 的 `ttlSecondsAfterFinished`** 为了防止 Job 完成后长时间占用集群资源,可以在 Job 的 YAML 文件中设置 `ttlSecondsAfterFinished` 参数。该参数表示 Job 完成后保留的时间(以秒为单位),超过此时间后,Job 会被自动清理。这对于调试完成后释放资源非常有用 [^3]。 8. **使用 `parallelism` 和 `completions` 控制并发** 如果 Job 需要处理大量任务,可以通过设置 `parallelism` 和 `completions` 参数来控制并发执行的 Pod 数量。合理设置这些参数可以减少资源竞争和失败的可能性 [^3]。 --- ### 示例:调整 Job 的 `backoffLimit` 以下是一个简单的 Job 配置示例,展示了如何调整 `backoffLimit`: ```yaml apiVersion: batch/v1 kind: Job metadata: name: my-job spec: backoffLimit: 10 template: spec: containers: - name: my-container image: my-image:latest command: ["sh", "-c", "echo 'Hello from the job'; exit 1"] restartPolicy: OnFailure ``` 在这个例子中,`backoffLimit` 被设置为 10,意味着 Job 会在 10 次失败后才停止。同时,`restartPolicy` 设置为 `OnFailure`,表示只有在失败时才会重启容器 [^3]。 --- ### 总结 `BackoffLimitExceeded` 错误通常表明 Job 的 Pod 在短时间内多次失败,并且已经达到了预设的重试次数上限。为了解决这个问题,建议从以下几个方面入手:调整 `backoffLimit` 和探针参数、检查 Pod 日志和事件、优化资源分配、验证镜像和配置、以及使用调试工具进行深入分析。通过这些方法,可以有效提高 Job 的稳定性和可靠性,确保任务能够顺利完成 [^1][^2][^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值