TerraformでAzureにVM構築&RDP接続設定を行う

に公開

はじめに

この記事では、Terraformを使ってAzureにWindowsVMを作成する方法と、RDP接続を有効にする方法を紹介します。本記事は以下の人を対象にしています。

  • AzureでのVM構築とRDP接続のやり方を知りたい人
  • TerraformでAzureにリソース作成をしたい人

RDP接続する方法

AzureでWindowsVMを作成しただけでは、RDP接続をすることはできません。以下の設定やリソースが必要になります。

  • Network Security Group(NSG)を作成して、宛先ポート3389(RDP)に対して受信を許可する。また、NSGをサブネットかネットワークインターフェース(NIC)に割り当てる。
  • パブリックIPアドレスを作成して、NICに割り当てる。

Azure Portalから仮想マシンを作成すると、RDP接続を有効にしますか?みたいな設定があり、NSGなど他のリソースも自動で作成してくれるので、RDP接続ができる状態でVMが作成されます。しかし、Terraformでリソースを作成する場合は、VM以外のリソースも明示的に作成する必要があります。個人的にはここがTerraformでつまづきやすいポイントの1つだと思っています。

作成するリソース

Terraformで以下のリソースを作成します。

  • リソースグループ
  • 仮想ネットワーク
  • サブネット
  • パブリックIPアドレス
  • NSG (送受信規則や割り当ても作成)
  • ネットワークインターフェース
  • 仮想マシン

コード

以下のコードをprovider.tfとmain.tfにそれぞれ記述します。

provider.tf
terraform {
  required_version = ">=1.0"
  
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~>4.0"
    }
  }
}

provider "azurerm" {
  # ここに作成先のサブスクリプションIDを入力
  subscription_id = "12345678-aaaa-bbbb-cccc-123456789012"
  
  features {
  
  }
}
main.tf
# リソースグループ
resource "azurerm_resource_group" "sample_rg" {
  name     = "sample-tf-rg"
  location = "japaneast"
}

# 仮想ネットワーク
resource "azurerm_virtual_network" "sample_vnet" {
  name                = "sample-vnet"
  location            = azurerm_resource_group.sample_rg.location
  resource_group_name = azurerm_resource_group.sample_rg.name
  address_space       = [ "10.110.0.0/17" ]
}

# サブネット
resource "azurerm_subnet" "sample_subnet" {
  name                 = "sample-subnet"
  resource_group_name  = azurerm_resource_group.sample_rg.name
  virtual_network_name = azurerm_virtual_network.sample_vnet.name
  address_space        = [ "10.110.11.0/24" ]
}

# パブリックIPアドレス
resource "azurerm_public_ip" "sample_pip" {
  name                 = "sample-public-ip"
  location             = azurerm_resource_group.sample_rg.location
  resource_group_name  = azurerm_resource_group.sample_rg.name
  allocation_method    = "Static"
}

# NSG
resource "azurerm_network_security_group" "sample_nsg" {
  name                 = "sample-nsg"
  location             = azurerm_resource_group.sample_rg.location
  resource_group_name  = azurerm_resource_group.sample_rg.name
}

# NSG 送受信規則
resource "azurerm_network_security_rule" "sample_nsg_rule" {
  name                        = "RDP-allow"
  resource_group_name         = azurerm_resource_group.sample_rg.name
  network_security_group_name = azurerm_network_security_group.sample_nsg.name
  priority                    = "300"
  direction                   = "Inbound"
  access                      = "Allow"
  protocol                    = "Tcp"
  source_port_range           = "*"
  destination_port_range      = "3389"
  source_address_prefix       = "*"
  destination_address_prefix  = "*"
}

# NSG サブネット割り当て
resource "azurerm_subnet_network_security_group_association" "nsg_to_subnet" {
  network_security_group_id = azurerm_network_security_group.sample_nsg.id
  subnet_id                 = azurerm_subnet.sample_subnet.id
}

# ネットワークインターフェース
resource "azurerm_network_interface" "sample_nic" {
  name                 = "sample-nic"
  resource_group_name  = azurerm_resource_group.sample_rg.name
  location             = azurerm_resource_group.sample_rg.location

  ip_congiguration {
    name                          = "ipconfig"
    private_ip_address_allocation = "Static"
    subnet_id                     = azurerm_subnet.sample_subnet.id
    private_ip_address            = "10.110.11.12"
    public_ip_address_id          = azurerm_public_ip.sample_pip.id
  }
}

# 仮想マシン
resource "azurerm_windows_virtual_machine" "sample_vm" {
  name                  = "sample-vm"
  resource_group_name   = azurerm_resource_group.sample_rg.name
  location              = azurerm_resource_group.sample_rg.location
  size                  = "Standard_D2s_v5"
  admin_username        = "localadmin"
  admin_password        = "Pass378Zenn!"
  network_interface_ids = [ azurerm_network_interface.sample_nic.id ]

  os_disk {
    name                 = "sample-OS-Disk"
    caching              = "ReadWrite"
    storage_account_type = "Premium_LRS"
  }

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

Portalで作成するときは自動で有効になっている項目も、Terraformで作成するときは無効になっている項目があります。
例えば、VMのトラステッド起動はPortalから作成するときは既定で有効ですが、Terraformでは指定しない場合は無効になります。設定したい項目については、公式ドキュメントを見るとよいでしょう。
https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/windows_virtual_machine

コードの実行

以下のコマンドをPowerShellから実行して、Azureにリソースを作成します。こちらの記事も参考に。
https://zenn.dev/dainamit2025/articles/6ecaf4bea0c2e1

  • Terraformの初期化を実行
terraform init -upgrade
  • リソース作成の計画を作成
terraform plan -out main.tfplan
  • リソース作成の適用
terraform apply main.tfplan

RDP接続のやり方

こちらのMicrosoft Learnの記事も参考に。
https://learn.microsoft.com/ja-jp/azure/virtual-machines/windows/connect-rdp

Portalから対象VMのRDPファイルをダウンロードして開いて、ユーザ名とパスワードを入れてVMに接続します。ユーザ名をいれてうまくいかない場合は、ユーザ名を"localuser\ユーザ名"とすれば接続できるかと思います。

おわりに

最後までご覧いただきありがとうございます!この記事では、Terraformを使って、Azure上にVM構築とRDP接続ができるように設定しました。今回は基本的なVM構築のやり方を紹介しましたが、ディスクのアタッチや詳細なVMの設定などのやり方も、今後まとめようと考えています。

Discussion