【问题标题】:Using function templatefile(path, vars) with a remote-exec provisioner将函数 templatefile(path, vars) 与 remote-exec 供应商一起使用
【发布时间】:2019-12-21 02:00:00
【问题描述】:

在 terraform 0.12 中,有一个 templatefile 函数,但我还没有弄清楚将非平凡映射作为第二个参数传递给它并使用远程执行的结果作为新创建实例的配置步骤的语法。

这是我正在尝试做的事情的要点,尽管它不能正确解析,因为不能只在名为 scriptstr 的资源块中创建一个局部变量。

虽然我真的在尝试获取要在远程端执行的模板文件调用的输出,但一旦供应商可以通过 ssh 连接到机器,到目前为止,我已经走上了尝试获取模板文件调用的道路通过 local-exec 配置器将输出写入本地文件。可能很容易,我只是没有找到文档或示例来理解必要的语法。 TIA

resource "aws_instance" "server" {
  count = "${var.servers}"

  ami           = "${local.ami}"
  instance_type = "${var.instance_type}"
  key_name      = "${local.key_name}"

  subnet_id              = "${element(aws_subnet.consul.*.id, count.index)}"
  iam_instance_profile   = "${aws_iam_instance_profile.consul-join.name}"
  vpc_security_group_ids = ["${aws_security_group.consul.id}"]

  ebs_block_device {
    device_name = "/dev/sda1"
    volume_size = 2
  }

  tags = "${map(
    "Name", "${var.namespace}-server-${count.index}",
    var.consul_join_tag_key, var.consul_join_tag_value
  )}"

  scriptstr = templatefile("${path.module}/templates/consul.sh.tpl",
      {
        consul_version = "${local.consul_version}"

        config = <<EOF
         "bootstrap_expect": ${var.servers},
         "node_name": "${var.namespace}-server-${count.index}",
         "retry_join": ["provider=aws tag_key=${var.consul_join_tag_key} tag_value=${var.consul_join_tag_value}"],
         "server": true
        EOF
      })

  provisioner "local-exec" {
    command = "echo ${scriptstr} > ${var.namespace}-server-${count.index}.init.sh"
  }

  provisioner "remote-exec" {
    script = "${var.namespace}-server-${count.index}.init.sh"

    connection {
      type     = "ssh"
      user     = "clear"
      private_key = file("${local.private_key_file}")
    }
  }
}

【问题讨论】:

  • 你为什么要在那里而不是在本地呢?我不知道它是否会像在本地一样工作,但很困惑你为什么要尝试目前的方法。
  • 猜我不知道如何在资源中创建本地。全局本地将无权访问资源的 count.index。

标签: terraform


【解决方案1】:

在您的问题中,我可以看到您似乎在这里试图解决的更高级别的问题是创建一个 HashiCorp Consul 服务器池,然后,一旦它们全部启动,就可以告诉它们彼此,以便它们可以形成一个集群。

Provisioner 本质上是 Terraform 中的“最后手段”,出于实用主义考虑,因为有时登录主机并在其上运行命令是完成工作的唯一方法。在这种情况下,另一种可用的方法是通过 aws_instance user_data 参数将信息从 Terraform 传递到服务器,这将允许服务器立即启动并形成集群,而不是延迟到 Terraform 能够通过 SSH 连接。

无论哪种方式,我通常都希望我打算运行的脚本主体已经包含在 AMI 中,以便 Terraform 可以使用一些参数运行它,因为这样可以将问题减少到只是模板化调用该脚本而不是整个脚本:

  provisioner "remote-exec" {
    inline = ["/usr/local/bin/init-consul --expect='${var.servers}' etc, etc"]

    connection {
      type     = "ssh"
      user     = "clear"
      private_key = file("${local.private_key_file}")
    }
  }

但是,如果模板化整个脚本是您想要或需要做的,我会先使用 file 配置器上传它,然后运行它,如下所示:

  provisioner "file" {
    destination = "/tmp/consul.sh"
    content = templatefile("${path.module}/templates/consul.sh.tpl", {
        consul_version = "${local.consul_version}"

        config = <<EOF
         "bootstrap_expect": ${var.servers},
         "node_name": "${var.namespace}-server-${count.index}",
         "retry_join": ["provider=aws tag_key=${var.consul_join_tag_key} tag_value=${var.consul_join_tag_value}"],
         "server": true
        EOF
    })
  }

  provisioner "remote-exec" {
    inline = ["sh /tmp/consul.sh"]
  }

【讨论】:

  • 感谢您提供详细信息。我已经离开了 user_data 的角度,因为它不起作用,但其他东西也仍然坏了。现在已经设置好并使用文件和配置步骤(但不如您的解决方案干净),我已经回到 user_data 方法,仍然发现 aws 实例没有创建脚本。 aws 控制台正确地向我显示了 user_data。我在 /var/lib/cloud/aws-user-data 文件的第二部分看到了它。但是没有创建 /var/lib/cloud/instances 目录,也没有 /usr/log/cloud-init-output.log。也许 clearlinux ami ...
猜你喜欢
  • 1970-01-01
  • 2010-10-26
  • 2019-12-11
  • 1970-01-01
  • 2021-12-16
  • 1970-01-01
  • 1970-01-01
  • 2017-12-13
  • 1970-01-01
相关资源
最近更新 更多