如何使用 Terraform 在 remote-exec 中运行节点应用程序

How to run node app inside remote-exec using Terraform

提问人:Wendy Rojas 提问时间:4/18/2023 更新时间:4/18/2023 访问量:345

问:

我想通过在 Terraform 脚本的 remote-exec 中配置节点应用程序的步骤来自动运行节点应用程序。但是,当我运行“terraform apply -auto-approve”时,我得到一个“仍在创建...[10 分 21 秒已过]“消息,直到它崩溃。

这是我正在使用的脚本:

resource "aws_instance" "server_1" {
  ami                     = "ami-<id>"
  instance_type           = "t3.micro"
  associate_public_ip_address = true
  key_name = "server_1_kp"
  iam_instance_profile = aws_iam_instance_profile.ec2_access_profile.name
  
  root_block_device {
    volume_size = 25
  }

  connection {
      type        = "ssh"
      user        = "centos"
      private_key = file("server_1_kp.pem")
      host        = self.public_ip
  }

  provisioner "remote-exec" {
    inline = [
      "echo 'Installing Git'",
      "sudo yum -y install git",
      "sudo yum install awscli -y",
      "git config --global credential.helper '!aws codecommit credential-helper $@'",
      "git config --global credential.UseHttpPath true",
      "git clone https://git-codecommit.us-east-1.amazonaws.com/v1/repos/server-1",
      "curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash",
      "source ~/.bashrc",
      "nvm install 16.18.1",
      "cd server-1-app",
      "npm install",
      "npm run dev / node src/index.js ",
      "echo 'node server.js > /dev/null 2>&1' > app.sh",
      "nohup ./app.sh"
    ]
  }
}

我得到的输出:

aws_instance.server-1: Still creating... [12m51s elapsed]
aws_instance.server-1: Still creating... [13m1s elapsed]
aws_instance.server-1: Still creating... [13m11s elapsed]
aws_instance.server-1: Still creating... [13m21s elapsed]
aws_instance.server-1: Still creating... [13m31s elapsed]
aws_instance.server-1: Still creating... [13m41s elapsed]
aws_instance.server-1: Still creating... [13m51s elapsed]
aws_instance.server-1: Still creating... [14m1s elapsed]
aws_instance.server-1: Still creating... [14m11s elapsed]
aws_instance.server-1: Still creating... [14m21s elapsed]
aws_instance.server-1: Still creating... [14m31s elapsed]
aws_instance.server-1: Still creating... [14m41s elapsed]
aws_instance.server-1: Still creating... [14m51s elapsed]
aws_instance.server-1: Still creating... [15m1s elapsed]
aws_instance.server-1: Still creating... [15m11s elapsed]
aws_instance.server-1: Still creating... [15m21s elapsed]
aws_instance.server-1: Still creating... [15m31s elapsed]
aws_instance.server-1: Still creating... [15m41s elapsed]
aws_instance.server-1: Still creating... [15m51s elapsed]

我试图执行这些命令来代替以下命令:

新选项 原始值
npm 运行开发 / 节点 src/index.js “echo '节点服务器.js > /dev/null 2>&1' > app.sh”, “nohup ./app.sh”
nohup 节点服务器.js > /dev/null 2>&1 & =
节点 .js terraform Terraform-provider-AWS 远程执行

评论

1赞 Paolo 4/18/2023
为什么不使用用户数据?

答:

1赞 Martin Atkins 4/18/2023 #1

在 Terraform 中,置备器是最后的手段,因为它们意味着所有额外的复杂性,您需要确保 Terraform CLI 可以通过 SSH 直接连接到 EC2 实例,可以成功执行所有命令,并干净地退出。

您描述的情况似乎可以通过 Terraform 文档中推荐的另外两个选项之一来解决:

我将在这里重点介绍第一个选项,因为它最接近您已经尝试过的选项,但如果您想了解有关该部分选项的更多信息,您可以参考 HashiCorp Tutorial Provision Infrastructure with Packer

“正在将数据传递到虚拟机...”文档部分列出了适用于不同云平台的一些不同方法。您使用的是 Amazon EC2,因此以下要点与您相关:

以下是与您的 EC2 实例(而不是块)一起使用的示例:user_dataprovisioner

resource "aws_instance" "server_1" {
  ami                     = "ami-<id>"
  instance_type           = "t3.micro"
  associate_public_ip_address = true
  key_name = "server_1_kp"
  iam_instance_profile = aws_iam_instance_profile.ec2_access_profile.name
  
  root_block_device {
    volume_size = 25
  }

  connection {
      type        = "ssh"
      user        = "centos"
      private_key = file("server_1_kp.pem")
      host        = self.public_ip
  }

  user_data = <<-EOT
    #!/bin/sh
    echo 'Installing Git'
    sudo yum -y install git
    sudo yum install awscli -y
    git config --global credential.helper '!aws codecommit credential-helper $@'
    git config --global credential.UseHttpPath true
    git clone https://git-codecommit.us-east-1.amazonaws.com/v1/repos/server-1
    curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash
    source ~/.bashrc
    nvm install 16.18.1
    cd server-1-app
    npm install
    npm run dev / node src/index.js
    echo 'node server.js > /dev/null 2>&1' > app.sh
    nohup ./app.sh
  EOT
}

请注意,这只是要运行的脚本。这假定您在参数中选择的 AMI 配置为在其启动过程中运行 cloud-init,这对于官方 Linux 发行版映像(例如 Ubuntu、Red Hat 和 Amazon 提供的映像)来说是典型的。user_dataami

纯脚本是 cloud-init 支持的user_data格式之一,因此它将在 EC2 实例的启动过程中检索并运行此脚本,而无需涉及 Terraform。


另外,请注意,这不是在生产环境中运行服务器的典型方法,因为在这种情况下,如果程序崩溃,则没有任何监督程序来重新启动它。nohup

虽然这是证明这个概念的合理方法,但如果你打算在生产中使用它,我建议研究如何与你所选择的操作系统的服务管理器集成 - 它通常是现代Linux发行版的systemd - 这样它就可以负责启动你的进程并监视它,以便在它崩溃时可以自动重新启动它, 等。nohup