Cloud Run で Python ジョブをビルドして作成する

シンプルな Cloud Run ジョブを作成して、ソースからデプロイする方法を学習します。コードをコンテナ イメージに自動的にパッケージ化し、コンテナ イメージを Artifact Registry にアップロードして、Cloud Run にデプロイします。ここでは説明されていない言語を使用することもできます。

始める前に

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  3. Make sure that billing is enabled for your Google Cloud project.

  4. Install the Google Cloud CLI.
  5. To initialize the gcloud CLI, run the following command:

    gcloud init
  6. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  7. Make sure that billing is enabled for your Google Cloud project.

  8. Install the Google Cloud CLI.
  9. To initialize the gcloud CLI, run the following command:

    gcloud init
  10. Cloud Run Admin API と Cloud Build API を有効にします。

    gcloud services enable run.googleapis.com \
        cloudbuild.googleapis.com

    Cloud Run Admin API を有効にすると、Compute Engine のデフォルトのサービス アカウントが自動的に作成されます。

  11. Cloud Build がソースをビルドできるようにするには、次のコマンドを実行して、Compute Engine のデフォルト サービス アカウントに Cloud Build サービス アカウントのロールを付与します。

    gcloud projects add-iam-policy-binding PROJECT_ID \
        --member=serviceAccount:PROJECT_NUMBER-compute@developer.gserviceaccount.com \
        --role=roles/cloudbuild.builds.builder

    PROJECT_NUMBER は Google Cloud プロジェクト番号に、PROJECT_ID は Google Cloud プロジェクト ID に置き換えます。プロジェクト ID とプロジェクト番号を確認する方法については、プロジェクトの作成と管理をご覧ください。

    Compute Engine のデフォルト サービス アカウントに Cloud Build サービス アカウントのロールを付与すると、反映されるまでに数分かかることがあります。

サンプルジョブの作成

Python でジョブを作成するには:

  1. jobs という名前の新しいディレクトリを作成し、そのディレクトリに移動します。

    mkdir jobs
    cd jobs
    
  2. 実際のジョブコードを記述する main.py ファイルを作成します。ここに次のサンプル行をコピーします。

    import json
    import os
    import random
    import sys
    import time
    
    # Retrieve Job-defined env vars
    TASK_INDEX = os.getenv("CLOUD_RUN_TASK_INDEX", 0)
    TASK_ATTEMPT = os.getenv("CLOUD_RUN_TASK_ATTEMPT", 0)
    # Retrieve User-defined env vars
    SLEEP_MS = os.getenv("SLEEP_MS", 0)
    FAIL_RATE = os.getenv("FAIL_RATE", 0)
    
    
    # Define main script
    def main(sleep_ms=0, fail_rate=0):
        """Program that simulates work using the sleep method and random failures.
    
        Args:
            sleep_ms: number of milliseconds to sleep
            fail_rate: rate of simulated errors
        """
        print(f"Starting Task #{TASK_INDEX}, Attempt #{TASK_ATTEMPT}...")
        # Simulate work by waiting for a specific amount of time
        time.sleep(float(sleep_ms) / 1000)  # Convert to seconds
    
        # Simulate errors
        random_failure(float(fail_rate))
    
        print(f"Completed Task #{TASK_INDEX}.")
    
    
    def random_failure(rate):
        """Throws an error based on fail rate
    
        Args:
            rate: a float between 0 and 1
        """
        if rate < 0 or rate > 1:
            # Return without retrying the Job Task
            print(
                f"Invalid FAIL_RATE env var value: {rate}. "
                + "Must be a float between 0 and 1 inclusive."
            )
            return
    
        random_failure = random.random()
        if random_failure < rate:
            raise Exception("Task failed.")
    
    
    # Start script
    if __name__ == "__main__":
        try:
            main(SLEEP_MS, FAIL_RATE)
        except Exception as err:
            message = (
                f"Task #{TASK_INDEX}, " + f"Attempt #{TASK_ATTEMPT} failed: {str(err)}"
            )
    
            print(json.dumps({"message": message, "severity": "ERROR"}))
            sys.exit(1)  # Retry Job Task by exiting the process

    Cloud Run ジョブを使用すると、実行するタスクの数を指定できます。次のサンプルコードは、組み込みの CLOUD_RUN_TASK_INDEX 環境変数を使用する方法を示しています。各タスクが、コンテナの 1 つの実行中のコピーを表します。タスクは通常、並行して実行されます。各タスクが独立してデータのサブセットを処理できる場合は、複数のタスクを使用すると便利です。

    各タスクはインデックスを認識し、CLOUD_RUN_TASK_INDEX 環境変数に格納されます。組み込みの CLOUD_RUN_TASK_COUNT 環境変数には、ジョブの実行時に --tasks パラメータを介して指定されたタスクの数が含まれています。

    このコードは、組み込みの CLOUD_RUN_TASK_ATTEMPT 環境変数を使用してタスクを再試行する方法を示しています。この変数はタスクの再試行回数を表します。最初の再試行が行われると、この変数に 0 が設定され、--max-retries になるまで再試行のたびに値が 1 ずつ増加します。

    このコードでは、再試行のテストやエラーログの生成も行うことができるため、問題の発生箇所を確認できます。

  3. 次の内容を含むテキスト ファイルをファイル拡張子のない Procfile という名前で作成します。

    web: python3 main.py

コードが完成し、コンテナにパッケージ化できるようになりました。

ジョブコンテナをビルドして Artifact Registry に送信し、Cloud Run にデプロイする

重要: 以下の説明では、このクイックスタートで使用するプロジェクトのオーナーロールまたは編集者ロールが付与されていることを前提としています。ロールが付与されていない場合は、Cloud Run ソース デベロッパー ロールで、ソースから Cloud Run リソースをデプロイするために必要な権限を確認してください。

このクイックスタートでは、コンテナをビルドして Artifact Registry にアップロードし、ジョブを Cloud Run にデプロイするソースからのデプロイを使用します。

gcloud run jobs deploy job-quickstart \
    --source . \
    --tasks 50 \
    --set-env-vars SLEEP_MS=10000 \
    --set-env-vars FAIL_RATE=0.1 \
    --max-retries 5 \
    --region REGION \
    --project=PROJECT_ID

ここで、PROJECT_ID はプロジェクト ID、REGION はリージョンです(例: us-central1)。パラメータの値は、テスト目的で使用する任意の値に変更できます。SLEEP_MS は作業をシミュレートし、FAIL_RATE でタスクの X% を失敗させます。これにより、並列処理をテストし、失敗したタスクを再試行できます。

Cloud Run でジョブを実行する

作成したジョブを実行するには:

gcloud run jobs execute job-quickstart --region REGION

REGION は、ジョブを作成してデプロイしたときに使用したリージョン(us-central1 など)に置き換えます。

次のステップ

コードソースからコンテナをビルドし、リポジトリに push する方法については、以下をご覧ください。