🔖

Cloud Run FunctionsにTerraformを使ってデプロイしてみた

に公開

今回はTerraformを利用してCloud Run Functionsにサービスをデプロイしてみました。

構築するアーキテクチャ

今回構築するアーキテクチャは以下のようになっています。Cloud Storageでは提供するアプリケーションのソースコードをZIPファイルで格納し、Cloud Run FunctionsではCloud Storageからソースコードを参照した上でサービスを展開します。

早速構築

Pythonアプリケーションの実装

今回は呼び出すとHello World!と返すエンドポイントの提供を目指します。そのような仕組みを実現するために必要なファイルは以下になります。

  • requirements.txt: 必要なライブラリの列挙
  • main.py: HTTPエンドポイント定義

まずはrequirements.txtを作成します。一番大事なのはfunctions-frmeworkの部分であり、main.pyではこちらを利用してエンドポイントを定義します。

functions-framework==3.9.2
flask==3.0.3
google-cloud-error-reporting==1.11.1
MarkupSafe==2.1.3

次にアプリケーションを実装します。main.pyを以下のように実装します。@functions_framework.httpデコレータを利用することでHTTPメソッドとして定義します。関数の引数にはflask.Request型のリクエストパラメータが入ります(今回は利用しません)。戻り値としてはHello World!という文字列だけ返します。

main.py
import functions_framework

@functions_framework.http
def hello_get(request):
    return "Hello World!"

これら二つのファイルが用意できたらZIPファイルにします。以下のようにしてZIPファイルを作成します。

zip -r function-source.zip main.py requirements.txt

なお、この時二つのファイルを含んだフォルダ自体をZIPにしたものを利用するとエラーになるため、必ずファイル二つをそれぞれ指定してください。

インフラの構築

それではTerraformを使ってインフラを定義していきます。まずファイル構成は以下になります。function-source.zipは先ほど作成したファイルを配置します。

main.tf
variables.tf
function-source.zip
modules/
  cloud_storage/
    main.tf
    variables.tf
    outputs.tf 
  cloud_run_functions/
    main.tf
    variables.tf

それぞれのファイルは以下のように定義しています。

modules/cloud_storage/variables.tf
modules/cloud_storage/variables.tf
variable "bucket_name" {
  description = "Cloud Storage's bucket name"
  type        = string
}

variable "location" {
  description = "Location"
  type        = string
  default     = "ASIA-NORTHEAST1"
}
modules/cloud_storage/main.tf
modules/cloud_storage/main.tf
resource "google_storage_bucket" "function_source" {
  name          = var.bucket_name
  location      = var.location
  force_destroy = true

  uniform_bucket_level_access = true
}

resource "google_storage_bucket_object" "object" {
  name   = "function-source.zip"
  bucket = google_storage_bucket.function_source.name
  source = "function-source.zip" # Add path to the zipped function source code
}
modules/cloud_storage/outputs.tf
modules/cloud_storage/outputs.tf
output "bucket_name" {
  description = "Bucket name"
  value       = google_storage_bucket.function_source.name
}
modules/cloud_run_functions/variables.tf
modules/cloud_run_functions/variables.tf
variable "bucket_name" {
  description = "Bucket name"
  type        = string
}

variable "location" {
  description = "location"
  type = string
}
modules/cloud_run_functions/main.tf
modules/cloud_run_functions/main.tf
resource "google_cloudfunctions2_function" "function" {
  name        = "function-v2"
  location    = var.location
  description = "a new function"

  build_config {
    runtime     = "python312"
    entry_point = "hello_get" # Set the entry point 
    source {
      storage_source {
        bucket = var.bucket_name
        object = "function-source.zip"
      }
    }
  }

  service_config {
    max_instance_count = 1
    available_memory   = "256M"
    timeout_seconds    = 60
  }
}
variables.tf
variables.tf
variable "project_id" {
  description = "The Google Cloud project ID"
  type        = string
}

variable "region" {
  description = "The Google Cloud region"
  type        = string
  default     = "asia-northeast1"
}

variable "bucket_name" {
  description = "Cloud Storage's bucket name"
  type        = string
  default     = "akasan-tech-blog-cloud-run-functions-source"
}
main.tf
main.tf
provider "google" {
  project = var.project_id
  region  = var.region
}

module "cloud_storage" {
  source = "./modules/cloud_storage/"

  bucket_name = var.bucket_name
}

module "cloud_run_functions" {
  source = "./modules/cloud_run_functions/"

  location    = var.region
  bucket_name = module.cloud_storage.bucket_name
}

特筆すべきような実装はしていませんが、Cloud StorageとCloud Run Functionsの実装をモジュールで分割しています。

実装ができましたので、terraform applyにてインフラを構築します。完了するとCloud Run Functionsに以下のように関数が構築されます。

エンドポイントの呼び出し

それでは早速構築したエンドポイントを呼び出してみます。URLをご自身のものと入れ替えてもらうと結果としてHello World!と帰ってくることを確認してもらえます。

curl -X POST "https://..." \
-H "Authorization: bearer $(gcloud auth print-identity-token)" \
-H "Content-Type: application/json" \

# 結果
Hello World!%

まとめ

今回はCloud Run FunctionsをTerraformからデプロイする方法を調べてみました。普段Cloud Runを使うことはよくあるのですが、Cloud Run Functionsもイベント処理の機能として用いる予定も多く改めて勉強してみました。関数の実装についてはパラメータにも依存しないシンプルなものしか試していないので、今後はより複雑なワークロードに対応させてみたいと思います。

Discussion