在 Terraform 中创建随机变量并将其传递给 GCE 启动脚本

Create random variable in Terraform and pass it to GCE startup script

我想在使用 Terraform 创建 GCE 实例时运行一个metadata_startup_script

这个脚本应该创建一个用户并为这个用户分配一个随机密码。

我知道我可以在 Terraform 中创建一个随机字符串,例如:

resource "random_string" "pass" {
  length  = 20
}

而我的 startup.sh 有时会像这样:

echo myuser:${PSSWD} | chpasswd

如何通过 metadata_startup_script 参数将 random_string 资源生成与适当的脚本调用链接在一起?

这里是 google_compute_instance 资源定义:

resource "google_compute_instance" "coreos-host" {
  name         = "my-vm"
  machine_type = "n1-stantard-2"
  zone         = "us-central1-a"

  boot_disk {
    initialize_params {
      image = "debian-cloud/debian-9"
      size = 20
      type = "pd-standard"
    }
  }

  network_interface {
    network = "default"

    access_config {
        network_tier = "STANDARD"
    }
  }

  metadata_startup_script = "${file("./startup.sh")}"

}

其中 startup.sh 包括以上行以非交互方式设置密码。

如果要将 Terraform 变量传递到模板文件中,则需要使用模板。

在 Terraform <0.12 中,您需要像这样使用 template_file data source

resource "random_string" "pass" {
  length  = 20
}

data "template_file" "init" {
  template = "${file("./startup.sh")}"
  vars = {
    password = "${random_string.pass.result}"
  }
}

resource "google_compute_instance" "coreos-host" {
  name         = "my-vm"
  machine_type = "n1-stantard-2"
  zone         = "us-central1-a"

  boot_disk {
    initialize_params {
      image = "debian-cloud/debian-9"
      size = 20
      type = "pd-standard"
    }
  }

  network_interface {
    network = "default"

    access_config {
        network_tier = "STANDARD"
    }
  }

  metadata_startup_script = "${data.template_file.startup_script.rendered}"
}

并将您的 startup.sh 脚本更改为:

echo myuser:${password} | chpasswd

请注意,模板使用 ${} 对 Terraform 传递到脚本中的变量进行插值。如果您需要在脚本中的其他任何地方使用 $,那么您需要通过使用 $$ 来转义它,以便在呈现的脚本中获得文字 $

在 Terraform 0.12+ 中有新的 templatefile function,如果您愿意,可以使用它代替 template_file 数据源:

resource "random_string" "pass" {
  length  = 20
}

resource "google_compute_instance" "coreos-host" {
  name         = "my-vm"
  machine_type = "n1-stantard-2"
  zone         = "us-central1-a"

  boot_disk {
    initialize_params {
      image = "debian-cloud/debian-9"
      size = 20
      type = "pd-standard"
    }
  }

  network_interface {
    network = "default"

    access_config {
        network_tier = "STANDARD"
    }
  }

  metadata_startup_script = templatefile("./startup.sh", {password = random_string.pass.result})
}

顺便说一句,您还应该注意 random_string:

上的警告

This resource does use a cryptographic random number generator.

Historically this resource's intended usage has been ambiguous as the original example used it in a password. For backwards compatibility it will continue to exist. For unique ids please use random_id, for sensitive random values please use random_password.

因此您应该使用 random_password resource:

resource "random_password" "password" {
  length = 16
  special = true
  override_special = "_%@"
}