Terraformで複数環境をデプロイするチュートリアル(tfvarsファイル編)
前回ローカルモジュールを使った複数環境へのデプロイのチュートリアルを作ってみました。
今回はtfvarsファイルを使ったパターンを作ってみました
このパターンはAWS公式ドキュメントのTerraform AWS プロバイダーを使用するためのベストプラクティスでも紹介されています。併せて確認するとよいと思います。
tfvarsファイルとは
Terraformではvariableブロックを使って、入力変数を定義できます。
以下では、Variables instance_type
を宣言して、Resourceaws_instance
で利用しています。
variable "instance_type" {
description = "The EC2 instance's type."
type = string
default = "t2.micro"
}
resource "aws_instance" "app_server" {
ami = data.aws_ami.ubuntu.id
instance_type = var.instance_type
vpc_security_group_ids = [module.vpc.default_security_group_id]
subnet_id = module.vpc.private_subnets[0]
}
Variablesは何も値を指定しないと、default
で設定した値がセットされます。
terraform plan # instance_typeは"t2.micro"になる
環境変数やオプションでVariablesに値を渡すことができます。
export TF_VAR_instance_type=t2.large
terraform plan # instance_typeは"t2.large"になる
terraform plan -var="instance_type=t2.medium" # instance_typeは"t2.medium"になる
Variablesは変数定義ファイルで渡すこともできます。この変数定義ファイルを、本記事ではtfvarsファイルと呼びます。
instance_type=t3.small
terraform plan -var-file="envs/stg/terraform.tfvars"
今回紹介するのは、tfvarsファイルを使って環境の差異を表現する方法です。
Variablesの詳細は(優先順位や自動読み込み等)については、以下の公式ドキュメントを確認ください。
前提
冒頭のブログと同様です。
ハンズオン
最終的には以下のディレクトリ構成になります。
.
├── envs
│ ├── prod
│ │ └── terraform.tfvars
│ └── stg
│ └── terraform.tfvars
├── main.tf
├── outputs.tf
├── terraform.tf
└── variables.tf
以降はこの構成になるプロセスを説明します。
ハンズオン用ファイルの用意
冒頭のブログを参考にハンズオン用ファイルを用意します。
tfvarsファイルの作成
環境ごとにtfvarsファイル格納用のディレクトリを作成します。
mkdir -p envs/prod
mkdir -p envs/stg
以下のファイルをそれぞれ作成します。
tfvarsファイルにて環境差異を表現します。
今回はinstance_name
とinstance_type
を環境ごとに設定する想定で、ファイルを作成します。
instance_name = "prod-server"
instance_type = "t3.small"
instance_name = "stg-server"
instance_type = "t3.micro"
バックエンド設定ファイルの用意
tfvarsファイルでは、全環境で同じディレクトリでTerraformを実行します。
この場合、デフォルトではステートファイルが同じ場所に同じ名前で作成されてしまいます。
「PROD用のステートファイルをSTG環境の設定で上書きしてしまう」といったことが起きます。
そのため、バックエンド設定を環境ごとに用意する必要があります。
まずは、ルートディレクトリにbackend.tf
を作成します。
デフォルトでlocal
バックエンドが使用されますが、-backend-config
オプションでバックエンドを分けるために明示的に指定する必要があります。
terraform {
backend "local" {}
}
環境ディレクトリにそれぞれバックエンド設定用ファイルを作成します。
path = "prod.tfstate"
path = "stg.tfstate"
デフォルトでは、ルートディレクトリにterraform.tfstate
という名前でステートファイルが作成されます。
環境ごとに、PRODだったらprod.tfstate
STGだったらstg.tfstate
という名前でファイルを作成するように指定しました。
動作確認: Terraformの実行
実際に2環境をデプロイしてみます。
以下のコマンドでPROD環境をデプロイします。
terraform init -backend-config="envs/prod/backend.config"
terraform plan -var-file="envs/prod/terraform.tfvars"
terraform apply -var-file="envs/prod/terraform.tfvars"
続いてSTG環境です。terraform init
でバックエンド切り替え時に、-reconfigure
オプションが必要なことに注意してください。
terraform init -reconfigure --backend-config="envs/stg/backend.config"
terraform plan -var-file="envs/stg/terraform.tfvars"
terraform apply -var-file="envs/stg/terraform.tfvars"
2つの環境へのデプロイが成功し、ステートファイルがそれぞれ作成できていることを確認できました。
ls | grep tfstate
prod.tfstate
stg.tfstate
クリーンアップ
最後に以下のコマンドで作成したリソースを削除します。
terraform init -reconfigure --backend-config="envs/prod/backend.config"
terraform destroy -var-file="envs/prod/terraform.tfvars"
terraform init -reconfigure --backend-config="envs/stg/backend.config"
terraform destroy -var-file="envs/stg/terraform.tfvars"
おまけ: S3 バックエンドを使っている場合のbackend.config
今回はベースとしたチュートリアルの都合上、localバックエンドを前提にしました。
S3バックエンドを使うパターンも多いかと思うので、軽く触れます。
backend.tf
は以下のようにS3に変更します。
terraform {
- backend "local" {}
+ backend "s3" {}
}
backend.config
は、S3バックエンドの引数に置き換えます。
- path = "prod.tfstate"
+ bucket = "prod-mybucket"
+ key = "path/to/my/key"
+ region = "us-east-1"
- path = "stg.tfstate"
+ bucket = "stg-mybucket"
+ key = "path/to/my/key"
+ region = "us-east-1"
おわりに
tfvarsファイルを使った環境分離についてでした。
ローカルモジュールパターンと比較するとステップ数が少ないです。
モジュール分離について悩まずに済むのも良い点ですね。
一方、環境切り替えやコマンドの実行については、ローカルモジュールパターンの方がシンプルです。
一長一短ありますが、個人的にはtfvarsファイルを使う方法が好きです。