跳到主要内容

JobとCronJob

Kubernetesでは、Webサーバーのような常駐型のアプリケーションだけでなく、一度だけ実行して終了するタスクや、定期的に実行されるタスクを管理するためのリソースも提供されています。それが JobCronJob です。

Job (ジョブ)

Jobは、1つ以上のPodを作成し、指定された数のPodが正常に終了(Succeeded)することを保証するリソースです。

主なユースケース

  • データベースのマイグレーション
  • バッチ処理(データ集計、レポート生成など)
  • 一回限りの初期化スクリプト

マニフェスト例

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

重要なパラメータ

  • restartPolicy: Jobの場合は OnFailure または Never を指定します(Alwaysは不可)。
  • completions: 成功させるべき回数。
  • parallelism: 同時に実行するPodの数。
  • backoffLimit: 失敗時のリトライ回数(デフォルトは6)。

CronJob (クロンジョブ)

CronJobは、Linuxのcron形式のスケジュールに基づいてJobを定期的に作成するリソースです。

主なユースケース

  • 定期的なバックアップ
  • 定期的なメール配信
  • 深夜のデータクレンジング

マニフェスト例

apiVersion: batch/v1
kind: CronJob
metadata:
name: hello
spec:
schedule: "*/1 * * * *"
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

重要なパラメータ

  • schedule: Cron形式のスケジュール(例: "0 0 * * *")。
  • concurrencyPolicy:
    • Allow: 同時実行を許可(デフォルト)。
    • Forbid: 前のジョブが終わっていなければスキップ。
    • Replace: 前のジョブをキャンセルして新しいジョブを開始。
  • successfulJobsHistoryLimit: 成功したJobの履歴保持数(デフォルト3)。
  • failedJobsHistoryLimit: 失敗したJobの履歴保持数(デフォルト1)。

ベストプラクティス

1. タイムアウトとクリーンアップの設定

Jobが無限に実行され続けるのを防ぐため、また終了したPodがリソースを圧迫しないように設定します。

  • activeDeadlineSeconds: Jobの実行時間の制限(秒)。これを超えるとJobは強制終了されます。
  • ttlSecondsAfterFinished: Job終了後、指定秒数が経過するとJobリソース(および関連Pod)を自動削除します(TTL Controller)。
spec:
ttlSecondsAfterFinished: 100 # 終了後100秒で削除
activeDeadlineSeconds: 1800 # 30分でタイムアウト

2. 冪等性(Idempotency)の確保

KubernetesのJobは、ネットワーク障害やノード障害により、稀に同じ処理が複数回実行される可能性があります。アプリケーション側で冪等性を担保する(同じ処理を何度実行しても結果が変わらないようにする)ことが重要です。

3. リソース制限の設定

バッチ処理は高負荷になりがちです。他のアプリケーションへの影響を防ぐため、必ず resources.requestsresources.limits を設定しましょう。

4. 同時実行ポリシーの検討 (CronJob)

ジョブの実行時間がスケジュール間隔を超える可能性がある場合、concurrencyPolicy を慎重に選択してください。データの整合性が重要な場合は Forbid が推奨されます。

5. 失敗時のハンドリング

backoffLimit を適切に設定し、無限リトライを防ぎます。また、アプリケーションログを適切に出力し、失敗原因を調査できるようにしておきましょう。

6. startingDeadlineSeconds の設定(重要)

.spec.startingDeadlineSeconds は、予定時刻を過ぎてからJobの開始を許容する秒数ですが、これはCronJobの停止を防ぐためにも重要です。 Kubernetesの仕様上、CronJobは「直近100回連続でスケジューリングに失敗する」と、それ以降Jobを生成しなくなります。startingDeadlineSeconds を設定していない場合、長期間の suspend: true や障害による連続失敗が100回に達すると、CronJobが壊れて再作成が必要になります。 この値を設定することで、判定対象が「その時間枠内での失敗」に限定されるため、意図しないCronJobの停止を防ぐことができます。

7. タイムゾーンの指定

デフォルトではCronJobはUTC(協定世界時)で動作します。JST(日本標準時)で実行したい場合、Kubernetes 1.27以降(AKS 1.27以降)では .spec.timeZone フィールドを利用できます。

spec:
timeZone: "Asia/Tokyo"
schedule: "0 0 * * *" # JST 0:00に実行

8. Spot VM (Preemptible Node) の回避

長時間実行される重要なバッチ処理は、コスト削減のためにSpot VM (Spot Node Pool) を使用しているクラスタであっても、Spot VM上での実行を避けるべきです。nodeAffinity を使用して、通常の(オンデマンド)ノードで実行されるように制御します。

spec:
template:
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.azure.com/scalesetpriority
operator: NotIn
values:
- spot

参考文献