創業から10年(先月10周年を迎えました)Herokuのおかげでインフラ管理とはほぼ無縁だったけど、ちょうど良いTerraformを活用できそうな機会があったという体験談を今日の技術雑談会で話しました。

TerraformでIaC初体験

目次

  • 目的と動機
  • 方針
  • 手順
  • 感想
  • 参考にした情報

目的と動機

ちょっとしたデータ連携のプロジェクトでバケットをたくさんつくる必要が発生したのでせっかくなら噂のTerraformでズババン!と作成してみたかった

方針

Cloud Storageの構成を管理することを目的とする

  • GCPのコンソールでポチポチ実行した内容をエクスポートして出来上がったファイルを参考にする
  • エクスポートしたものをそのまま利用せず、理解できるものからIaC化していくということがそもそも可能なのかやりながら試していく
    • GCPのコンソールでおこなったすべての作業(terraformが対応しているリソースのみ)がエクスポートされる
    • 当初の検証中にポチポチしたものが含まれていたり、terraformで管理しなくていいものもあるかもしれないという気持ち
    • BigQueryのSQL文を含むデータセットの定義などはさすがにterraformで管理しにくいのではという疑問
  • 今回構成管理したいリソースのみ対象にしてterraform importして既存の環境から.tfstateをつくってみる

手順

  1. gcloud CLIを利用してterraformの設定としてエクスポートする
  2. 生成されたファイル(./gcp-terraform-export/{modules.tf,import.sh})を参考にリポジトリ直下にmain.tfを作成する
  3. 現在のGCP上の状態をリソース別にインポートする
  4. GCSのバケットをterraformでスババン!してみる

1. gcloud CLIを利用してterraformの設定としてエクスポートする

# gcp-terraform-exportディレクトリにterraformの設定としてエクスポートする
$ gcloud beta resource-config bulk-export --resource-format=terraform --project=<PROJECT> --path=./gcp-terraform-export/

# tfstateにインポートするためのスクリプトを生成する
$ cd gcp-terraform-export
$ gcloud beta resource-config terraform generate-import . --output-script-file=import.sh --output-module-file=modules.tf
# => modules.tfとimport.shが生成される

生成されたmodules.tf

provider "google" {
    project = "<PROJECT>"
}

module "<module_name>" {
    source = "<PATH>"
}

# ...
# ずらずらとコンソールでポチポチした分のリソース分のmoduleが並ぶ
# ...

生成されたimport.sh

terraform import <RESOUCE_ADDRESS> <RESOURCE>
# ....
# 今回のプロジェクトだと79行の`terraform import`文ができあがった
# ...

2. 生成されたファイル(./gcp-terraform-export/{modules.tf,import.sh})を参考にリポジトリ直下にmain.tfを作成する

main.tf

resource "google_storage_bucket" "bucket" {
  force_destroy               = false
  location                    = "ASIA-NORTHEAST1"
  name                        = "<BUCKET_NAME>"
  project                     = "<PROJECT>"
  public_access_prevention    = "enforced"
  storage_class               = "STANDARD"
  uniform_bucket_level_access = true
}

3. 現在のGCP上の状態をリソース別にインポートする

# main.tfのあるリポジトリ直下でterraformを初期化する
$ terraform init

# おまけ:
# この時点で
$ terraform plan
# で確認すると、main.tfにかかれたリソースは新規に追加されるものとして出力される
# 続きの`terraform import ~`を実行していくと差分がなくなっていく

# 前段でexportしたファイルの記述されてるterraform import文を実行すると、terraform.tfstateに反映される
$ terraform import google_storage_bucket.<BUCKET_NAME> <BUCKET_NAME>

4. GCSのバケットをterraformでズババン!してみる

せっかくなのでterraformのvariablefor_eachをつかってみる

variables.tf

variable bucket_list {
  type        = list(string)
  description = "list of bucket-name"
  default     = [
    "<BUCKET_NAME_1>",
    "<BUCKET_NAME_2>",
    "<BUCKET_NAME_3>",
    "<BUCKET_NAME_4>",
    "<BUCKET_NAME_5>",
    "<BUCKET_NAME_6>",
    "<BUCKET_NAME_7>",
  ]
}

main.tfに追記

resource "google_storage_bucket" "<THE BUCKET>" {
  for_each = toset(var.bucket_list)
  force_destroy               = false
  location                    = "ASIA-NORTHEAST1"
  name                        = "<BUCKET_NAME>"
  project                     = "<PROJECT>"
  public_access_prevention    = "enforced"
  storage_class               = "STANDARD"
  uniform_bucket_level_access = true
}

やってみる

# 「7つのバケットを追加することになるよー」というのを確認できた
$ terraform plan
# ズババン!
$ terraform apply

感想

気持ち良かった! コンソールでポチポチしたり、gcloud CLIでいろいろやっていると自分がやっていることの再現性や暗黙知の発生に気になってモヤモヤしていたけど

  • 部分的にIaCを始めることができる
  • 公式ドキュメントがわかりやすい
  • CLIやコンソールで作成したリソースをterraformとしてエクスポートできる
  • terraform planでDry-Runできる

などなど、想像とは違いハードルが低いことがわかった。 他のプロジェクトや、TerraformのプロバイダにGoogle Workspaceもあることも知ったので活用していきたい。

参考にした情報