Arc Jumpstart は Azure Arc 環境のテスト環境を簡単に作成することができます
勉強がてら Bicep の Azure Verified Module に書き換えつつ、中身をのぞいてみます
今回は Azure VM を Azure Arc 対応サーバーにするシナリオです
Azure Arc Jumpstart
Windows 編
勉強対象の ARM Template は azure_arc/azure_arc_servers_jumpstart/azure/windows/arm_template at main · microsoft/azure_arc です
基にするファイル構成
このような構成になっています
ファイル名 |
説明 |
azuredeploy.json |
テンプレート本体 |
azuredeploy.parameters.json |
パラメータファイル |
scripts/install_arc_agent.ps1 |
Connected Machine Agent (Azure Arc のエージェント) のインストールスクリプト |
azuredeploy.json を Azure Verified Module に書き換えることにします
Connected Machine Agent のインストールスクリプトはサービスプリンシパルを利用しています
個人的に使いずらいのでデバイスコードを使ったインストール方法に変更します
Azure Verified Module に書き換える
azuredeploy.json を ARM Tepmlate から Bicep へ逆コンパイルをします
やり方は ARM テンプレート JSON を Bicep に逆コンパイルする - Azure Resource Manager | Microsoft Learn に記載があります
今回は Visual Studio Code を使用して Bicep ファイルを作成する - Azure Resource Manager | Microsoft Learn に書かれている Visual Studio Code の拡張機能を使った方法を取りました
コンパイル結果は割愛しますが、以下のリソースが含まれています
- NIC (Microsoft.Network/networkInterfaces)
- NSG (Microsoft.Network/networkSecurityGroups)
- NSG rule (Microsoft.Network/networkSecurityGroups/securityRules)
- Vnet (Microsoft.Network/virtualNetworks)
- Public IP (Microsoft.Network/publicIPAddresses)
- VM (Microsoft.Compute/virtualMachines)
- VM Extension (Microsoft.Compute/virtualMachines/extensions)
- Bastion Host (Microsoft.Network/bastionHosts)
コンパイル結果を参考にして、Azure Verified Module で書き換えました
モジュールを使っているので非常にスッキリしています
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
|
@description('すべてのリソースに共通する接頭語です')
param prefix string
@description('リソースの場所')
param location string = resourceGroup().location
@description('Azure Arc 対応サーバーのユーザー名')
param vmUserName string = 'AzureAdmin'
@description('Azure Arc 対応サーバーのパスワード')
@secure()
param vmPassword string
@description('VM のサイズ')
param vmSize string = 'Standard_D4s_v3'
@allowed([
'no'
'yes'
])
@description('Bastion をデプロイするかどうか')
param deployBastion string = 'no'
@description('Azure Arc の接続にデバイスコードを利用するかどうか。false の場合、サービスプリンシパルを利用')
param useDeviceCode bool = true
@description('サービス プリンシパルの ID。デバイスコードを利用する場合はスルー')
param appId string
@description('サービス プリンシパルの シークレット。デバイスコードを利用する場合は適当に埋める')
@secure()
param appSecret string
@description('Vnet のアドレス空間')
param vnetAdressPrefix string = '10.0.0.0/16'
var tenantId = subscription().tenantId
var subscriptionId = subscription().subscriptionId
var resourceGroupName = resourceGroup().name
var nicIpConfigurations = {
// Bastion を使わない場合、VM に Public IP を割り当てる
no: {
name: '${prefix}-ipconfig'
subnetResourceId: vnet.outputs.subnetResourceIds[0]
pipConfiguration: {
name: '${prefix}-pip'
}
}
yes: {
name: '${prefix}-ipconfig'
subnetResourceId: vnet.outputs.subnetResourceIds[0]
}
}
// NSG
module nsg 'br/public:avm/res/network/network-security-group:0.3.1' = {
name: '${prefix}-nsg'
params: {
name: '${prefix}-nsg'
// Non-required parameters
location: location
securityRules: [
{
name: 'Allow-RDP'
properties: {
access: 'Allow'
destinationAddressPrefix: 'VirtualNetwork'
destinationPortRanges: [
'3389'
]
direction: 'Inbound'
priority: 200
protocol: 'Tcp'
sourceAddressPrefix: '*'
sourcePortRange: '*'
}
}
]
}
}
// Vnet
module vnet 'br/public:avm/res/network/virtual-network:0.1.8' = {
name: '${prefix}-vnet'
params: {
addressPrefixes: [
vnetAdressPrefix
]
name: '${prefix}-vnet'
location: location
subnets: [
{
name: 'default'
addressPrefix: cidrSubnet(vnetAdressPrefix, 24, 0)
networkSecurityGroupResourceId: nsg.outputs.resourceId
}
{
name: 'AzureBastionSubnet'
addressPrefix: cidrSubnet(vnetAdressPrefix, 24, 1)
}
]
}
}
// VM
module vm 'br/public:avm/res/compute/virtual-machine:0.5.3' = {
name: '${prefix}-arcvm'
params: {
adminUsername: vmUserName
adminPassword: vmPassword
imageReference: {
publisher: 'MicrosoftWindowsServer'
offer: 'WindowsServer'
sku: '2022-datacenter-g2'
version: 'latest'
}
name: '${prefix}-arcvm'
nicConfigurations: [
{
nicSuffix: '-nic'
ipConfigurations: [
nicIpConfigurations[deployBastion]
]
}
]
osDisk: {
diskSizeGB: 128
managedDisk: {
storageAccountType: 'Standard_LRS'
}
}
osType: 'Windows'
vmSize: vmSize
zone: 0
// Arc 用の拡張機能
extensionCustomScriptConfig: {
enabled: true
fileData: [
{
uri: ((useDeviceCode)
? 'https://raw.githubusercontent.com/NakayamaKento/Azure_Bicep/main/products/ArcEnabledWindowsServer/scripts/install_arc_agent_deviceCode.ps1'
: 'https://raw.githubusercontent.com/NakayamaKento/Azure_Bicep/main/products/ArcEnabledWindowsServer/scripts/install_arc_agent.ps1')
}
]
}
extensionCustomScriptProtectedSetting: {
commandToExecute: ((useDeviceCode)
? 'powershell.exe -ExecutionPolicy Bypass -File install_arc_agent_deviceCode.ps1 -tenantId ${tenantId} -resourceGroup ${resourceGroupName} -subscriptionId ${subscriptionId} -location ${location} -adminUsername ${vmUserName}'
: 'powershell.exe -ExecutionPolicy Bypass -File install_arc_agent.ps1 -appId ${appId} -password ${appSecret} -tenantId ${tenantId} -resourceGroup ${resourceGroupName} -subscriptionId ${subscriptionId} -location ${location} -adminUsername ${vmUserName}')
}
}
}
// Bastion
module bastion 'br/public:avm/res/network/bastion-host:0.2.2' = if (deployBastion == 'yes'){
name: '${prefix}-bastion'
params: {
name: '${prefix}-bastion'
virtualNetworkResourceId: vnet.outputs.resourceId
}
}
|
デバイスコードを使ったインストールスクリプト
参考にした Jumpstart ではサービスプリンシパルを使っていました
サービスプリンシパルは作成後のライフサイクルを考える必要があります
そのため、検証のためサービスプリンシパルを作成 → 検証後に削除 という操作が必要になります
一方で、Azure Arc の登録にはデバイスコードを使ったインストール方法もあります
この方法は都度、ブラウザを開く必要がありますが、サービスプリンシパルのライフサイクルを考えなくてよいため個人的には使いやすいです
デバイスコードを使ったインストール方法に変更するため、scripts/install_arc_agent.ps1 の中身を見てみます
おおよそ以下の構成です
- パラメータの定義、環境変数の設定
- tmp フォルダの作成
- C:\tmp に LogonScript.ps1 を作成
- ユーザーのログオン時に LogonScript.ps1 が実行されるように設定
デバイスコードを使う場合、以下の修正が必要です
- パラメータからサービスプリンシパル関連のものを削除
- LogonScript.ps1 の中身をデバイスコードを使ったもの [–use-device-code] に変更
変更後のものはこちらになります
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
|
param (
[string]$subscriptionId,
[string]$tenantId,
[string]$resourceGroup,
[string]$location,
[string]$adminUsername
)
[System.Environment]::SetEnvironmentVariable('subscriptionId', $subscriptionId,[System.EnvironmentVariableTarget]::Machine)
[System.Environment]::SetEnvironmentVariable('tenantId', $tenantId,[System.EnvironmentVariableTarget]::Machine)
[System.Environment]::SetEnvironmentVariable('resourceGroup', $resourceGroup,[System.EnvironmentVariableTarget]::Machine)
[System.Environment]::SetEnvironmentVariable('location', $location,[System.EnvironmentVariableTarget]::Machine)
[System.Environment]::SetEnvironmentVariable('adminUsername', $adminUsername,[System.EnvironmentVariableTarget]::Machine)
New-Item -Path "C:\" -Name "tmp" -ItemType "directory" -Force
# Creating PowerShell Logon Script
$LogonScript = @'
Start-Transcript -Path C:\tmp\LogonScript.log
## Configure the OS to allow Azure Arc Agent to be deploy on an Azure VM
Write-Host "Configure the OS to allow Azure Arc Agent to be deploy on an Azure VM"
Set-Service WindowsAzureGuestAgent -StartupType Disabled -Verbose
Stop-Service WindowsAzureGuestAgent -Force -Verbose
New-NetFirewallRule -Name BlockAzureIMDS -DisplayName "Block access to Azure IMDS" -Enabled True -Profile Any -Direction Outbound -Action Block -RemoteAddress 169.254.169.254
## Azure Arc agent Installation
Write-Host "Onboarding to Azure Arc"
# Download the package
function download() {$ProgressPreference="SilentlyContinue"; Invoke-WebRequest -Uri https://aka.ms/AzureConnectedMachineAgent -OutFile AzureConnectedMachineAgent.msi}
download
# Install the package
msiexec /i AzureConnectedMachineAgent.msi /l*v installationlog.txt /qn | Out-String
# Run connect command
& "$env:ProgramFiles\AzureConnectedMachineAgent\azcmagent.exe" connect `
--use-device-code `
--resource-group $env:resourceGroup `
--tenant-id $env:tenantId `
--location $env:location `
--subscription-id $env:subscriptionId `
--tags "Project=jumpstart_azure_arc_servers" `
--correlation-id "d009f5dd-dba8-4ac7-bac9-b54ef3a6671a"
Unregister-ScheduledTask -TaskName "LogonScript" -Confirm:$False
Stop-Process -Name powershell -Force
'@ > C:\tmp\LogonScript.ps1
# Creating LogonScript Windows Scheduled Task
$Trigger = New-ScheduledTaskTrigger -AtLogOn
$Action = New-ScheduledTaskAction -Execute "PowerShell.exe" -Argument 'C:\tmp\LogonScript.ps1'
Register-ScheduledTask -TaskName "LogonScript" -Trigger $Trigger -User "${adminUsername}" -Action $Action -RunLevel "Highest" -Force
# Disabling Windows Server Manager Scheduled Task
Get-ScheduledTask -TaskName ServerManager | Disable-ScheduledTask
|
Linux 編
Linux の場合も同様に Azure Verified Module に書き換えます
詳細は省きますが、変更後のものは こちらになります
Azure_Bicep/products/ArcEnabledLinuxServer at main · NakayamaKento/Azure_Bicep
試してみる
Bicep ファイルをそのままデプロイに使ってもいいですが、Template Spec に登録しておきます
詳しくは ARM テンプレートとBicep 03 | Template Spec を試し隊 – クラウドを勉強し隊 を参考にしてください
Template Spec:
Template Spec からデプロイします
今回はデバイスコードを使ってみます
そのため、サービスプリンシパルのためのパラメータは使わないので、適当に値を入れておきます
Template Spec:
Template Spec:
デプロイ完了後、ログインしてみると無事にスクリプトが実行されました
途中、デバイスコードでの認証が求められ、認証を行うと Azure Arc に登録されました
Linux の方も問題なくデプロイできました
まとめ
Jumpstart の ARM Template を Azure Verified Module に書き換えてみました
ついでにデバイスコードを使ったインストール方法に変更し、使い勝手をよくできたので満足
参考