Terraform の Workspaces を利用して複数の tfstate を管理しているとき、tfvars ファイルも Workspaces に合わせて環境ごとに用意することがあると思います。
たとえばディレクトリ構成はこのようになっていて
├── main.tf
├── development.tfvars
├── production.tfvars
└── variables.tf
Terraform を実行するときに Workspace と tfvars をそれぞれ指定する運用です。
$ terraform workspace select development
$ terraform plan -var-file="development.tfvars"
この方法でも運用できるのですが、Workspace と -var-file
の組み合わせを間違えないようにする必要があり、毎回気をつけるのがしんどいので、どうにか楽にできないかと考えた記録を残します。
Terraform のバージョンは v0.13 です。
目次
方法1:plan, apply 用のシェルスクリプトを書く
ディレクトリ構成は以下の通り。冒頭のファイル構成に deploy.sh
を追加しています。
├── main.tf
├── deploy.sh
├── development.tfvars
├── production.tfvars
└── variables.tf
main.tf
にはリソースの定義
resource "aws_instance" "example" {
instance_type = "t2.micro"
ami = var.image_id
}
variables.tf
には変数定義
variable "image_id" {
type = string
description = "The id of the machine image (AMI) to use for the server."
}
development.tfvars
には変数の値が書かれています。
image_id = "ami-abc123"
この状況であらたにdeploy.sh
を書いて(簡略化のためヘルプや入力値チェックのコードを省略しています)
#!/bin/bash
set -e
COMMAND=$1
WORKSPACE=$2
terraform workspace select ${WORKSPACE}
terraform ${COMMAND} -var-file=${WORKSPACE}.tfvars
以下のように実行をします。
deploy.sh plan development
Terraform の実行は workspaces の切り替えなどをする必要がなく 1 コマンドで済みます。ただし、Terraform のプロジェクトが増えた場合にdeploy.sh
を毎回配置して回るのが少し面倒です。
その2:ローカル変数 (locals) を使う
locals を使うとローカル変数が定義できます。これを使って変数を管理します。
先に全体のディレクトリ構成。variables.tf
と .tfvars
がありません。
├── main.tf
├── locals.tf
├── locals_development.tf
└── locals_production.tf
locals.tf
で以下のように、ローカル変数の Maps/Objects を定義します。ローカル変数 variables
のキーには Workspace の名前と同じ文字列(development, production)をいれます。
locals {
variables = {
default = local.development
development = local.development
production = local.production
}
variable = local.variables[terraform.workspace]
}
locals_development.tf
では、Workspace が development
のときに使用するローカル変数を定義していきます。locals_production.tf
も同じようにします。
locals {
development = {
image_id = "ami-abc123"
}
}
main.tf
では、以下のようにローカル変数を指定します。このようにすると Workspace が development のとき、locals_development.tf
で定義した値が入るようになります。
resource "aws_instance" "example" {
instance_type = "t2.micro"
ami = local.variable["image_id"]
}
実行方法です。terraform planの後に -var-file
の指定がなくなり、Workspace を選択するだけで良くなります。
$ terraform workspace select development
$ terraform plan
2つの方法を本番環境で運用してみて、結局どうしたか
それぞれの方法で本番環境で運用をしてみて、現在はその 1 の方法を選ぶようになりました。
理由としては、その1の方法が
- 標準的な構造なので、他のメンバーが馴染みやすく理解しやすい
- 変数の型や説明を書くことができる
- 変数まわりでエディタの入力補完が効く
というところが大きかったです。また、When To Use Local Values を読んで、その 2 の方法がローカル値の想定された使い方からは外れていると考えるようになりました。
ローカル変数は、設定の中で同じ値または式を複数回繰り返さないようにするのに役立ちますが、使いすぎると、実際に使われている値が隠されてしまい、将来のメンテナが設定を読みにくくしてしまう可能性があります。
When To Use Local Values - Terraform by HashCorp
ローカル変数は、1 つの値や結果が多くの場所で使用され、その値が将来的に変更される可能性がある場合のみ、適度に使用してください。ローカル変数の主な利点は、一箇所で簡単に値を変更できることです。
参考になれば幸いです。