はじめに
プロビジョニングツールはAnsibleが好きなのだけれど、Windowsに対しては一手間必要なのが大変だなぁと思っている畑ケです。
前回までの記事で、Windows Server 2019 Datacenterの検証環境をTerraformの機能を使ってAzureに構築する方法を解説しました。今回はその第3回目です。 Windowsの機能でWinRMというWindowsのプロビジョニングに使用できる機能があります。
Ansibleはプロビジョニングツールの一種で、Windowsに対するプロビジョニングツールもサポートしています。
Azure上のWindows 10のインスタンスについてはボリュームライセンスを用意する必要があります。ライセンス認証については https://docs.microsoft.com/ja-jp/windows/deployment/windows-10-subscription-activation の記事をご覧ください。 この記事ではWindows Server 2019 Datacenterを用いて解説します。
WindowsインスタンスのWinRMを有効化する
WinRMを有効化するには、例えば、スタートアップコマンドに有効化を行うコマンドを登録する必要があります1。
## Windows 10 2016LTSBなど、古いVMでは以下を有効にしてTLS1.2を明示的に有効化する必要がある場合があるので注意
# [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Invoke-WebRequest -Uri https://raw.githubusercontent.com/ansible/ansible-documentation/devel/examples/scripts/ConfigureRemotingForAnsible.ps1 -OutFile ConfigureRemotingForAnsible.ps1
powershell -ExecutionPolicy RemoteSigned ConfigureRemotingForAnsible.ps1
Remove-Item -path ConfigureRemotingForAnsible.ps1 -force
上記のスクリプトをsettings.ps1として保存し、configディレクトリの下に配置します。
$ tree -L 1 config
config
└── settings.ps1
また、AzureのCustomData領域からsettings.ps1を別のファイル名として取得し、スタートアップ時に実行するコマンド群をXMLで定義します。
<FirstLogonCommands>
<SynchronousCommand>
<CommandLine>cmd /c "mkdir C:\terraform"</CommandLine>
<Description>Create the Terraform working directory</Description>
<Order>11</Order>
</SynchronousCommand>
<SynchronousCommand>
<CommandLine>cmd /c "copy C:\AzureData\CustomData.bin C:\terraform\winrm.ps1"</CommandLine>
<Description>Move the CustomData file to the working directory</Description>
<Order>12</Order>
</SynchronousCommand>
<SynchronousCommand>
<CommandLine>powershell.exe -sta -ExecutionPolicy Unrestricted -file C:\terraform\winrm.ps1</CommandLine>
<Description>Execute the WinRM enabling script</Description>
<Order>13</Order>
</SynchronousCommand>
</FirstLogonCommands>
このXMLをconfig以下に配置すると、configディレクトリは以下のファイルを含みます。
$ tree -L 1 config
config
├── FirstLogonCommands.xml
└── settings.ps1
0 directories, 2 files
diff --git a/main.tf b/main.tf
index 0d428b1..6568904 100644
--- a/main.tf
+++ b/main.tf
@@ -130,15 +130,43 @@ resource "azurerm_virtual_machine" "win10testing" {
computer_name = "cc-winserv"
admin_username = var.windows-username
admin_password = var.windows-password
+ custom_data = file("./config/settings.ps1")
}
os_profile_windows_config {
enable_automatic_upgrades = true
provision_vm_agent = true
+ winrm {
+ protocol = "http"
+ }
+ # Auto-Login's required to configure WinRM
+ additional_unattend_config {
+ pass = "oobeSystem"
+ component = "Microsoft-Windows-Shell-Setup"
+ setting_name = "AutoLogon"
+ content = "<AutoLogon><Password><Value>${var.windows-password}</Value></Password><Enabled>true</Enabled><LogonCount>1</LogonCount><Username>${var.windows-username}</Username></AutoLogon>"
+ }
+ # Unattend config is to enable basic auth in WinRM, required for the provisioner stage.
+ additional_unattend_config {
+ pass = "oobeSystem"
+ component = "Microsoft-Windows-Shell-Setup"
+ setting_name = "FirstLogonCommands"
+ content = file("./config/FirstLogonCommands.xml")
+ }
}
tags = {
CreatedBy = "clearcode"
Purpose = "Describe Terraform instruction"
}
+
+ connection {
+ host = azurerm_public_ip.testing.ip_address
+ type = "winrm"
+ port = 5985
+ https = false
+ timeout = "2m"
+ user = var.windows-username
+ password = var.windows-password
+ }
}
埋め込むと、上記のdiffのようになります。
Ansibleのインベントリを作成する
Ansibleに必要なライブラリをインストールする
Ansibleではプロビジョニング対象の情報をインベントリというファイルから取得してプロビジョニングを行います。 Windowsへプロビジョニングする際には、さらにWinRMというPythonのライブラリも必要です。
Python3で動作させる際には、venvを用いて環境をリポジトリ固有のものにします。
$ python3 -m venv management
$ source ./management/bin/activate
により、システムから隔離されたmanagement環境に入ります。
$ pip3 install ansible pywinrm
を実行し、Ansibleとpywinrmをインストールします。
Terraformでインベントリを作成する
Terraformでローカルにファイルを作成するには、localプロバイダーをインストールします。
terraform {
(中略)
required_providers {
(中略)
local = {
source = "hashicorp/local"
version = "~>1.4"
}
}
}
(中略)
provider "local" {
}
(2022年1月14日追記:例を最新のTerraformの仕様に合わせて更新しました)
localプロバイダーをTerraformにインストールするため、再度terraform init
を実行します。
Terraformの実行中のデータを格納するdataソースを定義していきます。 また、実行が終了した時にパブリックIPアドレスを出力してくれるoutputもついでに定義していきます。
data "azurerm_public_ip" "testing" {
name = azurerm_public_ip.testing.name
resource_group_name = azurerm_virtual_machine.winservtesting.resource_group_name
}
output "win10testing_instance_public_ip_address" {
value = data.azurerm_public_ip.testing.ip_address
}
AnsibleのインベントリとPlayBookを入れるためのansibleディレクトリを作成します。
$ mkdir ansible
Ansibleのインベントリはlocalファイルリソースにてローカルに出力します。
resource "local_file" "inventory" {
filename = "ansible/hosts"
content = <<EOL
[windows]
${data.azurerm_public_ip.testing.ip_address}
[windows:vars]
ansible_user=${var.windows-username}
ansible_password=${var.windows-password}
ansible_port=5986
ansible_connection=winrm
ansible_winrm_server_cert_validation=ignore
EOL
}
設定の適用
ここまでの設定を適用するには前回までのリソースを消しておかないといけません。
$ terraform destroy -auto-approve
を実行して前回までのリソースを削除しておきます。
再度、
$ terraform apply -auto-approve
を実行することで、ここまでに書き下した設定がAzureへ適用され、Terraformで設定した設定が流し込まれたインスタンスが立ち上がります。 ここまでの設定を流し込むことで、WinRMを用いたAnsibleによるプロビジョニングを行う準備ができたWindows Server 2019 Datacenterインスタンスが立ち上がってきます。
WinRMの有効化に成功している場合、Ansibleのwin_pingモジュールを使用するとpongが返ってきます。
$ ansible windows -i ansible/hosts -m win_ping -vvv
# ...
0.0.0.0 | SUCCESS => {
"changed": false,
"invocation": {
"module_args": {
"data": "pong"
}
},
"ping": "pong"
}
ここまでに作成したTerraformのスクリプトは https://gitlab.com/clear-code/terraform-example/-/tree/1430e3146c3a27c770fedf099cee3b79facea19b に置いてあります。
まとめ
Azure上のWindows Server 2019 DatacenterのインスタンスをWinRMを有効化してAnsibleによるプロビジョニングを実行する準備を整えるところまで複数回に分けて解説しました。 WindowsのWinRMを有効化したインスタンスを立ち上げることができれば、必要な設定を入れ込んだインスタンスを常時起動・休止されている必要はなく、必要な時に作成・不要な時に破棄することができるようになります。 クラウドサービスはとても便利ですが、必要な設定がきちんと入っているか、必要なリソースがちゃんと確保されているか、インスタンスタイプの変更をdiffで取得できるか、など管理コンソールから確認するのには一手間必要です。 EC2インスタンスやそれに準じたリソースを扱う際には、Terraformの設定に落とし込み設定変更が必要な際にはdiffとして出力することができる仕組みを整えてみてはいかがでしょうか。
-
ここで使用している
ConfigureRemotingForAnsible.ps1
は、元々はAnsibleプロジェクト本体のリポジトリにありましたが、2023年7月12日付の変更でドキュメント類専用の別リポジトリに移動されました。古いsettings.ps1を使用している場合はダウンロードに使用するURLを更新する必要があります。 ↩