Azure PowerShell を用いてリモート接続エンドポイントのポート番号を NAT 変換した Azure VM を構築してみました

スポンサーリンク
Surface Pro 4

検証なんかで Azure 上で仮想マシン (VM) を作るとき、以下の図のような構成を基本として作成していたりします。RDP する際、VPN 接続されていない環境から直接インターネットでデフォルト ポート番号である 3389 でアクセスするのはさすがによろしくないので、ロード バランサーの NAT 変換を使用して別のポート番号に変換しています。

これまで作成自体は Azure ポータルで行っていましたが、さすがに何回も構築してくると手間がかかるということで、スクリプト化してみました。

Azure VM 構築スクリプトについて

スクリプトの大まかな流れ

スクリプトの大まかな流れは、以下のとおりです。

  1. 作成するリソースのサブスクリプションの選択 (サブスクリプションが複数ある場合)
    構築する対象のサブスクリプションを選択します。
  2. リソース グループの作成
    リソース グループを作成します。
  3. VNet の作成
    VNet と仮想マシンが接続するサブネットを作成します。
  4. ネットワーク インターフェイスの作成
    ネットワーク インターフェイスとプライベート IP アドレスを作成、プライベート IP アドレスをネットワーク インターフェイスに紐づけます。
  5. ネットワーク セキュリティ グループの作成
    ネットワーク セキュリティ グループおよびルールを作成し、ネットワーク インターフェイスに紐づけます。
  6. ストレージ アカウントの作成
    ストレージ アカウントを作成します。
  7. VM の作成
    手順 3 ~ 6 のリソースを使用して、イメージから仮想マシンを作成します。
  8. ロード バランサーの作成
    ロード バランサーとパブリック IP アドレスを作成、ロード バランサーにパブリック IP アドレスを紐づけた後、RDP で接続するポートの NAT 変換の設定を行います。
  9. DNS 名ラベルの設定
    DNS 名ラベルを設定、パブリック IP アドレスに紐づけます。

Azure VM 構築スクリプト本体


#
# リモート接続エンドポイントのポートを NAT 変換した Azure VM 構築スクリプト (Windows)
# v20170913
#

#
# 変数 (サンプル)
# 実行する環境にあわせて変数の値を変更してください
#

$sub_name = "Azure Subscription"
$rg_name = "KogeTest-RG"
$location = "japaneast"

$vm_name = "Koge-VM"
$vm_size = "Standard_A2_v2"
$vm_publisher ="MicrosoftWindowsServer"
$vm_offer = "WindowsServer"
$vm_sku = "2016-Datacenter"

$vm_ni_name = $vm_name + "-NI"
$vm_os_disk_name = $vm_name + "-OSDisk.vhd"
$vm_os_disk_caching = "ReadWrite"
$vm_ip_config_name = $vm_name + "-PrivateIPConfig"
$vm_private_ip = "192.168.10.4"

$sn_name = "ServerSubnet"
$sn_ap = "192.168.10.0/25"

$vnet_name = $rg_name + "-VNet"
$vnet_ap = "192.168.10.0/24"

$nsg_rule_name = "rdp-rule"
$rdp_port = "3389"
$nsg_name = $vm_name + "-NSG"

$st_account_name = "kogevmosstorage339"
$st_account_sku = "Standard_LRS"

$UserName = "kogekoge"
$Password = ConvertTo-SecureString "P@ssw0rd!" -Force -AsPlainText
$Credential = New-Object System.Management.Automation.PsCredential($UserName,$Password)

$elb_name = $vm_name + "-ELB"
$elb_ip_name = $elb_name + "-PIP"
$elb_fe_ip_name = $elb_name + "-FrontEnd"

$nat_rule_name = "rdp"
$nat_rdp_port = "53389"

$dom_label = "kogetest"

#
# 1. 作成するリソースのサブスクリプションの選択 (サブスクリプションが複数ある場合)
#

Select-AzureRMSubScription -SubscriptionName $sub_name

#
# 2. リソース グループの作成
#

New-AzureRmResourceGroup -Name $rg_name -Location $location

#
# 3. VNet の作成
#

$subnet = New-AzureRmVirtualNetworkSubnetConfig -Name $sn_name -AddressPrefix $sn_ap
$vnet = New-AzureRmVirtualNetwork -Name $vnet_name -ResourceGroupName $rg_name `
	-Location $location -AddressPrefix $vnet_ap -Subnet $subnet

#
# 4. ネットワーク インターフェイスの作成
#

$ni_subnet = Get-AzureRmVirtualNetworkSubnetConfig -Name $sn_name -VirtualNetwork $vnet
$vm_IPconfig = New-AzureRmNetworkInterfaceIpConfig -Name $vm_ip_config_name `
	-PrivateIpAddressVersion IPv4 -PrivateIpAddress $vm_private_ip -subnet $ni_subnet
$vm_ni = New-AzureRmNetworkInterface -Name $vm_ni_name -ResourceGroupName $rg_name `
	-Location $location -IpConfiguration $vm_IPconfig

#
# 5. ネットワーク セキュリティ グループの作成
#

$nsg_rule = New-AzureRmNetworkSecurityRuleConfig -Name $nsg_rule_name -Access Allow `
	-Protocol Tcp -Direction Inbound -Priority 100 -SourceAddressPrefix Internet `
	-SourcePortRange * -DestinationAddressPrefix * -DestinationPortRange $rdp_port
$nsg = New-AzureRmNetworkSecurityGroup -ResourceGroupName $rg_name -Location $location `
	-Name $nsg_name -SecurityRules $nsg_rule
$vm_ni.NetworkSecurityGroup = $nsg
$vm_ni = Set-AzureRmNetworkInterface -NetworkInterface $vm_ni

#
# 6. ストレージ アカウントの作成
#

$st_account = New-AzureRmStorageAccount -Name $st_account_name -ResourceGroupName $rg_name `
	-Location $location -SkuName $st_account_sku -Kind "Storage"
$st_vhd_uri = $st_account.PrimaryEndpoints.Blob.ToString() + "vhds/" + $vm_os_disk_name

#
# 7. VM の作成
#

$vm_Config = New-AzureRmVMConfig -VMName $vm_name -VMSize $vm_size
$vm_Config = Set-AzureRmVMOperatingSystem -VM $vm_Config -ComputerName $vm_name -Windows `
	-Credential $Credential -ProvisionVMAgent -EnableAutoUpdate
$vm_Config = Set-AzureRmVMSourceImage -VM $vm_Config -PublisherName $vm_publisher -Offer `
	$vm_offer -Skus $vm_sku -Version "latest"
$vm_Config = Add-AzureRmVMNetworkInterface -VM $vm_Config -Id $vm_ni.Id
$vm_Config = Set-AzureRmVMOSDisk -VM $vm_Config -Name $vm_os_disk_name -VhdUri $st_vhd_uri `
	-Caching $vm_os_disk_caching -CreateOption "FromImage" -Windows
New-AzureRmVM -ResourceGroupName $rg_name -Location $location -VM $vm_Config -Verbose

#
# 8. ロード バランサーの作成
#

$elb_IPconfig = New-AzureRmPublicIpAddress -Name $elb_ip_name -ResourceGroupName $rg_name `
	-Location $location -AllocationMethod "Dynamic"
$elb_fe_IPconfig = New-AzureRmLoadBalancerFrontendIpConfig -Name $elb_fe_ip_name `
	-PublicIpAddress $elb_IPconfig
$elb = New-AzureRmLoadBalancer -Name $elb_name -ResourceGroupName $rg_name `
	-Location $location -FrontendIpConfiguration $elb_fe_IPconfig

$nat_rule = New-AzureRmLoadBalancerInboundNatRuleConfig -Name $nat_rule_name -Protocol TCP `
	-FrontendIpConfiguration $elb_fe_IPconfig -FrontendPort $nat_rdp_port -BackendPort $rdp_port
$elb.InboundNatRules = $nat_rule
$elb = Set-AzureRmLoadBalancer -LoadBalancer $elb
$vm_ni.IpConfigurations[0].LoadBalancerBackendAddressPools = $elb.BackendAddressPools
$vm_ni.IpConfigurations[0].LoadBalancerInboundNatRules = $elb.InboundNatRules
Set-AzureRmNetworkInterface -NetworkInterface $vm_ni

#
# 9. DNS 名ラベルの設定
#

$dns_setting = New-object Microsoft.Azure.Commands.Network.Models.PSPublicIpAddressDnsSettings
$dns_setting.DomainNameLabel = $dom_label
$elb_IPconfig = Get-AzureRmPublicIpAddress -Name $elb_ip_name -ResourceGroupName $rg_name
$elb_IPconfig.DnsSettings = $dns_setting
Set-AzureRmPublicIpAddress -PublicIpAddress $elb_IPconfig

スクリプトの実行結果について

スクリプトの実行後、Azure ポータル上からは作成できていることを確認できています。

補足

アカウントに紐付いているサブスクリプション名一覧を取得する

Get-AzureRMSubscription | Select Name

リージョン一覧を取得する

Get-AzureRmLocation | Select Location

リージョンに対するパブリッシャー一覧を取得する

※変数 $location は任意のリージョン名を指定

$location = "<リージョン名>"
Get-AzureRMVMImagePublisher -Location $location | Select PublisherName

リージョンに対する VM サイズ一覧を取得する

※変数 $location は任意のリージョン名を指定

$location = "<リージョン名>"
Get-AzureRMVMSize -Location $location | Select Name

リージョン、パブリッシャーに対するオファー一覧を取得する

※変数 $location、$publisher は任意のリージョン名、パブリッシャー名をそれぞれ指定

$location = "<リージョン名>"
$publisher = "<パブリッシャー名>"
Get-AzureRMVMImageOffer -Location $location -Publisher $publisher | Select Offer

リージョン、パブリッシャー、オファーに対する SKU 一覧を取得する

※変数 $location、$publisher、$offer は任意のリージョン名、パブリッシャー名、オファー名をそれぞれ指定

$location = "<リージョン名>"
$publisher = "<パブリッシャー名>"
$offer = "<オファー名>"
Get-AzureRMVMImageSku -Location $location -Publisher $publisher -Offer $offer | Select Skus

スクリプト作成にあたり参考にしたサイト

スクリプト作成にあたり、参考にしたサイトは以下となります。

参考