【问题标题】:Custom Packer AMI does not execute user_data specified by TerraformCustom Packer AMI 不执行 Terraform 指定的 user_data
【发布时间】:2022-02-04 22:16:49
【问题描述】:

我目前正在努力让 user_data 脚本在使用 Terraform 启动 EC2 实例时运行。我使用 Packer 预先配置了我的 AMI,并在我的 Terraform 文件中引用了自定义 AMI。由于在启动 EC2 实例时我现在需要 RDS 实例 URL,因此我尝试在 user_data 脚本中读取它们并将它们设置为环境变量。我的应用程序尝试读取这些环境变量并可以连接到数据库。一切都按预期在本地运行,并在运行测试时在 CI 上运行。手动设置变量并启动应用程序也可以按预期工作。唯一的问题是 user_data 脚本的执行,因为它在使用 Packer 创建 AMI 时已经运行。

注意我是如何在 Terraform 中读取当前数据库状态的,这就是为什么我不能使用会导致 user_data 脚本再次执行的传统方法。我还尝试按照this questionthis one 中的说明删除云数据,但没有成功。

这是我当前的 Packer 配置:

build {
  name    = "spring-ubuntu"
  sources = [
    "source.amazon-ebs.ubuntu"
  ]

  provisioner "file" {
    source      = "build/libs/App.jar"
    destination = "~/App.jar"
  }

  provisioner "shell" {
    inline = [
      "sleep 30",
      "sudo apt update",
      "sudo apt -y install openjdk-17-jdk",
      "sudo rm -Rf /var/lib/cloud/data/scripts",
      "sudo rm -Rf /var/lib/cloud/scripts/per-instance",
      "sudo rm -Rf /var/lib/cloud/data/user-data*",
      "sudo rm -Rf /var/lib/cloud/instances/*",
      "sudo rm -Rf /var/lib/cloud/instance",
    ]
  }
}

这是我当前的 Terraform 配置:

resource "aws_instance" "instance" {
  ami                    = "ami-123abc"
  instance_type          = "t2.micro"
  subnet_id              = tolist(data.aws_subnet_ids.all.ids)[0]
  vpc_security_group_ids = [aws_security_group.ec2.id]
  user_data              = <<EOF
                          #!/bin/bash
                          export DB_HOST=${data.terraform_remote_state.state.outputs.db_address}
                          export DB_PORT=${data.terraform_remote_state.state.outputs.db_port}
                          java -jar ~/App.jar
                          EOF

  lifecycle {
    create_before_destroy = true
  }
}

【问题讨论】:

  • 启动一个之前关闭的 EC2 实例还是启动一个全新的 EC2 实例?
  • 使用预配置的 AMI 启动全新的 ec2
  • 啊,好的,所以您在预烘焙的 AMI 中使用了 user_data,现在当您想要覆盖原始的 user_data 时,它什么都不做?
  • 完全正确。问题是,我需要在运行 jar 之前将 RDS URL 设置为环境变量..
  • 我知道应该少用,但remote-exec 会更好用吗?

标签: linux amazon-web-services terraform devops


【解决方案1】:

我尝试使用Marko E 建议的 remote-exec 配置程序运行命令。起初它失败并出现以下错误,但经过第二次尝试,它成功了。

This object does not have an attribute named "db_address".
This object does not have an attribute named "db_port".

这是工作配置

resource "aws_instance" "instance" {
  ami                    = "ami-0ed33809ce5c950b9"
  instance_type          = "t2.micro"
  key_name               = "myKeys"
  subnet_id              = tolist(data.aws_subnet_ids.all.ids)[0]
  vpc_security_group_ids = [aws_security_group.ec2.id]

  lifecycle {
    create_before_destroy = true
  }

  connection {
    type        = "ssh"
    user        = "ubuntu"
    private_key = file("~/Downloads/myKeys.pem")
    host        = self.public_ip
  }

  provisioner "remote-exec" {
    inline = [
      "export DB_HOST=${data.terraform_remote_state.state.outputs.db_address}",
      "export DB_PORT=${data.terraform_remote_state.state.outputs.db_port}",
      "java -jar ~/App.jar &",
    ]
  }
}

【讨论】:

  • 我唯一要改变的是定义局部变量,例如 db_addressdb_port 并分配这些值,而不是直接在配置器中使用 data 源。 :) 很高兴它有所帮助。 :)
  • 我现在有另一个问题,脚本运行但完成后取消正在运行的应用程序。我在命令后使用 nohup 和 & 运行:nohup java -jar ~/.App.jar &
  • 最后添加 sleep 30 会有所帮助
猜你喜欢
  • 2019-01-23
  • 2019-06-28
  • 1970-01-01
  • 2021-03-08
  • 2013-12-02
  • 2021-12-10
  • 2021-11-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多