📝

Cloud run functionデプロイにおけるgcloudとterraformの棲み分け

に公開

背景

Google Cloudのcloud function gen2で下記の構成でイベント駆動アーキテクチャを構築する際にterraformとgcloudによるCDパイプラインの責務で迷ったので備忘録として記録する。
CDパイプラインはGithub Actionsを利用したCloud run functionのソースコードを管理するリポジトリ単位のパイプラインとなっている。

Object put on Cloud strage -> Eventarc (contain PubSub) -> Cloud run function

最終的な管理構成

Terraformで管理する範囲

  • Service Account周り
    • Cloud run Function周り
    • Eventarc周り
  • Google Cloud Strageのリソース

gcloudコマンドでの管理(リポジトリのCDパイプラインでの管理)

  • Cloud run function
    • Cloud Run
    • Docker build
    • invokeされるEventarcとの連携
  • Eventarc
    • イベントの受信元のGoogle Cloud Strageとの連携

最終的なgcloudコマンド

gcloud functions deploy <FUNCTION_NAME> \
    --region=<REGION> \
    --runtime=go125 \
    --source=. \ // ソースコードのroot
    --service-account=<FUNCTION_SERVICE_ACCOUNT> \
    --set-env-vars=<FUNCTION_ENVIRONMENT_VAR> \
    --set-build-env-vars=GOOGLE_BUILDABLE=. \
    --entry-point=<FUNCTION_ENTORY_POINT> \
    --trigger-event-filters=type=google.cloud.storage.object.v1.finalized \
    --trigger-event-filters=bucket=<TRIGGER_BUCKET> \
    --trigger-location=<REGION> \
    --trigger-service-account=<TRIGGER_SERVICE_ACCOUNT> \
    --gen2 \
    --project=<GCP_PROJECT_ID> \

上記のコマンドをCDパイプラインとして組み込み、stagingやproductionといった環境ごとに分かれているプロジェクトごとにリリースできるようにした。

経緯

当初はCloud run functionのみをCDパイプラインでデプロイし、その他のリソースは事前に
terraformで作成/管理しようと思っていた。
AWSだとAWS Lambdaが似たような構成を取れる。例えばterraformでLambdaの箱だけを構築し、初期リリースを行い、その後lambrollなどのライブラリを用いて対象のLambdaに上書きデプロイをする。
こうすることで基本的なLambdaの設定や、SQSやStepFunctionなどのトリガーとの連携を全てterraformで管理でき、一元管理できる。
しかし、Google CloudのCloud run functionにはLambdaのように箱だけ作るという概念は存在せず、Cloud Run上で稼働するため、当然Cloud Runのデプロイと大きく依存する。terraformでCloud Runやfunctionを先に構築してしまうと、gcloudで既存のリソースをターゲットとできない。

それならと、Cloud run functionを先にgcloudでリリースし、後からterraformでimportしてEventarcとの連携を構築しようと思った。しかし、gcloudでさまざまな設定を簡単に更新できてしまうため、CDパイプラインの修正や改修とterraformのコードが密に依存してしまい、二重管理になる手間が出てきてしまう。

上記の経緯で、色々調べるとgcloudコマンドはかなり良しなに関連リソースを構築してくれるので、gcloudとterraformの責任境界が交わらないラインを考えた結果、最終管理構成のような形に落ち着いた。

Discussion