出于某些目的,有时需要在 Kubernetes 的一个 Pod 中,连续依次运行多个 Container。这种有明确结束预期的运行,即 Kubernetes 的 Job。但是,虽然一个 Job 可以在一个 Pod 内运行多个 Container,然而运行方式是并发的。
Kubernetes Job
经过调查发现,虽然 containers 不能依次运行,但是 initContainers 可以。它是在containers 运行前,执行的初始化操作,依次结束运行并且无异常后,正式的containers 才会运行。利用这一点,可以实现多个任务的依次执行,把前面的任务写到initContainers、后一个任务写到 containers 即可。
以下为三个 Containter 依次执行的样例。
apiVersion: batch/v1
kind: Job
metadata:
name: sequential-jobs
spec:
backoffLimit:
ttlSecondsAfterFinished: 3600
template:
spec:
activeDeadlinesSeconds: 60
restartPolicy: Never
initContainers:
- name: job-1
image: alpine:3.11
command:
- 'sh'
- '-c'
- >
for i in 1 2 3;
do
echo "job-1 `date`";
sleep 1s;
done;
echo code > /srv/input/code
volumeMounts:
- mountPath: /srv/input/
name: input
- name: job-2
image: alpine:3.11
command:
- 'sh'
- '-c'
- >
for i in 1 2 3;
do
echo "job-2 `date`";
sleep 1s;
done;
cat /srv/input/code &&
echo artifact > /srv/input/output/artifact
resources:
requests:
cpu: 3
volumeMounts:
- mountPath: /srv/input/
name: input
- mountPath: /srv/input/output/
name: output
containers:
- name: job-3
image: alpine:3.11
command:
- 'sh'
- '-c'
- >
echo "job-1 and job-2 completed";
sleep 3s;
cat /srv/output/artifact
volumeMounts:
- mountPath: /srv/output/
name: output
volumes:
- name: input
emptyDir: {}
- name: output
emptyDir: {}
securityContext:
runAsUser: 2000
runAsGroup: 2000
fsGroup: 2000
backoffLimit: 0,这句指定这个Job不要失败重启。
volumes 这部分,使用了 input 和 output 两个 emptyDir,作为输入输出。
securityContext 可以在镜像默认用户不确定的情况下,使用指定UID进行Volume操作,避免对 root 的依赖。
-
activeDeadlinesSeconds 指定了 Job 内 Pod 的超时时间。
这个字段同样可以给到Job。
ttlSecondsAfterFinished 指定了在多久以后,Job会被自动删除。
运行完毕后,日志如下:
$ kubectl logs sequential-jobs-r4725 job-1job-1 Tue Jul 28 07:50:10 UTC 2020job-1 Tue Jul 28 07:50:11 UTC 2020job-1 Tue Jul 28 07:50:12 UTC 2020$ kubectl logs sequential-jobs-r4725 job-2job-2 Tue Jul 28 07:50:13 UTC 2020job-2 Tue Jul 28 07:50:14 UTC 2020job-2 Tue Jul 28 07:50:15 UTC 2020code
$ kubectl logs sequential-jobs-r4725 job-3job-1 and job-2 completed
artifact
Volcano
stateDiagram [*] → Pending Pending → Aborted Pending → Running Aborted → Pending Running → Aborted Running → Completed Running → Terminated Completed → [*] Terminated → [*]
apiVersion: batch.volcano.sh/v1alpha1
kind: Job
metadata:
name: volcano-sequential-jobs
spec:
minAvailable: 1
schedulerName: volcano
queue: default
tasks:
- replicas: 1
name: "task-1"
template:
spec:
restartPolicy: Never
initContainers:
- name: job-1
image: alpine:3.11
command:
- 'sh'
- '-c'
- >
for i in 1 2 3;
do
echo "job-1 `date`";
sleep 1s;
done;
echo code > /srv/input/code
volumeMounts:
- mountPath: /srv/input/
name: input
- name: job-2
image: alpine:3.11
command:
- 'sh'
- '-c'
- >
for i in 1 2 3;
do
echo "job-2 `date`";
sleep 1s;
done;
cat /srv/input/code &&
echo artifact > /srv/input/output/artifact
resources:
requests:
cpu: 3
volumeMounts:
- mountPath: /srv/input/
name: input
- mountPath: /srv/input/output/
name: output
containers:
- name: job-done
image: alpine:3.11
command:
- 'sh'
- '-c'
- >
echo "job-1 and job-2 completed";
sleep 3s;
cat /srv/output/artifact
volumeMounts:
- mountPath: /srv/output/
name: output
volumes:
- name: input
emptyDir: {}
- name: output
emptyDir: {}
securityContext:
runAsUser: 2000
runAsGroup: 2000
fsGroup: 2000
上面与原生相比,虽然多了 tasks 这一层概念,但是在功能上并无帮助。
运行完毕后,日志如下:
$ kubectl logs volcano-sequential-jobs-task-1- job-1job-1 Tue Jul 28 07:53:17 UTC 2020job-1 Tue Jul 28 07:53:18 UTC 2020job-1 Tue Jul 28 07:53:20 UTC 2020$ kubectl logs volcano-sequential-jobs-task-1- job-2job-2 Tue Jul 28 07:53:21 UTC 2020job-2 Tue Jul 28 07:53:22 UTC 2020job-2 Tue Jul 28 07:53:23 UTC 2020code
$ kubectl logs volcano-sequential-jobs-task-1- job-3job-1 and job-2 completed
artifact