TerraformでGoogle Cloudのインフラ構成を管理し始めるためにやったこと
最近はGoogle Cloudを触る機会も増えており、コンソールからポチポチ設定していたが、コード管理していきたいなというところからTerraformを触り始めた。その際にやったことを書いておく。
導入
Terraformのインストールが必要になりますが、その際 tfutils/tfenv を使うのがよくある方法のよう。
nodenvやrbenvのような *.env 系のバージョン管理ツールで、rbenvにインスパイアされたツール。
この手のツールは数が多く、なんだっけとなりがちなので mise を導入してこちらで管理してみた。
miseの導入
jdx/miseはasdfという *.env
系のツールをいい感じに統合して扱えるツールをRustで再実装したようなツールで、Node.js以外はこちら経由で入れることが多い。ちなみにNode.jsについてはVoltaにしている。
ドキュメントに従い、以下のコマンドで導入する。
$ curl https://mise.run | sh
$ ~/.local/bin/mise --version
2024.6.6 linux-x64 (409d6e4 2024-06-20)
$ echo '~/.local/bin/mise activate fish | source' >> ~/.config/fish/paths.fish
$ source ~/.config/fish/paths.fish
$ mise --version
2024.6.6 linux-x64 (409d6e4 2024-06-20)
miseでTerraformを導入する
miseでTerraformを導入してみる。
$ mise install terraform
~中略~
mise terraform@1.8.5 ✓ installed
$ mise use terraform@1.8.5
mise ~/.mise.toml tools: terraform@1.8.5
$ mise use --global terraform@1.8.5
mise terraform is defined in ~/.mise.toml which overrides the global config (~/.config/mise/config.toml)
mise ~/.config/mise/config.toml tools: terraform@1.8.5
$ terraform --version
Terraform v1.8.5
on linux_amd64
どうでもいいが、ちゃんとインストールができるまで、「 terraforme」 とか 「terrafrom」 とかタイポがひどかった。
Google Cloudで使う設定をしてみる
※Google Cloudのプロジェクト作成とgcloud周りの設定は終わっている状態。
Terraform用のサービスアカウントを用意する
Terraformから各種リソースを操作していくために、専用のサービスアカウントを作成し、権限を付与しておく。
シェルスクリプト化したのでこちらを活用する。
#!/bin/bash
# 変数の定義
PROJECT_ID="your-project-id"
SERVICE_ACCOUNT_NAME="terraform"
DISPLAY_NAME="terraform"
KEY_FILE="terraform-sa.json"
# プロジェクトを設定
gcloud config set project $PROJECT_ID
# サービスアカウントを作成
gcloud iam service-accounts create $SERVICE_ACCOUNT_NAME \
--display-name="$DISPLAY_NAME"
# サービスアカウントに権限を付与
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME@$PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/editor"
# サービスアカウントキーの作成とダウンロード
gcloud iam service-accounts keys create $KEY_FILE \
--iam-account=$SERVICE_ACCOUNT_NAME@$PROJECT_ID.iam.gserviceaccount.com
オーナー権限を使うというのもあったが、編集権限である程度操作ができたので一旦こうしている。
Terraformのスクリプトを書いていく
一応スクリプトと呼称しているが、なんというのか分かっていない。
インフラサービス毎にスタートガイドのようなものが用意されていて、Google Cloudはこちらを参考に進めると良さそうだった。
https://developer.hashicorp.com/terraform/tutorials/gcp-get-started/google-cloud-platform-build
取り急ぎ main.tf
でTerraformのバージョンはなんとなく指定しておく。
terraform {
required_version = ">= 1.0.0, < 2.0.0"
}
この範囲外のバージョンで実行すると怒られる様になるらしい。
作成から実行までの流れ
なんとなくの流れとしては以下になる。
- 上記下準備をしておく
- Terraformで構築するリソースなど書いていく (main.tfなど)
- terraform init # terraform環境の初期化
- terraform plan # 何が作成されて、何が削除されるかが確認できるらしい
- terraform apply # リソースが実際に構築されるらしい
余談だが、環境差異で動かないこともあるらしく、terraform plan
や terraform apply
はCI/CD上で構築しておくのがいいらしい。
調べていると、4のタイミングで結果を PRにコメントとして出力させる方法があるろしい。すごく便利なのでWorkflowが構築できたら組み込みたい。
tfcmt で Terraform の CI/CD を改善する
また、合わせて組み込むと良さそうなツール類もいくつかあったので合わせて貼っておく。
Terraform開発時のDeveloper Experienceを爆上げする
小さい構成で作ってみる
main.tf
terraform {
required_providers {
google = {
source = "hashicorp/google"
version = "4.51.0"
}
}
}
provider "google" {
project = var.project_id
region = var.region
}
resource "google_storage_bucket" "bucket" {
name = var.bucket_name
location = var.region
strage_class = "STANDARD"
}
variables.tf
variable "project_id" {
description = "The ID of the project in which to create resources."
type = string
}
variable "region" {
description = "The region in which to create resources."
type = string
}
variable "bucket_name" {
description = "The name of the Cloud Storage bucket."
type = string
}
staging.tfvars
project_id = "PROJECT_ID"
region = "us-west1"
bucket_name = "bucket-name"
あるプロジェクトにリージョンを指定しつつ、Cloud Storageにバケットを作成するという内容。
スクリプトのチェックとリソース作成
$ terraform plan -var-file="staging.tfvars"
$ terraform apply -var-file="staging.tfvars"
terraform plan
で何が作られるかを確認。 terraform apply
でリソースの作成を行った
コマンド実行後にコンソールから作成できている事を確認。
terraform destroy
で削除されることまで確認済み。
terraform.tfstateのバックアップ
terraform.tfstate
に現状の構成がどうなっているかを保持しているらしい。
複数人開発なんかだと、これをStorageに持っておくのがいいらしい。どうやるかを以下の記事が書いている。
Terraform で入門する Google Cloud【セットアップ編】
専用のバケットを用意して、 terraform apply
時に自動でバックアップを取るというもの。
自動で取れるのでとてもいい気がする。
今回は構成が同じでいいので main.tf にまとめているが、環境ごとに分けるほうがいいのかもしれない。
元々このまま運用しても terraform.tfstate
がおかしくなるような気もする。varファイルを切り替えたときにどうなるか次第だけど、ファイル構成は要検討になってきた。
main.tfはどういう構成にしておくといいか
先述の話を踏まえて色々調べていると、 environments/staging/main.tf
みたいな環境毎に切り替える方法が出てきた。
これだと確かに先述の terraform.tfstate
が環境ごとにぶつかりそう問題がおそらく回避できる。かつ、バックアップも取りやすそう。
共通する部分については、モジュールを活用するといいのかもしれない。
やってみて
ChatGPTなんかを活用しながら入門してみたが、こういうことを始めるのにとてもいい環境が整ってきたなと感じた。
構成図を吐いてもらって画像に書き出して、ChatGPTに食わせて理解させ、Terraformのコードおーくれ ありがたい時代になった
— こにたん (@skd_nw) June 22, 2024
また、いつかやろうと思っていたのを満を持してやってみたが、いい感じに進めることができた。今後Cloud RunやCloud SQLなど他のサービスも絡めて書いてみようと思う。