TerraformでAzure VMを構築する【応用編】

コンピューティングサービス

Azure環境における仮想マシン(VM)の構築は、Terraformを活用することで高い再現性と自動化が実現できます。
本記事では、VM作成の基本をマスターした方向けの“応用編”として、運用フェーズを意識した追加構成を盛り込んだTerraformコードを解説します。

🔰 基本のVM作成(リソースグループ、VNet、NIC、VM本体)についてはこちらの記事をご覧ください。

今回のTerraform構成で対応する追加設定

以下の5つの要素をTerraformで自動構成します。すべてAzureポータルで手動設定すると手間がかかるため、IaC(Infrastructure as Code)で一括管理することに大きなメリットがあります。

  • 可用性ゾーンの設定
  • 受信ポートの設定
  • 自動シャットダウン設定
  • バックアップの有効化
  • 正常性プローブ拡張機能の追加

以下が、今回ご紹介したすべての設定を盛り込んだ完成形のTerraformコードです。
必要に応じてリソース名やタイムゾーンなどを調整して、自社環境に合わせてご活用ください。

# 仮想マシン(Windows Server 2016 Datacenter)
resource "azurerm_windows_virtual_machine" "vm01" {
  name                  = "ait-vm01"
  location              = azurerm_resource_group.rg01.location
  resource_group_name   = azurerm_resource_group.rg01.name
  size                  = "Standard_B1s"
  admin_username        = "azureuser"
  admin_password        = "P@ssw0rd1234!"

  network_interface_ids = [azurerm_network_interface.vm01_nic.id]

  zone                  = "1" #可用性ゾーンの設定

  os_disk {
    name                 = "ait-vm01-osdisk"
    caching              = "ReadWrite"
    storage_account_type = "Standard_LRS"
  }

  source_image_reference {
    publisher = "MicrosoftWindowsServer"
    offer     = "WindowsServer"
    sku       = "2016-Datacenter"
    version   = "latest"
  }

  provision_vm_agent = true

# マネージド ID を有効化
  identity {
    type = "SystemAssigned"
  }
}


# パブリックIP
resource "azurerm_public_ip" "vm01_pip" {
  name                = "ait-vm01-pip"
  location            = azurerm_resource_group.rg01.location
  resource_group_name = azurerm_resource_group.rg01.name
  allocation_method   = "Static"
  sku                 = "Standard"
  zones               = ["1"] 
}

# NIC
resource "azurerm_network_interface" "vm01_nic" {
  name                = "ait-vm01-nic"
  location            = azurerm_resource_group.rg01.location
  resource_group_name = azurerm_resource_group.rg01.name

  ip_configuration {
    name                           = "internal"
    subnet_id                      = azurerm_subnet.snet01.id
    private_ip_address_allocation  = "Dynamic"
    public_ip_address_id           = azurerm_public_ip.vm01_pip.id
  }
}

# ネットワークセキュリティグループ
resource "azurerm_network_security_group" "vm01_nsg" {
  name                = "ait-vm01-nsg"
  location            = azurerm_resource_group.rg01.location
  resource_group_name = azurerm_resource_group.rg01.name
}

# RDPポート(3389)を許可する受信規則
resource "azurerm_network_security_rule" "allow_rdp" {
  name                        = "Allow-RDP"
  priority                    = 200
  direction                   = "Inbound"
  access                      = "Allow"
  protocol                    = "Tcp"
  source_port_range           = "*"
  destination_port_range      = "3389"
  source_address_prefix       = "*"
  destination_address_prefix  = "*"
  network_security_group_name = azurerm_network_security_group.vm01_nsg.name
  resource_group_name         = azurerm_resource_group.rg01.name
}

# ネットワークインターフェースにNSGを関連付け
resource "azurerm_network_interface_security_group_association" "nic_nsg_assoc" {
  network_interface_id      = azurerm_network_interface.vm01_nic.id
  network_security_group_id = azurerm_network_security_group.vm01_nsg.id
}

# 自動シャットダウン設定
resource "azurerm_dev_test_global_vm_shutdown_schedule" "vm01_shutdown" {
  virtual_machine_id = azurerm_windows_virtual_machine.vm01.id
  location           = azurerm_resource_group.rg01.location
  enabled            = true

  daily_recurrence_time = "1900"  # 19:00:00
  timezone              = "Tokyo Standard Time"

  notification_settings {
    enabled         = true
    time_in_minutes = 30
    email           = "info@ait0303.com"
  }
}

# 正常性プローブ機能の追加
resource "azurerm_virtual_machine_extension" "vm_health_monitor" {
  name                 = "ApplicationHealthExtension"
  virtual_machine_id   = azurerm_windows_virtual_machine.vm01.id
  publisher            = "Microsoft.ManagedServices"
  type                 = "ApplicationHealthWindows"
  type_handler_version = "1.0"
  auto_upgrade_minor_version = true

  settings = jsonencode({
    requestPath = "/" 
    protocol = "http"
    port     = 80
    path     = "/"
  })
}

コードの記載、下記コマンドでコードのチェック、リソースの作成を行ってください。

terraform plan
terraform apply

可用性ゾーンの設定

可用性ゾーンとは、同じリージョン内に存在する物理的に独立したデータセンター群のこと。
Azureでは、その高可用性を支える重要な機能のひとつとして 可用性ゾーン(Availability Zones) が用意されています。
例えば「東日本リージョン」にはゾーン1、ゾーン2、ゾーン3というように、3つのゾーンが存在しており、それぞれが別の建物・電源・ネットワーク設備を持っています。

以下のコマンドで可用性ゾーンを指定します。

  zone  = "1"    # ここでゾーンを指定(例: 1, 2, 3)

パブリックIPアドレスを付与している場合、パブリックIPのコードにも同様に以下を追加する必要があります。

パブリックIPアドレスのSKUがBASICだと、可用性ゾーンの設定ができません。そのため、ゾーンを設定する場合は、SKUをStandard以上にする必要があります。

  sku                 = "Standard"
  zones               = ["1"] 

受信ポートの設定

「受信ポートの規則(インバウンドポートルール)」は、仮想マシンへの外部からの通信をどのポートで許可するかを定義するネットワークセキュリティ設定です。
特にAzureでは、仮想マシン(VM)にアクセスするには、RDP(リモートデスクトップ)やSSHなどの特定ポートを開放する必要があります。

たとえば、Windowsサーバーにリモート接続するには「TCPポート 3389(RDP)」を開ける必要があります。
逆に、これらのポートを無制限に開放すると、セキュリティリスクが高まるため、必要最小限に設定することが推奨されます。

Terraformで受信ポート規則を設定する方法

受信ポートの設定は、azurerm_network_security_groupazurerm_network_security_rule リソースを使用して行います。以下は、RDP(3389番ポート)を許可するルールの例です。

# ネットワークセキュリティグループ
resource "azurerm_network_security_group" "vm01_nsg" {
  name                = "ait-vm01-nsg"
  location            = data.azurerm_resource_group.existing.location
  resource_group_name = data.azurerm_resource_group.existing.name
}

# RDPポート(3389)を許可する受信規則
resource "azurerm_network_security_rule" "allow_rdp" {
  name                        = "Allow-RDP"
  priority                    = 200
  direction                   = "Inbound"
  access                      = "Allow"
  protocol                    = "Tcp"
  source_port_range           = "*"
  destination_port_range      = "3389"
  source_address_prefix       = "*"
  destination_address_prefix  = "*"
  network_security_group_name = azurerm_network_security_group.vm01_nsg.name
  resource_group_name         = data.azurerm_resource_group.existing.name
}

# ネットワークインターフェースにNSGを関連付け
resource "azurerm_network_interface_security_group_association" "nic_nsg_assoc" {
  network_interface_id      = azurerm_network_interface.vm01_nic.id
  network_security_group_id = azurerm_network_security_group.vm01_nsg.id
}

自動シャットダウン設定

自動シャットダウンは、Azure仮想マシン(VM)を毎日指定時刻に自動停止する機能です。
これにより、開発・検証用VMなどの無駄な稼働コストを削減できます。
通知メールの設定も可能で、シャットダウン前に確認が届きます。

以下のコードを vm.tf や別ファイル(例:shutdown.tf)に追加すれば、自動シャットダウンが有効になります。

resource "azurerm_dev_test_global_vm_shutdown_schedule" "vm01_shutdown" {
  virtual_machine_id = azurerm_windows_virtual_machine.vm01.id
  location           = azurerm_resource_group.rg01.location
  enabled            = true

  daily_recurrence_time = "1900"  # 19:00:00
  timezone              = "Tokyo Standard Time"

  notification_settings {
    enabled         = true
    time_in_minutes = 30
    email           = "info@ait0303.com"
  }
}

バックアップの有効化

Azure の 仮想マシンバックアップは、VM の状態を定期的に保存し、障害や操作ミスに備えて復元できるようにする重要な保護機能です。
Recovery Services コンテナーとポリシーを使って、1日複数回のバックアップ、最大30日間の保持など柔軟な管理が可能です。
この設定により、災害時や誤削除時も、迅速に復旧できます。

以下の3つのブロックを追加しましょう。

① Recovery Services コンテナの定義

resource "azurerm_recovery_services_vault" "vault" {
  name                = "defaultVault416"
  location            = azurerm_resource_group.rg01.location
  resource_group_name = azurerm_resource_group.rg01.name
  sku                 = "Standard"
  soft_delete_enabled = true
}

② 拡張ポリシーの作成

resource "azurerm_backup_policy_vm" "policy" {
  name                = "EnhancedPolicy-majd8392"
  resource_group_name = azurerm_resource_group.rg01.name
  recovery_vault_name = azurerm_recovery_services_vault.vault.name
  policy_type         = "Enhanced"

  timezone = "Tokyo Standard Time"

  backup {
    frequency = "Daily"
    time      = "19:00"
  }

  retention_daily {
    count = 30
  }
}

③ VM をバックアップ対象に登録

resource "azurerm_backup_protected_vm" "vm_backup" {
  resource_group_name     = azurerm_resource_group.rg01.name
  recovery_vault_name     = azurerm_recovery_services_vault.vault.name
  source_vm_id            = azurerm_windows_virtual_machine.vm01.id
  backup_policy_id        = azurerm_backup_policy_vm.policy.id
}

正常性プローブ拡張機能の追加

正常性プローブ拡張機能(Application Health Extension)は、Azure 仮想マシン上で動作するアプリケーションの稼働状態を定期的にチェックするための仕組みです。
HTTP や HTTPS のプロトコルで指定したポート・パスにアクセスし、**200系の応答があれば「正常」**と判定します。

これにより、Azure 内のサービス(スケールセット、ロードバランサーなど)が、アプリケーション単位での健全性を判断できるようになります。

resource "azurerm_virtual_machine_extension" "vm_health_monitor" {
  name                 = "ApplicationHealthExtension"
  virtual_machine_id   = azurerm_windows_virtual_machine.vm01.id
  publisher            = "Microsoft.ManagedServices"
  type                 = "ApplicationHealthWindows"
  type_handler_version = "1.0"
  auto_upgrade_minor_version = true

  settings = jsonencode({
    protocol = "http"
    port     = 80
    path     = "/"
  })
}

まとめ:Terraformで運用を見据えたAzure VM構築を実現しよう

今回の記事では、Azure仮想マシンをTerraformで構築する際の「応用的な構成要素」について解説しました。
可用性ゾーンの指定から始まり、セキュリティ強化、コスト最適化、自動バックアップ、正常性監視に至るまで、本番運用を見据えた構成がコードで再現できることをご理解いただけたと思います。

Terraformを使えば、これらの設定を人の手による操作ミスなく一貫して再現可能になり、変更管理や監査にも強くなります。
一度テンプレート化しておけば、開発・検証・本番といった異なる環境にも素早く展開できるのも大きなメリットです。

今後はさらに、自動スケーリングやKey Vault連携、診断ログの有効化なども組み合わせていくことで、より完成度の高いインフラ構築が可能になります。
ぜひ本記事のコードをベースに、自社・自チームの要件に合わせて柔軟にカスタマイズしてみてください。

プロフィール
TanaT

株式会社あいてぃ所属。
クラウドエンジニア(AWS・Azure)
取得資格:AWS SAP、AZ-104、AZ-305
フロントエンド、バックエンド開発もできるフルスタックエンジニアとして学習中。
「AIとクラウドについて学ぶ」サイトの編集長。

TanaTをフォローする
コンピューティングサービス
シェアする

コメント

タイトルとURLをコピーしました