Jobとは
常駐するアプリケーションでなく、単発で実行して実行完了後はそのまま終了するような用途にはJobを使用する。
ここではJobで起動したPodがエラーで停止した場合も、自動再実行せずにそのまま終了させたい場合の設定についての調査とまとめ。
以下の環境で確認
- Minikube v0.35.0 (Kubernetes v1.13.4)
- MiniShift v1.32.0 (OKD v3.11.0)
※ JobはrestartPolicy
はNever
前提とする
- 2019.04.02 精度について追記
TL;DR
以下の設定をspec
直下に追加してJobを作成する。
backoffLimit: 0
指定がない場合はデフォルト6として、リトライ制御(Podの再作成)が行われる。
Jobの作成と実行
YAML
apiVersion: batch/v1
kind: Job
metadata:
name: perl-sample-job
spec:
template:
spec:
containers:
- name: perl-sample-job
image: perl
command: ["perl", "-e", 'sleep 5; print "hello\n"; exit 0']
restartPolicy: Never
Jobリソースの作成
OpenShiftであればoc create -f <yaml-file>
PS C:\Users\zaki\src\containers\job> kubectl apply -f job-sample-valid.yaml
job.batch/perl-sample-job created
PS C:\Users\zaki\src\containers\job> kubectl get job
NAME COMPLETIONS DURATION AGE
perl-sample-job 0/1 3s 3s
PS C:\Users\zaki\src\containers\job> kubectl get pod
NAME READY STATUS RESTARTS AGE
perl-sample-job-xrrmz 1/1 Running 0 6s
実行完了
PS C:\Users\zaki\src\containers\job> kubectl get pod
NAME READY STATUS RESTARTS AGE
perl-sample-job-xrrmz 0/1 Completed 0 10s
実行ログ
STDOUTへの出力は常駐型の普通のPodと同様に、PodやJobに対してlogs
コマンドを使用すれば参照できる。
PS C:\Users\zaki\src\containers\job> kubectl logs pod/perl-sample-job-xrrmz
hello
PS C:\Users\zaki\src\containers\job> kubectl logs job/perl-sample-job
hello
終了ステータス
コンテナ内のプログラムの終了ステータスは、describe
やYAML形式でPodの状態を出力すれば確認できる
PS C:\Users\zaki\src\containers\job> kubectl describe pod perl-sample-job
:
:
Containers:
perl-sample-job:
:
:
State: Terminated
Reason: Completed
Exit Code: 0
Started: Thu, 28 Mar 2019 21:10:21 +0900
Finished: Thu, 28 Mar 2019 21:10:26 +0900
エラー時の動作
restartPolicy: Never
が指定されているPodはエラー時にそのまま停止(STATUSがErrorとなる)するが、Jobから再度Podが起動される。
エラーになるJobサンプル
apiVersion: batch/v1
kind: Job
metadata:
name: perl-sample-errorjob
spec:
template:
spec:
containers:
- name: perl-sample-errorjob
image: perl
command: ["perl", "-e", 'sleep 5; print "hello\n"; exit 1']
restartPolicy: Never
PS C:\Users\zaki\src\containers\job> kubectl get pod -w
NAME READY STATUS RESTARTS AGE
hello-minikube-6fd785d459-2xq6j 1/1 Running 1 112m
perl-sample-errorjob-bfd6w 0/1 Error 0 33s
perl-sample-errorjob-dp2c5 0/1 Error 0 43s
perl-sample-errorjob-jcgkw 0/1 Error 0 12s
:
:
PS C:\Users\zaki\src\containers\job> kubectl get pod
NAME READY STATUS RESTARTS AGE
perl-sample-errorjob-2ztrv 0/1 Error 0 21m
perl-sample-errorjob-bfd6w 0/1 Error 0 26m
perl-sample-errorjob-dp2c5 0/1 Error 0 26m
perl-sample-errorjob-jcgkw 0/1 Error 0 25m
perl-sample-errorjob-jpjk9 0/1 Error 0 25m
perl-sample-errorjob-prfkz 0/1 Error 0 24m
6回のエラーで停止している
backoffLimit
PS C:\Users\zaki\src\containers\job> kubectl get job perl-sample-errorjob -o yaml
apiVersion: batch/v1
kind: Job
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"batch/v1","kind":"Job","metadata":{"annotations":{},"name":"perl-sample-errorjob","namespace":"default"},"spec":{"template":{"spec":{"containers":[{"command":["perl","-e","sleep 5; print \"hello\\n\"; exit 1"],"image":"perl","name":"perl-sample-errorjob"}],"restartPolicy":"Never"}}}}
creationTimestamp: "2019-03-19T15:18:21Z"
labels:
controller-uid: 3b4b3b39-4a5a-11e9-b886-080027b9884e
job-name: perl-sample-errorjob
name: perl-sample-errorjob
namespace: default
resourceVersion: "9002"
selfLink: /apis/batch/v1/namespaces/default/jobs/perl-sample-errorjob
uid: 3b4b3b39-4a5a-11e9-b886-080027b9884e
spec:
backoffLimit: 6
completions: 1
parallelism: 1
selector:
matchLabels:
controller-uid: 3b4b3b39-4a5a-11e9-b886-080027b9884e
template:
metadata:
creationTimestamp: null
labels:
controller-uid: 3b4b3b39-4a5a-11e9-b886-080027b9884e
job-name: perl-sample-errorjob
spec:
containers:
- command:
- perl
- -e
- sleep 5; print "hello\n"; exit 1
image: perl
imagePullPolicy: Always
name: perl-sample-errorjob
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Never
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
status:
conditions:
- lastProbeTime: "2019-03-19T15:28:32Z"
lastTransitionTime: "2019-03-19T15:28:32Z"
message: Job has reached the specified backoff limit
reason: BackoffLimitExceeded
status: "True"
type: Failed
failed: 6
startTime: "2019-03-19T15:18:21Z"
backoffLimit
の値が6(デフォルト値)になっているため。
この値が6だと、エラー時の繰り返しが行われても総実行回数が6回に制限される。
backoffLimitの値を調整
apiVersion: batch/v1
kind: Job
metadata:
name: perl-sample-errjob-1shot
spec:
backoffLimit: 1
template:
spec:
containers:
- name: perl-sample-errjob-1shot
image: perl
command: ["perl", "-e", 'sleep 5; print "hello\n"; exit 89']
restartPolicy: Never
PS C:\Users\zaki\src\containers\job> kubectl apply -f job-sample-invalid-backofflimit.yaml
1だと2回実行される…
2だと3回…
PS C:\Users\zaki\src\containers\job> kubectl apply -f job-sample-invalid-backofflimit2.yaml
job.batch/perl-sample-errjob-1shot created
PS C:\Users\zaki\src\containers\job> kubectl get pod
NAME READY STATUS RESTARTS AGE
perl-sample-errjob-1shot-7bpqd 0/1 Error 0 25s
perl-sample-errjob-1shot-7dncf 0/1 Error 0 35s
perl-sample-errjob-1shot-cqptf 0/1 Error 0 15s
PS C:\Users\zaki\src\containers\job> kubectl get pod
NAME READY STATUS RESTARTS AGE
perl-sample-errjob-1shot-7bpqd 0/1 Error 0 59s
perl-sample-errjob-1shot-7dncf 0/1 Error 0 69s
perl-sample-errjob-1shot-cqptf 0/1 Error 0 49s
PS C:\Users\zaki\src\containers\job>
3にすれば3回になった。
PS C:\Users\zaki\src\containers\job> kubectl apply -f job-sample-invalid-backofflimit3.yaml
job.batch/perl-sample-errjob-1shot created
PS C:\Users\zaki\src\containers\job> kubectl get job
NAME COMPLETIONS DURATION AGE
perl-sample-errjob-1shot 0/1 4s 4s
PS C:\Users\zaki\src\containers\job> kubectl get pod
NAME READY STATUS RESTARTS AGE
perl-sample-errjob-1shot-h5pqs 1/1 Running 0 7s
PS C:\Users\zaki\src\containers\job> kubectl get pod
NAME READY STATUS RESTARTS AGE
perl-sample-errjob-1shot-7wbnj 0/1 Error 0 58s
perl-sample-errjob-1shot-8jpgn 0/1 Error 0 38s
perl-sample-errjob-1shot-h5pqs 0/1 Error 0 69s
PS C:\Users\zaki\src\containers\job>
0
を指定すれば、初回は起動してそれっきりとなった。
apiVersion: batch/v1
kind: Job
metadata:
name: perl-sample-errjob-1shot
spec:
backoffLimit: 0
template:
spec:
containers:
- name: perl-sample-errjob-1shot
image: perl
command: ["perl", "-e", 'sleep 5; print "hello\n"; exit 89']
restartPolicy: Never
PS C:\Users\zaki\src\containers\job> kubectl get pod
NAME READY STATUS RESTARTS AGE
perl-sample-errjob-1shot-t2d8w 0/1 Error 0 18s
PS C:\Users\zaki\src\containers\job> kubectl get job
NAME COMPLETIONS DURATION AGE
perl-sample-errjob-1shot 0/1 21s 21s
PS C:\Users\zaki\src\containers\job> kubectl get job perl-sample-errjob-1shot -o yaml
apiVersion: v1
items:
- apiVersion: batch/v1
kind: Job
metadata:
:
:
spec:
backoffLimit: 0
completions: 1
parallelism: 1
:
:
status:
conditions:
- lastProbeTime: "2019-03-20T13:36:59Z"
lastTransitionTime: "2019-03-20T13:36:59Z"
message: Job has reached the specified backoff limit
reason: BackoffLimitExceeded
status: "True"
type: Failed
failed: 1
startTime: "2019-03-20T13:36:48Z"
:
PS C:\Users\zaki\src\containers\job> kubectl get pod perl-sample-errjob-1shot-t2d8w -o yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: "2019-03-20T13:36:49Z"
generateName: perl-sample-errjob-1shot-
labels:
controller-uid: 365cadf1-4b15-11e9-8e88-080027b9884e
job-name: perl-sample-errjob-1shot
name: perl-sample-errjob-1shot-t2d8w
namespace: default
ownerReferences:
- apiVersion: batch/v1
blockOwnerDeletion: true
controller: true
kind: Job
name: perl-sample-errjob-1shot
uid: 365cadf1-4b15-11e9-8e88-080027b9884e
resourceVersion: "15779"
selfLink: /api/v1/namespaces/default/pods/perl-sample-errjob-1shot-t2d8w
uid: 36629733-4b15-11e9-8e88-080027b9884e
spec:
containers:
- command:
- perl
- -e
- sleep 5; print "hello\n"; exit 89
image: perl
imagePullPolicy: Always
name: perl-sample-errjob-1shot
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /var/run/secrets/kubernetes.io/serviceaccount
name: default-token-qr2gn
readOnly: true
dnsPolicy: ClusterFirst
enableServiceLinks: true
nodeName: minikube
priority: 0
restartPolicy: Never
schedulerName: default-scheduler
securityContext: {}
serviceAccount: default
serviceAccountName: default
terminationGracePeriodSeconds: 30
tolerations:
- effect: NoExecute
key: node.kubernetes.io/not-ready
operator: Exists
tolerationSeconds: 300
- effect: NoExecute
key: node.kubernetes.io/unreachable
operator: Exists
tolerationSeconds: 300
volumes:
- name: default-token-qr2gn
secret:
defaultMode: 420
secretName: default-token-qr2gn
status:
conditions:
- lastProbeTime: null
lastTransitionTime: "2019-03-20T13:36:49Z"
status: "True"
type: Initialized
- lastProbeTime: null
lastTransitionTime: "2019-03-20T13:36:59Z"
message: 'containers with unready status: [perl-sample-errjob-1shot]'
reason: ContainersNotReady
status: "False"
type: Ready
- lastProbeTime: null
lastTransitionTime: "2019-03-20T13:36:59Z"
message: 'containers with unready status: [perl-sample-errjob-1shot]'
reason: ContainersNotReady
status: "False"
type: ContainersReady
- lastProbeTime: null
lastTransitionTime: "2019-03-20T13:36:49Z"
status: "True"
type: PodScheduled
containerStatuses:
- containerID: docker://dadd972215e3f931ee99e06705a109ca60dc59029e5e2268794941eae98e69d1
image: perl:latest
imageID: docker-pullable://perl@sha256:457fd220e1bb557d2461bbb34a10a8cc3de72819c69b59f606b79f863cb7f420
lastState: {}
name: perl-sample-errjob-1shot
ready: false
restartCount: 0
state:
terminated:
containerID: docker://dadd972215e3f931ee99e06705a109ca60dc59029e5e2268794941eae98e69d1
exitCode: 89
finishedAt: "2019-03-20T13:36:58Z"
reason: Error
startedAt: "2019-03-20T13:36:53Z"
hostIP: 10.0.2.15
phase: Failed
podIP: 172.17.0.5
qosClass: BestEffort
startTime: "2019-03-20T13:36:49Z"
まとめ
backoffLimitの値 | 総実行回数 |
---|---|
0 | 1 |
1 | 2 |
2 | 3 |
3 | 3 |
4 | 4 |
5 | 5 |
6 (default) | 6 |
釈然としないけど、「Jobによるコンテナの1ショット実行/エラー発生してもリトライしない」動作が必要であれば、backoffLimit
の値を0に指定する。
もしかすると、Error停止してBackoffLimitExceeded
で処理終了される判定されるのにタイムラグがあって、次のPodがフライング的にリトライされているのかなぁ…??
(追記) backoffLimitの精度
何度か試してみたが、あまり精度はよくないようだ。
0
指定の場合は今のところ1回しか実行されていないが、デフォルトの6
の場合は総実行回数が4~8回ほど実行されたりして、振り幅が大きい。
回数に精度が求められる場合は注意したほうがよさそう。