当从已安装
cloud-init的AMI(这在许多官方Linux发行版中很常见)开始时,我们可以使用cloud-init的
write_files
模块将任意文件放置到文件系统中,只要它们足够小以适应
user_data
参数的限制以及所有其他
cloud-init
数据。
与所有cloud-init模块一样,我们使用
基于YAML的cloud-init配置格式配置
write_files
,它以特殊的标记字符串
#cloud-config
开头,后跟一个YAML数据结构。因为JSON是YAML的子集,所以我们可以使用Terraform的
jsonencode
生成有效值
[1]。
locals {
cloud_config_config = <<-END
#cloud-config
${jsonencode({
write_files = [
{
path = "/etc/example.txt"
permissions = "0644"
owner = "root:root"
encoding = "b64"
content = filebase64("${path.module}/example.txt")
},
]
})}
END
}
当我们设置 encoding = "b64"
时,write_files
模块可以接受以 base64 格式表示的数据,因此我们可以与 Terraform 的 filebase64
函数一起使用,包含外部文件的内容。这里还有其他可能的方法,例如使用 Terraform 模板动态生成字符串,并使用 base64encode
将其编码为文件内容。
如果您可以在一个配置文件中表达您希望 cloud-init 做的一切,那么您可以将 local.cloud_config_config
直接分配为您的实例 user_data
,并且 cloud-config 将会在系统启动时识别和处理它:
user_data = local.cloud_config_config
如果您需要将文件创建与其他操作(如运行shell脚本)结合起来,可以使用cloud-init的
multipart archive格式对多个“文件”进行编码以供cloud-init处理。Terraform有一个
cloudinit
提供程序,其中包含一个数据源,可轻松构建用于cloud-init的多部分存档。
data "cloudinit_config" "example" {
gzip = false
base64_encode = false
part {
content_type = "text/cloud-config"
filename = "cloud-config.yaml"
content = local.cloud_config_config
}
part {
content_type = "text/x-shellscript"
filename = "example.sh"
content = <<-EOF
#!/bin/bash
echo "Hello World"
EOT
}
}
此数据源将在cloudinit_config.example.rendered
处生成单个字符串,该字符串是适用于作为cloud-init
的user_data
使用的多部分归档文件:
user_data = data.cloudinit_config.example.rendered
EC2对
用户数据的最大大小限制为64千字节,因此所有编码数据的总和都必须在该限制范围内。如果您需要放置一个接近或超过该限制的大文件,则最好使用其他中间系统来传输该文件,例如让Terraform将文件写入Amazon S3存储桶,并使实例中的软件使用
实例配置文件凭据检索该数据。不过,对于用于系统配置的小型数据文件,则不需要这样做。
需要注意的是,从Terraform和EC2的角度来看,
user_data
的内容只是任意字符串。处理字符串中的任何问题必须在目标操作系统本身中进行调试,方法是读取cloud-init日志以查看它如何解释配置以及尝试执行这些操作时发生了什么。
[1]: 我们也可以潜在地使用yamlencode
,但是在我写这篇文章的时候,该函数有一个警告,即其确切格式可能会在未来的Terraform版本中发生变化,而这对于user_data
来说是不可取的,因为它会导致实例被替换。如果您正在未来阅读此内容,并且在yamldecode
文档中不存在该警告,请考虑改用yamlencode
。
.env
文件以避免 4K 环境限制。 - Vitim.usdata.
前缀。我会编辑答案。谢谢! - Martin Atkinswrite-files
模块之后运行很长时间。 - Martin Atkins