Kubernetes入门实践(Job/CronJob)
基于Pod的设计理念,Kubernetes有两种对象Job和CronJob
Job和CronJob组合了Pod,实现了对离线业务的处理。如Nginx和busybox,分别代表了Kubernetes里的两大类业务: Nginx这样长时间运行的在线业务和busybox这样的短时间运行的离线业务。在线业务类型的应用有: Nginx、Node.js、MySQL、Redis等等,一旦运行起来基本上不会停。
而离线业务类型的应用并不少见,一般不直接服务于外部用户,只对内部用户有意义,比如日志分析、数据建模、视频转码等等,虽然计算量很大,但只会运行一段时间,离线业务的特点是必定会退出,不会无期限地运行下去,其调度策略与在线业务存在很大的不同,要考虑运行超时、状态检查、失败重试、获取计算结果等管理事项。
这些业务特性与容器管理没有必然的联系,如果由Pod来实现就违反了"单一职责"的原则,所以应该将这部分功能分离到另外一个对象上实现,让这个对象去控制Pod的运行,完成附加的工作。
离线任务可以分为两种,一种是"临时任务",跑完就结束了,另一种是定时任务,可以按时间点周期运行。在Kubernetes中,临时任务就是API对象Job,定时任务就是API对象CronJob,使用这两个对象就能在Kubernetes中调度管理任意的离线任务。
使用YAML描述Job
Job的YAML的基本信息同样要包括3个基本字段:
- apiVersion不是v1,而是batch/v1
- kind是Job,这和对象名字一致
- metadata里要有name标记名字,可以用labels添加任意的标签
可以用kubectl命令explain job
来查看其字段说明
$ minikube kubectl -- explain job KIND: Job VERSION: batch/v1 DESCRIPTION: Job represents the configuration of a single job. FIELDS: apiVersion <string> APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources kind <string> Kind is a string value representing the REST resource this object ....
使用如下命令生成一个YAML模板:
$ minikube kubectl -- create job echo-job --image=busybox --dry-run=client -o yaml apiVersion: batch/v1 kind: Job metadata: creationTimestamp: null name: echo-job spec: template: metadata: creationTimestamp: null spec: containers: - image: busybox name: echo-job resources: {} restartPolicy: Never status: {}
对于非Pod的API对象来说,要使用create,而非run来启动,--dry-run指定为空运行,-o 是生成YAML格式
做一些简单的修改:
apiVersion: batch/v1 kind: Job metadata: name: echo-job spec: template: spec: containers: - image: busybox name: echo-job imagePullPolicy: IfNotPresent command: ["/bin/echo"] args: ["hello","world"] restartPolicy: OnFailure
可以发现Job对象的YAML描述比Pod在spec里多了一个template,然后其中又有一个spec,这是对Pod进行了一个简单的包装,template下的spec就可以理解为Pod的spec,这是一种模板思想,其中嵌入一个Pod,这样Job就可以从模板来创建出Pod。sepc中多了一个字段restartPolicy,确定Pod运行失败时的策略,这个字段有一些值: OnFailure失败原地重启容器,Never不重启容器,让Job重新调度生成一个新的Pod
Kubernetes中操作Job
使用apply创建Job对象:
$ minikube kubectl -- apply -f job.yml job.batch/echo-job created
创建之后Kubernetes就会从YAML的模板定义中提取Pod,在Job控制下运行Pod,可以用get job
和get pod
来分别查看Job和Pod状态:
$ minikube kubectl -- get job NAME COMPLETIONS DURATION AGE echo-job 1/1 2s 6m23s $ minikube kubectl -- get pod NAME READY STATUS RESTARTS AGE busy-pod 0/1 CrashLoopBackOff 55 (4m23s ago) 15h echo-job-hrqcz 0/1 Completed 0 8m54s ngx 1/1 Running 4 (158m ago) 2d14h
Pod被Job管理,就不会反复重启报错,而是会显示为Completed表示任务完成,而ger job
里也会列出运行成功的作业数量,这里只有一个作业,所以是1/1,从get pod
可知,Pod被自动关联了一个名字,用的是Job名字(echo-job)再加上一个随机字符串,这是Job管理下的作用
使用logs
查看Pod的输出:
$ minikube kubectl -- logs echo-job-hrqcz hello world
YAML给予了很大的灵活性,可以在Job级别、Pod级别添加任意的字段来定制业务
下面创建一个Job对象,名字叫"sleep-job",随机睡眠一段时间再退出,模拟运行时间较长的作业。Job的参数设置成15秒超时,最多重试2次,总共需要运行完4个Pod,但同一时刻最多并发两个Pod
先生成样板:
$ minikube kubectl -- create job sleep-job --image=busybox --dry-run=client -o yaml apiVersion: batch/v1 kind: Job metadata: creationTimestamp: null name: sleep-job spec: template: metadata: creationTimestamp: null spec: containers: - image: busybox name: sleep-job resources: {} restartPolicy: Never status: {}
修改样板文件:
apiVersion: batch/v1 kind: Job metadata: name: sleep-job spec: activeDeadlineSeconds: 15 backoffLimit: 2 completions: 4 parallelism: 2 template: metadata: spec: restartPolicy: OnFailure containers: - image: busybox name: sleep-job imagePullPolicy: IfNotPresent command: - sh - -c - sleep $(($RANDOM % 10 + 1)) && echo done
在spec下加了几个控制离线作业的重要字段:
名称 | 作用 |
---|---|
activeDeadlineSeconds | 设置Pod运行的超时时间 |
backoffLimit | 设置Pod的失败重试次数 |
completions | Job完成需要运行的Pod的数量,默认为1 |
parallelism | 与completions相关,表示 |
这4个字段不再template字段下,而是在spec字段下,属于Job级别,来控制模板里的Pod对象
创建Pod:
$ minikube kubectl -- apply -f sleep-job.yml job.batch/sleep-job created
使用get pod -w
可以实时查看Pod运行状态
$ minikube kubectl -- get pod -w NAME READY STATUS RESTARTS AGE busy-pod 0/1 Completed 66 (5m22s ago) 16h echo-job-hrqcz 0/1 Completed 0 61m ngx 1/1 Running 4 (3h31m ago) 2d15h sleep-job-8s68j 0/1 Completed 0 21m sleep-job-vxwkh 0/1 Completed 0 21m busy-pod 0/1 CrashLoopBackOff 66 (15s ago) 16h
使用YAML描述CronJob
Job为临时任务,而CronJob为定时任务,创建CronJob的YAML样板:
$ minikube kubectl -- create cj echo-cj --image=busybox --schedule="" --dry-run=client -o yaml apiVersion: batch/v1 kind: CronJob metadata: creationTimestamp: null name: echo-cj spec: jobTemplate: metadata: creationTimestamp: null name: echo-cj spec: template: metadata: creationTimestamp: null spec: containers: - image: busybox name: echo-cj resources: {} restartPolicy: OnFailure schedule: "" status: {}
编辑这个样板文件:
apiVersion: batch/v1 kind: CronJob metadata: name: echo-cj spec: schedule: '*/1 * * * *' jobTemplate: spec: template: spec: restartPolicy: OnFailure containers: - image: busybox name: echo-cj resources: {} imagePullPolicy: IfNotPresent command: ["/bin/echo"] args: ["hello","world"]
这个文件中spec嵌套了3层:
第一个spec是CronJob自己的对象规格声明
第二个spec从属于jobTemplate,定义了一个Job对象
第三个spec从属于template,定义了Job里运行的的Pod
CronJob事实上是组合了Job而生成的新对象,Job对象之外额外定义了一个字段schedule,用来定义任务周期运行的规则,使用标准的Cron语法,指定分钟、小时、天、月、周,和Linux上的crontab是一样的,这里指定了每分钟运行一次
# ┌───────────── minute (0 - 59) # │ ┌───────────── hour (0 - 23) # │ │ ┌───────────── day of the month (1 - 31) # │ │ │ ┌───────────── month (1 - 12) # │ │ │ │ ┌───────────── day of the week (0 - 6) (Sunday to Saturday; # │ │ │ │ │ 7 is also Sunday on some systems) # │ │ │ │ │ # │ │ │ │ │ # * * * * *
创建:
$ minikube kubectl -- apply -f cronjob.yml cronjob.batch/echo-cj created
查看CronJob:
$ minikube kubectl -- get cj NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE echo-cj */1 * * * * False 0 <none> 20s
查看pods:
$ minikube kubectl -- get pod NAME READY STATUS RESTARTS AGE echo-cj-27645457-95qz5 0/1 Completed 0 2m36s echo-cj-27645458-md9rs 0/1 Completed 0 96s echo-cj-27645459-59vp4 0/1 Completed 0 36s
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· 什么是nginx的强缓存和协商缓存
· 一文读懂知识蒸馏
· Manus爆火,是硬核还是营销?