GA になった Cloud Run で GCS バケットをストレージボリュームとしてマウントする機能を試した
はじめに
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 バケットをストレージボリュームとしてマウントするには、主に以下の手順で検証を行いました。
- マウントする GCS バケットを作成します。
- サービスアカウントを作成し、GCS バケットにアクセス権を付与します。
- Cloud Run サービスをデプロイします。
- Cloud Run サービスにリクエストを送信して、GCS バケットにアクセスします。
- Cloud Run サービスのログを確認して、正常に GCS バケットにアクセスできていることを確認します。
- Cloud Run サービスを削除します。
- サービスアカウントを削除します。
- Cloud Run サービスにマウントされた GCS バケットを削除します。
今回試した処理
BigQuery テーブルからマウントしている ファイルシステムにデータをダウンロードする処理を試しました。
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 バケットを作成
gcloud storage buckets create gs://test-gcs-vol-mount --location=us-central1 --default-storage-class=STANDARD --uniform-bucket-level-access
サービスアカウントを作成し、GCS バケットにアクセス権を付与
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 サービスをデプロイ
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 増やせばメモリも増えるのかも。
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 記事を参考にしました。
Discussion