如何使用 Terraform 出口管理基础架构數據

引言

Terraform的输出功能可以用來從專案狀態中提取有關基礎設施資源的資訊。透過使用Hashicorp Configuration Language(HCL)的其他功能(Terraform所用語言),可以查詢資源資訊並將其轉換為更複雜的數據結構,如列表和映射。輸出功能對於向外部軟體提供基礎設施資源的資訊很有用,該軟體可以对这些資源進行操作。

在這個教程中,您將通過創建一個部署Droplets的簡單基礎設施,學習Terraform輸出語法及其参数。您還將通過將它們轉化為JSON來程序化地解析輸出。

的先決條件

注意:此教學已被特定測試過與Terraform 1.0.2

定義輸出

在這一節中,您將宣告一個Droplet,將它部署到雲端,並通過宣告一個將顯示Droplet的IP地址的輸出來學習有關輸出的知識。

從您作為前提 Create the droplets.tf file for editing:

  1. nano droplets.tf

加入以下Droplet資源和輸出定義:

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

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

您首先宣告一個叫作web的Droplet資源。在雲端的實際名稱將是test-droplet,於fra1區域運行Ubuntu 20.04。

然後,您宣告一個稱為droplet_ip_address的輸出。在Terraform中,輸出用於導出和顯示內部和計算的值以及資源的資訊。在此處,您將value參數設定為宣告的Droplet的IP地址。在宣告時,它是未知的,但部署後將變得可用。部署後,輸出會被顯示和訪問。

保存並關閉文件,然後通過運行以下命令部署項目:

  1. 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命令顯示輸出:

  1. terraform output

输出行將列出项目中所有的outputs

Output
droplet_ip_address = ip_address

您也可以通過指定名稱為參數來查询特定的輸出:

  1. terraform output output_name

對於droplet_ip_address,輸出只包括IP地址:

Output
ip_address

除了指定必需的value外,輸出还有一些可选的参数:

  • description: 嵌入短期文档,详细说明输出的内容。
  • depends_on: 每個資源都可用的元参数,允許您明確指定 Terraform 在計劃過程中無法自動推理出的依賴資源。
  • sensitive: 接受布尔值,如果设置為true,则在部署後防止显示输出的内容。

sensitive参数在Terraform部署的日志公开可用但输出的内容應保持隐藏時很有用。您現在將其添加到您的Droplet資源定義中。

打開droplets.tf進行編輯,並添加突出的行:

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

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

完成後保存並關閉文件。通過運行以下命令再次部署項目:

  1. terraform apply -var "do_token=${DO_PAT}"

當提示時 enter yes。您會看到输出已被编辑:

Output
... Apply complete! Resources: 0 added, 0 changed, 0 destroyed. Outputs: droplet_ip_address = <sensitive>

即使它被標記為sensitive,通過其他渠道(如查看Terraform狀態或直接查询输出)仍然可以獲得输出的内容和相关信息。

在下一步,您將創建不同的Droplet和输出結構,因此通過運行以下命令销毁目前部署的項目:

  1. terraform destroy -var "do_token=${DO_PAT}"

最終的输出將是:

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

您已声明並部署了一个Droplet,并创建了一个显示其IP地址的输出。现在您将学习如何使用输出显示更复杂的结构,如列表和映射。

输出複雜結構

在這一節中,您將使用count關鍵字從同一份定義部署多個Droplet,並以各種格式输出它們的IP地址。

使用for迴圈

您需要修改Droplet資源定義,因此請打開它進行編輯:

  1. nano droplets.tf

將其修改為如下形式:

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

您指定了應該使用count關鍵字創建三個Droplet,並將當前索引添加到Droplet名稱中,這樣您後續能夠區分它們。移除下面的既有輸出。修改完畢後,保存並關閉文件。

通過運行以下代碼來應用修改:

  1. terraform apply -var "do_token=${DO_PAT}"

Terraform將計劃創建三個編 號的Droplet,名稱為test-droplet-0test-droplet-1test-droplet-2。當提示時,請輸入yes以完成過程。最後您將看到以下輸出:

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

這意味著所有三個Droplet都已成功部署,並且它們的所有資訊都已存儲在項目狀態中。

最容易存取其資源屬性的是使用輸出,但為每個Droplet創建一個却是不可擴展的解決方案。解決方法是使用for迴圈來遍歷Droplets的列表並搜集其屬性,或者選擇使用散射表達式(你稍后在這個步驟中會學習到)。

你將首先定義一個輸出,該輸出將傳送三個Droplet的IP位址,並配對其名稱。開啟droplets.tf以進行編輯:

  1. nano droplets.tf

添加以下行:

terraform-outputs/droplets.tf
resource "digitalocean_droplet" "web" {
  count  = 3
  image  = "ubuntu-20-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迴圈。因為它被大括號包圍,所以結果的型態將是地圖。迴圈遍歷Droplets的列表,對於每個實例,將其名稱與其IP位址配對並附加到結果地圖中。

保存並關閉文件,然後再次 Apply 该项目:

  1. 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 输出的详细信息包含三个部署的Droplet的IP地址。

使用 Terraform output 命令,你可以通过其命令参数以 JSON 格式获取输出的内容:

  1. terraform output -json droplet_ip_addresses

结果将与以下类似:

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

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

使用散列表达式

散列表達式提供了一种紧凑的方式遍歷列表中的所有元素,並收集從它們中每個元素的屬性內容,從而獲得一個列表。一個用於提取部署的三個滴落(Droplets)的IP地址的散列表達式將具有以下語法:

digitalocean_droplet.web[*].ipv4_address

左邊的[*]符號遍歷其左邊的列表,並對於每個元素,取其右邊指定屬性的內容。如果左邊的引用本身不是列表,它將被轉換為一個列表,其中它將是唯一元素。

您可以打開droplets.tf進行編輯,並修改以下行以實現此功能:

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

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

保存文件後,通過運行以下命令應用項目:

  1. 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接收,運行以下命令:

  1. terraform output -json droplet_ip_addresses

輸出將是一個單一的數組:

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

您已經使用了与合作表達式和for循環一起的輸出,以匯出部署的Droplets的IP地址。您也已經作為JSON接收了輸出的內容,現在您將使用jq—一個用於根據給定的表達式動態過濾JSON的工具—來解析它們。

使用jq解析輸出

在這個步驟中,您將安裝並學習jq,一個用於操作JSON文件的 tool。您將使用它來解析您的Terraform專案的輸出。

如果您在Ubuntu上,請運行以下命令來安裝jq

  1. sudo snap install jq

在macOS上,您可以使用Homebrew來安裝它:

  1. brew install jq

jq將提供的處理表達式應用於給定的輸入,可以通過管道傳輸。jq中最容易的任務是美觀打印輸入:

  1. terraform output -json droplet_ip_addresses | jq '.'

傳入身份運算符(.)意味著應該不進行修改地输出整個從輸入解析出来的JSON文件:

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

您可以使用數組方括號表示法,從零開始計算,來索取第二個IP位址:

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

輸出將是:

Output
"second_ip_address"

為了使處理結果成為一個數組,請將表達式包裹在方括號中:

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

您將得到一個美觀打印的JSON數組:

Output
[ "second_ip_address" ]

您可以通過指定索引範圍在方括號內來索取數組的部分,而不是單個元素:

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

輸出將是:

Output
[ "first_ip_address", "second_ip_address" ]

範圍 `0:2` 返回該範圍的第一个兩個元素—上界(2)不包括,所以只fetch位置為0和1的元素。

現在你可以透過執行:

  1. terraform destroy -var "do_token=${DO_PAT}"

來摧毁部署的資源。在這一步中,你已经安裝了jq並且用它来解析和處理Terraform项目的輸出,這 deploys three Droplets。

結論

你已經学习了Terraform输出,使用它们来显示部署资源的详细信息,并将其导出为外部处理的结构化数据。你还学会了如何使用输出显示单个资源属性以及包含资源属性的地图和列表。

欲了解有關jq的更多詳細資訊,請参閱其官方文档

本教程是《如何使用Terraform管理基础设施》系列的一部分。该系列涵盖了Terraform的多个主题,从安装Terraform到管理复杂项目。

Source:
https://www.digitalocean.com/community/tutorials/how-to-manage-infrastructure-data-with-terraform-outputs