🎉

GA になった Cloud Run で GCS バケットをストレージボリュームとしてマウントする機能を試した

2024/09/08に公開

はじめに

Google Cloud Run の GCS バケットボリュームマウント機能が GA になりました。これにより、Cloud Run で GCS バケットをストレージボリュームとしてマウントし、ファイルシステムとして直接操作することが可能になりました。

この記事では、Cloud Run で GCS バケットをストレージボリュームとしてマウントする機能を試してみた結果とつまづいたポイントを共有します。

元記事: Configure Cloud Storage volume mounts for services

TL;DR

Cloud Run から GCS バケットに直接アクセスする機能は便利だし簡単に実装できる。
一方で、メモリ制限が 1CPU あたり 4Gi に制限されているので、大容量のファイルを扱うバッチ処理などには向かない可能性がある。

Cloud Run で GCS バケットをストレージボリュームとしてマウントする

Cloud Run で GCS バケットをストレージボリュームとしてマウントするには、主に以下の手順で検証を行いました。

  1. マウントする GCS バケットを作成します。
  2. サービスアカウントを作成し、GCS バケットにアクセス権を付与します。
  3. Cloud Run サービスをデプロイします。
  4. Cloud Run サービスにリクエストを送信して、GCS バケットにアクセスします。
  5. Cloud Run サービスのログを確認して、正常に GCS バケットにアクセスできていることを確認します。
  6. Cloud Run サービスを削除します。
  7. サービスアカウントを削除します。
  8. Cloud Run サービスにマウントされた GCS バケットを削除します。

今回試した処理

BigQuery テーブルからマウントしている ファイルシステムにデータをダウンロードする処理を試しました。

main.py
import os

import pandas as pd
from flask import Flask
from google.cloud import bigquery

app = Flask(__name__)

# Cloud Storageのボリュームマウントポイント
MOUNT_PATH = os.environ.get("MOUNT_PATH", "/mnt/gcs")
PROJECT_ID = os.environ.get("PROJECT_ID", "any-development")
TABLE_NAME = os.environ.get("TABLE_NAME", "users")
SOURCE_DATASET = os.environ.get("SOURCE_DATASET", "TEST_DATA")
FILE_NAME = "users.gzip"
DESTINATION_URI = f"{MOUNT_PATH}/{FILE_NAME}"

@app.route('/')
def main():
    # BigQueryクライアントの初期化
    client = bigquery.Client()

    # MOUNT_PATH ディレクトリ内のファイルを再起的に削除
    os.system(f"rm -rf {MOUNT_PATH}/*")
    print(f"Deleted all files in {MOUNT_PATH}")

    query = f"SELECT * FROM {SOURCE_DATASET}.{TABLE_NAME}"
    query_job = client.query(query)
    print(f"Executing query: {query}")
    print(f"Result: {query_job.result()}")
    df = query_job.to_dataframe()

    # BigQueryからテーブルデータをロード
    df.to_csv(DESTINATION_URI, compression="gzip", index=False)

    return f"Exported {SOURCE_DATASET}.{TABLE_NAME} to {DESTINATION_URI}"

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=int(os.environ.get("PORT", 8080)))

その他ソースは Github にアップしています。ご参考にどうぞ。
Github

マウントする GCS バケットを作成

create-gcs-bucket.sh
gcloud storage buckets create gs://test-gcs-vol-mount --location=us-central1 --default-storage-class=STANDARD --uniform-bucket-level-access

サービスアカウントを作成し、GCS バケットにアクセス権を付与

create-service-account.sh
gcloud iam service-accounts create test-run-gcs-mount
gcloud projects add-iam-policy-binding any-development \
     --member "serviceAccount:test-run-gcs-mount@any-development.iam.gserviceaccount.com" \
     --role "roles/storage.objectAdmin"
gcloud projects add-iam-policy-binding any-development \
    --member "serviceAccount:test-run-gcs-mount@any-development.iam.gserviceaccount.com" \
    --role "roles/bigquery.admin"

Cloud Run サービスをデプロイ

deploy.sh
gcloud run deploy gcs-volume-mount-dev \
  --source=./src \
  --region=us-central1 \
  --allow-unauthenticated \
  --service-account test-run-gcs-mount \
  --add-volume=name=gcs-volume,type=cloud-storage,bucket=test-gcs-vol-mount \
  --add-volume-mount=volume=gcs-volume,mount-path=/mnt/gcs \
  --update-env-vars=MOUNT_PATH=/mnt/gcs,PROJECT_ID=any-development,TABLE_NAME=users,SOURCE_DATASET=TEST_DATA \
  --memory=3Gi

肝になっているオプションは、--add-volume--add-volume-mount です。これらのオプションを使って、GCS バケットを Cloud Run サービスにマウントします。

また、--memory オプションでメモリを 3Gi に設定しています。Cloud Run で GCS バケットをマウントする場合、メモリ制限が 1CPU あたり 4Gi に制限されているため、メモリを 4Gi 以上に設定することはできませんでした。
CPU 増やせばメモリも増えるのかも。

memory-error.log
ERROR: (gcloud.run.deploy) spec.template.spec.containers[0].resources.limits.memory: Invalid value specified for container memory. For 1.0 CPU, memory must be between 128Mi and 4Gi inclusive.
For more troubleshooting guidance, see https://cloud.google.com/run/docs/configuring/memory-limits

Cloud Run サービスにリクエストを送信し、結果を確認

curl コマンドを使って、Cloud Run サービスにリクエストを送信します。

バケットを確認したら、ファイルがダウンロードされていることを確認できました。

資材を削除

忘れずに、デプロイしたサービスやサービスアカウント、GCS バケットを削除してください。

まとめ

割と簡単に GCS バケットを Cloud Run にマウントすることができました。BigQuery -> GCS へのデータのダウンロードなど、ファイルシステムとして直接操作することが可能でした。
途中でパブリックデータセットのデータをダウンロードする処理を試しましたが、1.6GB のデータをダウンロードするのに メモリエラーが発生しました。
これは、Pandas の to_csv メソッドがメモリを大量に消費するためのようです、メモリを確認したら、3.7GB 使っていました。
しかし、マウント機能は、メモリ制限が 1CPU あたり 4Gi に制限されているため、大容量のファイルを扱うバッチ処理などには向かない可能性があるため、注意が必要です。
ユースケースについては、社内の有識者に相談してみたいと思います。

参考

公式の Zenn 記事を参考にしました。

Cloud Run と Cloud Storage FUSE (GCS FUSE) の基本

公式リファレンス

GitHubで編集を提案
ギックス

Discussion