kubernetesのCronJobを触る
kubernetes上で定期的に何か処理を行う場合どうやるのかなと思っていたら、Cron Jobsというものがあるらしい。軽く触ってどんなものか見てみた。
なお、使用したminikubeとkubernetesのバージョンは以下の通り。
$ minikube version
minikube version: v0.15.0
$ kubectl version
Client Version: version.Info{Major:"1", Minor:"5", GitVersion:"v1.5.2", GitCommit:"08e099554f3c31f6e6f07b448ab3ed78d0520507", GitTreeState:"clean", BuildDate:"2017-01-12T04:57:25Z", GoVersion:"go1.7.4", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"5", GitVersion:"v1.5.1", GitCommit:"82450d03cb057bab0950214ef122b67c83fb11df", GitTreeState:"clean", BuildDate:"1970-01-01T00:00:00Z", GoVersion:"go1.7.1", Compiler:"gc", Platform:"linux/amd64"}
CronJobのマニフェスト
以下のようにした。イメージはrails.ymlと同じものを使う。argsに、実行するコマンドを指定するようだ。実行タイミングはcron形式なのでなじみがありますね。
apiVersion: batch/v2alpha1
kind: CronJob
metadata:
name: hello
spec:
schedule: "*/1 * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: hello
image: localhost:5000/r_takaishi/docker-mysql-rails
args: ["bundle", "exec", "rake", "foo"]
env:
- name: RAILS_ENV
value: development
- name: MYSQL_HOST
value: mysql.default.svc.cluster.local
- name: MYSQL_USER
value: root
- name: MYSQL_PASSWORD
value: passw0rd
restartPolicy: Never
なお、実行するRakeタスクは追加してイメージを更新しておく。
desc "this is foo"
task :foo => :environment do
p :foo
end
さて、マニフェストを作成したらCronJobを作る。
$kubectl create -f ./cron.yml
cronjob "hello" created
作成されたことが確認できた。この時点ではジョブは1回も動いていない。
$ kubectl get cronjob
NAME SCHEDULE SUSPEND ACTIVE LAST-SCHEDULE
hello */1 * * * * False 0 <none>
ジョブが動いた!
ジョブが動作するとLAST-SCHEDULEが更新されるようだ。動作中だとACTIVEが1になるのかな。
$ kubectl get cronjob
NAME SCHEDULE SUSPEND ACTIVE LAST-SCHEDULE
hello */1 * * * * False 1 Tue, 07 Feb 2017 22:19:00 +0900
ジョブ一覧を見てみる。成功したようだ。
$ kubectl get job
NAME DESIRED SUCCESSFUL AGE
hello-1486473540 1 1 17s
ジョブ hello-1486473540 の詳細を見る。実際に動作したのはhello-1486473540-cxr0n というポッドの中ということがわかる。
$ kubectl describe job hello-148647354
Name: hello-1486473540
Namespace: default
Image(s): localhost:5000/r_takaishi/docker-mysql-rails
Selector: controller-uid=00f009f6-ed38-11e6-93b9-080027cb3417
Parallelism: 1
Completions: 1
Start Time: Tue, 07 Feb 2017 22:19:07 +0900
Labels: controller-uid=00f009f6-ed38-11e6-93b9-080027cb3417
job-name=hello-1486473540
Pods Statuses: 0 Running / 1 Succeeded / 0 Failed
No volumes.
Events:
FirstSeen LastSeen Count From SubObjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
34s 34s 1 {job-controller } Normal SuccessfulCreate Created pod: hello-1486473540-cxr0n
ポッドのログを見ると、Rakeに追加したタスクが実行されていることが確認できた!
$ kubectl logs hello-1486473540-cxr0n
:foo
yamlでマニフェストを書けば後はk8sにまかせられるという感じで、楽そうですね。
ところで、しばらく放置してからジョブ一覧を見るとこんな感じに。
$ kubectl get job
NAME DESIRED SUCCESSFUL AGE
hello-1486473540 1 1 7m
hello-1486473600 1 1 6m
hello-1486473660 1 1 5m
hello-1486473720 1 1 4m
hello-1486473780 1 1 3m
hello-1486473840 1 1 2m
hello-1486473900 1 1 1m
hello-1486473960 1 1 34s
ポッドも、-aオプションをつけると完了したものが残っている。
$ kubectl get pod -a
NAME READY STATUS RESTARTS AGE
hello-1486473540-cxr0n 0/1 Completed 0 8m
hello-1486473600-t3tls 0/1 Completed 0 7m
hello-1486473660-7m4w9 0/1 Completed 0 6m
hello-1486473720-6hjsc 0/1 Completed 0 5m
hello-1486473780-jq2vn 0/1 Completed 0 4m
hello-1486473840-f26cj 0/1 Completed 0 3m
hello-1486473900-3b5h6 0/1 Completed 0 2m
hello-1486473960-ph0db 0/1 Completed 0 1m
hello-1486474020-f44k3 0/1 Completed 0 50s
mysql-8kd4q 1/1 Running 2 6d
rails-8cnzn 1/1 Running 0 2d
ジョブの種類が増えて、しばらく時間が経過すると見るのが大変そうだと感じた。そのうち変わるのかな−。ある程度前のジョブは消すようにするのがいいのかも。
まとめ
CronJobを軽く触ってみた。ちゃんと動いていて、しかも実行時だけコンテナを起動しているのでFaaSっぽい雰囲気。ただ、ハンドリングに慣れないうちは中でcrondを動かすコンテナを常時起動しておき、今まで通りのcronで定期実行する方法も併用してもいいのかも。