【问题标题】:Error using user_data when creating instance in terrafom在 terraform 中创建实例时使用用户数据时出错
【发布时间】:2020-05-28 18:08:44
【问题描述】:

Terraform 版本 = 0.12

resource "aws_instance" "bespin-ec2-web" {
  ami = "ami-0bea7fd38fabe821a"
  instance_type = "t2.micro"
  vpc_security_group_ids = [aws_security_group.bespin-sg.id]
  subnet_id = aws_subnet.bespin-subnet-private-a.id
  associate_public_ip_address = true
  tags = {
    Name = "bespin-ec2-web-a"
  }
  user_data = <<EOF
   #!/bin/bash
   USERS="bespin"
   GROUP="bespin"
   for i in $USERS; do
   adduser ${i} -g ${GROUP};
   echo ${i}:${i}1! | chpasswd;

   cp -a /etc/ssh/sshd_config /etc/ssh/sshd_config_old
   sed -i 's/PasswordAuthentication no/#PasswordAuthentication no/' /etc/ssh/sshd_config
   sed -i 's/#PasswordAuthentication yes/PasswordAuthentication yes/' /etc/ssh/sshd_config
   systemctl restart sshd
EOF
}

为什么我在运行 terraform plan 时会出错?

错误:引用无效

在 instance.tf 第 15 行,资源“aws_instance”“bespin-ec2-web”中: 15: 添加用户 ${i} -g ${GROUP};

对资源类型的引用必须后跟至少一个属性 访问,指定资源名称。

错误:引用无效

在 instance.tf 第 15 行,资源“aws_instance”“bespin-ec2-web”中: 15: 添加用户 ${i} -g ${GROUP};

对资源类型的引用必须后跟至少一个属性 访问,指定资源名称。

【问题讨论】:

  • 如果你想保持内联,你需要用另一个$ 转义${}。此外,您不应该在 HEREDOC 内缩进。
  • 谢谢已解决。谢谢!

标签: amazon-web-services terraform instance


【解决方案1】:

此处错误的直接原因是${ ... }Terraform's string template interpolation syntax,因此Terraform 将${GROUP} 理解为尝试插入表达式GROUP,这不是有效的Terraform 表达式。正如错误消息所暗示的那样,Terraform 将 GROUP 理解为一种资源类型,就好像这是 aws_instance.foo 等引用的第一部分。

解决此问题的最小更改是通过在前面添加额外的$ 来转义${ ... } 序列,以便文字${GROUP} 可以传递给user_data 值:

  user_data = <<-EOF
   #!/bin/bash
   USERS="bespin"
   GROUP="bespin"
   for i in $USERS; do
   adduser ${i} -g $${GROUP};
   echo $${i}:$${i}1! | chpasswd;

   cp -a /etc/ssh/sshd_config /etc/ssh/sshd_config_old
   sed -i 's/PasswordAuthentication no/#PasswordAuthentication no/' /etc/ssh/sshd_config
   sed -i 's/#PasswordAuthentication yes/PasswordAuthentication yes/' /etc/ssh/sshd_config
   systemctl restart sshd
  EOF

请注意,只有${ ... } 需要转义,$USERS 之类的序列不需要转义:Terraform 不会将单个美元符号解释为特殊字符,因此它将始终按字面意思传递。


这个特定的user_data 表达式是完全静态的,不包含任何预期 Terraform 模板语法,因此可以通过将user_data 值移动到单独的文件中来完全避免转义,并且使用the file function 从字面上获取该文件的内容(根本没有模板解释):

  user_data = file("${path.module}/user_data.sh")

有时user_data 确实需要在 Terraform 配置中包含从其他地方插入的数据,并与 shell 语法混合。可以使用如上所述的转义来做到这一点,但是随着所需的字符串变得更加复杂,将包含插值的部分与文字部分分开会很有用,以便两全其美并避免在脚本主体:

  user_data = <<-EOT
    EXAMPLE_VARIABLE='${var.example}'
    ${file("${path.module}/user_data.sh")}
  EOT

【讨论】:

    【解决方案2】:

    user_data 应该与模板渲染一起传递,或者您也可以使用 base64encode 函数来传递您的文件。

    data "template_file" "user-data" {
      template = file("${path.module}/user-data.sh")
    }
    
    resource "aws_instance" "bespin-ec2-web" {
      ...
      ...
    
      user_data = "${data.template_file.user_data.rendered}"
    
      ...
    }
    

    【讨论】:

      猜你喜欢
      • 2019-06-14
      • 2018-11-17
      • 2021-03-16
      • 1970-01-01
      • 2018-09-26
      • 2021-09-26
      • 1970-01-01
      • 2023-04-02
      • 2021-03-02
      相关资源
      最近更新 更多