🛠️

【GCP】GCPの環境をTerraformで構築する

2022/07/03に公開

概要

GCPのインフラ管理をTerraformを使って行う際の事前準備や、設定などに関する記事になります。

使用するツール

※ TerraformやTerragruntの細かい解説などは今回は行ってません。

事前準備

Getting Started with the Google provider | Guides | hashicorp/google | Terraform Registry

gcloud auth を使用してクレデンシャルファイルを生成し、Terraformで実行する際に利用できるようにします。その為、まずはgcloudとterraform両方を使えるDocker環境を作成します。

# https://hub.docker.com/r/hashicorp/terraform
FROM hashicorp/terraform:1.1.8 as terraform

FROM google/cloud-sdk:377.0.0-alpine

COPY --from=terraform /bin/terraform /usr/local/bin/terraform

RUN apk --update add \
      vim

# https://github.com/gruntwork-io/terragrunt/releases
RUN curl -L "https://github.com/gruntwork-io/terragrunt/releases/download/v0.36.7/terragrunt_linux_amd64" -o /usr/local/bin/terragrunt \
    && chmod +x /usr/local/bin/terragrunt

※ 各Verは適宜変更して下さい
↑ではmulti-stage buildsを使用して google/cloud-sdk イメージにterraformの実行ファイルをコピーして使っています

↓ ちなみにgcloudのDockerfileのリポジトリは以下になります
GoogleCloudPlatform/cloud-sdk-docker: Docker image with all the components of the Google Cloud SDK

次に docker-compose.yml を以下で作成します。

version: '3.8'
services:
  infra:
    build: .
    image: xxxx/infra
    container_name: "xxxx-infra"
    volumes:
      - ./:/infrastructure
      - gcloud_config:/root/.config/gcloud
    working_dir: /infrastructure
    entrypoint: bash

volumes:
  gcloud_config:

アカウントログインとクレデンシャル作成

コンテナ内でもろもろ作業していきます。

$ docker-compose run --rm infra
$ gcloud auth login --no-launch-browser

↑URLが発行されるのでWebブラウザで開き、該当のアカウントでログイン後認証コードを入力する。

$ gcloud projects list

↑正しいアカウントでちゃんとログインできているか確認(アカウントの管理下のプロジェクト一覧が表示される)

$ gcloud auth application-default login --no-launch-browser

↑でクレデンシャル作成実施。実際のファイルは /root/.config/gcloud 配下に生成されます。
今回はgcloud_config volumeにマウントしてます。

tfstateファイルをGCPのCloud Storageで管理する

最初にtfstateを格納するCloud Storageのバケットを作成します。

$ gsutil mb -l asia-northeast1 gs://xxx-tfstate
$ gsutil versioning set on gs://xxx-tfstate
$ gsutil lifecycle set /infrastructure/tfstate_lifecycle.json gs://xxx-tfstate

tfstate_lifecycle.json の中身としては以下

{
  "rule":
  [
    {
      "action": {"type": "Delete"},
      "condition": {"numNewerVersions": 5}
    }
  ]
}

↑世代管理をして古いものは削除する様にしました。

サンプル

準備としては以上になります。折角なので実際にGCP内のリソースを作成するサンプルを載せていきます。

CloudSQLのインスタンスを作成するサンプル

サンプルのケースとしては、プライベートIPでのCloudSQLインスタンス作成。かつアクセスユーザーをCloudSQLProxy用のユーザーとCloudRunアクセス用のユーザーの2つ作成する想定です。

# プライベートIPを使用した場合のCloudSQLインスタンス作成のサンプル
resource "google_sql_database_instance" "master" {
  name             = "xxxxx-db-master"
  database_version = "${var.database_version}"
  region           = "${var.region}"

  settings {
    tier      = "${var.tier}"
    disk_type = "${var.disk_type}"
    disk_size = "${var.disk_size}"

    ip_configuration {
      ipv4_enabled    = false
      require_ssl     = true
      private_network = "${var.private_network}"
      allocated_ip_range = "${var.allocated_ip_range}"
    }
  }
}

# CloudSQLProxy用のユーザー
resource "google_sql_user" "proxy_user" {
  name     = "${var.proxy_user}"
  instance = "${google_sql_database_instance.master.name}"
  host     = "cloudsqlproxy~%"
  password = "${var.proxy_password}"
}

# CloudRunアクセス用のユーザー
resource "google_sql_user" "cloud_run_user" {
  name     = "${var.cloud_run_user}"
  instance = "${google_sql_database_instance.master.name}"
  host     = "%"
  password = "${var.cloud_run_password}"
}

CloudStorageのバケットを作成するサンプル

サンプルのケースとしては、プロジェクトのオーナーと、特定のサービスアカウントに roles/storage.admin のロールを持たせるバケットを作成する想定です。

resource "google_storage_bucket" "storage" {
  name          = "xxxx-storage"
  location      = "${var.location}"
  storage_class = "${var.storage_class}"
  uniform_bucket_level_access = true
  force_destroy = true
}

data "google_iam_policy" "role_binding" {
  binding {
    role = "roles/storage.admin"

    members = [
      "projectOwner:{プロジェクトID}",
    ]
  }

  binding {
    role = "roles/storage.objectAdmin"

    members = [
      "serviceAccount:${var.allowed_service_account}",
    ]
  }
}

resource "google_storage_bucket_iam_policy" "policy_binding" {
  bucket      = google_storage_bucket.storage.name
  policy_data = data.google_iam_policy.role_binding.policy_data
}

参考URL

Discussion