k8s容器编排技术实践——k8s对象job应用详解

k8s容器编排技术实践------K8s对象deployment应用详解https://blog.csdn.net/xiaochenXIHUA/article/details/161427275k8s容器编排技术实践------k8s的介绍及其整体运行架构https://coffeemilk.blog.csdn.net/article/details/161011629

一、job简介

容器按照持续运行的时间可分为两类:【服务类容器】和【工作类容器】:

  1. 【服务类容器】通常持续提供服务,需要一直运行(如:http server,mysql db等)。
  2. 【工作类容器】则是一次性任务(如批处理程序,完成后容器就退出)。

k8s中的的Deployment、ReplicaSet和DaemonSet都用于管理服务类容器;

对于工作类容器,可以使用Job。

1.1、job是什么

job 是 Kubernetes(k8s) 原生的一类控制器(Controller) ,专门用于管理一次性、短时运行的任务 ,核心目标是保证任务最终成功执行完成

与 Deployment/StatefulSet 这类常驻服务控制器有本质区别:

  • Deployment:期望 Pod 永久运行(业务服务、接口、中间件等),Pod 退出会立刻重建;
  • Job:期望 Pod 执行完任务后正常退出,只要任务未完成,就会不断重试,直到任务执行成功。
序号 k8s中job的工作机制
1 Job 会根据配置创建一组 Pod,持续监控 Pod 运行状态;
2 若 Pod 异常崩溃、节点宕机、任务执行失败,Job 会自动重建 / 重启 Pod 重试任务;
3 所有指定任务全部执行成功后,Job 标记为完成状态,不再新建 Pod;
4 默认情况下,执行完成 / 失败的 Pod 会保留在集群中,方便查看日志、排查问题。

1.2、job有啥用

job的核心作用 说明
保障一次性任务可靠执行 天然内置重试机制,规避节点故障、程序闪退导致的任务中断,保证任务不丢失;
统一调度与资源管控 继承 K8s 完整能力(资源配额、节点亲和、污点容忍、网络 / 存储挂载等),和集群业务统一管理;
支持并行批处理 通过调整并发数,实现大批量任务并行执行,提升处理效率;
任务状态可追溯 完成 / 失败的 Pod 默认保留,日志、运行现场可留存,便于问题排查;
作为定时任务基础 K8s 的 CronJob(定时任务)底层就是定时创建 Job,是集群标准定时批处理方案。

1.3、job的适用与不适用场景

✅Job主打短生命周期、一次性、离线、批处理类任务,在生产中最常用的场景如下表:

✅job的典型适用场景 说明
数据批处理 & ETL 离线任务 日志清洗、数据同步、数据库全量备份 / 恢复、大数据计算、文件批量转换、报表离线统计等。 > 例:凌晨批量同步业务数据、每日日志归档。
集群临时运维操作 集群初始化、数据库建库 / 初始化脚本、批量修改配置、批量清理临时文件、节点巡检脚本执行等。 > 例:新环境上线前执行一次性初始化脚本。
短时计算 / 测试任务 短时压力测试、离线模型推理、批量校验数据、临时脚本运行等(执行时长从几秒到几小时都可)。
定时任务(配合 CronJob) 这是生产高频用法:基于 Cron 表达式定时触发 Job,实现周期性任务。 > 例:每天 0 点数据库备份、每周一生成业务报表、每小时清理垃圾文件。
批量异步任务 拆分大量独立子任务,通过 Job 并行执行,比如批量推送消息、批量处理订单数据等。
❌job绝对不适用场景 说明
常驻业务服务 Web 服务、API 接口、网关、消息队列等需要 7×24 运行的服务(用 Deployment/StatefulSet);
长周期不间断任务 持续数天的超长时间任务(节点重启、网络波动会频繁触发重试,易造成重复执行);
复杂多步骤流水线 串行 / 分支 / 依赖的多阶段任务(原生 Job 无编排能力,建议用 Argo Workflows、Tekton);
需要断点续跑的任务 大文件分片上传、超大计算任务(Job 失败默认从头重试,不支持断点);
需要灰度 / 滚动更新的业务 Job 是一次性任务,没有版本迭代、灰度发布设计。

1.4、job的优缺点

✅job的优点 说明
可靠性高,开箱即用重试 原生支持失败重试、最大重试次数限制,无需自己开发重试逻辑,解决裸跑 Pod 任务中断丢失的问题。
轻量简单,学习成本低 配置简洁,只聚焦 "任务执行" 本身,没有常驻服务的滚动更新、探针、扩缩容等复杂逻辑。
灵活支持并行批处理 通过 parallelismcompletions 组合,轻松实现串行、分批并行、全并行三种任务模式,适配不同批量场景。
集群生态统一 完整支持 K8s 资源限制、存储、网络、权限、调度策略,和集群其他组件无缝配合。
状态可审计、可排查 失败 / 完成的 Pod 默认保留,可随时查看容器日志、运行状态,定位任务失败原因。
定时能力扩展强 结合 CronJob 即可实现标准定时任务,是 K8s 官方推荐的定时方案,替代传统 Crontab。
❌job的缺点 说明
Pod 不会自动清理,资源易堆积 Job 完成后 Pod 默认永久保留,大量历史 Job 会堆积无用 Pod,占用集群 etcd 和节点资源。 > 解决方案:开启 spec.ttlSecondsAfterFinished,任务完成后自动删除 Pod。
原生不支持断点续跑 任务一旦中断 / 失败,只能整体重新执行,无法从失败位置继续,对超大任务不友好。
复杂任务编排能力弱 无法原生实现「任务 A 执行完再跑任务 B」「分支判断」「循环执行」等流水线逻辑,复杂作业必须依赖第三方工作流组件。
重试粒度粗 仅支持 Pod 级别整体重试,不能针对任务内部局部异常单独重试,小问题也会重跑整个任务。
运行中无法动态调整并发 Job 启动后,想修改并行数 parallelism 需要手动编辑 Job 配置,原生不支持运行时动态弹性扩缩。
长时间任务稳定性差 若任务运行时间极长,节点重启、网络抖动都会触发重试,极易导致任务重复执行(比如重复备份、重复写入数据)。
无自愈之外的高级运维能力 没有健康探针、优雅终止、流量管理等常驻服务的能力,不适合对外提供服务。

二、job示例解析

2.1、job示例

bash 复制代码
#job示例
#1-创建job示例
cat >jobdemo.yml<<EOF
# 1. API 版本:指定使用的K8s API组和版本
apiVersion: batch/v1
# 2. 资源类型:定义这是一个Job资源
kind: Job
# 3. 元数据:Job的基本标识信息
metadata:
  name: myjob  # Job的唯一名称(集群内不可重复)
# 4. Job规格:定义任务的执行规则
spec:
  # Pod模板:Job的核心,Job会基于这个模板创建Pod来执行任务
  template:
     spec:
        # 容器定义:Pod中运行的容器
        containers:
            - name: job          # 容器名称
              image: library/busybox     # 容器使用的镜像(轻量级Linux基础镜像,自带常用命令)
              command: ["echo","hello k8s"]  # 容器启动后执行的命令:打印 hello k8s
        # 重启策略:容器退出后,K8s的重启规则
        restartPolicy: Never
EOF


#2-创建Job资源
kubectl apply -f jobdemo.yml

#3-查看当前所有pod状态
kubectl get pod

#4-查看当前所有的Job状态
kubectl get Job

#5-查看指定Job的日志
kubectl logs myjob-8dt8v

#6-删除指定Job资源
kubectl delete -f jobdemo.yml
deployment资源文件内容 说明
apiVersion 当前配置格式的版本(先执行kubectl api-resources找到所有的资源,再执行命令 kubectl explain jobs即可获取到版本和类型信息)
kind 要创建的资源类型,这里是Job
metadata 该资源的元数据,name是必需的元数据项,后面名字任意起一个即可。
第一个spec 第一个spec部分是该Job的规格说明
template 定义Pod的模板,这是配置文件的重要部分。
第二个spec 第二个spec描述Pod的规格,此部分定义Pod中每一个容器的属性,name和image是必需的。 注意:最后name前面需要加个中杠,是因为container后面是一个列表。
restartPolicy 用来指定什么情况下需要重启容器。对于Job,只能设置为NeverOnFailure 对于其它的controller(比如 Deployment)可以设置为Always。 1. Never表示不论状态为何, kubelet都不重启该容器; 2. OnFailure表示容器终止运行,且退出码不为0时重启; 3. Always表示容器失效时,kubelet自动重启该容器;

2.2、job失败分析

上面展示了job执行成功的情况,若执行失败会怎样呢?(模拟错误:修改 jobdemo.yml,故意引入一个错误【即将 command: "echo","hello k8s"修改为:command: "echocoffeemilk","hello k8s"):

bash 复制代码
#手动模拟一个故障job
#1-修改 jobdemo.yml,故意引入一个错误【即将 command: ["echo","hello k8s"]修改为:command: ["echocoffeemilk","hello k8s"]

#2-创建job资源
kubectl apply -f jobdemo.yml

#3-查看当前所有Pod状态
kubectl get pod

#4-查看指定pod的详细信息(可通过该命令了解到具体的执行流程内容与报错信息)
kubectl describe pod myjob-ckn4d

通过如上截图可以了解到是由于echocoffeemilk命令不存在,导致的报错。

为什么kubectl get pod会看到这么多个失败的 Pod?如下图所示:

kubectl get pod会看到这么多个失败的 Pod看到很多原因解析 说明
restartPolicy: Never 的作用(控制单个 Pod 内部是否重启容器) 这个策略只作用于单个 Pod: 当 Pod 内的容器启动失败 / 异常退出时,kubelet 不会在当前这个 Pod 里重启容器 ,直接把整个 Pod 标记为「失败 Pod」,所以截图里所有 myjob Pod 的RESTARTS列都是 0。
Job 控制器的重试逻辑(控制新建 Pod) Job 控制器的目标:生成 spec.completions(默认值 = 1)个正常执行完成的 Pod 才算任务结束。 * 当前所有新建的 Pod 全部启动失败(StartError),成功完成的 Pod 数量 = 0,没达到目标值 1; * 只要成功 Pod 数量不足,Job 控制器就会不断创建全新的 Pod 重新尝试; * Job 默认配置 backoffLimit: 6:最多重试创建 6 个失败 Pod,到达上限后 Job 停止新建 Pod。 截图里正好 6 个myjob-xxx失败 Pod,就是触发了默认 6 次重试上限。 为了终止这个行为,只能删除此job。
bash 复制代码
#优化 Job 配置(避免大量失败 Pod)
cat > jobdemo.yml <<EOF
apiVersion: batch/v1
kind: Job
metadata:
  name: myjob
spec:
  backoffLimit: 2 # 最多只重试2次,只会产生3个Pod(初始1+重试2)
  template:
     spec:
        containers:
            - name: job
              image: busybox
              command: ["echocoffeemilk","hello k8s"]
        restartPolicy: Never
EOF

如果将restartPolicy 设置为OnFailure会怎么样(根据OnFailure的含义,当pod失败后,会进行重启,因此,可以看到pod只有一个,但是pod的RESTARTS会不断增加,这说明了容器失败后会自动重启)。

bash 复制代码
#将restartPolicy 设置为OnFailure
cat >jobdemo.yml <<EOF
apiVersion: batch/v1
kind: Job
metadata:
  name: myjob
spec:
  backoffLimit: 3  # 最多3次失败重试(默认6)
  template:
    spec:
      containers:
      - name: job
        image: busybox
        command: ["echocoffeemilk","hello k8s"] #(模拟失败)
      restartPolicy: OnFailure  # 关键修改
EOF


#创建资源
kubectl apply -f jobdemo.yml

#查看所有资源的状态
kubectl get pod

#最后一定要删除资源
kubectl delete -f jobdemo.yml

2.3、定时执行job

Linux中有crontab程序定时执行任务,k8s的CronJob也提供了类似的功能,可以定时执行Job。

bash 复制代码
#定时执行job示例
cat >cronjob.yml<<EOF
apiVersion: batch/v1
kind: CronJob
metadata:
  name: cronjobdemo
spec:
  schedule: "*/1 * * * *"
  jobTemplate:
    spec:
      template:
         spec:
           containers:
             - name: cronjobdemo
               image: busybox
               command: ["echo","hello k8s cron_job!"]
           restartPolicy: OnFailure
EOF


#创建资源
kubectl apply -f cronjob.yml

#查看所有cronjobs配置内容
kubectl get cronjobs

#查看所有真正执行定时任务的状态
kubectl get job

#查看所有pod状态
kubectl get pod

#查看指定的pod定时任务日志
kubectl logs cronjobdemo-29670621-xrclb

#删除指定资源
kubectl delete -f cronjob.yml