Terraformでは、movedブロックを利用することで、リソースの再作成を行わずにローカル名を変更できます。 developer.hashicorp.com
今回は本機能を試してみようと思います。
movedブロックとは
moved ブロックは、既存リソースの参照を安全に移動するための仕組みです。
これにより「ローカル名を変えたいだけなのに、リソースが削除・再作成されてしまう」という問題を避けることができます。
事前準備
リソース作成用のTerraform定義ファイルを作成する
Terraform定義ファイルを作成します。
今回は既存リソースグループに仮想ネットワークを作成します。
以下、仮想ネットワークを作成するためのTerraform定義ファイルを示します。
main.tfの作成
provider情報、状態格納先ストレージアカウントを記載します。
# Env info provider "azurerm" { features {} subscription_id = var.subscription_id tenant_id = var.tenant_id } # Azure Provider terraform { required_providers { azurerm = { source = "hashicorp/azurerm" } } # Store Terraform state in Azure Storage backend "azurerm" { resource_group_name = "<Resource Group名(状態格納用ストレージアカウントが格納されているResource Group)>" storage_account_name = "<Storage Account名>" container_name = "<Blob Container名>" # Statment File Name key = "terraform.tfstate" } }
rg.tfの作成
リソースグループ設定を記載します。
#------------------------------- # Resource Group #------------------------------- # Resource Group data "azurerm_resource_group" "rg" { name = var.resource_group_name }
vnet.tfの作成
仮想ネットワーク設定を記載します。
#------------------------------- # Virtual Network #------------------------------- # Virtual Network resource "azurerm_virtual_network" "vnet" { name = var.virtual_network_name address_space = var.vnet_address_space location = data.azurerm_resource_group.rg.location resource_group_name = data.azurerm_resource_group.rg.name depends_on = [ data.azurerm_resource_group.rg ] } # Subnet resource "azurerm_subnet" "snet-before" { name = var.subnet_name resource_group_name = data.azurerm_resource_group.rg.name virtual_network_name = azurerm_virtual_network.vnet.name address_prefixes = var.snet_address_space depends_on = [ data.azurerm_resource_group.rg, azurerm_virtual_network.vnet ] }
variables.tfの作成
各リソースの値を記載します。
# Subscription ID variable "subscription_id" {} # TenantID variable "tenant_id" {} #------------------------------- # Resource Group #------------------------------- # Resource Group Name variable "resource_group_name" { default = "nishiyamas-tf-rg" } #---------------------------------- # Virtual Network #---------------------------------- # Virtual Network Name variable "virtual_network_name" { default = "nishiyamas-tf-moved-vnet" } # Subnet Name variable "subnet_name" { default = "tf-moved-snet" } # Vnet Address Space variable "vnet_address_space" { default = ["10.120.0.0/16"] } # Subnet Address Space variable "snet_address_space" { default = ["10.120.0.0/24"] }
terraform.tfvarsの作成
環境情報等を記載
※環境情報等を別ファイル管理をする場合に作成
# Tenand ID tenant_id = "<Tenant ID>" # SubScription ID subscription_id = "<Subscription ID>"
リソースを作成する
定義ファイルの準備が出来たらリソースを作成します。
実行コマンドについては以下URLの「Terraformコマンドの実行」をご参照ください。
リソース作成後にtfstateファイルを確認すると、サブネットのローカル名は「snet-before」になっていることがわかります。
【terraform.tfstate ※一部抜粋】
{ "mode": "managed", "type": "azurerm_subnet", "name": "snet-before", "provider": "provider[\"registry.terraform.io/hashicorp/azurerm\"]", "instances": [
ローカル名を変更する
movedブロックを使わない場合
movedブロックを利用せず、以下のようにローカル名を変更します。
今回はサブネットのローカル名を「snet-before」から「snet-after」に変更します。
【vnet.tf】
#------------------------------- # Virtual Network #------------------------------- # Virtual Network resource "azurerm_virtual_network" "vnet" { name = var.virtual_network_name address_space = var.vnet_address_space location = data.azurerm_resource_group.rg.location resource_group_name = data.azurerm_resource_group.rg.name depends_on = [ data.azurerm_resource_group.rg ] } # Subnet resource "azurerm_subnet" "snet-after" { # 更新 name = var.subnet_name resource_group_name = data.azurerm_resource_group.rg.name virtual_network_name = azurerm_virtual_network.vnet.name address_prefixes = var.snet_address_space depends_on = [ data.azurerm_resource_group.rg, azurerm_virtual_network.vnet ] }
この状態でterraform planを実行すると、以下のような差分が発生します。

上記の場合、既存リソースが一度削除され、新規作成されてしまいます。
movedブロックを使った場合
以下のように moved ブロックを追加します。
【vnet.tf】
#------------------------------- # Virtual Network #------------------------------- # Virtual Network resource "azurerm_virtual_network" "vnet" { name = var.virtual_network_name address_space = var.vnet_address_space location = data.azurerm_resource_group.rg.location resource_group_name = data.azurerm_resource_group.rg.name depends_on = [ data.azurerm_resource_group.rg ] } # Subnet resource "azurerm_subnet" "snet-after" { # 更新 name = var.subnet_name resource_group_name = data.azurerm_resource_group.rg.name virtual_network_name = azurerm_virtual_network.vnet.name address_prefixes = var.snet_address_space depends_on = [ data.azurerm_resource_group.rg, azurerm_virtual_network.vnet ] } # movedブロックを追加 moved { from = azurerm_subnet.snet-before to = azurerm_subnet.snet-after }
この状態でterraform planを実行すると、以下のようになります。

上記の場合、既存リソースの削除や新規作成はされず、stateの参照を移行することができます。
terraform apply後にtfstateファイルを確認すると、以下のようにローカル名が「snet-after」変更されていることがわかります。
【terraform.tfstate ※一部抜粋】
{ "mode": "managed", "type": "azurerm_subnet", "name": "snet-after", "provider": "provider[\"registry.terraform.io/hashicorp/azurerm\"]", "instances": [
おわりに
Terraformのローカル名を単純に書き換えると、Terraform は別リソースと認識し、リソースの再作成が起こってしまいます。
movedブロックを利用すれば、既存リソースを保持したまま安全にローカル名を変更可能です。
本記事が、Terraformを使用する際の参考となれば幸いです。