Terraformでcloud-configを記述する
AWSのEC2インスタンスでは、User Dataにシェルスクリプトを渡すことで起動時にスクリプトを実行できます。ファイルを配置したり、パッケージをインストールしたり、といった複雑なことがやりたい場合はcloud-initが便利です。詳しくは公式ドキュメントの例を参照してください。
例えば、下記のようなYAMLをUser Dataに指定すると、OSの起動時にsystemdで独自のサービスを開始できます。
#cloud-config write_files: - path: /etc/systemd/system/helloworld.service" content: | [Unit] Description = Hello World [Service] ExecStart = /usr/local/bin/helloworld.sh Restart = always Type = simple [Install] WantedBy = multi-user.target - path: /usr/local/bin/helloworld.sh" permissions: 0755 content: | #!/bin/sh while true; do date; sleep 1; done runcmd: - ["systemctl", "start", "helloworld"] - ["systemctl", "enable", "helloworld"]
Terraformでcloud-configを指定する場合、下記のように外部ファイルを読み込むと簡単に書けます。
resource "aws_instance" "this" { user_data_base64 = filebase64('./cloud-config.yaml') }
ただ、YAMLの中にインラインでシェルスクリプトなどをベタ書きしているため、可読性がよくないというデメリットがあります。エディタで開いてもsyntax highlightingしてくれません。
そこで、下記のように動的にYAMLを組み立てることで、シェルスクリプトなどのファイルを外部化できます。
resource "aws_instance" "this" { user_data_base64 = base64encode(join("\n", [ "#cloud-config", yamlencode({ write_files : [ { path : "/etc/systemd/system/helloworld.service", content : file("./helloworld.service"), }, { path : "/usr/local/bin/helloworld", content : file("./helloworld.sh"), permissions : "0755", }, ], runcmd : [ ["systemctl", "enable", "helloworld"], ["systemctl", "start", "helloworld"], ], }) ])) }
サンプルが下記にあるので参考にどうぞ。