ジョブの実行

このページでは、Google Kubernetes Engine(GKE)でジョブを実行する方法について説明します。

概要

GKE では、ジョブは有限のタスクを表すコントローラ オブジェクトです。ジョブは、他のコントローラ オブジェクトとは異なり、進行中の目的の状態(実行中のポッドの総数など)を管理するのではなく、実行されるタスクを完了するまで管理します。

ジョブは、大規模な計算やバッチ指向のタスクに役立ちます。ジョブは、ポッドの並列実行をサポートするために使用できます。ジョブを使用して、メールの送信、フレームのレンダリング、ファイルのコード変換、データベース キーのスキャンなど、独立しているが関連性のある作業項目を並行して実行できます。ただし、ジョブはバックグラウンド プロセスの連続するストリームのような密接なやり取りを行う並列処理を想定したものではありません。

GKE には、次の 2 種類のジョブがあります。

  • 非並列ジョブ: ポッドを 1 つだけ作成し(ポッドが正常に終了しなかった場合はポッドを再作成する)、ポッドが正常に終了したときに完了するジョブ。
  • 完了数を指定した並列ジョブ: 一定数のポッドが正常に終了すると完了するジョブ。completions フィールドを使用して必要な完了の数を指定します。

Job は、Kubernetes のJob オブジェクトで表されます。ジョブが作成されると、ジョブ コントローラが 1 つ以上のポッドを作成し、ジョブのポッドが正常に終了するかどうかを確認します。ポッドが終了すると、ジョブはタスクが正常に完了したポッドの数を追跡します。正常な完了が必要な数に達すると、ジョブは完了します。

他のコントローラと同様に、ジョブ コントローラはいずれかのポッドが失敗したり削除されたりすると、新しいポッドを作成します。

始める前に

作業を始める前に、次のことを確認してください。

  • Google Kubernetes Engine API が有効になっていることを確認します。
  • Google Kubernetes Engine API の有効化
  • Google Cloud CLI がインストールされていることを確認します。
  • 次のいずれかの方法で、プロジェクトにデフォルトの Google Cloud CLI 設定をセットアップします。
    • プロジェクトのデフォルトの設定全般を確認する場合は、gcloud init を使用します。
    • gcloud config を使用して、プロジェクト ID、ゾーン、リージョンを個別に設定します。

    gcloud init

    1. gcloud init を実行して、次の操作を行います。

      gcloud init

      リモート サーバーで SSH を使用している場合は、--console-only フラグを指定して、コマンドがブラウザを起動しないようにします。

      gcloud init --console-only
    2. Google Cloud アカウントを使用できるように、gcloud CLI の承認手順を行います。
    3. 新しい構成を作成するか、既存の構成を選択します。
    4. Google Cloud プロジェクトを選択します。
    5. デフォルトの Compute Engine ゾーンを選択します。
    6. デフォルトの Compute Engine リージョンを選択します。

    gcloud config

    1. デフォルトのプロジェクト ID を設定します。
      gcloud config set project PROJECT_ID
    2. デフォルトの Compute Engine リージョン(例: us-central1)を設定します。
      gcloud config set compute/region COMPUTE_REGION
    3. デフォルトの Compute Engine ゾーン(例: us-central1-c)を設定します。
      gcloud config set compute/zone COMPUTE_ZONE
    4. gcloud を最新バージョンに更新します。
      gcloud components update

    デフォルトの場所を設定することで、gcloud CLI のエラー(One of [--zone, --region] must be supplied: Please specify location など)を防止できます。

ジョブを作成する

Job を作成するには、kubectl apply マニフェスト ファイルを使用します。

以下は、ジョブのマニフェストの例です。

apiVersion: batch/v1
kind: Job
metadata:
  # Unique key of the Job instance
  name: example-job
spec:
  template:
    metadata:
      name: example-job
    spec:
      containers:
      - name: pi
        image: perl
        command: ["perl"]
        args: ["-Mbignum=bpi", "-wle", "print bpi(2000)"]
      # Do not restart containers after they exit
      restartPolicy: Never
  # of retries before marking as failed.
  backoffLimit: 4

マニフェストを config.yaml という名前のファイルにコピーし、ジョブを作成します。

kubectl apply -f config.yaml

このジョブは、円周率を 2,000 桁まで計算し、それを出力します。

Job オブジェクトの要件は 1 つだけです。Pod template フィールドが必須になります。

ジョブの完了数

一定の数のポッドが正常に終了すると、ジョブが完了します。デフォルトでは、ポッドを 1 つだけ含む非並列ジョブは、ポッドが正常に終了した直後に完了します。

並列ジョブを使用する場合は、オプションの completions フィールドを使用してジョブの完了数を設定できます。このフィールドには、ジョブが完了するまでに正常に終了する必要があるポッドの数を指定します。completions フィールドにはゼロ以外の正の値を指定できます。

completions を省略するか、ゼロを指定すると、いずれかのポッドの正常終了がすべてのポッドの正常終了を示すようになります。

前の例の config.yamlconfig-2.yaml という名前のファイルにコピーします。config-2.yaml で、nameexample-job-2 に変更し、completions: 8 をジョブの spec フィールドに追加します。これは、8 個の正常な完了が必要であることを指定しています。

apiVersion: batch/v1
kind: Job
metadata:
  name: example-job-2
spec:
  completions: 8
  template:
    metadata:
      name: example-job-2
    spec:
      ...

ジョブを作成します。

kubectl apply -f config-2.yaml

completions のデフォルト値は 1 です。completions が設定されている場合、parallelism フィールドは特に設定しない限り 1 に設定されます。両方のフィールドが設定されていない場合、デフォルト値はどちらも 1 です。

並列処理を管理する

デフォルトでは、ジョブのポッドは並列で実行されません。オプションの parallelism フィールドは、ジョブで同時に実行するポッドの最大数を指定します。

残りの作業が parallelism の値より少ない場合は、定常状態で実行されているポッドの実際の数が parallelism の値より少なくなる可能性があります。completions も設定されている場合、並列で実行されるポッドの実際の数が残りの完了数を超えることはありません。ポッドの作成に何度も失敗する場合、ジョブはポッドの作成を抑制することがあります。

前の例の config.yamlconfig-3.yaml という名前のファイルにコピーします。config-3.yaml で、nameexample-job-3 に変更し、parallelism: 5 をジョブの spec フィールドに追加します。これは、5 個の同時実行ポッドを実行することを指定しています。

apiVersion: batch/v1
kind: Job
metadata:
  name: example-job-3
spec:
  parallelism: 5
  template:
    metadata:
      name: example-job-3
    spec:
      ...

ジョブを作成します。

kubectl apply -f config-3.yaml

parallelism フィールドを省略した場合や、別の値に設定しなかった場合のデフォルト値は、1 です。値を 0 に設定すると、値が増加するまで Job は一時停止されます。

再試行を指定する

デフォルトでは、Job が失敗しない限り、Job は中断されずに実行されます。失敗すると、Job は backoffLimit に従います。backoffLimit フィールドには、Job を失敗としてマークするまでの再試行回数を指定します。デフォルト値は 6 です。再試行回数は、グローバルではなく、Pod ごとに適用されます。つまり、複数の Pod が失敗した場合(parallelism が 1 より大きい場合)、1 つの Pod の失敗回数が backoffLimit に達するまで Job が実行されます。backoffLimit に達すると、Job は失敗としてマークされ、実行中の Pod は終了します。

たとえば、この Job の例では、再試行回数を 4 に設定しています。

apiVersion: batch/v1
kind: Job
metadata:
  name: example-job
spec:
  template:
    metadata:
      name: example-job
    spec:
      containers:
      ...
  backoffLimit: 4

Pod の代替

次のような状況で現在の Pod が失敗したと思われる場合、Job は backoffLimit に基づいて Pod を再作成します。

  • Pod コンテナがゼロ以外のエラーコードで終了する。
  • ノードが再起動されると、kubelet は再起動後に Pod を Failed とマークすることがある。

次のような特定のシナリオでは、完了していない Job が backoffLimit を考慮せずに Pod を置き換えます。

  • Pod を手動で強制終了しても、Pod のフェーズは Failed に設定されない。交換 Pod は、現在の Pod の終了猶予期間が終了する前でも作成できます。
  • ノードがドレインされると(手動または自動アップグレード中に)、Pod はドレインの猶予期間に従って終了し、置き換えられます。
  • ノードが削除されると、Pod はガベージ コレクション(削除済みとしてマーク)され、置き換えられます。

期限を指定する

デフォルトでは、ポッドが連続して失敗した場合、ジョブは新しいポッドを無期限に作成します。Job を無期限に再試行したくない場合は、Job のオプションの .spec.activeDeadlineSeconds フィールドを使用して期限の値を指定できます。

期限によって、ジョブを終了する前にタスクを正常に完了するための時間(秒単位)がジョブに与えられます。activeDeadlineSeconds 値は Job の startTime を基準にしており、作成された Pod の数に関係なく、Job の継続時間に適用されます。

期限を指定するには、マニフェスト ファイルで activeDeadlineSeconds の値をジョブの spec フィールドに追加します。たとえば、次の構成では、ジョブの正常完了の期限として 100 秒が指定されています。

apiVersion: batch/v1
kind: Job
metadata:
  name: example-job
spec:
  activeDeadlineSeconds: 100
  template:
    metadata:
      name: example-job
    spec:
      ...

期限前にジョブが正常に完了しなかった場合、ジョブは DeadlineExceeded ステータスで終了します。これにより、ポッドの作成が中止され、既存のポッドが削除されます。

ポッドセレクタを指定する

ジョブのポッド テンプレートを更新したいが、ジョブの現在のポッドを更新されたジョブで実行したい場合は、セレクタを手動で指定すると便利です。

ジョブは selector フィールドによってインスタンス化されます。selector は、ジョブのポッドに一意の識別子を生成します。生成された ID は他のジョブと重複しません。通常、ユーザーがこのフィールドを設定することはありません。設定した selector の値が別のジョブと重複すると、他のジョブのポッドに問題が発生する可能性があります。ユーザーがこのフィールドを設定するには、ジョブの spec フィールドに manualSelector: True を指定する必要があります。

たとえば、kubectl get job my-job --output=yaml を実行してジョブの仕様を表示すると、ジョブのポッドのために生成されたセレクタが仕様に含まれています。

kind: Job
metadata:
  name: my-job
...
spec:
  completions: 1
  parallelism: 1
  selector:
    matchLabels:
      controller-uid: a8f3d00d-c6d2-11e5-9f87-42010af00002
...

新しいジョブを作成するときに、manualSelector の値を True に設定し、selector フィールドの job-uid の値を次のように設定できます。

kind: Job
metadata:
  name: my-new-job
  ...
spec:
  manualSelector: true
  selector:
    matchLabels:
      controller-uid: a8f3d00d-c6d2-11e5-9f87-42010af00002
  ...

my-new-job によって作成されたポッドは、上記のポッド UID を使用します。

ジョブを検査する

kubectl

ジョブのステータスを確認するには、次のコマンドを実行します。

kubectl describe job my-job

完了したジョブによって作成されたポッドを含むクラスタ内のすべてのポッドリソースを表示するには、次のコマンドを実行します。

kubectl get pods -a

-a フラグは、指定されたタイプのすべてのリソース(この場合はポッド)を表示するように指定します。

Console

kubectl を使用してジョブを作成した後は、次の手順に沿ってジョブを検査できます。

  1. Cloud Console の [ワークロード] ページに移動します。

    [ワークロード] に移動

  2. ワークロード リストで、検査するジョブの名前をクリックします。

  3. [ジョブの詳細] ページで、次のいずれかの操作を行います。

    • [変更履歴] タブをクリックして、Job の変更履歴を確認します。
    • [イベント] タブをクリックして、Job に関連するすべてのイベントを表示します。
    • [ログ] タブをクリックして、Job に関連するすべてのコンテナログを表示します。
    • [YAML] タブをクリックして、Job のライブ構成の表示、コピー、ダウンロードを行います。

Job を削除する

ジョブが完了すると、ジョブはポッドの作成を中止します。ジョブが完了しても、ジョブ API オブジェクトは削除されないため、ジョブのステータスを表示できます。ジョブによって作成されたポッドは削除されませんが、終了します。ポッドは保持されるため、ポッドのログを表示したり、ポッドを操作したりできます。

kubectl

ジョブを削除するには、次のコマンドを実行します。

kubectl delete job my-job

ジョブを削除すると、ジョブのポッドもすべて削除されます。

ジョブを削除してポッドを保持するには、--cascade false フラグを指定します。

kubectl delete jobs my-job --cascade false

Console

ジョブを削除するには、次の手順を行います。

  1. Cloud Console の [ワークロード] ページに移動します。

    [ワークロード] に移動

  2. ワークロード リストで、削除するジョブを 1 つ以上選択します。

  3. [ 削除] をクリックします。

  4. 確認のメッセージが表示されたら、[削除] をクリックします。

次のステップ