Kuberntesには、ジョブというコントローラがあり、バッチ処理をスケジュールすることが出来ます。
しかし、Kuberntesはスケジュールするという表現が使われるのですが、業務システムで利用されるジョブのスケジューラーの様にジョブネットを組んで、前後関係を管理しながら、ジョブ全体の正常終了を管理するものでも無く、科学計算系で利用される様な、計算ノード群へ、ジョブを割り当てて、並列なバッチ処理をサポートするタイプとも、少し違う感じがします。
そこで、実際に試して確認する事にします。
シェルスクリプト作成
ローカルの環境で、下記のサンプルとなるシェル・スクリプトを作成します。 このシェルは、第一引数でループの回数を設定します。1増えるごとに、終了時間が3秒づつ長くなります。 そして、第二引数で終了コードを設定できます。
#!/bin/bash
if [ $# -ne 2 ]; then
echo "指定された引数は$#個です。" 1>&2
echo "実行するには2個の引数が必要です。" 1>&2
echo "my-shell ループ数 完了時終了コード" 1>&2
exit 1
fi
x=0
while true
do
let x=x+1
echo $x `uuid`
if [ $x -eq $1 ]; then
exit $2
fi
sleep 3
done
シェルのコンテナ化
このシェルを次のDockerfileでコンテナ化します。 ここでコンテナ実行時のデフォルトの引数として、ループ回数=3、終了コード=0 を指定します。 このパラメータは後に、オーバーライトできますので、サクッとテストできるものが適切でしょう。
FROM ubuntu:latest
COPY ./my-shell /my-shell
RUN apt-get update
RUN apt-get install uuid -y
CMD ["/my-shell", "3","0"]
Dockerfile と my-shell の2つのファイルがあるディレクトリで、コンテナのビルドを実行します。
$ docker build --tag job-x .
これでローカルのリポジトリに登録されたコンテナを確認します。
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
job-x latest 4481e04e94e7 37 seconds ago 151MB
次に、コンテナで動作するシェルを確認しておきます。
$ docker run --rm --name job-x job-x:latest "/my-shell" 2 7
1 ecab8456-071e-11e8-b25b-0242ac110002
2 ee7599ca-071e-11e8-aa3d-0242ac110002
$ echo $?
7
リモート・レジストリへ、コンテナ・イメージを登録
テストで問題がなければ、リモート・リポジトリのタグを付けて、リモート・リポジトリへプッシュします。
$ docker tag job-x:latest registry.au-syd.bluemix.net/takara/job:v1
$ docker push registry.au-syd.bluemix.net/takara/job:v1
リモート・リポジトリへの登録結果を確認します。
$ bx cr images
Listing images...
REPOSITORY NAMESPACE TAG CREATED SIZE VULNERABILITY STATUS
registry.au-syd.bluemix.net/takara/job takara v1 6 minutes ago 72 MB Vulnerable
コンテナ・イメージの登録に失敗していたら、bx cr login を再実行して、docker pushをリトライして、認証の問題を解決します。
k8sクラスタでジョブ実行
次のジョブを実行するためのYAMLファイルを作成して、k8sクラスタ上にジョブを投入します。 ここで、command:
フィールドに、オーバーライドするパラメータを書いておきます。
apiVersion: batch/v1
kind: Job
metadata:
name: job-batch
spec:
template:
spec:
containers:
- name: job-batch
image: registry.au-syd.bluemix.net/takara/job:v1
command: ["/my-shell", "2", "0"]
restartPolicy: Never
backoffLimit: 4
kubectlコマンドでYAMLファイルを設定して実行するだけです。
kubctl create -f job.yml
成功終了の場合、ジョブはスグに終了して、結果を参照できます。kubectl get jobs
で、ジョブの終了結果を参照できます。さらに、細かい情報が知りたければ、次の様にコマンドを実行します。 ここでは、Pod Statuses:
フィールドで、正常終了が確認できます。 終了コード=0に指定しているので、正常終了したと見なされます。 もしも、ゼロ以外の値の場合は、Failed と見なされ、再試行に入ります。
$ kubectl describe job job-batch
Name: job-batch
Namespace: default
Selector: controller-uid=16725165-0720-11e8-8cfc-76140a51e2a9
Labels: controller-uid=16725165-0720-11e8-8cfc-76140a51e2a9
job-name=job-batch
Annotations: <none>
Parallelism: 1
Completions: 1
Start Time: Thu, 01 Feb 2018 07:18:23 +0000
Pods Statuses: 0 Running / 1 Succeeded / 0 Failed
Pod Template:
Labels: controller-uid=16725165-0720-11e8-8cfc-76140a51e2a9
job-name=job-batch
Containers:
job-batch:
Image: registry.au-syd.bluemix.net/takara/job:v1
Port: <none>
Command:
/my-shell
2
0
Environment: <none>
Mounts: <none>
Volumes: <none>
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulCreate 1m job-controller Created pod: job-batch-kk8dd
既にジョブが終了しており、'kubectl get podsでは参照できないので、
--show-all`を付加して、参照します。
$ kubectl get pods --show-all
NAME READY STATUS RESTARTS AGE
...
job-batch-kk8dd 0/1 Completed 0 3m
...
ポッドを指定して、ログを表示すると、前述のローカルで実行したものと同じ様に、結果を見ることが出来ます。
$ kubectl logs job-batch-kk8dd
1 1bfdf5da-0720-11e8-babf-877ba3ad5a1c
2 1dca4cd8-0720-11e8-b9d6-274d9f3cf681
ログをコマンド1行で表示するには、ちょっと長いですが、以下の様にします。
$ kubectl logs $(kubectl get pods --show-all --selector=job-name=job-batch --output=jsonpath={.items..metadata.name})
1 1bfdf5da-0720-11e8-babf-877ba3ad5a1c
2 1dca4cd8-0720-11e8-b9d6-274d9f3cf681
ジョブの削除
次のコマンドでジョブの削除を実行して、確認します。 結果から確かに削除されたことが解ります。
$ kubectl delete -f job.yml
job "job-batch" deleted
$ kubectl get job job-batch
Error from server (NotFound): jobs.batch "job-batch" not found
ジョブの失敗ケース
シェルの終了コードが 1となる様に、command: ["/my-shell", "2", "1"]
を修正します。これは、Dockerfileを参照すれば、CMD ["/my-shell", "3","0"]
の様にコンテナを開始した時に、my-shellコマンドが引数と共に実行するように、セットされているのですが、job.yml
に再設定することで、コンテナのCMDを上書きすることができます。
そして、backoffLimit: 2
に設定します。 最初の実行から2回リトライして、やはり失敗したらジョブの再試行を終了するというものです。
apiVersion: batch/v1
kind: Job
metadata:
name: job-batch
spec:
template:
spec:
containers:
- name: job-batch
image: registry.au-syd.bluemix.net/takara/job:v1
command: ["/my-shell", "2", "1"]
restartPolicy: Never
backoffLimit: 2
ジョブを実行します。
$ kubectl create -f job.yml
約1分後に、ジョブの状態を確認すると、SUCCESSFUL(成功)が0の状態になっています。
$ kubectl get job job-batch
NAME DESIRED SUCCESSFUL AGE
job-batch 1 0 1m
何回試行(backoff)したのかを確認します。次のコマンドで確認したところ、
初回起動時に加えて、2回試行して、終了していることが確認できます。
$ kubectl describe job job-batch
Name: job-batch
Namespace: default
Selector: controller-uid=f60bbdef-0723-11e8-8cfc-76140a51e2a9
Labels: controller-uid=f60bbdef-0723-11e8-8cfc-76140a51e2a9
job-name=job-batch
Annotations: <none>
Parallelism: 1
Completions: 1
Start Time: Thu, 01 Feb 2018 07:46:06 +0000
Pods Statuses: 0 Running / 0 Succeeded / 3 Failed
Pod Template:
Labels: controller-uid=f60bbdef-0723-11e8-8cfc-76140a51e2a9
job-name=job-batch
Containers:
job-batch:
Image: registry.au-syd.bluemix.net/takara/job:v1
Port: <none>
Command:
/my-shell
2
1
Environment: <none>
Mounts: <none>
Volumes: <none>
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulCreate 27s job-controller Created pod: job-batch-spvnl
Normal SuccessfulCreate 21s job-controller Created pod: job-batch-w5wpt
Normal SuccessfulCreate 11s job-controller Created pod: job-batch-xq6qh
Warning BackoffLimitExceeded 1s job-controller Job has reach the specified backoff limit
以上