Terraform Moduleとは
Terraform Moduleを使うことで、同じリソースを複数作成する際に、変更したいパラメータだけを記述して簡単にリソースを作成できます。詳細については以下の記事が役立ちました。
- 参考
今回はAzureを対象に構成を検討してみました。Terraformの構成はシステムごとにベストプラクティスが異なるため、あくまで一例としてご参考ください。
全体構成
terraform-azure │ .gitignore │ README.md │ ├───environments │ ├───dev │ │ main.tf ... シンボリックリンク │ │ providers.tf ... シンボリックリンク │ │ terraform.tfvars │ │ variables.tf ... シンボリックリンク │ │ │ ├───prod │ │ main.tf ... シンボリックリンク │ │ providers.tf ... シンボリックリンク │ │ terraform.tfvars │ │ variables.tf ... シンボリックリンク │ │ │ └───stg │ main.tf ... シンボリックリンク │ providers.tf ... シンボリックリンク │ terraform.tfvars │ variables.tf ... シンボリックリンク │ └───shared │ main.tf │ providers.tf │ variables.tf │ └───modules ├───management │ main.tf │ output.tf │ variables.tf │ ├───network ├───security └───vm
モジュールがshared/modules
、それを呼び出すルートがenvironments
です。ルートは環境ごとに管理したいためenvironment/dev
のようにdev/stg/prodでそれぞれディレクトリを用意しています。
Terraformでは環境の分け方としてディレクトリの他にもWorkspaceを使う方法がありますのでお好みで。
environments
ルート側のファイルは4つありますが、実はそのうち3つが共通の記述で使えるため、shared
配下にあるファイルのシンボリックリンクにしています。
- main.tf ... 作成したいリソースを記載する。主な変更箇所。
- providers.tf ... azurermのversion等を記載する。変更しない。
- variables.tf ... 以下のtfvarsに記載する変数を記述する。環境ごとに変わらない。
- terraform.tfvars ... 環境ごとに異なる変数を記載する。シンボリックリンクでない唯一のファイル。
environments/main.tf
locals { resource_group_name_test = "rg-${var.env_name}-test" resource_group_name_test2 = "rg-${var.env_name}-test2" } # TEST用のRG module "management" { source = "../../shared/modules/management" resource_group_name = local.resource_group_name_test } # TEST用のRGその2 module "management2" { source = "../../shared/modules/management" resource_group_name = local.resource_group_name_test2 }
main.tfでは実際に作成するリソースを記述します。上記の例ではモジュール../../shared/modules/management
を呼び出しています。これはリソースグループのモジュールです。managementとmanagement2で2回呼び出しているためRGが2つ作成されます。
environments/variables.tf
variable "env_name" { type = string description = "環境名" }
env_name
は環境ごとに値を変えたいためvariablesに記載しています。具体的な値はtfvarsに記載します。
environments/terraform.tfvars
env_name = "dev"
modules
shared/modules
にモジュールを記載します。今回は検証のためにmanagementモジュールだけを作成します。
- main.tf ... モジュールを記載する。
- output.tf ... 他のリソースで呼び出したいouputを記載します。今回はなし。
- variables.tf ...
environments/main.tf
で呼び出す変数を記載します。中にはdefaultの値を記載している変数もあります。
main.tf
resource "azurerm_resource_group" "main" { name = var.resource_group_name location = var.resource_group_location }
managementモジュールではリソースグループのみ記載しています。そのためresouce_groupモジュールのような名称を付けた方が良い気はしますが、今後複数のリソースをmanagementとして管理したいなぁと思ったためこう記載しています。どちらが有用かはわかりません。
variables.tf
variable "resource_group_name" {} variable "resource_group_location" { default = "japaneast" }
ルート側でresource_group_name
とresource_group_location
を指定したいため上記のように記述しています。ただしresource_group_location
はdefaultに東日本を指定しているため、ルート側で指定がなければデフォルトの値でリソースを作成します。
実行
# 準備
az login
terraform init
terraform plan Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with thefollowing symbols: + create Terraform will perform the following actions: # module.management.azurerm_resource_group.main will be created + resource "azurerm_resource_group" "main" { + id = (known after apply) + location = "japaneast" + name = "rg-dev-test" } # module.management2.azurerm_resource_group.main will be created + resource "azurerm_resource_group" "main" { + id = (known after apply) + location = "japaneast" + name = "rg-dev-test2" }
想定通り2つのRGが作成されます。moduleのazurerm_resource_group.mainが複数ありますがモジュールなので問題ないようです。削除するときにはターゲットにmodule.management2
を指定することで片方のみ削除が可能でした。
terraform plan -destroy -target=module.management2 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: # module.management2.azurerm_resource_group.main will be destroyed - resource "azurerm_resource_group" "main" { - id = "xxx" -> null - location = "japaneast" -> null - name = "rg-dev-test2" -> null - tags = {} -> null }
terraform destroy -target=module.management2
もっとこうした方が良い等あればコメントください。