Cloud Run worker pools を触ってみた

Cloud Run worker pools を触ってみた

Clock Icon2025.07.14

データ事業本部のはんざわです。

先日、ついに Cloud Run worker pools がプレビュー公開されました!

worker pools は、Google Cloud Next '25 で発表された Cloud Run の新たなモデルで、従来の services、jobs、functions に続く第4のモデルとなります。

https://dev.classmethod.jp/articles/whats-new-in-cloud-run-googlecloudnext/

本ブログでは、この新しいモデルを実際に試してみたいと思います。

Cloud Run worker pools とは?

https://cloud.google.com/run/docs/deploy-worker-pools

Cloud Run worker pools は、Cloud Run services、jobs、functions に続く第4の実行モデルで、長時間稼働する「常駐型のバックグラウンド処理」に特化したモデルです。

worker pools は、他の Cloud Run モデルにはあった以下のような機能がありません。

  • エンドポイント / URL
  • リクエストを受け取るポート
  • 自動スケーリング

そのため、外部から直接呼び出すことはできず、各コンテナインスタンスが外部にアクセスしにいく(例、キューイングされたメッセージを取りに行く)ようなユースケースに適しています。

また、自動スケーリング機能がないため、インスタンス数は手動で設定する必要があります。基本的に起動数は固定され、常に稼働した状態になります。

https://cloud.google.com/run/docs/configuring/workerpools/manual-scaling

デプロイしてみる

https://cloud.google.com/run/docs/deploy-worker-pools

上記のドキュメントを参考に、実際に Cloud Run worker pools をデプロイしてみます。

必要なリソースを作成

まずは、Pub/Sub トピックとサブスクリプション、Cloud Storage バケットを作成します。

Pub/Subトピックを作成
gcloud pubsub topics create worker-pools
Pub/Subサブスクリプションを作成
gcloud pubsub subscriptions create worker-pools-sub --topic=worker-pools
Cloud Storageバケットを作成
gcloud storage buckets create gs://cm-hanzawa-yuya-worker-pools \
    --location='asia-northeast1' \
    --uniform-bucket-level-access

実行するスクリプトの作成

次に、コンテナ内で実行する Python スクリプトを作成します。
このスクリプトは、以下のような流れで処理を行います。

  1. Pub/Sub のサブスクリプションからメッセージを Pull し続ける
  2. Pull したメッセージを Cloud Storage バケットにテキスト形式でアップロード
main.py
import os
import sys
from datetime import datetime
from google.cloud import pubsub_v1
from google.cloud import storage

def upload_to_storage(bucket_name, message_text):
    """メッセージをCloud Storageにアップロードする関数"""
    storage_client = storage.Client()
    bucket = storage_client.bucket(bucket_name)

    # ファイル名を生成
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S_%f")
    filename = f"message_{timestamp}.txt"

    # Cloud Storageにメッセージを保存
    blob = bucket.blob(filename)
    blob.upload_from_string(message_text, content_type="text/plain; charset=utf-8")
    print(f"Message saved to gs://{bucket_name}/{filename}")

def pull_messages(project_id, subscription_id, bucket_name):
    """メッセージを StreamingPull する関数"""
    subscriber = pubsub_v1.SubscriberClient()
    subscription_path = subscriber.subscription_path(project_id, subscription_id)

    def callback(message):
        """メッセージを受信したときのコールバック関数"""
        try:
            message_text = message.data.decode("utf-8")
            print(f"Received message: {message_text}")

            # Cloud Storageにメッセージをアップロード
            upload_to_storage(bucket_name, message_text)

            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 subscriptions/{subscription_id}...")

    try:
        # メッセージをPullし続ける
        streaming_pull_future.result()
    except Exception as e:
        streaming_pull_future.cancel()
        print(f"Stopped listening for messages due to error: {e}")
        raise

def main():
    # 環境変数を取得
    project_id = os.getenv("PROJECT_ID")
    subscription_id = os.getenv("SUBSCRIPTION_ID")
    bucket_name = os.getenv("BUCKET_NAME")

    if None in [project_id, subscription_id, bucket_name]:
        print("Error: PROJECT_ID, SUBSCRIPTION_ID, and BUCKET_NAME environment variables are required")
        sys.exit(1)

    try:
        pull_messages(project_id, subscription_id, bucket_name)
    except Exception as e:
        print(f"Error: {e}")
        sys.exit(1)

if __name__ == "__main__":
    main()
.local.env
PROJECT_ID=<PROJECT_ID>
SUBSCRIPTION_ID="worker-pools-sub"
BUCKET_NAME="cm-hanzawa-yuya-worker-pools"

コンテナイメージの作成

今回は、Buildpacks を使ってコンテナイメージを作成します。
Buildpacks の詳細は以下のブログを参考にしてください。

https://dev.classmethod.jp/articles/google-cloud-buildpacks/

まずは Artifact Registry のリポジトリを作成します。

リポジトリの作成
gcloud artifacts repositories create python-images \
    --repository-format docker \
    --location asia-northeast1

Buildpacks の設定ファイルは以下のように記述します。

project.toml
[[build.env]]
    name = "GOOGLE_ENTRYPOINT"
    value = "python main.py"

コンテナイメージをビルドして Artifact Registry に push します。

Buildpacksでコンテナイメージをビルド
gcloud builds submit --pack image=asia-northeast1-docker.pkg.dev/<PROJECT_ID>/python-images/worker-pools

worker pools を作成

プレビュー期間中は、CLI でのみデプロイ可能です。
デプロイコマンドの各オプションは、以下のドキュメントを参考にしてください。

https://cloud.google.com/sdk/gcloud/reference/beta/run/worker-pools/deploy

worker poolsをデプロイ
gcloud beta run worker-pools deploy worker-pools-test \
    --region=asia-northeast1 \
    --image=asia-northeast1-docker.pkg.dev/<PROJECT_ID>/python-images/worker-pools:latest \
    --env-vars-file=.local.env

Cloud Console を開き、Worker Pools が正常にデプロイされているか確認してみます。

スクリーンショット 2025-07-10 18.07.47

正常にデプロイされていました!

動かしてみる

worker pools のデプロイが正常に完了したので、実際に動かしてみます。

作成した Pub/Sub トピック worker-pools にメッセージをパブリッシュします。

スクリーンショット 2025-07-10 18.13.03

上記のキャプチャの通り、コンソールから 10 個のメッセージを 2 秒間隔で送信してみます。

続いて、worker pools のログを確認してみます。

スクリーンショット 2025-07-10 18.17.06

メッセージを取得し、Cloud Storage にファイルをアップロードしていることが確認できました。
実際に Cloud Storage に保存されたファイルの中身を確認してみます。

$ gcloud storage cat gs://cm-hanzawa-yuya-worker-pools/message_20250710_091357_497317.txt
> こんにちわ

料金

https://cloud.google.com/run/pricing?hl=en

東京リージョンにおける Cloud Run worker pools の料金は以下の表の通りです。

料金単価 無料枠
CPU $0.000011244 / vCPU 秒 240,000 vCPU 秒
メモリ $0.000001235 / GiB 秒 450,000 GiB 秒

以下は、Cloud Run services(リクエストベース)および Cloud Run jobs との比較です。
括弧内は「worker pools の単価 ÷ 各モデルの単価」で、相対的なコスト感を示しています。

CPU(相対比) メモリ(相対比)
Cloud Run services
(リクエストベース)
0.4685(= 0.000011244 / 0.00002400) 0.494(= 0.000001235 / 0.00000250)
Cloud Run jobs 0.6247(= 0.000011244 / 0.00001800) 0.6175(= 0.000001235 / 0.00000200)

このように、Cloud Run worker pools は他の Cloud Run モデルと比較しても、CPU・メモリの単価がかなり低く、コストを抑えたい常駐型のバックグラウンド処理の用途に適していることが分かります。

まとめ

Cloud Run worker pools は、常駐型のバックグラウンド処理に特化した新しい実行モデルです。
外部からのリクエストを受けず、自ら外部リソースにアクセスするようなユースケースに適しています。
そういったケースに直面した際には、選択肢のひとつとしてぜひ検討してみてください。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.