赞
踩
容器按照持续运行的时间可分为两类:服务类容器和工作类容器。
服务类容器通常持续提供服务,需要一直运行,比如 http server,daemon 等。工作类容器则是一次性任务,比如批处理程序,完成后容器就退出。
Kubernetes 的 Deployment、ReplicaSet 和 DaemonSet 都用于管理服务类容器;对于工作类容器,我们用 Job。
简单的 Job 配置文件 myjob.yml:
- [root@master ~]# vim myjob.yml
-
- apiVersion: batch/v1
- kind: Job
- metadata:
- name: myjob
- spec:
- template:
- metadata:
- name: myjob
- spec:
- containers:
- - name: hello
- image: busybox
- command: ["echo","hello k8s job!"]
- restartPolicy: Never
① batch/v1 是当前 Job 的 apiVersion。
② kind: Job指明当前资源的类型为 Job。
③ restartPolicy 指定什么情况下需要重启容器。对于 Job,只能设置为 Never 或者 OnFailure。对于其他 controller(比如 Deployment)可以设置为 Always 。
通过 kubectl apply -f myjob.yml 启动 Job。
- [root@master ~]# kubectl apply -f myjob.yml
- job.batch/myjob created
- [root@master ~]# kubectl get job
- NAME COMPLETIONS DURATION AGE
- myjob 0/1 15s 15s
kubectl get job
查看 Job 的状态:
- [root@master ~]# kubectl get job
- NAME COMPLETIONS DURATION AGE
- myjob 1/1 18s 19s
DESIRED
和 SUCCESSFUL
都为 1
,表示按照预期启动了一个 Pod,并且已经成功执行。kubectl get pod
查看 Pod 的状态:
- [root@master ~]# kubectl get pod
- NAME READY STATUS RESTARTS AGE
- myjob-q2fln 0/1 Completed 0 17s
kubectl logs
可以查看 Pod 的标准输出:
- [root@master ~]# kubectl logs myjob-q2fln
- hello k8s job!
如果失败了会怎么样呢?
修改 myjob.yml,故意引入一个错误:
- apiVersion: batch/v1
- 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:
- [root@master ~]# kubectl delete -f myjob.yml
- job.batch "myjob" deleted
如果将 restartPolicy
设置为 OnFailure
会怎么样?下面我们实践一下,修改 myjob.yml 后重新启动。
运行新的 Job 并查看状态:
- [root@master ~]# vi myjob.yml
- [root@master ~]# kubectl apply -f myjob.yml
- job.batch/myjob created
- [root@master ~]# kubectl get job
- NAME COMPLETIONS DURATION AGE
- myjob 0/1 12s 12s
当前COMPLETIONS 的 Pod 数量为 0/1
,查看 Pod 的状态:
- [root@master ~]# kubectl get pod
- NAME READY STATUS RESTARTS AGE
- myjob-7qfd5 0/1 ContainerCannotRun 0 32s
- myjob-kpp2t 0/1 ContainerCannotRun 0 12s
- myjob-mvcql 0/1 ContainerCannotRun 0 42s
- myjob-pkwbg 0/1 ContainerCannotRun 0 46s
可以看到有多个 Pod,状态均不正常。kubectl describe pod
查看某个 Pod 的启动日志:
日志显示没有可执行程序
为什么 kubectl get pod
会看到这么多个失败的 Pod?
原因是:当第一个 Pod 启动时,容器失败退出,根据 restartPolicy: Never
,此失败容器不会被重启,但 Job DESIRED
的 Pod 是 1
,目前 COMPLETIONS
为 0/1
,不满足,所以 Job controller 会启动新的 Pod,直到 COMPLETIONS
为 1/1
。对于我们这个例子,COMPLETIONS
永远也到不了 1/1
,所以 Job controller 会一直创建新的 Pod。为了终止这个行为,只能删除 Job。
- [root@master ~]# kubectl delete -f myjob.yml
- job.batch "myjob" deleted
如果将 restartPolicy
设置为 OnFailure
会怎么样?下面我们实践一下,修改 myjob.yml 后重新启动。
- [root@master ~]# vim myjob.yml
- apiVersion: batch/v1
- kind: Job
- metadata:
- name: myjob
- spec:
- template:
- metadata:
- name: myjob
- spec:
- containers:
- - name: hello
- image: busybox
- command: ["invalid_command","hello k8s job!"]
- restartPolicy: OnFailure
- [root@master ~]# kubectl apply -f myjob1.yml
- job.batch/myjob created
- [root@master ~]# kubectl get job
- NAME COMPLETIONS DURATION AGE
- myjob 0/1 33s 33s
Job 的 COMPLETIONS
Pod 数量还是为 0/1
,看看 Pod 的情况:
- [root@master ~]# kubectl get pod
- NAME READY STATUS RESTARTS AGE
- myjob-8lmmp 0/1 RunContainerError 3 69s
这里只有一个 Pod,不过 RESTARTS
为 3
,而且不断增加,说明 OnFailure
生效,容器失败后会自动重启。
同时运行多个 Pod,提高 Job 的执行效率。这个可以通过 parallelism
设置。
- [root@master ~]# vim myjob.yml
- apiVersion: batch/v1
- kind: Job
- metadata:
- name: myjob
- spec:
- parallelism: 2
- template:
- metadata:
- name: myjob
- spec:
- containers:
- - name: hello
- image: busybox
- command: ["echo","hello k8s job!"]
- restartPolicy: Never
这里我们将并行的 Pod 数量设置为 2,实践一下:
- [root@master ~]# kubectl apply -f myjob.yml
- job.batch/myjob created
- [root@master ~]# kubectl get pod
- NAME READY STATUS RESTARTS AGE
- myjob-lc5kl 0/1 Completed 0 16s
- myjob-mdrdr 0/1 Completed 0 16s
- [root@master ~]# kubectl get job
- NAME COMPLETIONS DURATION AGE
- myjob 2/1 of 2 5s 31s
- [root@master ~]# kubectl get pod
- NAME READY STATUS RESTARTS AGE
- myjob-lc5kl 0/1 Completed 0 33s
- myjob-mdrdr 0/1 Completed 0 33s
Job 一共启动了两个 Pod,而且 AGE
相同,可见是并行运行的。
我们还可以通过 completions
设置 Job 成功完成 Pod 的总数:
- [root@master ~]# vim myjob.yml
-
- apiVersion: batch/v1
- kind: Job
- metadata:
- name: myjob
- spec:
- completions: 6
- parallelism: 2
- template:
- metadata:
- name: myjob
- spec:
- containers:
- - name: hello
- image: busybox
- command: ["echo","hello k8s job!"]
- restartPolicy: Never
上面配置的含义是:每次运行两个 Pod,直到总共有 6 个 Pod 成功完成
- [root@master ~]# kubectl apply -f myjob.yml
- job.batch/myjob created
- [root@master ~]# kubectl get job
- NAME COMPLETIONS DURATION AGE
- myjob 3/6 8s 8s
- [root@master ~]# kubectl get pod
- NAME READY STATUS RESTARTS AGE
- myjob-4zclr 0/1 Completed 0 14s
- myjob-66dqx 0/1 Completed 0 14s
- myjob-cqt9d 0/1 Completed 0 10s
- myjob-j92f8 0/1 Completed 0 10s
- myjob-v6f68 0/1 Completed 0 6s
- myjob-zjz6p 0/1 Completed 0 6s
DESIRED
和 SUCCESSFUL
均为 6
,符合预期。如果不指定 completions
和 parallelism
,默认值均为 1
。
上面的例子只是为了演示 Job 的并行特性,实际用途不大。不过现实中确实存在很多需要并行处理的场景。比如批处理程序,每个副本(Pod)都会从任务池中读取任务并执行,副本越多,执行时间就越短,效率就越高。这种类似的场景都可以用 Job 来实现。
Linux 中有 cron 程序定时执行任务,Kubernetes 的 CronJob 提供了类似的功能,可以定时执行 Job。CronJob 配置文件示例如下:
- [root@master ~]# vim cronjob.yml
-
- apiVersion: batch/v2alpha1
- kind: CronJob
- metadata:
- name: hello
- spec:
- schedule: "* /1 * * * *"
- jobTemplate:
- spec:
- template:
- spec:
- containers:
- - name: hello
- image: busybox
- command: ["echo","hello k8s job!"]
- restartPolicy: OnFailure
① apiVersion: batch/v2alpha1 是当前 CronJob 的 apiVersion。
② kind: CronJob 指明当前资源的类型为 CronJob。
③ schedule: "* /1 * * * *"指定什么时候运行 Job,其格式与 Linux cron 一致。这里 */1 * * * * 的含义是每一分钟启动一次。
④ jobTemplate 定义 Job 的模板,格式与前面 Job 一致。
执行后报如下错误:
- [root@master ~]# kubectl apply -f cronjob.yml
- error: unable to recognize "cronjob.yml": no matches for kind "CronJob" in version "batch/v2alpha1"
失败了。这是因为 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:
- [root@master ~]# kubectl api-versions
- admissionregistration.k8s.io/v1
- admissionregistration.k8s.io/v1beta1
- apiextensions.k8s.io/v1
- apiextensions.k8s.io/v1beta1
- apiregistration.k8s.io/v1
- apiregistration.k8s.io/v1beta1
- apps/v1
- authentication.k8s.io/v1
- authentication.k8s.io/v1beta1
- authorization.k8s.io/v1
- authorization.k8s.io/v1beta1
- autoscaling/v1
- autoscaling/v2beta1
- autoscaling/v2beta2
- batch/v1
- batch/v1beta1
- batch/v2alpha1
- certificates.k8s.io/v1
- certificates.k8s.io/v1beta1
- coordination.k8s.io/v1
- coordination.k8s.io/v1beta1
- discovery.k8s.io/v1beta1
- events.k8s.io/v1
- events.k8s.io/v1beta1
- extensions/v1beta1
- flowcontrol.apiserver.k8s.io/v1beta1
- networking.k8s.io/v1
- networking.k8s.io/v1beta1
- node.k8s.io/v1
- node.k8s.io/v1beta1
- policy/v1beta1
- rbac.authorization.k8s.io/v1
- rbac.authorization.k8s.io/v1beta1
- scheduling.k8s.io/v1
- scheduling.k8s.io/v1beta1
- storage.k8s.io/v1
- storage.k8s.io/v1beta1
- v1
再次创建CronJob:
- [root@master ~]# kubectl apply -f cronjob.yml
- cronjob.batch/hello created
通过 kubectl get cronjob
查看 CronJob 的状态:
- [root@master ~]# kubectl get cronjob
- NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
- hello */1 * * * * False 0 <none> 17s
等待几分钟,然后通过 kubectl get jobs
查看 Job 的执行情况:
- [root@master ~]# kubectl get jobs
- NAME COMPLETIONS DURATION AGE
- hello-1608188820 1/1 6s 2m25s
- hello-1608188880 1/1 6s 85s
- hello-1608188940 1/1 5s 25s
可以看到每隔一分钟就会启动一个 Job。执行 kubectl logs
可查看某个 Job 的运行日志:
- [root@master ~]# kubectl get pod
- NAME READY STATUS RESTARTS AGE
- hello-1608188880-hqm7t 0/1 Completed 0 2m34s
- hello-1608188940-2md8k 0/1 Completed 0 94s
- hello-1608189000-4khvt 0/1 Completed 0 33s
- [root@master ~]# kubectl logs hello-1608188880-hqm7t
- hello k8s job!
运行容器化应用是 Kubernetes 最重要的核心功能。为满足不同的业务需要,Kubernetes 提供了多种 Controller,包括 Deployment、DaemonSet、Job、CronJob
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。