LoginSignup
13
9

More than 3 years have passed since last update.

k8sで定期実行と1回だけバッチを実行する (CronJobとJob)

Posted at

cronみたいな定期実行のバッチや1回しか使わないバッチをDockerコンテナとしてパッケージにして定期実行することができます。
k8sのkind CronJobってのがcron的なもので、Jobってのがその時だけ実行するやつですね。

Dockerコンテナ内でcrontabを書いておく不安な方法よりも、実行するときだけPodsが起動するのでエコです。

それぞれ、失敗したときの挙動とか、並列実行とか設定できるので便利。詳しくは下記ページをご参照あれ。

Job: https://kubernetes.io/docs/concepts/workloads/controllers/jobs-run-to-completion/
CronJob: https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/

Job

Jobの方から試してみましょう。

こんな感じのファイルを用意します。

Dockerfile
FROM docker/whalesay:latest
ENTRYPOINT [ ":" ] # なにもしない。Dockerfile作る意味はとくにない。
k8s.cowsay.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: cowsay-job-20190520
spec:
  template:
    spec:
      containers:
      - name: cowsay-job
        image: murata/cowsay-job:v3
        command: ["cowsay", "わたしはk8sです。"]
      restartPolicy: OnFailure
  backoffLimit: 5

Dockerfileをビルドします。

~/tmp/k8s-job
❯ docker build -t murata/cowsay-job:v3 .
Sending build context to Docker daemon  3.072kB
Step 1/2 : FROM docker/whalesay:latest
 ---> 6b362a9f73eb
Step 2/2 : ENTRYPOINT [ ":" ] # なにもしない。Dockerfile作る意味ない。
 ---> Running in 93cd12fc5d81
Removing intermediate container 93cd12fc5d81
 ---> 453bf70f357d
Successfully built 453bf70f357d
Successfully tagged murata/cowsay-job:v3

k8sに食わせます。

~/tmp/k8s-job
❯ kubectl apply -f ./k8s.cowsay.job.yaml
job.batch/cowsay-job-20190520 created

job.batchとpodが出来上がっています。

すでに終わっていますね。

~/tmp/k8s-job
❯ kubectl get all
NAME                            READY   STATUS      RESTARTS   AGE
pod/cowsay-job-20190520-fpvmm   0/1     Completed   0          26s

NAME                            COMPLETIONS   DURATION   AGE
job.batch/cowsay-job-20190520   1/1           2s         26s

ログをみてみましょう。

~/tmp/k8s-job
❯ kubectl log job.batch/cowsay-job-20190520
log is DEPRECATED and will be removed in a future version. Use logs instead.
 __________________________ 
< わたしはk8sです。 >
 -------------------------- 
    \
     \
      \     
                    ##        .            
              ## ## ##       ==            
           ## ## ## ##      ===            
       /""""""""""""""""___/ ===        
  ~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ /  ===- ~~~   
       \______ o          __/            
        \    \        __/             
          \____\______/   

うごいていますね。

エラーの場合

backoffLimit: 5としているので失敗しても5回まで実行してくれます。失敗させてみましょう。
下記のように存在しないコマンドにしてみます。

apiVersion: batch/v1
kind: Job
metadata:
  name: pepesay-job-20190520
spec:
  template:
    spec:
      containers:
      - name: pepesay-job
        image: murata/cowsay-job:v3
        command: ["pepesay", "わたしはペペです。"]
      restartPolicy: OnFailure
  backoffLimit: 5

がんばっているようです。すでに2回リスタートしています。

~/tmp/k8s-job
❯ kubectl get all
NAME                             READY   STATUS              RESTARTS   AGE
pod/cowsay-job-20190520-fpvmm    0/1     Completed           0          5m30s
pod/pepesay-job-20190520-gchs9   0/1     RunContainerError   2          37s

NAME                             COMPLETIONS   DURATION   AGE
job.batch/cowsay-job-20190520    1/1           2s         5m30s
job.batch/pepesay-job-20190520   0/1           37s        37s

ちゃんと5回(リスタートは4回)終わって諦めたようです。

❯ kubectl get all
NAME                             READY   STATUS             RESTARTS   AGE
pod/cowsay-job-20190520-fpvmm    0/1     Completed          0          7m44s
pod/pepesay-job-20190520-gchs9   0/1     CrashLoopBackOff   4          2m51s

NAME                             COMPLETIONS   DURATION   AGE
job.batch/cowsay-job-20190520    1/1           2s         7m44s
job.batch/pepesay-job-20190520   0/1           2m51s      2m51s

jobのdescribeを見てみるとだめだったぽよってWarningが出ていますね。

❯ kubectl describe job.batch/pepesay-job-20190520
Name:           pepesay-job-20190520
Namespace:      cowsay
Selector:       controller-uid=28ea1281-7c74-11e9-9b99-080027ae51c3
Labels:         controller-uid=28ea1281-7c74-11e9-9b99-080027ae51c3
                job-name=pepesay-job-20190520
Annotations:    kubectl.kubernetes.io/last-applied-configuration:
                  {"apiVersion":"batch/v1","kind":"Job","metadata":{"annotations":{},"name":"pepesay-job-20190520","namespace":"cowsay"},"spec":{"backoffLim...
Parallelism:    1
Completions:    1
Start Time:     Wed, 22 May 2019 18:29:55 +0900
Pods Statuses:  0 Running / 0 Succeeded / 1 Failed
Pod Template:
  Labels:  controller-uid=28ea1281-7c74-11e9-9b99-080027ae51c3
           job-name=pepesay-job-20190520
  Containers:
   pepesay-job:
    Image:      murata/cowsay-job:v3
    Port:       <none>
    Host Port:  <none>
    Command:
      pepesay
      わたしはk8sです。
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Events:
  Type     Reason                Age    From            Message
  ----     ------                ----   ----            -------
  Normal   SuccessfulCreate      3m25s  job-controller  Created pod: pepesay-job-20190520-gchs9
  Normal   SuccessfulDelete      11s    job-controller  Deleted pod: pepesay-job-20190520-gchs9
  Warning  BackoffLimitExceeded  11s    job-controller  Job has reached the specified backoff limit

エラーjobの仕込み方が悪かったのかログがでていない。。。

❯ kubectl logs job.batch/pepesay-job-20190520
error: timed out waiting for the condition

CronJob

cronjobの場合は、scheduleにcrontab形式で記載します。また、前の処理が終わっていなかった場合にどうするかをconcurrencyPolicyで決めます。(終わるまでまつ、やらない、殺して実行とか。)

1分に1回実行してみます。

k8s.cowsay.cronjob.yaml
apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: cowsay-cronjob-20190520
spec:
  concurrencyPolicy: Replace
  schedule: "*/1 * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: cowsay-cronjob
            image: murata/cowsay-job:v3
            command: ["cowsay", "わたしはCronJobです。"]
          restartPolicy: OnFailure

こんな感じcronjobが配置されます。

❯ kubectl get all,jobs -o wide
NAME                            READY   STATUS      RESTARTS   AGE   IP           NODE       NOMINATED NODE   READINESS GATES
pod/cowsay-job-20190520-fpvmm   0/1     Completed   0          57m   172.17.0.6   minikube   <none>           <none>

NAME                            COMPLETIONS   DURATION   AGE   CONTAINERS   IMAGES                 SELECTOR
job.batch/cowsay-job-20190520   1/1           2s         57m   cowsay-job   murata/cowsay-job:v3   controller-uid=7a5a3b6b-7c73-11e9-9b99-080027ae51c3

NAME                                    SCHEDULE      SUSPEND   ACTIVE   LAST SCHEDULE   AGE   CONTAINERS       IMAGES                 SELECTOR
cronjob.batch/cowsay-cronjob-20190520   */1 * * * *   False     0        <none>          18s   cowsay-cronjob   murata/cowsay-job:v3   <none>

しばらくするとこんな感じに表示されます。

❯ kubectl get all,jobs -o wide
NAME                                           READY   STATUS      RESTARTS   AGE   IP           NODE       NOMINATED NODE   READINESS GATES
pod/cowsay-cronjob-20190520-1558520580-xtwq7   0/1     Completed   0          89s   172.17.0.6   minikube   <none>           <none>
pod/cowsay-cronjob-20190520-1558520640-br724   0/1     Completed   0          29s   172.17.0.6   minikube   <none>           <none>
pod/cowsay-job-20190520-fpvmm                  0/1     Completed   0          59m   172.17.0.6   minikube   <none>           <none>

NAME                                           COMPLETIONS   DURATION   AGE   CONTAINERS       IMAGES                 SELECTOR
job.batch/cowsay-cronjob-20190520-1558520580   1/1           1s         89s   cowsay-cronjob   murata/cowsay-job:v3   controller-uid=97619397-7c7b-11e9-9b99-080027ae51c3
job.batch/cowsay-cronjob-20190520-1558520640   1/1           1s         29s   cowsay-cronjob   murata/cowsay-job:v3   controller-uid=bb45dacd-7c7b-11e9-9b99-080027ae51c3
job.batch/cowsay-job-20190520                  1/1           2s         59m   cowsay-job       murata/cowsay-job:v3   controller-uid=7a5a3b6b-7c73-11e9-9b99-080027ae51c3

NAME                                    SCHEDULE      SUSPEND   ACTIVE   LAST SCHEDULE   AGE    CONTAINERS       IMAGES                 SELECTOR
cronjob.batch/cowsay-cronjob-20190520   */1 * * * *   False     0        36s             2m8s   cowsay-cronjob   murata/cowsay-job:v3   <none>

実行結果をみてみます。

❯ kubectl logs pod/cowsay-cronjob-20190520-1558520580-xtwq7
 ______________________________ 
< わたしはCronJobです。 >
 ------------------------------ 
    \
     \
      \     
                    ##        .            
              ## ## ##       ==            
           ## ## ## ##      ===            
       /""""""""""""""""___/ ===        
  ~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ /  ===- ~~~   
       \______ o          __/            
        \    \        __/             
          \____\______/   

自分の環境の場合、完了後のpodは3個残るようです。

.spec.successfulJobsHistoryLimit.spec.failedJobsHistoryLimit で設定できるみたい。

まとめ

今回はk8sでバッチを実行してみました。まぁ普通は並列実行とかしないので、k8sじゃない限りは、crontabでもよいのですが、k8s環境にいる人はぜひ使うと捗りそうです。

なによりロギングが楽。
crontabに適当に書いて、 /dev/null に捨てちゃったりしていませんか?
ちゃんと設定すればよいのですが、デフォルトがメールやら/var/log/cronなので、他コンテナと同様に処理されるのはよいですね。

デーモン的な永遠に動き続けるもの場合はDaemonSet というものがあります。
https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/
pm2も便利かもしれません。 http://pm2.keymetrics.io/
ただしpm2を使う場合1podの中にあまり詰め込みすぎないように気をつけましょう。ノード負荷が偏ります。

13
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
9