При запуске из AMI, в котором установлен cloud-init (что часто встречается во многих официальных Linux дистрибутивах), мы можем использовать модуль write_files
cloud-init * для помещать в файловую систему произвольные файлы, если они достаточно малы, чтобы соответствовать ограничениям аргумента user_data
вместе со всеми другими cloud-init
данными.
Как и все модули cloud-init, мы настраиваем write_files
с использованием формата конфигурации cloud-init на основе YAML , который начинается со специальной строки маркера #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
}
write_files
модуль может принимать данные в формате base64, когда мы устанавливаем encoding = "b64"
, поэтому мы используем это вместе с функцией Terraform filebase64
для включения содержимого внешнего файла. Здесь возможны другие подходы, такие как динамическое создание строки с использованием шаблонов Terraform и использование base64encode
для ее кодирования в качестве содержимого файла.
Если вы можете express все, что хотите, облако -init для выполнения в одном файле конфигурации, как указано выше, тогда вы можете назначить local.cloud_config_config
непосредственно как свой экземпляр user_data
, и облачная конфигурация должна распознать и обработать его при загрузке системы:
user_data = local.cloud_config_config
Если вместо этого вам нужно совместить создание файла с некоторыми другими действиями, такими как запуск сценария оболочки, вы можете использовать формат multipart archive cloud-init для кодирования нескольких «файлов» для обработки 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
, которая является подходящим составным архивом. для использования в качестве user_data
для cloud-init:
user_data = cloudinit_config.example.rendered
EC2 устанавливает максимальный размер пользовательских данных 64 килобайт, поэтому все закодированные данные вместе должны соответствовать этому пределу . Если вам нужно разместить большой файл, который приближается к этому пределу или превышает его, вероятно, было бы лучше использовать другую промежуточную систему для передачи этого файла, например, чтобы Terraform записал файл в корзину Amazon S3 и поместил программное обеспечение в ваш экземпляр получает эти данные, используя профиль экземпляра учетные данные. Однако в этом не должно быть необходимости для небольших файлов данных, используемых для конфигурации системы.
Важно отметить, что с точки зрения Terraform и EC2 содержимое user_data
- это просто произвольная строка. Любые проблемы при обработке строки должны быть отлажены в самой целевой операционной системе путем чтения журналов cloud-init, чтобы увидеть, как она интерпретировала конфигурацию и что произошло, когда она попыталась предпринять эти действия.
[1] : Мы также потенциально могли бы использовать yamlencode
, но в то время, когда я пишу это, эта функция имеет предупреждение о том, что ее точное форматирование может измениться в будущих версиях Terraform, и это нежелательно для user_data
, потому что это приведет к замене экземпляра. Если вы читаете это в будущем и этого предупреждения больше нет в документах yamldecode
, рассмотрите возможность использования вместо него yamlencode
.