【Cloud Run】ジョブにCloud Storageバケットをマウントする方法

【Cloud Run】ジョブにCloud Storageバケットをマウントする方法 GCP

Cloud Run ジョブのコンテナに Cloud Storage のバケットをマウントし、バケットの中身をファイルとして読み書きできるようにする手順です。数 GB ある動画やダンプのような大きな入力を、コンテナの中へコピーせずにバケットから直接読ませたいときに使えます。マウントには Cloud Storage FUSE が使われ、設定は gcloud run jobs update の --add-volume で足します。前提は、作成済みの Cloud Run ジョブとバケットがあり、gcloud CLI(この記事では Google Cloud SDK 590.0.1 で確認)が使えることです。2026年11月時点の公式ドキュメントに基づきます。

必要な権限を付ける

バケットを読むのは、ジョブに設定したサービスアカウント(サービス ID)です。このサービスアカウントに、バケットに対する次のどちらかのロールを付けます。

用途 ロール
読むだけ Storage オブジェクト閲覧者(roles/storage.objectViewer)
書き込みもする Storage オブジェクト ユーザー(roles/storage.objectUser)

バケット単位で付ける場合は次のとおりです。

gcloud storage buckets add-iam-policy-binding gs://BUCKET_NAME \
  --member="serviceAccount:SERVICE_ACCOUNT_EMAIL" \
  --role="roles/storage.objectViewer"

ジョブの設定を変える側(コマンドを打つ人や CI のサービスアカウント)には、ジョブに対する Cloud Run デベロッパー(roles/run.developer)と、ジョブのサービスアカウントに対するサービス アカウント ユーザー(roles/iam.serviceAccountUser)が必要です。

バケットをマウントする

コンテナが1つのジョブなら、--add-volume に mount-path を含めるだけでマウントまで済みます。

gcloud run jobs update JOB \
  --region=REGION \
  --add-volume mount-path=MOUNT_PATH,type=cloud-storage,bucket=BUCKET_NAME,readonly=true
  • JOB: ジョブの名前
  • MOUNT_PATH: コンテナの中でバケットを見せるパス(例: /mnt/input)
  • BUCKET_NAME: バケットの名前(gs:// は付けない)
  • readonly: true なら読み取り専用、false なら書き込みもできる

書き込む必要が無いなら readonly=true にしておくと、処理の誤りで入力を壊すことを防げます。gcloud run jobs deploy でも同じパラメータを使えます。

設定を変えただけでは実行は始まりません。次の実行から、コンテナの MOUNT_PATH の下にバケットのオブジェクトがファイルとして見えます。

gcloud run jobs execute JOB --region=REGION

コンテナが複数あるジョブの場合

サイドカーなどコンテナが複数あるジョブでは、ボリュームに名前を付けて定義し、コンテナごとに --add-volume-mount でマウント先を指定します。--add-volume の mount-path は、コンテナが1つの構成でしか使えません。

gcloud run jobs update JOB \
  --region=REGION \
  --add-volume name=VOLUME_NAME,type=cloud-storage,bucket=BUCKET_NAME \
  --container CONTAINER_1 \
  --add-volume-mount volume=VOLUME_NAME,mount-path=MOUNT_PATH \
  --container CONTAINER_2 \
  --add-volume-mount volume=VOLUME_NAME,mount-path=MOUNT_PATH2

バケットの一部だけをマウントする

既定ではバケット全体がマウントされます。特定のディレクトリだけを見せたいときは、Cloud Storage FUSE のマウント オプション only-dir を mount-options で渡します。

gcloud run jobs update JOB \
  --region=REGION \
  --add-volume mount-path=/mnt/input,type=cloud-storage,bucket=BUCKET_NAME,readonly=true,mount-options="only-dir=images"

gcloud でオプションを複数渡すときは、先頭のハイフンを付けずに、セミコロン(;)で区切ります。

mount-options="only-dir=images;metadata-cache-ttl-secs=120"

YAML で設定する

設定をファイルで管理しているなら、ジョブの YAML に volumes と volumeMounts を足します。今の設定は次のコマンドで書き出せます。

gcloud run jobs describe JOB --region=REGION --format export > job.yaml

足す部分は次のとおりです。

apiVersion: run.googleapis.com/v1
kind: Job
metadata:
  name: JOB_NAME
spec:
  template:
    metadata:
      annotations:
        run.googleapis.com/execution-environment: gen2
    spec:
      template:
        spec:
          containers:
          - image: IMAGE_URL
            volumeMounts:
            - mountPath: MOUNT_PATH
              name: VOLUME_NAME
          volumes:
          - name: VOLUME_NAME
            csi:
              driver: gcsfuse.run.googleapis.com
              readOnly: IS_READ_ONLY
              volumeAttributes:
                bucketName: BUCKET_NAME

IS_READ_ONLY は True か False です。マウント オプションは volumeAttributes の mountOptions に、カンマ区切りで書きます(gcloud のセミコロンと区切りが違います)。編集したら反映します。

gcloud run jobs replace job.yaml --region=REGION

動作を確認する

ジョブの設定を書き出して、ボリュームが入っていることを確かめます。

gcloud run jobs describe JOB --region=REGION --format export

出力の volumes に driver: gcsfuse.run.googleapis.com と bucketName があり、containers の volumeMounts に指定した mountPath があれば設定は入っています。

実際に読めるかは、ジョブを実行して確かめます。--wait を付けると、実行が終わるまでコマンドが待ちます(付けないと、実行が始まった時点でコマンドは終わります)。

gcloud run jobs execute JOB --region=REGION --wait

コンテナの処理の最初でマウント先のファイル一覧(ls MOUNT_PATH に当たる処理)をログに出しておくと、どのオブジェクトが見えているかを Cloud Logging で確かめられます。

マウントを外す

コンテナが1つのジョブで、ボリュームとマウントをすべて外すときは次のとおりです。

gcloud run jobs update JOB \
  --region=REGION \
  --clear-volumes \
  --clear-volume-mounts

--clear-volumes は、シークレットとしてマウントしたボリュームも含めて全部を外します。1つだけ外したいときは --remove-volume にボリューム名、--remove-volume-mount にマウント先のパスを渡します。ボリュームを外すときは、そのボリュームを使っているマウントもすべて外す必要があります。

使う前に知っておく制限

Cloud Storage FUSE はバケットをファイルシステムのように見せる仕組みで、ローカル ディスクと同じには動きません。

  • 同じファイルへの同時書き込みを制御する仕組み(ファイル ロック)が無い。複数の書き込みが同じファイルを置き換えようとすると、最後の書き込みだけが残る
  • POSIX に完全には準拠していない
  • stat キャッシュと type キャッシュはメモリ上に置かれ、読み書きにもコンテナのメモリを使う。大きなファイルを書き込むジョブは、メモリの上限に余裕を持たせる

並列タスクが同じバケットに書くジョブでは、タスクごとに出力先のファイル名を分けておくと、上書きで結果を失うことを避けられます。

うまくいかないとき

ジョブの実行が始まらない

コンテナは、Cloud Storage FUSE のマウントに成功したときだけ起動します。マウントに失敗すると、ジョブの実行は開始に失敗します。次を順に確かめます。

  • ジョブのサービスアカウントに、バケットへの roles/storage.objectViewer(書き込むなら roles/storage.objectUser)が付いているか
  • bucket に指定した名前のバケットが存在するか
  • マウントに時間がかかりすぎていないか。Cloud Run がすべてのマウントに使える時間は合計30秒で、これを超えると開始に失敗する

ジョブに設定されているサービスアカウントは、gcloud run jobs describe JOB --region=REGION --format export の出力にある serviceAccountName で確かめられます。

マウント先に指定できないパスがある

/dev・/proc・/sys と、その下のディレクトリにはマウントできません。/mnt/ の下など、別のパスを使います。

あるはずのファイルが見えない

mount-options に implicit-dirs=false を指定していると、mydir/myfile.txt のようにディレクトリのオブジェクトを作らずに置いたファイルを、一覧にも読み込みにも出せなくなります。暗黙のディレクトリは既定で有効なので、このオプションを外します。only-dir を指定している場合は、そのディレクトリの外にあるオブジェクトは見えません。

書き込めない

readonly=true でマウントしているか、サービスアカウントのロールが roles/storage.objectViewer のままになっていないかを確かめます。書き込むには readonly=false と roles/storage.objectUser の両方が要ります。

参考

この記事を書いた人

渋谷で働くよわよわエンジニア。TypeScript(Next.js/Node.js)/Golang/AWS/Flutterなど
LINE API Expert(2023/1~)

tokkuをフォローする
オススメ記事
在宅ワークが多くなって、デスクの配線周りに困っている方は、拡張デスクの導入がおすすめです。Windows/MacOS/Linuxの複数の機器をスッキリとデスク周りに収める事ができました!リモートからサーバーメンテを行うインフラエンジニアは必見です!
GCP
シェアする
tokkuをフォローする

コメント

タイトルとURLをコピーしました