CloudRunのボリュームマウント機能を試してみる with GCS&Terraform
こんにちは。
この記事では、terraformを使って、GCP の CloudRun をGCSマウントして構築する方法をまとめました。
CloudRun の GCS マウントとは何か
CloudRunとはGCPのフルマネージドコンピューティングサービスです。
必要な時だけインスタンスを立ち上げて、サービスを利用することが可能です。使ってない時はインスタンスを全て落とすことができるので、低コストでWebサービスやAPIを運用できます。
CloudRunでは利用時に、ゼロからコンテナイメージが立ち上がる形になっています。コンテナの仮想ディスクは使うことができますが、インスタンスが落ちるタイミングでディスク内のデータは消えてしまいます。
ただ、場合によっては静的なディスクを確保して永続的にデータを保存・更新したい場合もあるかと思います。
そんな時に活用できるのが、2024年1月のアップデートから使えるようになったCloudRunのボリュームマウント機能です。
追加のコードなどは必要なく、これを使用すると直接 GCS のバケットでマウントでき、インスタンスの普通のストレージと同じような感覚でファイル読み取り・保存ができるようになります。
料金について
料金についてはマウントしたストレージへの操作(ファイルアップロード/更新/ダウンロードなど)は通常のストレージ操作として課金されます。
更新・保存などのファイル操作回数が多い場合、費用が拡大する可能性があるので、確認が必要です。
ちなみに、ファイルのアップロードや更新、ダウンロードはクラス A オペレーションになるので、マウントするストレージがシングルリージョンのStandartストレージの場合、1000オペレーションあたり0.005$になります。
本題
全スクリプトはこちらに置いています。
https://github.com/M0T0-2020/GCP-memorandum/tree/master/cr-gcs-mount-0923
pythonバックエンド コンテナ作成
CloudRunで使用するコンテナイメージを作成します。
https://github.com/M0T0-2020/GCP-memorandum/tree/master/cr-gcs-mount-0923/src
2種類のAPIを作成しました。
ディレクトリ下の全ファイル・ディレクトリ名を返す
パスパラメータを文字列としてテキストファイルに書き込んで保存
スクリプトを見ると分かると思いますが、GCSにアクセスするためのクライアントライブラリなどを使用していません。
ファイル検索や保存は通常のローカルストレージを使用するような記述になっています。
# main.py
import os
from pathlib import Path
from fastapi import FastAPI
app = FastAPI()
# GCSバケットのファイルを一覧する関数
def list_files():
bucket_path = Path(os.environ.get("MOUNTPATH", "./"))
if os.path.exists(bucket_path):
files = os.listdir(bucket_path)
return files
return []
@app.get("/")
def index():
files = list_files()
return {"files_in_gcs": files}
@app.post("/upload/{string:str}")
def upload(string: str):
bucket_path = Path(os.environ.get("MOUNTPATH", "./"))
with open(bucket_path / f"{string}.txt", "w") as f:
f.write(string)
return f"{string}.txt"
requirements.txt とDockerfile も用意します
# requirements.txt
fastapi
uvicorn
# Dockerfile
FROM python:3.9-slim
# 作業ディレクトリ
WORKDIR /app
# アプリケーションのコピー
COPY . .
RUN pip install --no-cache-dir -r requirements.txt
EXPOSE 8080
# アプリケーションの起動
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8080"]
これを CloudBuildを使って、Artifact Registry にアップします。
gcloud builds submit . -t us-central1-docker.pkg.dev/$PROJECT_ID/$REPOSITORY/$IMAGE_NAME
terraform
terraform 部分は必要なところだけ抜粋して記述します。
詳しくはこちらを見ていたければと思います。
https://github.com/M0T0-2020/GCP-memorandum/tree/master/cr-gcs-mount-0923/terraform
GCSのバケットを新しく作成して、そのバケットを CloudRun でマウントします。
CloudRunのサービスアカウントにマウントするストレージへの書き込みなどができる権限をつけています。(`roles/storage.objectUser`)
# GCSバケットの作成
resource "google_storage_bucket" "default" {
name = var.storage_name
location = var.region
force_destroy = true
}
# サービスアカウントにGCSアクセス権限を付与
resource "google_project_iam_member" "storage" {
project = var.project
role = "roles/storage.objectUser"
member = "serviceAccount:${google_service_account.cloud_run_sa.email}"
}
# Cloud Run サービスの作成
resource "google_cloud_run_v2_service" "service" {
depends_on = [google_storage_bucket.default]
name = "gcs-fuse-sample-0923"
location = var.region
deletion_protection = false
template {
service_account = google_service_account.cloud_run_sa.email
timeout = "3.5s"
containers {
image = var.image_path
env {
name = "MOUNTPATH"
value = var.mount_path
}
volume_mounts {
name = "bucket"
mount_path = var.mount_path
}
ports {
container_port = 8080
}
}
volumes {
name = "bucket"
gcs {
bucket = google_storage_bucket.default.name
read_only = false
}
}
scaling {
min_instance_count = 0
max_instance_count = 1
}
}
ingress = "INGRESS_TRAFFIC_ALL"
}
resource "google_cloud_run_v2_service_iam_member" "member" {
project = google_cloud_run_v2_service.service.project
location = google_cloud_run_v2_service.service.location
name = google_cloud_run_v2_service.service.name
role = "roles/run.invoker"
member = "user:${var.user_email}"
}
結果
terraformで作成したCloudRunを試用してみます。
まずはuploadの方から試してみます。
しっかりと保存したファイル名が返ってきているので、正しく動いてそうです。
curl -X POST -H "Authorization: Bearer $(gcloud auth print-identity-token)" <CloudRunのURL>/upload/test0923byMoto
# 結果: "test0923byMoto.txt"%
コンソールの方でバケットを確認しても、正しくファイルが保存されてそうです。(何回かテストしたので、別のファイルも保存されています。)
ファイル一覧表示も試してみます。
しっかりと全ファイル名が返ってきているようです。
curl -X GET -H "Authorization: Bearer $(gcloud auth print-identity-token)" <CloudRunのURL>/
# 結果: {"files_in_gcs":["test0923byMoto.txt","test1234.txt","test4649.txt","test555.txt"]}%
まとめ
簡単に CloudRun に静的なストレージをマウントすることができました。手段として把握していると活用の機会もあるかと思います。
最後まで読んでいただきありがとうございました。
この記事が気に入ったらサポートをしてみませんか?