haihai Blog

Google Cloud で Terraform の利用を開始する

2024-04-20

はじめに

Google Cloud で Terraform を利用してリソースを作成します。
ブラウザから操作できる Cloud Shell から gcloud CLI を利用し Terraform State 用の Google Cloud Storage (GCS) および Terraform 実行用のサービスアカウントを作成します。
その後、クライアント (mac) の設定を行い、 サービスアカウントの権限で Terraform を実行しリソースを作成します。

前提事項

  • Google Cloud
    • プロジェクトが作成してあること
    • IAM および GCS 作成権限を持っているアカウントでログインしていること
    • Terraform から操作するために必要な API を有効化してあること
  • クライアント
    • Terraform がインストールされていること

Terraform State 用の Google Cloud Storage を作成する

Google Cloud コンソールの上部にあるボタンから Cloud Shell を起動します。
Cloud Shell に gcloud CLI は最初からインストールされています。

gcloud --version
# Google Cloud SDK 472.0.0
# 以下、略

gcloud CLI から GCS を作成します。作成後、バージョニングを有効にします。

gcloud storage buckets create gs://{BUCKET_NAME} --location={BUCKET_LOCATION} --versioning=true
# Creating gs://BUCKET_NAME/...
gcloud storage buckets update gs://{BUCKET_NAME} --versioning
# Updating gs://{BUCKET_NAME}/...
#   Completed 1

# 例
# gcloud storage buckets create gs://project-name-tfstate --location=asia-northeast1
# gcloud storage buckets update gs://project-name-tfstate --versioning

Terraform 実行用のサービスアカウントを作成する

gcloud CLI を利用して、サービスアカウントを作成します。
今回は、 GCS を作成できる権限を付与します。

# サービスアカウント作成
gcloud iam service-accounts create {project-name-terraform-sa} \
    --description="Service account for Terraform" \
    --display-name="Terraform Service Account"

作成したサービスアカウントへ GCS の事前定義ロールである Storage 管理者(roles/storage.admin) を付与します。

# サービスアカウントへロールの割り当て
gcloud projects add-iam-policy-binding {project-id} \
    --member="serviceAccount:{project-name-terraform-sa}@{project-id}.iam.gserviceaccount.com" \
    --role="roles/storage.admin"

サービスアカウントのキーを JSON 形式で Cloud Shell 上に作成し、ブラウザを使ってクライアントへダウンロードします。

# サービスアカウントのキーを作成
gcloud iam service-accounts keys create ~/terraform-sa-key.json \
    --iam-account {project-name-terraform-sa}@{project-id}.iam.gserviceaccount.com

# ダウンロード
cloudshell download terraform-sa-key.json

Terraform を利用してリソースを作成する

以下の 3 つのファイルを作成します。

> tree
.
├── main.tf
├── terraform.tfvars
└── variables.tf

Git 管理する場合は、 .gitignore ファイルを作成し、必要に応じて tfvars や Git 管理不要なファイルを追加します。

# Terraform
.terraform/
*.tfstate
*.tfstate.backup
*.tfvars
.terraform.lock.hcl
crash.log
override.tf
override.tf.json

以下は、 main.tf です。セキュアな情報や変更頻度な高いものは変数化します。

terraform {
  backend "gcs" {
    bucket = "{BUCKET_NAME}"
    prefix = "terraform/state"
  }
}

provider "google" {
  project     = var.project_id
  region      = var.region
}

resource "google_storage_bucket" "example_bucket" {
  name                        = var.bucket_name
  location                    = "ASIA-NORTHEAST1"
  uniform_bucket_level_access = true
  force_destroy               = true
}

以下は、 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 = "The name of the GCS bucket to create"
  type        = string
}

以下は、 terraform.tfvars です。任意の値を設定します。

project_id  = "your-project-id"
region      = "your-project-reqion"
bucket_name = "your-bucket-name"

上記のコードを記載したら、サービスアカウントの権限でアクセスするために、先ほどダウンロードした JSON ファイルのパスを環境変数 GOOGLE_APPLICATION_CREDENTIALS に設定します。

export GOOGLE_APPLICATION_CREDENTIALS="/your/path/terraform-sa-key.json"

terraform init を実行します。
successfully と表示され、 .terraform ディレクトリや .terraform.lock.hcl など生成されました。

terraform init
# Terraform has been successfully initialized!

terraform plan を実行し、表示内容を確認します。
Plan: 1 to add, 0 to change, 0 to destroy. が表示されました。

terraform apply を実行します。
先程の terraform plan 同様、実行後の差分が表示され、アクションを実行するか質問があります。 yes を入力します。

> terraform apply

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the
following symbols:
  + create

Terraform will perform the following actions:

  # google_storage_bucket.example_bucket will be created
  + resource "google_storage_bucket" "example_bucket" {
      + effective_labels            = (known after apply)
      + force_destroy               = true
      + id                          = (known after apply)
      + location                    = "ASIA-NORTHEAST1"
      + name                        = "project-name"
      + project                     = (known after apply)
      + project_number              = (known after apply)
      + public_access_prevention    = (known after apply)
      + rpo                         = (known after apply)
      + self_link                   = (known after apply)
      + storage_class               = "STANDARD"
      + terraform_labels            = (known after apply)
      + uniform_bucket_level_access = (known after apply)
      + url                         = (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

google_storage_bucket.example_bucket: Creating...
google_storage_bucket.example_bucket: Creation complete after 2s [id=project-id]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

実行後にブラウザから、 GCS バケットが作成されていることが確認できます。

Terraform を利用してリソースを削除する

作成した GCS バケットを削除します。
terraform destroy コマンド実行すると削除後の変更内容が表示され、確認メッセージが表示されます。 yes を入力します。

> terraform destroy

google_storage_bucket.example_bucket: Refreshing state... [id=project-id]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the
following symbols:
  - destroy

Terraform will perform the following actions:

  # google_storage_bucket.example_bucket will be destroyed
  - resource "google_storage_bucket" "example_bucket" {
      - default_event_based_hold    = false -> null
      - effective_labels            = {} -> null
      - enable_object_retention     = false -> null
      - force_destroy               = true -> null
      - id                          = "project-id" -> null
      - labels                      = {} -> null
      - location                    = "ASIA-NORTHEAST1" -> null
      - name                        = "project-id" -> null
      - project                     = "project-name" -> null
      - project_number              = 469977965666 -> null
      - public_access_prevention    = "inherited" -> null
      - requester_pays              = false -> null
      - self_link                   = "https://www.googleapis.com/storage/v1/b/project-id" -> null
      - storage_class               = "STANDARD" -> null
      - terraform_labels            = {} -> null
      - uniform_bucket_level_access = false -> null
      - url                         = "gs://project-id" -> null

      - soft_delete_policy {
          - effective_time             = "2024-04-20T12:20:43.611Z" -> null
          - retention_duration_seconds = 604800 -> null
        }
    }

Plan: 0 to add, 0 to change, 1 to destroy.

Do you really want to destroy all resources?
  Terraform will destroy all your managed infrastructure, as shown above.
  There is no undo. Only 'yes' will be accepted to confirm.

  Enter a value: yes

google_storage_bucket.example_bucket: Destroying... [id=project-id]
google_storage_bucket.example_bucket: Destruction complete after 0s

Destroy complete! Resources: 1 destroyed.

実行後にブラウザから、 GCS バケットが削除されていることが確認できます。

参考 URL