不使用 Terraform 文件供应器将本地文件部署到实例

Deploy local files to instances without using Terraform file provisioners

作为其他几位发布到 Whosebug 的用户,我 运行 遇到了文件配置器的问题,Terraform 文档说我们不应该依赖它们。

解决文件供应器的最佳方法是什么 - 特别是针对本地配置文件和脚本?

一种非常有效且不需要直接连接到实例的解决方案是使用用户数据作为 "install" 来自文件的 base64 版本的文件的挂钩。

我们实际上可以将文件作为 base64 字符串嵌入到用户数据初始化脚本中。这适用于 AWS 中的 Windows 和 Linux 实例,并且还与启动时具有用户数据脚本 运行 兼容。

解决方案说明:

  1. terraform plan 期间,使用 terraform 函数将您需要的任何本地文件编码为 base64 字符串 base64encode(file("path/to/file"))
  2. (可选)在用户数据执行开始时保存一个标记文件(_INIT_STARTED_);此文件将具有 userdata 执行开始时的创建时间戳。
  3. 在 运行 执行 actual 用户数据脚本之前,将 base64 字符串写入文本文件。 (实际命令在 windows 和 linux 之间变化,请参见下面的示例。)
  4. 运行 userdata 脚本本身(userdata_win.batuserdata_lin.sh
  5. (可选)最后,保存第二个标记文件 (_INIT_COMPLETE_),该文件将具有 userdata 脚本完成时的创建时间戳。 (缺少此文件也有助于检测脚本故障 and/or still-运行 登录实例后的脚本。)

对于 AWS Linux 个实例:

data "template_file" "userdata_lin" {
  template = <<EOF
#!/bin/bash
mkdir -p /home/ubuntu/setup-scripts
cd /home/ubuntu/setup-scripts
touch _INIT_STARTED_
echo ${base64encode(file("${path.module}/userdata_lin.sh"))} | base64 --decode > userdata.sh
echo ${base64encode(file("${path.module}/config.json"))} | base64 --decode > config.json
${file("${path.module}/userdata_lin.sh")}
sudo chmod 777 *
touch _INIT_COMPLETE_
EOF
}

# ...

resource "aws_instance" "my_linux_instance" {
  # ...
  user_data = data.template_file.userdata_lin.rendered
}

对于 AWS Windows 个实例:

data "template_file" "userdata_win" {
  template = <<EOF
<script>
mkdir C:\Users\Administrator\setup-scripts
cd C:\Users\Administrator\setup-scripts
echo "" > _INIT_STARTED_
echo ${base64encode(file("${path.module}/userdata_win.bat"))} > tmp1.b64 && certutil -decode tmp1.b64 userdata.bat
echo ${base64encode(file("${path.module}/config.json"))} > tmp2.b64 && certutil -decode tmp2.b64 config.json
${file("${path.module}/userdata_win.bat")}
echo "" > _INIT_COMPLETE_
</script>
<persist>false</persist>
EOF
}

# ...

resource "aws_instance" "my_windows_instance" {
  # ...
  user_data = data.template_file.userdata_win.rendered
}