Terraform Export from the Azure Portalを試してみた

AzureリソースをAzure Portal上からTerraform定義ファイルでエクスポート可能な機能が発表されました。

techcommunity.microsoft.com

今回は本機能を試してみようと思います。

Terraform Export from the Azure Portalとは

Terraform Export from the Azure Portalとは、既存のAzureリソースをAzure PortalよりTerraform定義ファイルにエクスポート可能な機能です。

現在はAzureRM、AzureAPIにて定義ファイルをエクスポート可能です。

試してみる

事前準備

リソースプロバイダーを登録する

事前にサブスクリプションに「Microsoft.AzureTerraform」リソースプロバイダーを登録します。

  1. 対象のサブスクリプション、左ペイン[設定] > [リソース プロバイダー]を選択する。

  2. 「Microsoft.AzureTerraform」を選択し、上部の[登録]をクリックする。

    リソースプロバイダー登録(1)

  3. 状態が「registered」と表示されることを確認する。

    リソースプロバイダー登録(2)

事前準備

今回エクスポートするリソース

今回は以下リソースをエクスポートします。

  • リソースグループ
  • Network Security Group
  • 仮想ネットワーク
  • 仮想マシン
  • パブリックIPアドレス
  • ネットワークインターフェイス
  • ディスク
    エクスポートリソース
エクスポートする

実際にリソースをTerraform定義ファイルにエクスポートしていきます。

※今回はAzureRMにてエクスポートします。

  1. Azure Portalにて対象のリソースグループを選択し、[オートメーション] > [テンプレートのエクスポート]を選択する。

  2. [Terraform]タブにて、[AzureRM]を選択し、上部の[ダウンロード]をクリックする。

    テンプレートのエクスポート
    上記の手順でダウンロードされた定義ファイルは以下です。

【main.tf】

terraform {
  required_providers {
    azurerm = {
      source  = "azurerm"
      version = "4.24.0"
    }
  }
}
provider "azurerm" {
  features {}
}
resource "azurerm_resource_group" "res-0" {
  location   = "japaneast"
  managed_by = ""
  name       = "nishiyamas-tf-rg"
  tags = {
    Owner = "<Owner>"
  }
}
resource "azurerm_windows_virtual_machine" "res-1" {
  admin_password                                         = "" # Masked sensitive attribute
  admin_username                                         = "<ユーザ名>"
  allow_extension_operations                             = true
  availability_set_id                                    = ""
  bypass_platform_safety_checks_on_user_schedule_enabled = false
  capacity_reservation_group_id                          = ""
  computer_name                                          = "nsymtfvm01"
  custom_data                                            = "" # Masked sensitive attribute
  dedicated_host_group_id                                = ""
  dedicated_host_id                                      = ""
  disk_controller_type                                   = "SCSI"
  edge_zone                                              = ""
  enable_automatic_updates                               = true
  encryption_at_host_enabled                             = false
  eviction_policy                                        = ""
  extensions_time_budget                                 = "PT1H30M"
  hotpatching_enabled                                    = false
  license_type                                           = ""
  location                                               = "japaneast"
  max_bid_price                                          = -1
  name                                                   = "nsymtfvm01"
  network_interface_ids                                  = ["/subscriptions/<サブスクリプションID>/resourceGroups/nishiyamas-tf-rg/providers/Microsoft.Network/networkInterfaces/nsymtfvm01270"]
  patch_assessment_mode                                  = "ImageDefault"
  patch_mode                                             = "AutomaticByOS"
  platform_fault_domain                                  = -1
  priority                                               = "Regular"
  provision_vm_agent                                     = true
  proximity_placement_group_id                           = ""
  reboot_setting                                         = ""
  resource_group_name                                    = "nishiyamas-tf-rg"
  secure_boot_enabled                                    = true
  size                                                   = "Standard_B2ms"
  source_image_id                                        = ""
  tags = {
    Owner = "<Owner>"
  }
  timezone                          = ""
  user_data                         = ""
  virtual_machine_scale_set_id      = ""
  vm_agent_platform_updates_enabled = true
  vtpm_enabled                      = true
  zone                              = ""
  additional_capabilities {
    hibernation_enabled = false
    ultra_ssd_enabled   = false
  }
  boot_diagnostics {
    storage_account_uri = ""
  }
  identity {
    identity_ids = []
    type         = "SystemAssigned"
  }
  os_disk {
    caching                          = "ReadWrite"
    disk_encryption_set_id           = ""
    disk_size_gb                     = 127
    name                             = "nsymtfvm01_OsDisk_1_587090eb77804668bffe32e5edcaf45d"
    secure_vm_disk_encryption_set_id = ""
    security_encryption_type         = ""
    storage_account_type             = "Standard_LRS"
    write_accelerator_enabled        = false
  }
  source_image_reference {
    offer     = "WindowsServer"
    publisher = "MicrosoftWindowsServer"
    sku       = "2025-datacenter-g2"
    version   = "latest"
  }
  depends_on = [
    azurerm_network_interface.res-4,
  ]
}
resource "azurerm_virtual_machine_extension" "res-2" {
  auto_upgrade_minor_version  = true
  automatic_upgrade_enabled   = true
  failure_suppression_enabled = false
  name                        = "AzurePolicyforWindows"
  protected_settings          = "" # Masked sensitive attribute
  provision_after_extensions  = []
  publisher                   = "Microsoft.GuestConfiguration"
  settings                    = jsonencode({})
  tags = {
    Owner = "<Owner>"
  }
  type                 = "ConfigurationforWindows"
  type_handler_version = "1.1"
  virtual_machine_id   = "/subscriptions/<サブスクリプションID>/resourceGroups/nishiyamas-tf-rg/providers/Microsoft.Compute/virtualMachines/nsymtfvm01"
  depends_on = [
    azurerm_windows_virtual_machine.res-1,
  ]
}
resource "azurerm_dev_test_global_vm_shutdown_schedule" "res-3" {
  daily_recurrence_time = "1900"
  enabled               = true
  location              = "japaneast"
  tags = {
    Owner = "<Owner>"
  }
  timezone           = "Tokyo Standard Time"
  virtual_machine_id = "/subscriptions/<サブスクリプションID>/resourceGroups/nishiyamas-tf-rg/providers/Microsoft.Compute/virtualMachines/nsymtfvm01"
  notification_settings {
    email           = "<メールアドレス>"
    enabled         = true
    time_in_minutes = 30
    webhook_url     = ""
  }
  depends_on = [
    azurerm_windows_virtual_machine.res-1,
  ]
}
resource "azurerm_network_interface" "res-4" {
  accelerated_networking_enabled = false
  auxiliary_mode                 = ""
  auxiliary_sku                  = ""
  dns_servers                    = []
  edge_zone                      = ""
  internal_dns_name_label        = ""
  ip_forwarding_enabled          = false
  location                       = "japaneast"
  name                           = "nsymtfvm01270"
  resource_group_name            = "nishiyamas-tf-rg"
  tags = {
    Owner = "<Owner>"
  }
  ip_configuration {
    gateway_load_balancer_frontend_ip_configuration_id = ""
    name                                               = "ipconfig1"
    primary                                            = true
    private_ip_address                                 = "10.0.0.4"
    private_ip_address_allocation                      = "Dynamic"
    private_ip_address_version                         = "IPv4"
    public_ip_address_id                               = "/subscriptions/<サブスクリプションID>/resourceGroups/nishiyamas-tf-rg/providers/Microsoft.Network/publicIPAddresses/nsymtfvm01-ip"
    subnet_id                                          = "/subscriptions/<サブスクリプションID>/resourceGroups/nishiyamas-tf-rg/providers/Microsoft.Network/virtualNetworks/nishiyamas-tf-vnet01/subnets/snet-vm01"
  }
  depends_on = [
    azurerm_public_ip.res-7,
    # One of azurerm_subnet.res-9,azurerm_subnet_network_security_group_association.res-10 (can't auto-resolve as their ids are identical)
  ]
}
resource "azurerm_network_security_group" "res-5" {
  location            = "japaneast"
  name                = "nishiyamas-tf-nsg01"
  resource_group_name = "nishiyamas-tf-rg"
  security_rule = [{
    access                                     = "Allow"
    description                                = ""
    destination_address_prefix                 = "*"
    destination_address_prefixes               = []
    destination_application_security_group_ids = []
    destination_port_range                     = "3389"
    destination_port_ranges                    = []
    direction                                  = "Inbound"
    name                                       = "AllowRDPInbound"
    priority                                   = 100
    protocol                                   = "Tcp"
    source_address_prefix                      = "<ソースIPアドレス>"
    source_address_prefixes                    = []
    source_application_security_group_ids      = []
    source_port_range                          = "*"
    source_port_ranges                         = []
  }]
  tags = {
    Owner = "<Owner>"
  }
  depends_on = [
    azurerm_resource_group.res-0,
  ]
}
resource "azurerm_network_security_rule" "res-6" {
  access                                     = "Allow"
  description                                = ""
  destination_address_prefix                 = "*"
  destination_address_prefixes               = []
  destination_application_security_group_ids = []
  destination_port_range                     = "3389"
  destination_port_ranges                    = []
  direction                                  = "Inbound"
  name                                       = "AllowRDPInbound"
  network_security_group_name                = "nishiyamas-tf-nsg01"
  priority                                   = 100
  protocol                                   = "Tcp"
  resource_group_name                        = "nishiyamas-tf-rg"
  source_address_prefix                      = "<ソースIPアドレス>"
  source_address_prefixes                    = []
  source_application_security_group_ids      = []
  source_port_range                          = "*"
  source_port_ranges                         = []
  depends_on = [
    azurerm_network_security_group.res-5,
  ]
}
resource "azurerm_public_ip" "res-7" {
  allocation_method       = "Static"
  ddos_protection_mode    = "VirtualNetworkInherited"
  edge_zone               = ""
  idle_timeout_in_minutes = 4
  ip_tags                 = {}
  ip_version              = "IPv4"
  location                = "japaneast"
  name                    = "nsymtfvm01-ip"
  resource_group_name     = "nishiyamas-tf-rg"
  sku                     = "Standard"
  sku_tier                = "Regional"
  tags = {
    Owner = "<Owner>"
  }
  zones = []
  depends_on = [
    azurerm_resource_group.res-0,
  ]
}
resource "azurerm_virtual_network" "res-8" {
  address_space                  = ["10.0.0.0/16"]
  bgp_community                  = ""
  dns_servers                    = []
  edge_zone                      = ""
  flow_timeout_in_minutes        = 0
  location                       = "japaneast"
  name                           = "nishiyamas-tf-vnet01"
  private_endpoint_vnet_policies = "Disabled"
  resource_group_name            = "nishiyamas-tf-rg"
  subnet = [{
    address_prefixes                              = ["10.0.0.0/24"]
    default_outbound_access_enabled               = false
    delegation                                    = []
    id                                            = "/subscriptions/<ソースIPアドレス>/resourceGroups/nishiyamas-tf-rg/providers/Microsoft.Network/virtualNetworks/nishiyamas-tf-vnet01/subnets/snet-vm01"
    name                                          = "snet-vm01"
    private_endpoint_network_policies             = "Disabled"
    private_link_service_network_policies_enabled = true
    route_table_id                                = ""
    security_group                                = "/subscriptions/<ソースIPアドレス>/resourceGroups/nishiyamas-tf-rg/providers/Microsoft.Network/networkSecurityGroups/nishiyamas-tf-nsg01"
    service_endpoint_policy_ids                   = []
    service_endpoints                             = []
  }]
  tags = {
    Owner = "<Owner>"
  }
  depends_on = [
    azurerm_network_security_group.res-5,
    azurerm_subnet_network_security_group_association.res-10,
  ]
}
resource "azurerm_subnet" "res-9" {
  address_prefixes                              = ["10.0.0.0/24"]
  default_outbound_access_enabled               = true
  name                                          = "snet-vm01"
  private_endpoint_network_policies             = "Disabled"
  private_link_service_network_policies_enabled = true
  resource_group_name                           = "nishiyamas-tf-rg"
  service_endpoint_policy_ids                   = []
  service_endpoints                             = []
  virtual_network_name                          = "nishiyamas-tf-vnet01"
  depends_on = [
    azurerm_virtual_network.res-8,
  ]
}
resource "azurerm_subnet_network_security_group_association" "res-10" {
  network_security_group_id = "/subscriptions/<ソースIPアドレス>/resourceGroups/nishiyamas-tf-rg/providers/Microsoft.Network/networkSecurityGroups/nishiyamas-tf-nsg01"
  subnet_id                 = "/subscriptions/<ソースIPアドレス>/resourceGroups/nishiyamas-tf-rg/providers/Microsoft.Network/virtualNetworks/nishiyamas-tf-vnet01/subnets/snet-vm01"
  depends_on = [
    azurerm_network_security_group.res-5,
    azurerm_subnet.res-9,
  ]
}

エクスポートした定義ファイルにて新規リソースを作成する

今回はエクスポートした定義ファイルより、既存リソースとは別で新規リソース作成をしてみます。

定義ファイルを修正する

エクスポートした定義ファイルより各リソース名や、パスワード情報、依存関係を更新、不要箇所の削除をします。

※エクスポートされた定義ファイルをそのままの利用するとCycleエラー等が発生しました。

Cycleエラー

今回は以下の形に更新をかけました。
【main.tf】

terraform {
  required_providers {
    azurerm = {
      source  = "azurerm"
      version = "4.24.0"
    }
  }
}
provider "azurerm" {
  features {}
  subscription_id = "<サブスクリプションID>"
  tenant_id       = "<テナントID>"
}
resource "azurerm_resource_group" "res-0" {
  location = "japaneast"
  name = "nishiyamas-tf-new-rg"
  tags = {
    Owner = "<Owner>"
  }
}
resource "azurerm_windows_virtual_machine" "res-1" {
  admin_password             = "<パスワード>"
  admin_username             = "<ユーザ名>"
  allow_extension_operations = true
  bypass_platform_safety_checks_on_user_schedule_enabled = false
  computer_name = "nsymtfnewvm01"
  disk_controller_type = "SCSI"
  enable_automatic_updates   = true
  encryption_at_host_enabled = false
  extensions_time_budget = "PT1H30M"
  hotpatching_enabled    = false
  location              = "japaneast"
  max_bid_price         = -1
  name                  = "nsymtfnewvm01"
  network_interface_ids = ["/subscriptions/<サブスクリプションID>/resourceGroups/nishiyamas-tf-new-rg/providers/Microsoft.Network/networkInterfaces/nsymtfnewvm01270"]
  patch_assessment_mode = "ImageDefault"
  patch_mode            = "AutomaticByOS"
  priority           = "Regular"
  provision_vm_agent = true
  resource_group_name = "nishiyamas-tf-new-rg"
  secure_boot_enabled = true
  size                = "Standard_B2ms"
  tags = {
    Owner = "<Owner>"
  }
  vm_agent_platform_updates_enabled = true
  vtpm_enabled                      = true
  additional_capabilities {
    hibernation_enabled = false
    ultra_ssd_enabled   = false
  }
  identity {
    type = "SystemAssigned"
  }
  os_disk {
    caching = "ReadWrite"
    disk_size_gb = 127
    name         = "nsymtfnewvm01_OsDisk_1_587090eb77804668bffe32e5edcaf45d"
    storage_account_type      = "Standard_LRS"
    write_accelerator_enabled = false
  }
  source_image_reference {
    offer     = "WindowsServer"
    publisher = "MicrosoftWindowsServer"
    sku       = "2025-datacenter-g2"
    version   = "latest"
  }
  depends_on = [
    azurerm_network_interface.res-4,
  ]
}
resource "azurerm_virtual_machine_extension" "res-2" {
  auto_upgrade_minor_version  = true
  automatic_upgrade_enabled   = true
  failure_suppression_enabled = false
  name                        = "AzurePolicyforWindows"
  protected_settings          = ""
  publisher = "Microsoft.GuestConfiguration"
  settings  = jsonencode({})
  tags = {
    Owner = "<Owner>"
  }
  type                 = "ConfigurationforWindows"
  type_handler_version = "1.1"
  virtual_machine_id   = "/subscriptions/<サブスクリプションID>/resourceGroups/nishiyamas-tf-new-rg/providers/Microsoft.Compute/virtualMachines/nsymtfnewvm01"
  depends_on = [
    azurerm_windows_virtual_machine.res-1,
  ]
}
resource "azurerm_dev_test_global_vm_shutdown_schedule" "res-3" {
  daily_recurrence_time = "1900"
  enabled               = true
  location              = "japaneast"
  tags = {
    Owner = "<Owner>"
  }
  timezone           = "Tokyo Standard Time"
  virtual_machine_id = "/subscriptions/<サブスクリプションID>/resourceGroups/nishiyamas-tf-new-rg/providers/Microsoft.Compute/virtualMachines/nsymtfnewvm01"
  notification_settings {
    email           = "<メールアドレス>"
    enabled         = true
    time_in_minutes = 30
  }
  depends_on = [
    azurerm_windows_virtual_machine.res-1,
  ]
}
resource "azurerm_network_interface" "res-4" {
  accelerated_networking_enabled = false
  ip_forwarding_enabled = false
  location              = "japaneast"
  name                  = "nsymtfnewvm01270"
  resource_group_name   = "nishiyamas-tf-new-rg"
  tags = {
    Owner = "<Owner>"
  }
  ip_configuration {
    name                          = "ipconfig1"
    primary                       = true
    private_ip_address            = "10.0.0.4"
    private_ip_address_allocation = "Dynamic"
    private_ip_address_version    = "IPv4"
    public_ip_address_id          = "/subscriptions/<サブスクリプションID>/resourceGroups/nishiyamas-tf-new-rg/providers/Microsoft.Network/publicIPAddresses/nsymtfnewvm01-ip"
    subnet_id                     = "/subscriptions/<サブスクリプションID>/resourceGroups/nishiyamas-tf-new-rg/providers/Microsoft.Network/virtualNetworks/nishiyamas-tf-new-vnet01/subnets/snet-vm01"
  }
  depends_on = [
    azurerm_public_ip.res-7,
    azurerm_subnet.res-9,
  ]
}
resource "azurerm_network_security_group" "res-5" {
  location            = "japaneast"
  name                = "nishiyamas-tf-new-nsg01"
  resource_group_name = "nishiyamas-tf-new-rg"
  tags = {
    Owner = "<Owner>"
  }
  depends_on = [
    azurerm_resource_group.res-0,
  ]
}
resource "azurerm_network_security_rule" "res-6" {
  access = "Allow"
  destination_address_prefix = "*"
  destination_port_range = "3389"
  direction                   = "Inbound"
  name                        = "AllowRDPInbound"
  network_security_group_name = "nishiyamas-tf-new-nsg01"
  priority                    = 100
  protocol                    = "Tcp"
  resource_group_name         = "nishiyamas-tf-new-rg"
  source_address_prefix       = "147.161.196.246"
  source_port_range = "*"
  depends_on = [
    azurerm_network_security_group.res-5,
  ]
}
resource "azurerm_public_ip" "res-7" {
  allocation_method    = "Static"
  ddos_protection_mode = "VirtualNetworkInherited"
  idle_timeout_in_minutes = 4
  ip_version          = "IPv4"
  location            = "japaneast"
  name                = "nsymtfnewvm01-ip"
  resource_group_name = "nishiyamas-tf-new-rg"
  sku                 = "Standard"
  sku_tier            = "Regional"
  tags = {
    Owner = "<Owner>"
  }
  zones = []
  depends_on = [
    azurerm_resource_group.res-0,
  ]
}
resource "azurerm_virtual_network" "res-8" {
  address_space = ["10.0.0.0/16"]
  location                       = "japaneast"
  name                           = "nishiyamas-tf-new-vnet01"
  private_endpoint_vnet_policies = "Disabled"
  resource_group_name            = "nishiyamas-tf-new-rg"
  tags = {
    Owner = "<Owner>"
  }
  depends_on = [
    azurerm_resource_group.res-0,
  ]
}
resource "azurerm_subnet" "res-9" {
  address_prefixes                              = ["10.0.0.0/24"]
  default_outbound_access_enabled               = true
  name                                          = "snet-vm01"
  private_endpoint_network_policies             = "Disabled"
  private_link_service_network_policies_enabled = true
  resource_group_name                           = "nishiyamas-tf-new-rg"
  service_endpoint_policy_ids                   = []
  virtual_network_name                          = "nishiyamas-tf-new-vnet01"
  depends_on = [
    azurerm_virtual_network.res-8,
  ]
}
resource "azurerm_subnet_network_security_group_association" "res-10" {
  network_security_group_id = "/subscriptions/<サブスクリプションID>/resourceGroups/nishiyamas-tf-new-rg/providers/Microsoft.Network/networkSecurityGroups/nishiyamas-tf-new-nsg01"
  subnet_id                 = "/subscriptions/<サブスクリプションID>/resourceGroups/nishiyamas-tf-new-rg/providers/Microsoft.Network/virtualNetworks/nishiyamas-tf-new-vnet01/subnets/snet-vm01"
  depends_on = [
    azurerm_network_security_group.res-5,
    azurerm_subnet.res-9,
  ]
}
Terraformを実行する

Terraformを実行していきます。 実行コマンドについては以下URLの「Terraformコマンドの実行」をご参照ください。 blog.jbs.co.jp

作成されたリソースを確認する

作成されたリソースを確認します。 リソース名が変更されたリソースが作成されていることが確認できます。

作成リソース

おわりに

本記事を最後までお読みいただき、ありがとうございます。

本記事がTerraformを使用する際の参考となれば幸いです。

執筆担当者プロフィール
西山 正太郎

西山 正太郎(日本ビジネスシステムズ株式会社)

クラウドソリューション事業本部に所属。近年は業務で主にMicrosoft Azureに携わっています。山登りが趣味です。

担当記事一覧