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

pka*_*mol 4 bash google-cloud-platform terraform terraform-provider-gcp

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

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

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

resource "random_string" "pass" {
  length  = 20
}
Run Code Online (Sandbox Code Playgroud)

我的startup.sh意志在某些时候是这样的:

resource "random_string" "pass" {
  length  = 20
}
Run Code Online (Sandbox Code Playgroud)

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

这是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")}"

}
Run Code Online (Sandbox Code Playgroud)

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

yda*_*coR 5

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

在 Terraform <0.12 中,您需要像这样使用template_file数据源

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}"
}
Run Code Online (Sandbox Code Playgroud)

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

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}"
}
Run Code Online (Sandbox Code Playgroud)

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

在 Terraform 0.12+ 中,如果您愿意,可以使用新templatefile函数代替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})
}
Run Code Online (Sandbox Code Playgroud)

顺便说一句,您还应该注意以下警告random_string

此资源确实使用加密随机数生成器。

从历史上看,此资源的预期用途一直不明确,因为原始示例在密码中使用了它。为了向后兼容,它将继续存在。对于唯一的 id,请使用 random_id,对于敏感的随机值,请使用 random_password。

因此,您应该改用random_password资源

resource "random_password" "password" {
  length = 16
  special = true
  override_special = "_%@"
}
Run Code Online (Sandbox Code Playgroud)