如何使用 Terraform 输出管理基础设施数据

介绍

Terraform输出用于从项目状态中提取有关基础设施资源的信息。使用 Terraform 使用的 Hashicorp 配置语言 (HCL) 的其他功能,可以查询资源信息并将其转换为更复杂的数据结构,例如列表和地图。输出对于向外部软件提供信息很有用,这些软件可以对创建的基础设施资源进行操作。

在本教程中,您将通过创建部署 Droplet 的简单基础架构来了解 Terraform 输出语法及其参数。您还将通过将输出转换为 JSON 以编程方式解析输出。

先决条件

注意:本教程已经专门使用 Terraform 进行了测试0.13

定义输出

在本节中,您将声明一个 Droplet,将其部署到云中,并通过定义一个将显示 Droplet 的 IP 地址的输出来了解输出。

假设您在terraform-outputs目录中,创建并打开droplets.tf文件进行编辑:

  • nano droplets.tf

添加以下 Droplet 资源和输出定义:

terraform-outputs/droplets.tf
resource "digitalocean_droplet" "web" {
  image  = "ubuntu-18-04-x64"
  name   = "test-droplet"
  region = "fra1"
  size   = "s-1vcpu-1gb"
}

output "droplet_ip_address" {
  value = digitalocean_droplet.web.ipv4_address
}

首先声明一个名为web. 它在云中的实际名称将是test-droplet,在该地区fra1,运行 Ubuntu 18.04。

然后,您声明一个名为droplet_ip_address. 在 Terraform 中,输出用于导出和显示有关资源的内部和计算值以及信息。在这里,您将value接受要输出的数据参数设置 为声明的 Droplet 的 IP 地址。在声明时,它是未知的,但是一旦部署了 Droplet,它就会变得可用。每次部署后都会显示和访问输出。

保存并关闭文件,然后通过运行以下命令部署项目:

  • terraform apply -var "do_token=${DO_PAT}"

yes出现提示时输入以应用。您将看到的输出的结尾与此类似:

Output
... digitalocean_droplet.web: Creating... ... digitalocean_droplet.web: Creation complete after 32s [id=207631771] Apply complete! Resources: 1 added, 0 changed, 0 destroyed. Outputs: droplet_ip_address = ip_address

突出显示的 IP 地址属于您新部署的 Droplet。当所有资源属性都可用时,应用项目会将资源部署到云并在最后显示输出。如果没有droplet_ip_address输出,Terraform 将不会显示有关 Droplet 的更多信息,除了它已部署。

也可以使用以下output命令显示输出

  • terraform output

输出将列出outputs项目中的所有内容:

Output
droplet_ip_address = ip_address

您还可以通过将其指定为参数来按名称查询特定输出:

  • terraform output output_name

对于droplet_ip_address,输出将仅包含 IP 地址:

Output
ip_address

除了指定 required 之外value,输出还有一些可选参数:

  • description:嵌入了详细说明输出内容的简短文档。
  • sensitive: 接受一个布尔值,如果设置为 ,则防止在部署后显示输出的内容true
  • depends_on:每个资源可用的元参数,允许您明确指定输出所依赖的资源,Terraform 在规划期间无法自动推断。

sensitive当 Terraform 部署的日志将公开可用时,参数很有用,但输出内容应保持隐藏。您现在将把它添加到您的 Droplet 资源定义中。

打开droplets.tf以进行编辑并添加突出显示的行:

terraform-outputs/droplets.tf
resource "digitalocean_droplet" "web" {
  image  = "ubuntu-18-04-x64"
  name   = "test-droplet"
  region = "fra1"
  size   = "s-1vcpu-1gb"
}

output "droplet_ip_address" {
  value      = digitalocean_droplet.web.ipv4_address
  sensitive = true
}

完成后保存并关闭文件。您可以通过运行以下命令再次尝试部署项目:

  • terraform apply -var "do_token=${DO_PAT}"

您将看到输出已被编辑:

Output
digitalocean_droplet.web: Refreshing state... [id=207631771] Apply complete! Resources: 0 added, 0 changed, 0 destroyed. Outputs: droplet_ip_address = <sensitive>

即使标记为sensitive,输出及其内容仍可通过其他渠道获得,例如查看 Terraform 状态或直接查询输出。

在下一步中,您将创建不同的 Droplet 和输出结构,因此通过运行以下命令销毁当前部署的结构:

  • terraform destroy -var "do_token=${DO_PAT}"

最后的输出将是:

Output
... Destroy complete! Resources: 1 destroyed.

您已经声明并部署了一个 Droplet,并创建了一个显示其 IP 地址的输出。您现在将了解如何使用输出来显示更复杂的结构,例如列表和地图。

输出复杂结构

在本节中,您将使用count关键字从同一定义部署多个 Droplet ,并以各种格式输出它们的 IP 地址。

使用for循环

你需要修改 Droplet 资源定义,所以打开它进行编辑:

  • nano droplets.tf

将其修改为如下所示:

terraform-outputs/droplets.tf
resource "digitalocean_droplet" "web" {
  count  = 3
  image  = "ubuntu-18-04-x64"
  name   = "test-droplet-${count.index}"
  region = "fra1"
  size   = "s-1vcpu-1gb"
}

您已指定应使用count密钥创建三个 Droplet ,并将当前索引添加到 Droplet 名称,以便您以后能够区分它们。完成后,保存并关闭文件。

通过运行应用代码:

  • terraform apply -var "do_token=${DO_PAT}"

Terraform将计划建立三个编号的液滴,叫test-droplet-0test-droplet-1test-droplet-2输入yes提示完成该过程时。最后你会看到以下输出:

Output
... Apply complete! Resources: 3 added, 0 changed, 0 destroyed.

这意味着所有三个 Droplet 都已成功部署,并且有关它们的所有信息都存储在项目状态中。

访问它们的资源属性的最简单方法是使用输出,尽管为每个 Droplet 创建一个是不可扩展的。解决方案是使用for循环遍历 Droplet 列表并收集它们的属性,或者使用splat 表达式您将在此步骤的稍后部分了解它们。

您将首先定义一个输出,该输出将输出三个 Droplet 的 IP 地址,并与其名称配对。打开droplets.tf编辑:

  • nano droplets.tf

添加以下几行:

terraform-outputs/droplets.tf
resource "digitalocean_droplet" "web" {
  count  = 3
  image  = "ubuntu-18-04-x64"
  name   = "test-droplet-${count.index}"
  region = "fra1"
  size   = "s-1vcpu-1gb"
}

output "droplet_ip_addresses" {
  value = {
    for droplet in digitalocean_droplet.web:
    droplet.name => droplet.ipv4_address
  }
}

的输出值droplet_ip_addresses是使用for循环构造的因为它被大括号包围,所以结果类型将是一个映射。该循环遍历 Droplet 列表,对于每个实例,将其名称与其 IP 地址配对,并将其附加到结果映射中。

保存并关闭文件,然后再次尝试应用该项目:

  • terraform apply -var "do_token=${DO_PAT}"

输入yes提示时,你会收到在最后的输出内容:

Output
Apply complete! Resources: 0 added, 0 changed, 0 destroyed. Outputs: droplet_ip_addresses = { "test-droplet-0" = "ip_address" "test-droplet-1" = "ip_address" "test-droplet-2" = "ip_address" }

droplet_ip_addresses输出的详细三个部署液滴的IP地址。

使用 Terraformoutput命令,您可以使用其命令参数以 JSON格式获取输出内容:

  • terraform output -json droplet_ip_addresses

结果将类似于以下内容:

Output
{"test-droplet-0":"ip_address","test-droplet-1":"ip_address","test-droplet-2":"ip_address"}

JSON 解析在许多编程语言中被广泛使用和支持。这样,您就可以以编程方式解析有关已部署的 Droplet 资源的信息。

使用 Splat 表达式

Splat 表达式提供了一种紧凑的方式来迭代列表的所有元素,并从每个元素中收集属性的内容,从而生成一个列表。提取三个部署的 Droplet 的 IP 地址的 splat 表达式将具有以下语法:

digitalocean_droplet.web[*].ipv4_address

[*]符号遍历其左侧的列表,并为每个元素获取其右侧指定的属性的内容。如果左边的引用本身不是一个列表,它将被转换为一个唯一的元素。

您可以打开droplets.tf以进行编辑和修改以下行以实现此目的:

terraform-outputs/droplets.tf
resource "digitalocean_droplet" "web" {
  count  = 3
  image  = "ubuntu-18-04-x64"
  name   = "test-droplet-${count.index}"
  region = "fra1"
  size   = "s-1vcpu-1gb"
}

output "droplet_ip_addresses" {
  value = digitalocean_droplet.web[*].ipv4_address
}

保存文件后,通过运行以下命令来应用项目:

  • terraform apply -var "do_token=${DO_PAT}"

您将收到现在是一个列表的输出,并且只包含 Droplets 的 IP 地址:

Output
Apply complete! Resources: 0 added, 0 changed, 0 destroyed. Outputs: droplet_ip_addresses = [ "ip_address", "ip_address", "ip_address", ]

要以 JSON 格式接收输出,请运行以下命令:

  • terraform output -json droplet_ip_addresses

输出将是单个数组:

Output
["ip_address","ip_address","ip_address"]

您已经将输出与 splat 表达式和for循环一起使用来导出部署的 Droplet 的 IP 地址。您还收到了 JSON 格式的输出内容,现在您将使用jq一种根据给定表达式动态过滤 JSON 的工具来解析它们。

使用解析输出 jq

在此步骤中,您将安装并学习jqJSON 文档操作工具的基础知识您将使用它来解析 Terraform 项目的输出。

如果您使用的是 Ubuntu,请运行以下命令进行安装jq

  • sudo snap install jq

在 macOS 上,你可以使用Homebrew来安装它:

  • brew install jq

jq在给定的输入上应用提供的处理表达式,可以通过管道输入。最简单的任务jq是漂亮地打印输入:

  • terraform output -json droplet_ip_addresses | jq '.'

传入身份运算符 ( .) 意味着从输入中解析出的整个 JSON 文档应该不加修改地输出:

Output
[ "first_ip_address", "second_ip_address", "third_ip_address" ]

您可以使用数组括号表示法请求第二个 IP 地址,从零开始计数:

  • terraform output -json droplet_ip_addresses | jq '.[1]'

输出将是:

Output
"second_ip_address"

要使处理结果成为数组,请将表达式括在括号中:

  • terraform output -json droplet_ip_addresses | jq '[.[1]]'

你会得到一个漂亮的 JSON 数组:

Output
[ "second_ip_address" ]

您可以通过在括号内指定索引范围来检索数组的一部分而不是单个元素:

  • terraform output -json droplet_ip_addresses | jq '.[0:2]'

输出将是:

Output
[ "first_ip_address", "second_ip_address" ]

范围0:2返回前两个元素——范围的上半部分 ( 2) 不包括在内,因此只获取位置0位置的元素1

您现在可以通过运行以下命令销毁已部署的资源:

  • terraform destroy -var "do_token=${DO_PAT}"

在此步骤中,您已安装jq并使用它来解析和操作 Terraform 项目的输出,该项目部署了三个 Droplet。

结论

您已经了解了 Terraform 输出,如何使用它们显示有关已部署资源的详细信息,以及如何使用它们导出数据结构以供以后外部处理。您还看到了如何使用输出来显示单个资源的属性,以及如何显示构建的地图和包含资源属性的列表。

有关 的功能的更多详细信息jq,请访问官方文档

要了解有关 Terraform 的更多信息,请查看系列:如何使用 Terraform 管理基础设施

觉得文章有用?

点个广告表达一下你的爱意吧 !😁