ARM Template の書き方 その6 CustomScript
やりたいこと
目的
VirtualMachine を構築した後にこう思います。普段使うツールはサーバーを立てるときに自動的にインストールしておきたいなと。新たにサーバーを立てる度にツールをインストールしてと、毎回同じことを繰り返すのは面倒ですよね。
そこで、今回紹介するのは AWS でいうところの user_data に "近い" 機能です(同じとは言ってない)。ARM で Linux サーバーをデプロイする際に任意のスクリプトを root で実行してくれます。
公式の ARM Template はこちらの GitHub で、公式の解説はこちら Use the Azure Custom Script Extension Version 2 with Linux virtual machines です。
構成
今回は GitHub にあるスクリプトを ARM でデプロイするときに一緒に流し込みます。
CustomScript と CustomData
私は最初、名前が似ている機能が2つ存在しているということが理解できず、大変迷いました。
- Customdata:VirtualMachine のプロパティの1つ
- CustomScript:VirtualMachin の Extensions の1つ
CustomData はパラメータで指定した文字列(コマンド)をサーバー上で実行させるもので、実行ユーザーなども自由に設定できます。ただし、CustomData は文字列で指定しなければならないため、複数のコマンドを実行するのには不便です。
CustomScript は Microsoft.Compute virtualMachines/extensions の一種です。CustomScript では複数のスクリプトを実行することもできますし、GitHub、ローカル、StorageAccount といった様々な場所にあるスクリプトを利用できるのでとても便利です。
今回は CustomScript で実施します。
やってみた
実際に用意したのが以下のテンプレートです。
ARM Template サンプル
{
"comments": "Virtual Machine",
"name": "[variables('virtualMachines').vm01.name]",
"type": "Microsoft.Compute/virtualMachines",
"apiVersion": "2019-07-01",
"location": "[variables('location')]",
"dependsOn": [
"[variables('resourceID').nic01]"
],
"tags": "[variables('tags')]",
"properties": {
"osProfile": {
"computerName": "[variables('virtualMachines').vm01.computerName]",
"adminUsername": "[variables('virtualMachines').vm01.adminUsername]",
"adminPassword": "[parameters('adminPassword')]",
"linuxConfiguration": {
"disablePasswordAuthentication": true,
"ssh": {
"publicKeys": [
{
"path": "[concat('/home/',variables('virtualMachines').vm01.adminUsername, '/.ssh/authorized_keys')]",
"keyData": "[reference(parameters('publicSshKeyID'),'2020-12-01').publicKey]"
}
]
}
}
},
"hardwareProfile": {
"vmSize": "Standard_DS2_v2"
},
"storageProfile": {
"imageReference": {
// Get-AzVMImagePublisher -Location eastus | Out-File publisher.txt
"publisher": "OpenLogic",
// Get-AzVMImageOffer -Location eastus -PublisherName OpenLogic | Out-File offer.txt
"offer": "CentOS",
// Get-AzVMImageSku -Location eastus -PublisherName OpenLogic -Offer CentOS | Out-File sku.txt
"sku": "8_3",
"version": "latest"
},
"osDisk": {
"name": "[variables('virtualMachines').vm01.osDiskName]",
"osType": "Linux",
"diskSizeGB": 127,
"caching": "ReadWrite",
"createOption": "FromImage",
"managedDisk": {
"storageAccountType": "StandardSSD_LRS"
}
}
},
"networkProfile": {
"networkInterfaces": [
{
"properties": {
"primary": true
},
"id": "[variables('resourceID').nic01]"
}
]
}
},
"resources": [
{
// https://docs.microsoft.com/en-us/azure/virtual-machines/extensions/custom-script-linux
"name": "installDBAtools",
"type": "extensions",
"location": "[variables('location')]",
"apiVersion": "2019-03-01",
"dependsOn": [
"[variables('resourceID').vm01]"
],
"tags": "[variables('tags')]",
"properties": {
"publisher": "Microsoft.Azure.Extensions",
"type": "CustomScript",
"typeHandlerVersion": "2.1",
"autoUpgradeMinorVersion": true,
"settings": {
"fileUris": [
"https://raw.githubusercontent.com/atsushikoizumi/azure_arm_v1/master/dba/customscript.sh"
]
},
"protectedSettings": {
"commandToExecute": "[concat('bash customscript.sh ',variables('virtualMachines').vm01.adminUsername)]"
}
}
}
]
}
customscript.sh サンプル
#!/bin/bash
USERNAME=$1
LOGFILE=/var/log/customscript.log
# start
touch $LOGFILE
whoami >> $LOGFILE
pwd >> $LOGFILE
echo "USERNAME=$USERNAME" >> $LOGFILE
ポイント
上記のテンプレート内にもコメントとして記載しておりますが、公式のドキュメントを読むことが最重要です。
fileUris の記入箇所が公式ドキュメントと異なりますが、これは、protectedSettings で書くと、デプロイ時の予想結果にスクリプトが表示されないので settings に書いています。
vscode の罠
おそらく、ほとんどの人が ARM template を書く時、VSCode を使っていると思いますが、なんと、そこに罠がありました。上記のテンプレートを VSCode で展開すると以下のエラーが表示されます。
メッセージの内容は以下です。
- Missing required property "storageAccountName"
- Missing required property "storageAccountKey"
言われるがままに StorageAccount の情報を入れるとエラーになります。そんなの知らねーよ、って感じですが、このエラーは無視しましょう。これで3時間くらいハマりました。
分かったこと
スクリプトの実行結果を確認
サーバーにログインして確認してみます。
上記の結果から分かることは以下です。
- 実行ユーザー:root
- 実行パス:/var/lib/waagent/custom-script/download/0
- テンプレート内で指定した引数をスクリプトで受け取れる
Azure Linux Agent(waagent)
実は内部で Azure Linux Agent なるものが CustomScript を実行しています。それは上記の結果における実行パスからも予想できます。
ちょっと覗いてみましょう。
テンプレートで設定したスクリプトがサーバーに配置されていることが確認できました。また、waagent の設定ファイルの一番下の行で、customscript が除外されていることも確認できました。
最後に
VirtualMachine を1つとっても、細かくみていくと色々な機能があるものですね。AWS もそうですが、Azure もすごいなと感心いたしました。もっと使いこなしていきたいと思います。