🚰

個人開発でTerraformを使ったCloudflare R2とCloud Run(コスト最小限のコンテナ設定)の効率的なデプロイ

2023/10/28に公開

はじめに

テスト環境や本番環境のインフラのコストやサーバー代は、個人開発者にとって重要な課題となっています。本記事では、「run-2」というプロジェクトを紹介し、Cloudflare R2とGoogle Cloud Run(コスト最小限のコンテナ)をスムーズかつ効率的にデプロイする方法を解説します。Terraformを活用してインフラストラクチャをコードとして管理し、DevOpsのプラクティスを強化しましょう。


run-2

https://github.com/eternaleight/run-2

run-2とは?

run-2」は、Terraformを用いてCloudflare R2バケットとGoogle Cloud Runサービスを自動的にデプロイするためのプロジェクトです。
下記の最小限のコスト設定(Cloud Run)でデプロイかつスムーズなデプロイメントプロセスを実現します。

Cloud Runの設定
コンテナPORT:8001

メモリ 128MiB # 最小の設定
vcpuの数 1

リクエストタイムアウト 300s
最大同時リクエスト数 80

リクエストの処理中にのみCPUを割り当てる

実行環境
デフォルト

自動スケーリング
インスタンスの最小数 0 # 最小の設定
インスタンスの最大数 1 # 最小の設定

起動時の CPU ブースト 無し

プロジェクト構成

run-2プロジェクトは、以下の主要なファイルで構成されています。

  • .terraform_example.tfvars: Terraform変数のサンプル値を定義したファイルで、ユーザーが自身の設定に基づいてカスタマイズするためのテンプレートとして機能します。.terraform_example.tfvarsを参考に.terraform.tfvarsファイルを作成して下さい。
  • cloud_run.tf: Google Cloud Runの設定を定義するTerraform設定ファイルです。
  • cloudbuild.yaml: Google Cloud Buildで使用されるビルド構成を定義するYAMLファイルです。Dockerイメージのビルドとプッシュ、そしてGoogle Cloud Runへのデプロイが自動化されます。
  • cloudflare_r2.tf: Cloudflare R2のバケットリソースを管理するためのTerraform設定ファイルです。

前提条件

  • Terraformのインストール
  • Google Cloud SDKのインストール
  • Google Cloud Platformのアカウント
  • GitHubのアカウント(リポジトリ)
  • Cloudflareのアカウント

これらのツールとアカウントがセットアップされていることを確認してください。

セットアップされてない方は以下をご覧ください、
コマンドラインを使用してそれぞれの前提条件をセットアップするための詳しいガイドです。

1. Terraformのインストール

Linux (Debian/Ubuntuベース)

sudo apt-get update && sudo apt-get install -y gnupg software-properties-common curl
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt-get update && sudo apt-get install terraform

macOS

brew tap hashicorp/tap
brew install hashicorp/tap/terraform

Windows (PowerShell)

PowerShellを管理者として開き、以下のコマンドを実行します。

choco install terraform

Terraform バージョン管理ツール (tfenv)

tfenvはTerraformのバージョン管理ツールで、異なるプロジェクトで異なるTerraformのバージョンを使用する際に非常に便利です。

tfenvのインストール

  1. Homebrewを使用してtfenvをインストール
brew install tfenv
  1. インストールの確認
tfenv --version

tfenv自体のバージョン(terraformのバージョンとは違う)

Terraformのバージョンのインストールと切り替え

  1. 利用可能なバージョンの一覧を表示
tfenv list-remote
  1. 特定のバージョンをインストール
    1.5.2バージョンをインストール。
tfenv install 1.5.2
  1. インストールされているバージョンの一覧を表示
tfenv list
  1. バージョンの切り替え
    インストールしたバージョンに切り替えるには以下のコマンドを使用します。
tfenv use 1.5.2

これで、tfenvを使用してTerraformのバージョンを簡単に切り替えることができます。

2. Google Cloud SDKのインストール

Linux (Debian/Ubuntuベース)

echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] http://packages.cloud.google.com/apt cloud-sdk main" | sudo tee -a /etc/apt/sources.list.d/google-cloud-sdk.list
curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo gpg --dearmor -o /usr/share/keyrings/cloud.google.gpg
sudo apt-get update && sudo apt-get install google-cloud-sdk

macOS

brew install google-cloud-sdk

Windows (PowerShell)

PowerShellを管理者として開き、以下のコマンドを実行します。

choco install gcloudsdk

3. Google Cloud Platformのアカウントのセットアップ

アカウントがまだない場合は、
https://cloud.google.com/
でサインアップします。

GCPの初期設定

gcloud init

4. GitHubのアカウントとリポジトリのセットアップ

GitHubアカウントがまだない場合は、
https://github.com/
でサインアップし、新しいリポジトリを作成します。

5. Cloudflareのアカウントのセットアップ

Cloudflareアカウントがまだない場合は、
https://www.cloudflare.com/
でサインアップします。

これらのステップを完了すると、Terraformプロジェクト「run-2」を実行する準備が整います。

ファイル構成

run-2
run-2
├── .terraform_example.tfvars // .terraform.tfvarsの例
├── .terraform.tfvars // .terraform_example.tfvarsを参考に作成
├── cloud_run.tf
├── cloudbuild.yaml
└── cloudflare_r2.tf

cloudflare_r2.tf

cloudflare_r2.tf
# Terraformの設定ブロック
terraform {
  # 必要なプロバイダーの定義
  required_providers {
    # Cloudflareプロバイダーの設定
    cloudflare = {
      # Cloudflareプロバイダーのソースとバージョンの指定
      source  = "cloudflare/cloudflare"
      version = "~> 4"
    }
  }
}

# APIトークンを格納するための変数の定義
variable "api_token" {}
# ゾーンIDを格納するための変数の定義
variable "zone_id" {}
# アカウントIDを格納するための変数の定義
variable "account_id" {}
# R2のバケット名を格納するための変数の定義
variable "bucket_name" {}

# Cloudflareプロバイダーの設定
provider "cloudflare" {
  # APIトークンの設定(変数から取得)
  api_token = var.api_token
}

# Cloudflare R2バケットのリソースを定義
resource "cloudflare_r2_bucket" "example" {
  # アカウントIDの設定(変数から取得)
  account_id = var.account_id
  
  # バケットの名前
  name = var.bucket_name
}

cloud_run.tf

cloud_run.tf
# Google Cloudプロバイダの設定
provider "google" {
  # 使用するGoogle CloudプロジェクトのID
  project = var.project_id
  
  # デフォルトで使用するリージョン
  region  = var.region
}

# Google CloudプロジェクトIDを格納する変数
variable "project_id" {}
# 使用するリージョンを格納する変数
variable "region" {}
# Cloud Runのサービス名を格納する変数
variable "service_name" {}
# GitHubのリポジトリの所有者名を格納する変数
variable "github_owner" {}
# GitHubリポジトリ名を格納する変数
variable "github_repo" {}

# 環境変数を格納するマップ型の変数
variable "env_vars" {
  description = "Environment variables as a map."
  type        = map(string)
}

# Google Cloud Runサービスのリソース
resource "google_cloud_run_service" "default" {
  # サービス名
  name = var.service_name
  
  # サービスのリージョン
  location = var.region

  template {
    metadata {
      # 自動スケーリングの設定
      annotations = {
        "autoscaling.knative.dev/minScale" = "0"
        "autoscaling.knative.dev/maxScale" = "1"
      }
    }

    spec {
      containers {
        # 使用するコンテナイメージ
        image = "gcr.io/${var.project_id}/${var.github_repo}"

        # 環境変数の設定
        dynamic "env" {
          for_each = var.env_vars
          content {
            name  = env.key
            value = env.value
          }
        }

        # コンテナのポート設定
        ports {
          container_port = 8001
        }

        # リソース制限の設定
        resources {
          limits = {
            memory = "128Mi"
            cpu    = "1"
          }
        }
      }
      # サービスアカウントの設定
      service_account_name  = google_service_account.cloud_run_service_account.email
      
      # コンテナの同時実行数の制限
      container_concurrency = 80
      
      # タイムアウトの設定(秒)
      timeout_seconds       = 300
    }
  }

  # リビジョン名を自動生成するかどうか
  autogenerate_revision_name = true
  
  # トラフィックの設定
  traffic {
    percent         = 100
    latest_revision = true
  }
}

# Google Cloud Run用のサービスアカウント
resource "google_service_account" "cloud_run_service_account" {
  # サービスアカウントのID
  account_id   = "cloud-run-service-account"
  
  # サービスアカウントの表示名
  display_name = "Cloud Run Service Account"
}

# GitHubトリガー用のCloud Buildトリガー
resource "google_cloudbuild_trigger" "github_trigger" {
  # トリガーの名前
  name        = "github-trigger"
  
  # トリガーの説明
  description = "Trigger for GitHub commits"

  # GitHubの設定
  github {
    owner = var.github_owner
    name  = var.github_repo
    push {
      branch = "^main$"
    }
  }

  # Cloud Buildの設定ファイル名
  filename = "cloudbuild.yaml"
}

cloudbuild.yaml

cloudbuild.yaml
# Cloud Buildのステップを定義
steps:
  # 第1ステップ: Dockerイメージのビルド
  - name: 'gcr.io/cloud-builders/docker'  # 使用するDockerイメージ
    args:
      - 'build'  # Dockerコマンド
      - '-t'  # タグを付けるオプション
      - 'gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA'  # イメージのタグ(プロジェクトID、リポジトリ名、コミットSHAを使用)
      - '.'  # Dockerfileのあるディレクトリ(ここではカレントディレクトリ)

  # 第2ステップ: Dockerイメージのプッシュ
  - name: 'gcr.io/cloud-builders/docker'  # 使用するDockerイメージ
    args:
      - 'push'  # Dockerコマンド
      - 'gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA'  # プッシュするイメージのタグ

  # 第3ステップ: Google Cloud Runにデプロイ
  - name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'  # Google Cloud SDKを使用
    args:
      - 'run'  # gcloudコマンド
      - 'deploy'  # deployサブコマンド
      - '$REPO_NAME'  # デプロイするサービス名
      - '--image'  # イメージを指定するオプション
      - 'gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA'  # 使用するDockerイメージ
      - '--region'  # リージョンを指定するオプション
      - 'asia-northeast1'  # 使用するリージョン
    env:
      - 'CLOUDSDK_COMPUTE_REGION=asia-northeast1'  # 環境変数でリージョンを設定
      - 'CLOUDSDK_CORE_DISABLE_PROMPTS=1'  # ユーザー入力を求めるプロンプトを無効化

セットアップ

Terraform変数の設定: .terraform.tfvars ファイルを作成し、必要な変数を設定します。例として、.terraform_example.tfvars ファイルを参考にしてください。

.terraform_example.tfvars
# Cloudflare R2の設定
api_token = "<your_api_token>"  # CloudflareのAPIトークン
zone_id = "<your_zone_id>"      # CloudflareのゾーンID
account_id = "<your_account_id>"# CloudflareのアカウントID
bucket_name = "<your_bucket_name>"# Cloudflare R2のバケット名

# Google Cloud Runの設定
project_id = "<YOUR_GCP_PROJECT_ID>"          # Google CloudプロジェクトID
region = "asia-northeast1"                    # Google Cloudリージョン
service_name = "<YOUR_CLOUD_RUN_SERVICE_NAME>"# Cloud Runのサービス名
github_owner = "<YOUR_GITHUB_USERNAME_OR_ORG_NAME>" # GitHubのリポジトリの所有者(ユーザー名または組織名)
github_repo = "<YOUR_GITHUB_REPO_NAME>"       # GitHubリポジトリ名

# 環境変数の設定
env_vars = {
  BACKEND_ENV_NAME = "<BACKEND_ENV_VALUE>"    # 環境変数1
  BACKEND_ENV_NAME2 = "<BACKEND_ENV_VALUE2>"  # 環境変数2
  # ... 他の環境変数
}

使用方法

Google Cloud RunサービスとCloudflare R2バケットをデプロイするには、以下のTerraformコマンドを実行します。

terraform init
terraform apply -var-file=".terraform.tfvars"

リソースの削除

デプロイしたリソースを削除するには、以下のコマンドを実行します。

terraform destroy -var-file=".terraform.tfvars"

まとめ

run-2」を利用することで、Cloudflare R2とGoogle Cloud Runをスムーズかつ最小限のコスト設定でデプロイすることが可能になります。このプロジェクトを利用して、デプロイメントプロセスを効率化しましょう。

https://github.com/eternaleight/run-2

Discussion