You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Terraform template_file传递数组至脚本时渲染失败求助

问题:Terraform传递数组至EC2用户数据脚本报错及正确实现

问题场景

尝试通过Terraform的template_file将数组传递到EC2实例的用户数据脚本中,相关代码及执行terraform plan时的报错如下:

Terraform代码

variable "services" {
   type = list(string)
   default = ["Service1", "Service2", "service3"]
}

variable "passwords" {
   type = list(string)
   default = ["Password1", "Password2", "Password3"]
}

data "template_file" "configure" {
  template = "${file("${path.module}/init/configure")}"
  vars = {
    services  = join(",",var.services)
    passwords = join(",",var.passwords)
  }
}

resource "aws_instance" "grafana_nodes" {
  ...
  user_data = data.template_file.config
  ...
}  

用户数据脚本(init/configure)

#!/bin/bash
declare -a services_array
services_array=($(echo "${services}" | tr "," " "))

declare -a passwords_array
passwords_array=($(echo "${passwords}" | tr "," " "))

sudo echo "${services_array[@]}" >> /tmp/isp_services_array.txt
sudo echo "${passwords_array[@]}" >> /tmp/influx_db_passwords_array.txt

报错信息

Error: failed to render : <template_file>:8,29-30: Invalid character; This character is not used within the language., and 2 other diagnostic(s)
│ 
│   with module.mymodule.data.template_file.configure,
│   on modules/mymodule/main.tf line 417, in data "template_file" "configure":
│  417: data "template_file" "configure" {

错误原因

  1. 模板语法错误:template = "${file("${path.module}/init/configure")}" 中嵌套的双引号导致Terraform解析失败。Terraform 0.12+版本中,file()函数本身已是插值表达式,无需再嵌套${}。
  2. template_file已被弃用:Terraform官方推荐使用内置的templatefile()函数替代data "template_file",后者属于旧版资源,语法限制更多。
  3. 资源引用错误:aws_instance中user_data引用的data.template_file.config是错误的,template_file资源的正确输出字段为rendered。

正确实现方式

方式一:修复现有template_file配置

修改data "template_file"的语法错误及资源引用:

data "template_file" "configure" {
  template = file("${path.module}/init/configure") # 移除外层多余的${}
  vars = {
    services  = join(",",var.services)
    passwords = join(",",var.passwords)
  }
}

resource "aws_instance" "grafana_nodes" {
  ...
  user_data = data.template_file.configure.rendered # 修正为正确的输出字段
  ...
}  

方式二:使用推荐的templatefile()函数(更健壮)

直接用templatefile()替代旧的template_file资源,同时优化数组传递逻辑,避免脚本中手动分割字符串的潜在问题:

  1. 修改Terraform代码:
variable "services" {
   type = list(string)
   default = ["Service1", "Service2", "service3"]
}

variable "passwords" {
   type = list(string)
   default = ["Password1", "Password2", "Password3"]
}

resource "aws_instance" "grafana_nodes" {
  ...
  user_data = templatefile("${path.module}/init/configure", {
    services  = var.services
    passwords = var.passwords
  })
  ...
}  
  1. 修改用户数据脚本(通过Terraform模板直接生成bash数组):
#!/bin/bash
# 直接由Terraform模板生成bash数组,无需手动分割字符串
declare -a services_array=(
%{ for s in services ~}
"${s}"
%{ endfor ~}
)

declare -a passwords_array=(
%{ for p in passwords ~}
"${p}"
%{ endfor ~}
)

sudo echo "${services_array[@]}" >> /tmp/isp_services_array.txt
sudo echo "${passwords_array[@]}" >> /tmp/influx_db_passwords_array.txt

这种方式的优势:

  • 避免了字符串分割可能带来的问题(比如元素包含空格、逗号等特殊字符)
  • 代码更简洁,符合Terraform最新最佳实践

额外注意事项

  • 若数组元素包含特殊字符(如空格、引号),方式二的模板生成逻辑会自动处理,确保bash数组解析正确;而方式一中的join(",", ...)会在元素含逗号时失效,因此方式二更健壮。
  • 确保用户数据脚本包含#!/bin/bash shebang,保证EC2实例能正确识别脚本类型。

内容的提问来源于stack exchange,提问作者Marco Ferrara

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 09:03:16