カスタムデータ(Custom Data)は、Azureで仮想マシン作成時にOS上での設定(apt install等)をおこなうための機能です。
Terraformでも対応していますが、オプション項目で ドキュメント には記法の記載が無かったので、書き方をまとめておきます。例はUbuntuのものです。
Terraformの同様な機能にprovisioner(remote-exec)もあるので、最後にその例も記載しています。
1) custom_data使用(シェルスクリプト)
azurerm_virtual_machineブロック -> os_profile -> custom_data に実行したい内容をそのまま記載します。
resource "azurerm_virtual_machine" "tf_name_vm1" {
# ※ここではcustom_dataに必要な部分のみ記載しています※
os_profile {
custom_data = <<-EOF
#!/bin/bash
apt-get update
apt-get -y dist-upgrade
apt install -y nginx
apt install -y nodejs
apt install -y npm
EOF
}
}
スクリプトを別のファイルで管理したい場合は、custom_dataに$file変数を記載しても動きません。template_fileとしてファイルを記載し、custom_dataではそのrendered属性を参照する必要があります。
data "template_file" "my_init_script" {
template = "${file("/home/azureuser/init_test.sh")}"
}
resource "azurerm_virtual_machine" "tf_name_vm1" {
# ※ここではcustom_dataに必要な部分のみ記載しています※
os_profile {
custom_data = "${data.template_file.my_init_script.rendered}"
}
}
custom_dataはroot権限で実行されるのでsudoは無くても構いません。
$ cat init_test.sh
#!/bin/bash
apt-get update
apt-get -y dist-upgrade
apt install -y nginx
apt install -y nodejs
apt install -y npm
2) custom_data使用(cloud-init)
Cloud Init に対応したOSであれば、同様に os_profile -> custom_data に実行したい内容をそのまま記載できます。
resource "azurerm_virtual_machine" "tf_name_vm1" {
# ※ここではcustom_dataに必要な部分のみ記載しています※
os_profile {
custom_data = <<-EOF
#cloud-config
package_upgrade: true
packages:
- nginx
- nodejs
- npm
EOF
}
}
スクリプトを別のファイルで管理したい場合も、同様にtemplate_fileとしてファイルを記載し、custom_dataではそのrendered属性を参照する必要があります。
data "template_file" "my_init_script" {
template = "${file("/home/azureuser/cloud_init_test.yml")}"
}
resource "azurerm_virtual_machine" "tf_name_vm1" {
# ※ここではcustom_dataに必要な部分のみ記載しています※
os_profile {
custom_data = "${data.template_file.my_init_script.rendered}"
}
}
$ cat cloud_init_test.yml
#cloud-config
package_upgrade: true
packages:
- nginx
- nodejs
- npm
3) provisioner(remote-exec)使用
remote-execはTerraformの機能で、Ansibleと同様に仮想マシンにSSH接続して設定を行うものです。以下が設定例です。
resource "azurerm_network_interface" "tf_name_nic1" { # NICの設定
# ※ここではremote-execに必要な部分のみ記載しています※
ip_configuration {
private_ip_address_allocation = "Static" # VM作成直後にSSH接続する必要があるため、
private_ip_address = "10.10.0.5" # 静的IPアドレスを割り当てる。
}
}
resource "azurerm_virtual_machine" "tf_name_vm1" {
# ※ここではremote-execに必要な部分のみ記載しています※
os_profile {
admin_username = "azureuser" # VM上のユーザ
}
os_profile_linux_config {
ssh_keys {
path = "/home/azureuser/.ssh/authorized_keys" # VM上のユーザ(azureuser)の鍵設定
key_data = "${file("/home/ubuntu/azureuser-key/.ssh/id_rsa.pub")}" # 設定する鍵(指定してあるファイルはTerraformを実行するユーザのローカルファイル)
}
}
provisioner "remote-exec" {
connection {
host = "10.10.0.5" # azurerm_network_interfaceで設定したIPアドレス
type = "ssh"
user = "azureuser" # os_profileで設定したユーザ
private_key = "${file("/home/ubuntu/azureuser-key/.ssh/id_rsa")}" # os_profile_linux_configで設定した鍵(のプライベートキー)
}
inline = [ # 実行するスクリプト
"sudo apt-get update",
"sudo apt-get -y dist-upgrade",
"sudo apt install -y nginx",
"sudo apt install -y nodejs"
"sudo apt install -y npm"
]
}
}
ここでのポイントは、
- VM作成直後にSSH接続するため、静的IPを設定しておく
- 設定したIPと鍵を使うよう、provisioner(remote-exec)ブロック内の設定を記載する
- 鍵はパスフレーズなしにする必要がある
の3点です。現状、SSH接続に使う鍵にはパスフレーズが設定されていると実行エラーになってしまいます。
Error: Failed to read ssh private key: password protected keys are
not supported. Please decrypt the key prior to use.
以上が記法の例となります。
remote-execは ドキュメント には「この機能は"last resort"で、クラウド標準の機能を優先して使うべき」という旨の記載があるのですが、実行すると結果が標準出力に出るのでエラーの調査がしやすいというメリットがあります(custom_dataを間違えて途中で止まった場合の調査は大変...)。実績のない設定の検証用途で使うのがよさそうです。