介绍
使用Terraform使用的Hashicorp配置语言(HCL)的其他功能,资源信息可以查询并转化为更复杂的数据结构,如列表和地图。
在本教程中,您将通过创建部署 Droplets 的简单基础设施来了解 Terraform 输出语法及其参数。
前提条件
通过DigitalOcean控制面板创建的DigitalOcean个人访问代码(DigitalOcean Personal Access Token),您可以在DigitalOcean产品文档中找到指示(How to Create a Personal Access Token)(https://docs.digitalocean.com/reference/api/create-personal-access-token/)。
*在您的本地机器上安装了Terraform,并与DigitalOcean提供商一起创建了一个项目。 完成How To Use Terraform with DigitalOcean
(https://andsky.com/tech/tutorials/how-to-use-terraform-with-digitalocean)教程的 Step 1和 Step 2,并确保您将项目文件夹命名为terraform-outputs
,而不是load balance
。在 Step 2中,不要包括pvt_key
变量和SSH关键资源
熟悉HCL数据类型和循环
<$>[注]
**注:**本教程已被特定的测试与Terraform 1.0.2
<$>
定义输出
在本节中,您将宣布 Droplet,将其部署到云端,并通过定义一个将显示 Droplet 的 IP 地址来了解输出。
从您作为先决条件所创建的terraform-outputs
目录中,创建并打开droplets.tf
文件进行编辑:
1nano droplets.tf
添加以下 Droplet 资源和输出定义:
1[label terraform-outputs/droplets.tf]
2resource "digitalocean_droplet" "web" {
3 image = "ubuntu-20-04-x64"
4 name = "test-droplet"
5 region = "fra1"
6 size = "s-1vcpu-1gb"
7}
8
9output "droplet_ip_address" {
10 value = digitalocean_droplet.web.ipv4_address
11}
你首先宣布一个Droplet资源,称为Web
,在云中它的实际名称将是test-droplet
,在区域内是fra1
,运行Ubuntu 20.04.
然后,您声明一个名为droplet_ip_address
的输出。在Terraform中,输出用于导出并显示内部和计算值和资源信息。在这里,您将接受数据输出的值
参数设置为声明 Droplet 的 IP 地址。在声明时间,它是未知的,但一旦 Droplet 部署,它将成为可用。
保存和关闭文件,然后通过运行以下命令部署该项目:
1terraform apply -var "do_token=${DO_PAT}"
请在提示时输入是
以应用,输出的结尾将类似于此:
1[secondary_label Output]
2...
3digitalocean_droplet.web: Creating...
4...
5digitalocean_droplet.web: Creation complete after 32s [id=207631771]
6
7Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
8
9Outputs:
10
11droplet_ip_address = ip_address
突出显示的 IP 地址属于您新部署的 Droplet. 应用该项目将资源部署到云中,并在所有资源属性可用时显示输出。
输出也可以使用输出
命令显示:
1terraform output
输出将列出项目中的所有输出
:
1[secondary_label Output]
2droplet_ip_address = ip_address
您也可以通过将其指定为参数来以名义查询特定输出:
1terraform output output_name
对于droplet_ip_address
,输出将仅包括 IP 地址:
1[secondary_label Output]
2ip_address
除了指定强制性的值
,输出有几个可选参数:
描述
:嵌入简短的文档,详细说明输出显示的内容depends_on
:每个资源可用的元参数,允许您明确指定输出所依赖的资源,而Terraform在规划过程中无法自动推断。
当Terraform部署的日志公开可用时,敏感
参数是有用的,但输出内容应该隐藏。
打开droplets.tf
进行编辑并添加突出的行:
1[label terraform-outputs/droplets.tf]
2resource "digitalocean_droplet" "web" {
3 image = "ubuntu-20-04-x64"
4 name = "test-droplet"
5 region = "fra1"
6 size = "s-1vcpu-1gb"
7}
8
9output "droplet_ip_address" {
10 value = digitalocean_droplet.web.ipv4_address
11 sensitive = true
12}
完成后,保存并关闭文件。
1terraform apply -var "do_token=${DO_PAT}"
当提示时输入是
时,你会看到输出已被编辑:
1[secondary_label Output]
2...
3
4Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
5
6Outputs:
7
8droplet_ip_address = <sensitive>
即使标记为敏感
,输出和其内容仍然可通过其他渠道访问,例如查看Terraform状态或直接查询输出。
在下一步中,您将创建不同的 Droplet 和输出结构,因此通过运行来摧毁当前部署的系统:
1terraform destroy -var "do_token=${DO_PAT}"
最终的结果将是:
1[secondary_label Output]
2...
3Destroy complete! Resources: 1 destroyed.
您已经宣布并部署了 Droplet,并创建了一种显示其 IP 地址的输出,现在您将了解如何使用输出来显示更复杂的结构,如列表和地图。
清除复杂结构
在本节中,您将使用数
关键字部署相同定义的多个Dropplets,并以各种格式输出其IP地址。
使用for
循环
您需要修改 Droplet 资源定义,所以打开它以进行编辑:
1nano droplets.tf
更改它看起来像这样:
1[label terraform-outputs/droplets.tf]
2resource "digitalocean_droplet" "web" {
3 count = 3
4 image = "ubuntu-20-04-x64"
5 name = "test-droplet-${count.index}"
6 region = "fra1"
7 size = "s-1vcpu-1gb"
8}
您已指定使用计数
键创建三个 Droplets,并将当前索引添加到 Droplet 名称中,以便您稍后能够区分它们。
使用代码运行:
1terraform apply -var "do_token=${DO_PAT}"
Terraform 将计划创建三个编号的 Droplets,称为 test-dropplet-0
, test-dropplet-1
,和 test-dropplet-2
。
1[secondary_label Output]
2...
3Apply complete! Resources: 3 added, 0 changed, 0 destroyed.
这意味着所有三个Dropplets都成功部署,所有有关它们的信息都存储在项目状态中。
访问其资源属性的最简单方法是使用输出,但创建每个 Droplet 的一个不是可扩展的。 解决方案是使用for
循环穿过 Droplets 列表并收集其属性,或者替代使用 splat 表达式(在此步骤中稍后您将了解)。
您首先将定义一个输出,该输出将输出三个Dropplets的IP地址,并与它们的名称相配。
1nano droplets.tf
添加以下几行:
1[label terraform-outputs/droplets.tf]
2resource "digitalocean_droplet" "web" {
3 count = 3
4 image = "ubuntu-20-04-x64"
5 name = "test-droplet-${count.index}"
6 region = "fra1"
7 size = "s-1vcpu-1gb"
8}
9
10output "droplet_ip_addresses" {
11 value = {
12 for droplet in digitalocean_droplet.web:
13 droplet.name => droplet.ipv4_address
14 }
15}
droplet_ip_addresses
的输出值是用一个for
循环构建的,因为它被环绕着,结果的类型将是一个地图。
保存并关闭文件,然后再次应用该项目:
1terraform apply -var "do_token=${DO_PAT}"
提示时输入是
并在结束时收到输出内容:
1[secondary_label Output]
2Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
3
4Outputs:
5
6droplet_ip_addresses = {
7 "test-droplet-0" = "ip_address"
8 "test-droplet-1" = "ip_address"
9 "test-droplet-2" = "ip_address"
10}
droplet_ip_addresses
输出详细介绍了部署的三个 dropplets 的 IP 地址。
使用Terraform输出
命令,您可以使用其命令参数将输出内容获得为 JSON:
1terraform output -json droplet_ip_addresses
结果将与以下相似:
1[secondary_label Output]
2{"test-droplet-0":"ip_address","test-droplet-1":"ip_address","test-droplet-2":"ip_address"}
JSON 解析在许多编程语言中被广泛使用和支持,这样你就可以对部署的 Droplet 资源的信息进行编程解析。
使用 Splat 表达式
Splat 表达式提供了对列表的所有元素进行重复的紧凑的方式,并从每个元素中收集一个属性的内容,从而产生一个列表。
1digitalocean_droplet.web[*].ipv4_address
[*]
符号穿过列表在其左侧,对每个元素,采取其属性在其右侧指定的内容. 如果左侧的参考不是一个列表本身,它将转换为一个它将是唯一的元素。
您可以打开droplets.tf
进行编辑,并修改以下行来执行此操作:
1[label terraform-outputs/droplets.tf]
2resource "digitalocean_droplet" "web" {
3 count = 3
4 image = "ubuntu-20-04-x64"
5 name = "test-droplet-${count.index}"
6 region = "fra1"
7 size = "s-1vcpu-1gb"
8}
9
10output "droplet_ip_addresses" {
11 value = digitalocean_droplet.web[*].ipv4_address
12}
保存文件后,通过运行以下命令来应用该项目:
1terraform apply -var "do_token=${DO_PAT}"
您将收到现在是一个列表的输出,其中仅包含 Droplets 的 IP 地址:
1[secondary_label Output]
2...
3Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
4
5Outputs:
6
7droplet_ip_addresses = [
8 "ip_address",
9 "ip_address",
10 "ip_address",
11]
若要将输出接收为 JSON,请执行以下命令:
1terraform output -json droplet_ip_addresses
输出将是一个单一的数组:
1[secondary_label Output]
2["ip_address","ip_address","ip_address"]
您已使用输出,加上 splat 表达式和for
循环来导出部署的 Droplets 的 IP 地址,您还将输出内容作为 JSON 接收,现在您将使用jq
– 一个工具来根据给定的表达式动态过滤 JSON – 来分析它们。
使用jq
进行分解输出
在此步骤中,您将安装并学习jq
的基本知识,这是一种用于操纵 JSON 文档的工具,您将使用它来分析您的 Terraform 项目的输出。
如果你在Ubuntu上,请运行以下命令来安装jq
:
1sudo snap install jq
在 macOS 上,您可以使用 Homebrew 来安装它:
1brew install jq
jq
将所提供的处理表达式应用于给定的输入,该输入可以被导入。
1terraform output -json droplet_ip_addresses | jq '.'
输入身份操作员(.
)意味着从输入中解析的整个JSON文档应该在没有修改的情况下输出:
1[secondary_label Output]
2[
3 "first_ip_address",
4 "second_ip_address",
5 "third_ip_address"
6]
您可以使用数组支架标注仅请求第二个 IP 地址,从零计算:
1terraform output -json droplet_ip_addresses | jq '.[1]'
产量将是:
1[secondary_label Output]
2"second_ip_address"
要使处理的结果成为一个数组,将表达式包装成支架:
1terraform output -json droplet_ip_addresses | jq '[.[1]]'
您将获得一个非常好的打印的 JSON 数组:
1[secondary_label Output]
2[
3 "second_ip_address"
4]
您可以通过在分组中指定一个指数范围来检索分组的部分而不是单个元素:
1terraform output -json droplet_ip_addresses | jq '.[0:2]'
产量将是:
1[secondary_label Output]
2[
3 "first_ip_address",
4 "second_ip_address"
5]
範圍「0:2」返回前兩個元素,範圍的上部(「2」)不包括,因此只收集位於「0」和「1」的元素。
您现在可以通过运行来摧毁部署的资源:
1terraform destroy -var "do_token=${DO_PAT}"
在此步骤中,您已经安装了jq
,并使用它来分析和操纵您的Terraform项目的输出,该项目部署了三个Dropplets。
结论
您已经了解了 Terraform 输出,使用它们来显示部署的资源的详细信息,并将数据结构导出用于后续外部处理,您还使用了输出来显示单个资源的属性,以及显示包含资源属性的构建地图和列表。
有关jq
的功能的详细信息,请访问 官方文件。
本教程是《如何使用Terraform管理基础设施》系列的一部分,该系列涵盖了许多Terraform主题,从首次安装Terraform到管理复杂项目。