Pub/Sub キューの量に基づいてワーカープールを自動スケーリングする

このチュートリアルでは、Cloud Run ワーカープールをデプロイして Pub/Sub メッセージを処理し、 キューの深さに基づいてコンシューマ インスタンスを自動的にスケーリングする方法について説明します。Cloud Run 外部指標 自動スケーリング(CREMA)を使用します。

目標

このチュートリアルの内容は次のとおりです。

費用

このドキュメントでは、課金対象である次のコンポーネントを使用します。 Google Cloud

料金計算ツールを使うと、予想使用量に基づいて費用の見積もりを生成できます。

新規の Google Cloud ユーザーは無料トライアルをご利用いただける場合があります。

始める前に

  1. アカウントにログインします。 Google Cloud を初めて使用する場合は、 アカウントを作成して、 実際のシナリオでプロダクトがどのように機能するかを評価してください。 Google Cloud新規のお客様には、ワークロードの実行、テスト、デプロイができる無料クレジット $300 分を差し上げます。
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  3. Verify that billing is enabled for your Google Cloud project.

  4. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  5. Verify that billing is enabled for your Google Cloud project.

  6. Cloud Run、Parameter Manager、Artifact Registry、Pub/Sub、Cloud Build の各 API を有効にします。

    API を有効にするために必要なロール

    API を有効にするには、serviceusage.services.enable 権限を含む Service Usage 管理者 IAM ロール(roles/serviceusage.serviceUsageAdmin)が必要です。詳しくは、ロールを付与する方法をご覧ください。

    API を有効にする

  7. gcloud CLI をインストールして初期化します
  8. コンポーネントを更新します。
    gcloud components update
  9. このチュートリアルでは、いくつかの環境変数を使用します。デバッグを改善するには、次のコマンドを実行して、設定されていないローカル環境変数を参照したときにエラーを生成します。
    set -u
  10. このチュートリアルで使用する CREMA の構成変数を設定します。
    export PROJECT_ID=PROJECT_ID
    export REGION=us-central1
    export TOPIC_ID=crema-pubsub-topic
    export SUBSCRIPTION_ID=crema-subscription
    export CREMA_SA_NAME=crema-service-account
    export CONSUMER_SA_NAME=consumer-service-account
    export CONSUMER_WORKER_POOL_NAME=worker-pool-consumer
    export CREMA_SERVICE_NAME=my-crema-service
    PROJECT_ID は、 Google Cloud プロジェクトの ID に置き換えます。
  11. 次のコマンドを実行して、プロジェクト ID を設定します。
    gcloud config set project $PROJECT_ID
  12. Cloud Run スケーリング サービスの料金は、スケーリングをトリガーする頻度に基づいて発生します。詳細については、料金計算ツールで費用を見積もってください。

必要なロール

チュートリアルを完了するために必要な権限を取得するには、プロジェクトに対する次の IAM ロールを付与するよう管理者に依頼してください。

ロールの付与については、プロジェクト、フォルダ、組織へのアクセス権の管理をご覧ください。

必要な権限は、カスタムロールや他の事前定義ロールから取得することもできます。

Pub/Sub トピックとサブスクリプションを作成する

ワーカーを自動スケーリングするには、次の手順でコンシューマ アプリケーションのプル サブスクリプションを作成します。

  1. メッセージ フィードを表す Pub/Sub トピックを作成します。

    gcloud pubsub topics create $TOPIC_ID
    
  2. Pub/Sub トピックからメッセージを使用するプル サブスクリプションを作成します。

    gcloud pubsub subscriptions create $SUBSCRIPTION_ID --topic=$TOPIC_ID
    

カスタム サービス アカウントを作成する

このチュートリアルでは、プロビジョニングされた リソースを使用するために必要な最小 権限を持つ次の 2 つのサービス アカウントが必要です。

  • コンシューマ サービス アカウント: メッセージを処理するコンシューマ ワーカープールの ID。次のコマンドを実行して、コンシューマ サービス アカウントを作成します。

    gcloud iam service-accounts create $CONSUMER_SA_NAME \
      --display-name="Pub/Sub consumer service account"
    
  • CREMA サービス アカウント: オートスケーラーの ID。次のコマンドを実行して、CREMA サービス アカウントを作成します。

    gcloud iam service-accounts create $CREMA_SA_NAME \
      --display-name="CREMA service account"
    

カスタム サービス アカウントに追加の権限を付与する

ワーカープールをスケーリングするには、カスタム サービス アカウントに次の権限を付与します。

  1. Parameter Manager から読み取る権限を CREMA サービス アカウントに付与します。

    gcloud projects add-iam-policy-binding $PROJECT_ID \
      --member="serviceAccount:$CREMA_SA_NAME@$PROJECT_ID.iam.gserviceaccount.com" \
      --role="roles/parametermanager.parameterViewer"
    
  2. ワーカープールをスケーリングする権限を CREMA サービス アカウントに付与します。

    gcloud projects add-iam-policy-binding $PROJECT_ID \
      --member="serviceAccount:$CREMA_SA_NAME@$PROJECT_ID.iam.gserviceaccount.com" \
      --role="roles/run.developer"
    
  3. CREMA サービス アカウントにサービス アカウント ユーザーのロールを付与します。

    gcloud projects add-iam-policy-binding $PROJECT_ID \
      --member="serviceAccount:$CREMA_SA_NAME@$PROJECT_ID.iam.gserviceaccount.com" \
      --role="roles/iam.serviceAccountUser"
    
  4. 指標を表示する権限を CREMA サービス アカウントに付与します。

     gcloud projects add-iam-policy-binding $PROJECT_ID \
       --member="serviceAccount:$CREMA_SA_NAME@$PROJECT_ID.iam.gserviceaccount.com" \
       --role="roles/monitoring.viewer"
    
  5. 指標を書き込む権限を CREMA サービス アカウントに付与します。

     gcloud projects add-iam-policy-binding $PROJECT_ID \
       --member="serviceAccount:$CREMA_SA_NAME@$PROJECT_ID.iam.gserviceaccount.com" \
       --role="roles/monitoring.metricWriter"
    
  6. Pub/Sub メッセージを表示する権限を CREMA サービス アカウントに付与します。

    gcloud pubsub subscriptions add-iam-policy-binding $SUBSCRIPTION_ID \
      --member="serviceAccount:$CREMA_SA_NAME@$PROJECT_ID.iam.gserviceaccount.com" \
      --role="roles/pubsub.viewer"
    
  7. サブスクリプションからメッセージをプルする権限をコンシューマ サービス アカウントに付与します。

    gcloud pubsub subscriptions add-iam-policy-binding $SUBSCRIPTION_ID \
      --member="serviceAccount:$CONSUMER_SA_NAME@$PROJECT_ID.iam.gserviceaccount.com" \
      --role="roles/pubsub.subscriber"
    

Cloud Run ワーカープールをデプロイする

Pub/Sub サブスクリプションからメッセージを使用するワーカープールをデプロイする手順は次のとおりです。

  1. consumer という名前のフォルダを作成し、そのフォルダに移動します。

    mkdir consumer
    cd consumer
    
  2. worker.py という名前のファイルを作成し、次のコードを追加します。

    import os
    import time
    from google.cloud import pubsub_v1
    from concurrent.futures import TimeoutError
    
    # Configuration
    PROJECT_ID = os.environ.get('PROJECT_ID')
    SUBSCRIPTION_ID = os.environ.get('SUBSCRIPTION_ID')
    
    subscription_path = f"projects/{PROJECT_ID}/subscriptions/{SUBSCRIPTION_ID}"
    
    print(f"Worker Pool instance starting. Watching {subscription_path}...")
    
    subscriber = pubsub_v1.SubscriberClient()
    
    def callback(message):
        try:
            data = message.data.decode("utf-8")
            print(f"Processing job: {data}")
            time.sleep(5)  # Simulate work
            print(f"Done {data}")
            message.ack()
        except Exception as e:
            print(f"Error processing message: {e}")
            message.nack()
    
    streaming_pull_future = subscriber.subscribe(subscription_path, callback=callback)
    print(f"Listening for messages on {subscription_path}...")
    
    # Wrap subscriber in a 'with' block to automatically call close() when done.
    with subscriber:
        try:
            # When `timeout` is not set, result() will block indefinitely,
            # unless an exception is encountered first.
            streaming_pull_future.result()
        except TimeoutError:
            streaming_pull_future.cancel()  # Trigger the shutdown.
            streaming_pull_future.result()  # Block until the shutdown is complete.
        except Exception as e:
            print(f"Streaming pull failed: {e}")
    
  3. Dockerfile を作成し、次のコードを追加します。

    FROM python:3.12-slim
    RUN pip install google-cloud-pubsub
    COPY worker.py .
    CMD ["python", "-u", "worker.py"]
    
  4. CREMA がスケールアップするように、0 個のインスタンスでコンシューマ ワーカープールをデプロイします。

    gcloud beta run worker-pools deploy $CONSUMER_WORKER_POOL_NAME \
      --source . \
      --region $REGION \
      --service-account="$CONSUMER_SA_NAME@$PROJECT_ID.iam.gserviceaccount.com" \
      --instances=0 \
      --set-env-vars PROJECT_ID=$PROJECT_ID,SUBSCRIPTION_ID=$SUBSCRIPTION_ID
    

オートスケーラー CREMA サービスをデプロイする

Pub/Sub からメッセージを使用するようにワーカープールをデプロイしたら、メッセージの量に基づいてワーカー インスタンスをプロビジョニングするように CREMA オートスケーラーを構成します。

オートスケーラーを構成する

このチュートリアルでは、Parameter Manager を 使用して CREMA の YAML 構成ファイルを保存します。

  1. Parameter Manager にパラメータを作成して、CREMA のパラメータ バージョンを保存します。

    PARAMETER_ID=crema-config
    PARAMETER_REGION=global
    gcloud parametermanager parameters create $PARAMETER_ID --location=$PARAMETER_REGION --parameter-format=YAML
    
  2. 次のコマンドを実行して、プロジェクトのルート ディレクトリに移動します。

    cd
    
  3. ルート ディレクトリに YAML ファイル my-crema-config.yaml を作成して、オートスケーラーの構成を定義します。

    apiVersion: crema/v1
    kind: CremaConfig
    spec:
      pollingInterval: 30
      triggerAuthentications:
        - metadata:
            name: adc-trigger-auth
          spec:
            podIdentity:
              provider: gcp
      scaledObjects:
        - spec:
            scaleTargetRef:
              name: projects/PROJECT_ID/locations/us-central1/workerpools/worker-pool-consumer
            triggers:
              - type: gcp-pubsub
                metadata:
                  subscriptionName: "crema-subscription"
                  # Target number of undelivered messages per worker instance
                  value: "10"
                  mode: "SubscriptionSize"
                authenticationRef:
                  name: adc-trigger-auth
    

    PROJECT_ID は、 Google Cloud プロジェクト ID に置き換えます。

  4. ローカルの YAML ファイルを新しいパラメータ バージョンとしてアップロードします。

    LOCAL_YAML_CONFIG_FILE=my-crema-config.yaml
    PARAMETER_VERSION=1
    
    gcloud parametermanager parameters versions create $PARAMETER_VERSION \
      --location=$PARAMETER_REGION \
      --parameter=$PARAMETER_ID \
      --payload-data-from-file=$LOCAL_YAML_CONFIG_FILE
    
  5. 次のコマンドを実行して、パラメータの追加が成功したことを確認します。

    gcloud parametermanager parameters versions list \
    --parameter=$PARAMETER_ID \
    --location=$PARAMETER_REGION
    

    パラメータ パス(projects/PROJECT_ID/locations/global/parameters/crema-config/versions/1 など)が表示されます。

サービスをデプロイしてワークロードをスケーリングする

サービスをデプロイしてワーカープールをスケーリングするには、ビルド済みのコンテナ イメージを使用して次のコマンドを実行します。

CREMA_CONFIG_PARAM_VERSION=projects/$PROJECT_ID/locations/$PARAMETER_REGION/parameters/$PARAMETER_ID/versions/$PARAMETER_VERSION
IMAGE=us-central1-docker.pkg.dev/cloud-run-oss-images/crema-v1/autoscaler:1.0

gcloud beta run deploy $CREMA_SERVICE_NAME \
  --image=${IMAGE} \
  --region=${REGION} \
  --service-account="${CREMA_SA_NAME}" \
  --no-allow-unauthenticated \
  --no-cpu-throttling \
  --base-image=us-central1-docker.pkg.dev/serverless-runtimes/google-24/runtimes/java25 \
  --labels=created-by=crema \
  --set-env-vars="CREMA_CONFIG=${CREMA_CONFIG_PARAM_VERSION},OUTPUT_SCALER_METRICS=True"

自動スケーリング サービスをテストする

100 個のメッセージを生成して Pub/Sub キューにプッシュするスクリプトを作成して、CREMA サービスをテストします。

  1. ルート ディレクトリに load-pubsub.sh という名前のファイルを作成し、次のコードを追加します。

    #!/bin/bash
    
    TOPIC_ID=${TOPIC_ID}
    PROJECT_ID=${PROJECT_ID}
    NUM_MESSAGES=100
    
    echo "Publishing $NUM_MESSAGES messages to topic $TOPIC_ID..."
    
    for i in $(seq 1 $NUM_MESSAGES); do
      gcloud pubsub topics publish $TOPIC_ID --message="job-$i" --project=$PROJECT_ID &
      if (( $i % 10 == 0 )); then
        wait
        echo "Published $i messages..."
      fi
    done
    wait
    echo "Done. All messages published."
    
  2. 負荷テストを実行します。

    chmod +x load-pubsub.sh
    ./load-pubsub.sh
    

このコマンドは、100 個のメッセージを生成して Pub/Sub サブスクリプションにプッシュします。

スケーリングをモニタリングする

load-pubsub.sh スクリプトが完了したら、3 ~ 4 分 待ってから、 ログを確認します。サービスは my-crema-service です。CREMA オートスケーラー サービスは、コンシューマ ワーカー インスタンスを 0 からスケールアップします。

次のログが表示されます。

各ログメッセージには、それを生成したコンポーネントのラベルが付いています。

[INFO] [METRIC-PROVIDER] Starting metric collection cycle
[INFO] [METRIC-PROVIDER] Successfully fetched scaled object metrics ...
[INFO] [METRIC-PROVIDER] Sending scale request ...
[INFO] [SCALER] Received ScaleRequest ...
[INFO] [SCALER] Current instances ...
[INFO] [SCALER] Recommended instances ...

または、次のコマンドを実行して、CREMA サービスがキューの深さに基づいてインスタンスを推奨していることを確認します。

gcloud logging read "resource.type=cloud_run_revision AND resource.labels.service_name=$CREMA_SERVICE_NAME AND textPayload:SCALER" \
  --limit=20 \
  --format="value(textPayload)" \
  --freshness=5m

メッセージを使用するコンシューマ ログを表示するには、次のコマンドを実行します。

gcloud beta run worker-pools logs tail $CONSUMER_WORKER_POOL_NAME --region=$REGION

Done job-100 という形式のログが表示されます。

クリーンアップ

Google Cloud アカウントで追加料金が発生しないようにするには、このチュートリアルでデプロイしたすべてのリソースを削除します。

プロジェクトを削除する

このチュートリアル用に新規プロジェクトを作成した場合は、そのプロジェクトを削除します。既存のプロジェクトを使用し、このチュートリアルで行った変更を加えずに残す場合は、チュートリアル用に作成したリソースを削除します。

課金をなくす最も簡単な方法は、チュートリアル用に作成したプロジェクトを削除することです。

プロジェクトを削除するには:

  1. コンソールで [**リソースの管理**] ページに移動します。 Google Cloud

    [リソースの管理] に移動

  2. プロジェクト リストで、削除するプロジェクトを選択し、[削除] をクリックします。
  3. ダイアログでプロジェクト ID を入力し、 [Shut down] をクリックしてプロジェクトを削除します。

チュートリアル リソースの削除

  1. このチュートリアルでデプロイした Cloud Run サービスを削除します。Cloud Run サービスの費用は、リクエストを受け取るまでは発生しません。

    Cloud Run サービスを削除するには、次のコマンドを実行します。

    gcloud run services delete SERVICE-NAME

    SERVICE-NAME は、サービスの名前に置き換えます。

    Cloud Run サービスは Google Cloud コンソールで削除することもできます。

  2. チュートリアルの設定時に追加した gcloud のデフォルトのリージョン構成を削除します。

     gcloud config unset run/region
    
  3. プロジェクト構成を削除します。

     gcloud config unset project
    
  4. Pub/Sub リソースを削除します。

    gcloud pubsub subscriptions delete $SUBSCRIPTION_ID
    gcloud pubsub topics delete $TOPIC_ID
    
  5. このチュートリアルで作成した他の Google Cloud リソースを削除します。

次のステップ