【问题标题】:How do I keep terraform's remote-exec shell persistent?如何保持 terraform 的 remote-exec shell 持久化?
【发布时间】:2019-11-07 15:55:37
【问题描述】:

早安,

我正在通过 vSphere with Terraform 上的模板配置虚拟机。虚拟机启动后,文件配置器会复制本地静态内容(图片)。完成后,remote-exec provisioner 会执行以下操作:

provisioner "remote-exec" {
     inline = [
       "mkdir /home/foo/static",
       "mv /home/foo/logo.jpg /home/foo/static/",
       "echo 'python /home/foo/app.py 2>&1 &' > /home/foo/start_app.sh",
       "chmod u+x /home/foo/start_app.sh",
       "/home/foo/start_app.sh 2>&1",
       "sleep 60"
     ]
}

app.py 是一个 Python Flask 项目。代码启动并提供内容正常.. 大约 60 秒。当我的睡眠定时器到期时,我怀疑 Terraform 生成的 shell 会死掉,app.py 也会死掉。我尝试在后台启动 start_app.sh,我尝试 sudo (前台和后台)无济于事。相同的行为。如果我直接在 remote-exec 块内启动 python /home/foo/app.py 而不是调用 start_app.sh,那么 TF 永远不会退出 shell,我的 Jenkins 构建会永远旋转。

我认为这没有什么区别,但要完成我的 TF VMware 计划,当 Git 向 Jenkins 发送一个 webhook 时就会应用它。 Jenkins 调用 TF 计划作为流水线阶段的一部分。这是 Jenkins 的控制台输出:

vsphere_virtual_machine.vm[1]: Provisioning with 'file'...
vsphere_virtual_machine.vm[1]: Provisioning with 'remote-exec'...
vsphere_virtual_machine.vm[1] (remote-exec): Connecting to remote host via SSH...
vsphere_virtual_machine.vm[1] (remote-exec):   Host: 1.1.1.200
vsphere_virtual_machine.vm[1] (remote-exec):   User: foo
vsphere_virtual_machine.vm[1] (remote-exec):   Password: true
vsphere_virtual_machine.vm[1] (remote-exec):   Private key: false
vsphere_virtual_machine.vm[1] (remote-exec):   SSH Agent: false
vsphere_virtual_machine.vm[1] (remote-exec):   Checking Host Key: false
vsphere_virtual_machine.vm[1] (remote-exec): Connected!
vsphere_virtual_machine.vm[1] (remote-exec):  * Serving Flask app "app" (lazy loading)
vsphere_virtual_machine.vm[1] (remote-exec):  * Environment: production
vsphere_virtual_machine.vm[1] (remote-exec):    WARNING: This is a development server. Do not use it in a production deployment.
vsphere_virtual_machine.vm[1] (remote-exec): [2m   Use a production WSGI server inst
vsphere_virtual_machine.vm[1] (remote-exec):  * Debug mode: off
vsphere_virtual_machine.vm[1] (remote-exec):  * Running on http://0.0.0.0:8080/ (Press CTRL+C to quit)
vsphere_virtual_machine.vm.1: Still creating... (8m30s elapsed)
vsphere_virtual_machine.vm.0: Still creating... (8m30s elapsed)
vsphere_virtual_machine.vm.1: Still creating... (8m40s elapsed)
vsphere_virtual_machine.vm.0: Still creating... (8m40s elapsed)
vsphere_virtual_machine.vm.1: Still creating... (8m50s elapsed)
vsphere_virtual_machine.vm.0: Still creating... (8m50s elapsed)
vsphere_virtual_machine.vm.1: Still creating... (9m0s elapsed)
vsphere_virtual_machine.vm.0: Still creating... (9m0s elapsed)
vsphere_virtual_machine.vm.1: Still creating... (9m10s elapsed)
vsphere_virtual_machine.vm.0: Still creating... (9m10s elapsed)
vsphere_virtual_machine.vm[0]: Creation complete after 9m15s (ID: 4228d941-a19c-361d-073a-4441cde5973e)

如何在 TF 的远程执行完成后保持 TF 生成的 shell?

【问题讨论】:

  • 不要这样做。您应该使用操作系统的服务机制将应用程序作为服务运行。在大多数现代 Linux 发行版中,这将是一个 systemd 单元文件。您还应该考虑使用 Packer 之类的工具将这些 remote-exec 步骤烘焙到图像中,这样您就可以完全删除 remote-exec
  • 我正在/正在尝试保持我的 VM 模板尽可能干净,并在实例化时运行代码。这样,我就没有用于 Web 服务器的模板和用于数据库服务器的模板。对于 EC2/Azure 虚拟机,我会使用 Cloud Init 而不是 Packer 生成的 AMI/画廊。
  • 即使您想这样做,您仍然希望将应用程序作为服务运行。这可以完全通过 remote-exec shell 脚本进行配置,但如果您真的想即时配置,我建议您运行诸如 Ansible/Chef 之类的东西。但是,仅仅创建更多的模板/图像来拥有超专业的图像真的不应该是一个大问题。我个人构建了一个基础 AMI(我在 AWS 中运行),然后在此之上为任何特殊的东西创建 AMI(然后我还通过 ECS 在 Docker 中运行应用程序,但如果您不需要它,那就没有必要了)。
  • @ydaetskcoR - 谢谢,我认为这是有道理的。我发现了一个丑陋的黑客,但这只是一个实验室演示,我将在下面回答我自己的问题。

标签: jenkins terraform


【解决方案1】:

好的 - 我发现了一个非常糟糕的 hack。 Terraform 不再运行 remote-exec,它只是使用文件配置器推送我的 python Flask 应用程序及其相关的静态内容。在 Jenkins 内部,我有一个如下所示的阶段:

def remote = [:]
remote.name = "1.1.1.200"
remote.host = "1.1.1.200"
remote.allowAnyHosts = true

node {
    withCredentials([usernamePassword(credentialsId: 'sshUserAccount', passwordVariable: 'password', usernameVariable: 'userName')]) {
        remote.user = userName
        remote.password = password
        stage("SSH Steps Rocks!") {
            try {
              timeout(time: 1, unit: 'MINUTES') {
                sshCommand remote: remote, command: '/home/foo/start_app.sh &' 
              }
            } catch (err){
               currentBuild.result = 'SUCCESS'
              }
        }
   }
}

一旦 Jenkins SSH 线程在一分钟后退出,我的 python 应用程序将继续在远程计算机上运行。耶!这只是一个实验室演示,而不是我考虑在产品中做的事情。我会按照建议使用自定义模板。

【讨论】:

    猜你喜欢
    • 2013-09-17
    • 2012-02-18
    • 1970-01-01
    • 2020-12-19
    • 1970-01-01
    • 2016-11-14
    • 2014-01-31
    • 2011-02-20
    • 1970-01-01
    相关资源
    最近更新 更多