🌲

入門Kubernetes Jobs・CronJob

2022/04/24に公開

概要

KubernetesのWorkloadリソースであるJobsとCronJobの公式ドキュメントの内容について、個人の備忘録としてまとめていきます。

https://kubernetes.io/docs/concepts/workloads/controllers/job/
https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/

Jobs

Jobは一つ以上のPodを作成することである特定数のPodが正常終了するまでリトライしながら処理を実行するKubernetesのWorkloadリソースです。

Jobの利用シーンとして、1つのJobを正常通りに処理するために1つのJobオブジェクトを作成するケースがあります。Podの実行が失敗したり削除された場合はJobは新たにPodを起動します。

Jobは平行に複数のPodを起動することもできます。

ex)

job.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: pi
spec:
  template:
    spec:
      containers:
      - name: pi
        image: perl
        command: ["perl",  "-Mbignum=bpi", "-wle", "print bpi(2000)"]
      restartPolicy: Never
  backoffLimit: 4

jobを実行

kubectl applyjob.yaml

Job spec

apiVersionkindmetada、そして .specセクションを指定します。

https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#spec-and-status

Pod Template

.specフィールドにおいて唯一必須の項目が.spec.templateです。
spec.templateは基本的に pod templateと同一の内容になります。

https://kubernetes.io/docs/concepts/workloads/pods/#pod-templates

Podのspecと共通ですが、フィールドの指定に関して注意点があります。
KubernetesのcommandはDockerでのEntryPointに該当し、
DockerのCMDに対応するものはKubernetesではcommandではなくargsで指定するようにします。(ex: サブコマンドを指定した場合はcommandではなくargsの方に指定するようにします)

https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#entrypoint

Jobでは、Pod templateで必須のフィールドに加えて、適切なラベル( https://kubernetes.io/docs/concepts/workloads/controllers/job/#pod-selector )と適切な起動ポリシーの指定が必須です。

RestartPolicyNever又はOnFailureのみ指定可能です。

https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy

Jobの平行実行

Jobの実行において主に3つのシチュエーションが考えられます

  1. 単一のJob
    • Podが失敗しない限り通常は1つのPodのみが起動します
    • Podが正常終了したタイミングでJobが完了します
  2. Podの実行完了数が固定された平行実行
    • .spec.completionsに正の数が指定される場合
    • Jobは全体のタスクを表し、指定の.spec.completions数のPodの実行が完了したタイミングでJobが完了します
    • .spec.completionMode="Indexed"が指定されている場合は、0から.spec.completions=1の範囲でPodは異なるインデックスを取得します
  3. work queueを利用した平行実行
    • .spec.completionsは指定しません
    • それぞれのPodがどの処理を実行するかを決めるために、Pod間又は外部サービス間で調整する必要があります
    • 個々のPodはJob全体が完了しかたかどうかを個別に判断できます
    • JobのPodが正常終了又停止された場合、新しいPodが作成されます
    • Podが正常終了してその他全てのPodも終了している場合、Jobが正常に終了します
    • いずれかのPodが正常終了した場合、その他のPodはその作業を処理したり出力したりすることはできません

CronJob

CronJobはJobをcronのように定期実行するためのKubernetesのWorkloadリソースです。
スケジュールは Cron形式で指定します。

https://en.wikipedia.org/wiki/Cron

ex)

cronjob.yaml
apiVersion: batch/v1
kind: CronJob
metadata:
  name: hello
spec:
  schedule: "* * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: hello
            image: busybox:1.28
            imagePullPolicy: IfNotPresent
            command:
            - /bin/sh
            - -c
            - date; echo Hello from the Kubernetes cluster
          restartPolicy: OnFailure

Cronスケジュール構文

# ┌───────────── minute (0 - 59)
# │ ┌───────────── hour (0 - 23)
# │ │ ┌───────────── day of the month (1 - 31)
# │ │ │ ┌───────────── month (1 - 12)
# │ │ │ │ ┌───────────── day of the week (0 - 6) (Sunday to Saturday;
# │ │ │ │ │                                   7 is also Sunday on some systems)
# │ │ │ │ │                                   又は sun, mon, tue, wed, thu, fri, sat
# │ │ │ │ │
# * * * * *

ex)
0 0 13 * 5

上の例では、毎月13日の金曜日の00:00に定期実行する

CronJobの制限

スケジュール毎に"およそ"1つのJobオブジェクトを生成します。
たまに2つのjobや1つのjobが生成されない場合もありえます。
そのため、CronJobは冪等的に実装される必要があります。

CronJob毎に、CronJobコントローラーは最後の実行から現在に至るまでどれくらいの数のスケジュールがスキップされたかをチェックしています。
もし100回以上のスケジュールがスキップされている場合は、それ以上のjobを実行したりログを出力したりエラーを出力したりしません。

Cannot determine if job needs to be started. Too many missed start time (> 100). Set or decrease .spec.startingDeadlineSeconds or check clock skew.

startingDeadlineSecondsフィールドがセットされている場合、
startingDeadlineSecondsから現在に至るまでどれくらいのJobがスキップされたかをCronJobコントローラーはカウントします。

startingDeadlineSecondsでスケジュールされた時間にCronJobが生成できないと失敗したとみなされます。例えば、concurrencyPolicyForbidに設定されている場合、前回のスケジュールがまだ実行中にCronJobをスケジュールしようとするとCronJobは生成されません。

CronJobはスケジュールに一致するJobの作成のみを管理し、そのJobがPodの管理を行います。

Discussion