如何使用 Terraform 变量、依赖关系和条件句提高灵活性

介绍

Hashicorp Configuration Language(HCL)使用的Terraform(https://www.terraform.io/)提供了许多有用的结构和功能,这些结构和功能存在于其他编程语言中。在您的基础设施代码中使用循环可以大大减少代码重复和增加可读性,使未来更容易重构和更灵活。

虽然在运行代码时构建的执行图表已经包含被检测的链接(在大多数情况下都是正确的),但您可能需要强制建立一个Terraform无法检测到的依赖关系。

在本文中,我们将审查HCL提供的数据结构,其资源循环特性(计数密钥,for_eachfor),处理已知和未知值的条件以及资源之间的依赖关系。

前提条件

您可以在 DigitalOcean 产品文档中找到 如何创建个人访问令牌。 *在本地机器上安装的 Terraform 和与 DigitalOcean 提供商一起建立的项目。 完成 如何使用 Terraform 与 DigitalOcean教程的 步骤 1步骤 2,并确保项目文件夹命名为 terraform-flexibility,而不是 load balance

<$>[注] **注:**本教程已被特定的测试与Terraform 1.0.2 <$>

HCL中的数据类型

在您了解更多关于 HCL 循环和其他功能的信息之前,这些功能使您的代码更加灵活,我们首先将讨论可用的数据类型及其用途。

Hashicorp 配置语言支持 primitivecomplex 数据类型. 原始数据类型是字符串、数字和布尔值,这些是无法从其他类型中提取的基本类型。

结构类型允许将不同类型的值组合在一起。主要例子是您使用的资源定义来指定您的基础设施将是什么样子。与结构类型相比,集合类型也组合值,但只有相同类型的集合类型。

列表

列表类似于其他编程语言的数组. 它们包含一个已知的相同类型的元素数量,可以使用数组符号([])通过其整数索引访问,从0开始,以下是列表变量声明的示例,其中包含您将在以下步骤中部署的Dropplets名称:

1variable "droplet_names" {
2  type    = list(string)
3  default = ["first", "second", "third"]
4}

对于类型,您指定它是一个列表,其元素类型是字符串,然后提供它的默认值。

地图

地图是密钥值对的集合,每个值都是使用其类型的字符串密钥访问的。有两种方法可以指定曲线轴内的地图:使用列(:)或等符号(=)来指定值。

以下地图定义包含不同环境的 Droplet 名称是使用平等符号写的:

1variable "droplet_env_names" {
2  type = map(string)
3
4  default = {
5    development = "dev-droplet"
6    staging = "staging-droplet"
7    production = "prod-droplet"
8  }
9}

如果键始于一个数字,则必须使用结肠语法:

1variable "droplet_env_names" {
2  type = map(string)
3
4  default = {
5    "1-development": "dev-droplet"
6    "2-staging": "staging-droplet"
7    "3-production": "prod-droplet"
8  }
9}

座位

集不支持元素排序,这意味着跨集并不能保证每次产生相同的顺序,并且它们的元素无法以有针对性的方式访问。

声明集类似于声明列表,唯一的区别是变量的类型:

1variable "droplet_names" {
2  type    = set(string)
3  default = ["first", "second", "third", "fourth"]
4}

现在,您已经了解了 HCL 提供的数据结构类型,并审查了我们将在本教程中使用的列表,地图和集合语法,您将尝试在 Terraform 中部署相同资源的多个实例的一些灵活方法。

使用计数密钥设置资源数量

在本节中,您将使用计数键创建相同资源的多个实例。

你会看到它是如何工作的,写一个Droplet资源,你会将其存储在名为droplets.tf的文件中,在你创建的项目目录中作为前提的一部分。

1nano droplets.tf

添加以下几行:

1[label terraform-flexibility/droplets.tf]
2resource "digitalocean_droplet" "test_droplet" {
3  count  = 3
4  image  = "ubuntu-20-04-x64"
5  name   = "web"
6  region = "fra1"
7  size   = "s-1vcpu-1gb"
8}

这个代码定义了一个名为test_droplet的 Droplet 资源,运行 Ubuntu 20.04 具有 1 GB 的 RAM 和 CPU 核心。

请注意,的值设置为3,这意味着Terraform将尝试创建同一资源的三个实例。

您可以计划项目,以查看通过运行 Terraform 会采取哪些行动:

1terraform plan -var "do_token=${DO_PAT}"

结果将类似于此:

 1[secondary_label Output]
 2...
 3Terraform used the selected providers to generate the following execution plan. Resource actions are indicated
 4with the following symbols:
 5  + create
 6
 7Terraform will perform the following actions:
 8
 9  # digitalocean_droplet.test_droplet[0] will be created
10  + resource "digitalocean_droplet" "test_droplet" {
11    	...
12    	name                 = "web"
13    	...
14    }
15
16  # digitalocean_droplet.test_droplet[1] will be created
17  + resource "digitalocean_droplet" "test_droplet" {
18    	...
19    	name                 = "web"
20    	...
21    }
22
23  # digitalocean_droplet.test_droplet[2] will be created
24  + resource "digitalocean_droplet" "test_droplet" {
25    	...
26    	name                 = "web"
27    	...
28    }
29
30Plan: 3 to add, 0 to change, 0 to destroy.
31...

输出细节表明,Terraform会创建三个test_droplet的实例,所有的实例都具有相同的名称web。虽然可能,但它不是偏好,所以让我们修改Droplet定义以使每个实例的名称独一无二。

1nano droplets.tf

更改突出的线条:

1[label terraform-flexibility/droplets.tf]
2resource "digitalocean_droplet" "test_droplet" {
3  count  = 3
4  image  = "ubuntu-20-04-x64"
5  name   = "web.${count.index}"
6  region = "fra1"
7  size   = "s-1vcpu-1gb"
8}

保存并关闭文件。

对象提供索引参数,该参数包含当前迭代的索引,从0开始。当前索引被用 string interpolation替换为Dropplet的名称,这允许您通过替换变量动态构建一个字符串。

1terraform plan -var "do_token=${DO_PAT}"

结果将类似于此:

 1[secondary_label Output]
 2...
 3Terraform used the selected providers to generate the following execution plan. Resource actions are indicated
 4with the following symbols:
 5  + create
 6
 7Terraform will perform the following actions:
 8
 9  # digitalocean_droplet.test_droplet[0] will be created
10  + resource "digitalocean_droplet" "test_droplet" {
11    	...
12    	name                 = "web.0"
13    	...
14    }
15
16  # digitalocean_droplet.test_droplet[1] will be created
17  + resource "digitalocean_droplet" "test_droplet" {
18    	...
19    	name                 = "web.1"
20    	...
21    }
22
23  # digitalocean_droplet.test_droplet[2] will be created
24  + resource "digitalocean_droplet" "test_droplet" {
25    	...
26    	name                 = "web.2"
27    	...
28    }
29
30Plan: 3 to add, 0 to change, 0 to destroy.
31...

这次,test_droplet的三个实例将有他们的索引在他们的名字,使他们更容易追踪。

您现在知道如何使用计数键创建资源的多个实例,以及在配置过程中获取和使用实例的索引。

从列表中提取滴滴名称

在相同资源的多个实例需要有自定义名称的情况下,您可以动态地从您定义的列表变量中获取它们。

首先,您需要定义一个包含 Droplet 名称的列表,创建一个名为 `variables.tf’ 的文件,然后打开它以进行编辑:

1nano variables.tf

添加以下几行:

1[label terraform-flexibility/variables.tf]
2variable "droplet_names" {
3  type    = list(string)
4  default = ["first", "second", "third", "fourth"]
5}

保存和关闭文件. 此代码定义了一个名为droplet_names的列表,其中包含第一第二第三第四字符串。

打开droplets.tf来编辑:

1nano droplets.tf

更改突出的线条:

1[label terraform-flexibility/droplets.tf]
2resource "digitalocean_droplet" "test_droplet" {
3  count  = length(var.droplet_names)
4  image  = "ubuntu-20-04-x64"
5  name   =  var.droplet_names[count.index]
6  region = "fra1"
7  size   = "s-1vcpu-1gb"
8}

为了提高灵活性,而不是手动指定恒定的元素数目,您将dropplet_names列表的长度转移到count参数,该参数将始终返回列表中的元素数目。

尝试重新规划项目,您将收到类似于此的输出:

 1[secondary_label Output]
 2...
 3Terraform used the selected providers to generate the following execution plan. Resource actions are indicated
 4with the following symbols:
 5  + create
 6
 7Terraform will perform the following actions:
 8
 9  # digitalocean_droplet.test_droplet[0] will be created
10  + resource "digitalocean_droplet" "test_droplet" {
11    	...
12      + name                 = "first"
13    	...
14    }
15
16  # digitalocean_droplet.test_droplet[1] will be created
17  + resource "digitalocean_droplet" "test_droplet" {
18    	...
19      + name                 = "second"
20    	...
21    }
22
23  # digitalocean_droplet.test_droplet[2] will be created
24  + resource "digitalocean_droplet" "test_droplet" {
25    	...
26      + name                 = "third"
27    	...
28    }
29
30  # digitalocean_droplet.test_droplet[3] will be created
31  + resource "digitalocean_droplet" "test_droplet" {
32      ...
33      + name                 = "fourth"
34      ...
35
36Plan: 4 to add, 0 to change, 0 to destroy.
37...

由于这些修改,将部署四个Dropplets,随后命名为droplet_names列表中的元素。

您已经了解了,其功能和语法,并与列表一起使用它来修改资源实例,现在您将看到其缺点以及如何克服它们。

了解计数的缺点

现在你知道如何使用计数,让我们在修改它所使用的列表时检查它的缺点。

让我们试着将 Droplets 部署到云端:

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

当提示时输入时,输出的结尾将类似于此:

1[secondary_label Output]
2Apply complete! Resources: 4 added, 0 changed, 0 destroyed.

现在让我们通过扩大droplet_names列表来创建另一个Droplet实例,打开variables.tf进行编辑:

1nano variables.tf

将新元素添加到列表的开始:

1[label terraform-flexibility/variables.tf]
2variable "droplet_names" {
3  type    = list(string)
4  default = ["zero", "first", "second", "third", "fourth"]
5}

完成后,保存并关闭文件。

计划项目:

1terraform plan -var "do_token=${DO_PAT}"

你会收到这样的输出:

 1[secondary_label Output]
 2...
 3Terraform used the selected providers to generate the following execution plan. Resource actions are indicated
 4with the following symbols:
 5  + create
 6  ~ update in-place
 7
 8Terraform will perform the following actions:
 9
10  # digitalocean_droplet.test_droplet[0] will be updated in-place
11  ~ resource "digitalocean_droplet" "test_droplet" {
12      ...
13      ~ name               = "first" -> "zero"
14      ...
15    }
16
17  # digitalocean_droplet.test_droplet[1] will be updated in-place
18  ~ resource "digitalocean_droplet" "test_droplet" {
19      ...
20      ~ name               = "second" -> "first"
21      ...
22    }
23
24  # digitalocean_droplet.test_droplet[2] will be updated in-place
25  ~ resource "digitalocean_droplet" "test_droplet" {
26      ...
27      ~ name               = "third" -> "second"
28      ...
29    }
30
31  # digitalocean_droplet.test_droplet[3] will be updated in-place
32  ~ resource "digitalocean_droplet" "test_droplet" {
33      ...
34      ~ name               = "fourth" -> "third"
35      ...
36    }
37
38  # digitalocean_droplet.test_droplet[4] will be created
39  + resource "digitalocean_droplet" "test_droplet" {
40      ...
41      + name                 = "fourth"
42      ...
43    }
44
45Plan: 1 to add, 4 to change, 0 to destroy.
46...

输出显示,Terraform将重新命名前四个Droplets,并创建一个第五个Droplets,称为第四个,因为它将实例视为一个排序列表,并通过列表中的索引号识别元素(Droplets)。

Index Number0123
Droplet Namefirstsecondthirdfourth

当新 Droplet zero 被添加到开始时,其内部列表表示看起来如下:

Index Number01234
Droplet Namezerofirstsecondthirdfourth

然后,Terraform比较了表中所代表的两个状态:在位置 0,Droplet 被称为 first,并且由于在第二表中不同,它计划更新操作。

这意味着将新元素添加到列表中的任何地方,但最终会导致资源在不需要时被修改,如果从dropplet_names列表中删除一个元素,则会计划类似的更新操作。

不完整的资源跟踪是使用计数来部署同一资源的不同实例的动态数量的主要缺陷。对于恒定的常数实例来说,计数是一种简单的解决方案,效果很好,但在这种情况下,当某些属性被从变量中拉进时,您将在本教程中稍后了解的for_each循环是一个更好的选择。

参考当前资源(‘自我’)

计数的另一个缺点是,在某些情况下,不可能将资源的任意实例引用其索引。

主要的例子是 Destroy-time provisioners,它们在资源计划被摧毁时运行,原因是所请求的实例可能不存在(它已经被摧毁),或者会产生相互依赖的循环。

为了展示其使用情况,您现在将添加到test_droplet定义中一个 destroy-time 局部提供器,该定义在运行时会显示一个消息。

1nano droplets.tf

添加以下突出的线条:

 1[label terraform-flexibility/droplets.tf]
 2resource "digitalocean_droplet" "test_droplet" {
 3  count  = length(var.droplet_names)
 4  image  = "ubuntu-20-04-x64"
 5  name   =  var.droplet_names[count.index]
 6  region = "fra1"
 7  size   = "s-1vcpu-1gb"
 8
 9  provisioner "local-exec" {
10    when    = destroy
11    command = "echo 'Droplet ${self.name} is being destroyed!'"
12  }
13}

保存并关闭文件。

本地执行提供程序在本地机器 Terraform 上运行命令. 因为参数设置为破坏,它只会在资源被破坏时运行。

因为您将在下一节以不同的方式创建 Droplets,因此,通过运行以下命令来摧毁当前部署的 Droplets:

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

当提示时输入时,您将收到本地执行提供器运行四次:

 1[secondary_label Output]
 2...
 3digitalocean_droplet.test_droplet[0] (local-exec): Executing: ["/bin/sh" "-c" "echo 'Droplet first is being destroyed!'"]
 4digitalocean_droplet.test_droplet[1] (local-exec): Executing: ["/bin/sh" "-c" "echo 'Droplet second is being destroyed!'"]
 5digitalocean_droplet.test_droplet[1] (local-exec): Droplet second is being destroyed!
 6digitalocean_droplet.test_droplet[2] (local-exec): Executing: ["/bin/sh" "-c" "echo 'Droplet third is being destroyed!'"]
 7digitalocean_droplet.test_droplet[2] (local-exec): Droplet third is being destroyed!
 8digitalocean_droplet.test_droplet[3] (local-exec): Executing: ["/bin/sh" "-c" "echo 'Droplet fourth is being destroyed!'"]
 9digitalocean_droplet.test_droplet[3] (local-exec): Droplet fourth is being destroyed!
10digitalocean_droplet.test_droplet[0] (local-exec): Droplet first is being destroyed!
11...

在此步骤中,您了解了计数的缺点,现在您将了解for_each循环构造,它可以克服它们,并在更广泛的变量类型上工作。

使用for_each

在本节中,您将考虑for_each循环,其语法,以及在定义多个实例的资源时如何提供灵活性。

「for_each」是每个资源上可用的参数,但与「数」不同,它需要创建多个实例,「for_each」接受一张地图或一组。提供的集合中的每个元素被穿过一次,并且为此创建了一个实例。

因为它提供了每个对象中的当前元素,所以您不必像在列表中那样手动访问所需的元素。对于集,这甚至是不可能的,因为它没有可观察的内部排序。

使用「for_each」的主要优点,除了能够列出所有三种收集数据类型之外,只有受影响的元素才会被修改、创建或删除。

让我们将Droplet资源从转换为for_each,看看它在实践中是如何工作的。

1nano droplets.tf

更改突出的线条:

1[label terraform-flexibility/droplets.tf]
2resource "digitalocean_droplet" "test_droplet" {
3  for_each = toset(var.droplet_names)
4  image    = "ubuntu-20-04-x64"
5  name     = each.value
6  region   = "fra1"
7  size     = "s-1vcpu-1gb"
8}

您可以删除local-exec提供程序. 完成后,保存并关闭文件。

第一行取代并召唤for_each,以使用toset函数以集合形式进入droplet_names列表,该函数自动转换给定的输入。

计划通过运行项目:

1terraform plan -var "do_token=${DO_PAT}"

输出将详细说明Terraform将采取的步骤:

 1[secondary_label Output]
 2...
 3
 4Terraform used the selected providers to generate the following execution plan. Resource actions are indicated
 5with the following symbols:
 6  + create
 7
 8Terraform will perform the following actions:
 9
10  # digitalocean_droplet.test_droplet["first"] will be created
11  + resource "digitalocean_droplet" "test_droplet" {
12      ...
13      + name                 = "first"
14      ...
15    }
16
17  # digitalocean_droplet.test_droplet["fourth"] will be created
18  + resource "digitalocean_droplet" "test_droplet" {
19      ...
20      + name                 = "fourth"
21      ...
22    }
23
24  # digitalocean_droplet.test_droplet["second"] will be created
25  + resource "digitalocean_droplet" "test_droplet" {
26      ...
27      + name                 = "second"
28      ...
29    }
30
31  # digitalocean_droplet.test_droplet["third"] will be created
32  + resource "digitalocean_droplet" "test_droplet" {
33      ...
34      + name                 = "third"
35      ...
36    }
37
38  # digitalocean_droplet.test_droplet["zero"] will be created
39  + resource "digitalocean_droplet" "test_droplet" {
40      ...
41      + name                 = "zero"
42      ...
43    }
44
45Plan: 5 to add, 0 to change, 0 to destroy.
46...

与使用计数相反,Terraform 现在将每个实例视为单独,而不是作为排序列表的元素。

将计划应用到云中,运行:

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

当提示时输入时,当它完成时,您将从droplet_names列表中删除一个元素,以证明其他实例不会受到影响。

1nano variables.tf

更改列表,看起来像这样:

1[label terraform-flexibility/variables.tf]
2variable "droplet_names" {
3  type    = list(string)
4  default = ["first", "second", "third", "fourth"]
5}

保存并关闭文件。

重新规划项目,您将收到以下输出:

 1[secondary_label Output]
 2...
 3
 4Terraform used the selected providers to generate the following execution plan. Resource actions are indicated
 5with the following symbols:
 6  - destroy
 7
 8Terraform will perform the following actions:
 9
10  # digitalocean_droplet.test_droplet["zero"] will be destroyed
11  - resource "digitalocean_droplet" "test_droplet" {
12      ...
13      - name               = "zero" -> null
14      ...
15    }
16
17Plan: 0 to add, 0 to change, 1 to destroy.
18...

这一次,Terraform只会摧毁删除的实例(‘zero’),不会触及任何其他实例,这是正确的行为。

在此步骤中,您了解了for_each,如何使用它,以及它对的优点,接下来,您将了解for循环,其语法和使用,以及何时可以用来自动化某些任务。

使用for

for 循环在集合上工作,并通过对输入的每个元素应用转换来创建一个新的集合。准确的输出类型将取决于循环是否被([])或({})所包围,分别为列表或地图。

for循环的通用语法是:

1for element in collection:
2transform(element)
3if condition

类似于其他编程语言,你首先命名跨度变量(‘元素’)并指定要列出的‘集合’。 循环的身体是转换步骤,可选的‘如果’条款用于过滤输入集合。

您现在将通过使用输出的一些示例进行工作. 您将将其存储在名为 `outputs.tf 的文件中. 通过运行以下命令创建用于编辑:

1nano outputs.tf

将下列行添加到部署的 Droplet 名称和其 IP 地址的输出对:

1[label terraform-flexibility/outputs.tf]
2output "ip_addresses" {
3  value = {
4    for instance in digitalocean_droplet.test_droplet:
5    instance.name => instance.ipv4_address
6  }
7}

此代码指定了一个名为ip_addresses的输出,并指定了一个for循环,该循环在你在以前的步骤中自定义的test_droplet资源的实例上重复。由于循环被弯曲的轴包包包包围,它的输出将是一个地图。

保存和关闭文件,然后更新 Terraform 状态以执行新的输出:

1terraform refresh -var "do_token=${DO_PAT}"

Terraform刷新命令将本地状态与云中的实际基础设施状态更新。

然后,检查输出的内容:

1[secondary_label Output]
2ip_addresses = {
3  "first" = "ip_address"
4  "fourth" = "ip_address"
5  "second" = "ip_address"
6  "third" = "ip_address"
7}

Terraform 显示了 ip_addresses 输出的内容,这是由 for 循环构建的地图。 (输入的顺序可能对您有所不同.) 循环将为每个输入数量无缝工作,这意味着您可以将一个新元素添加到 droplet_names 列表中,而新的 Droplet 将自动显示在此输出中。

例如,您只能输出 Droplet IP 地址,这对可能分析数据的外部软件有用。

1[label terraform-flexibility/outputs.tf]
2output "ip_addresses" {
3  value = [
4    for instance in digitalocean_droplet.test_droplet:
5    instance.ipv4_address
6  ]
7}

在这里,转换步骤选择了IP地址属性,它会产生以下输出:

1[secondary_label Output]
2ip_addresses = [
3  "ip_address",
4  "ip_address",
5  "ip_address",
6  "ip_address",
7]

如前所述,您还可以使用如果条款过滤输入集合,以下是您将循环按fra1区域过滤的方式:

1[label terraform-flexibility/outputs.tf]
2output "ip_addresses" {
3  value = [
4    for instance in digitalocean_droplet.test_droplet:
5    instance.ipv4_address
6    if instance.region == "fra1"
7  ]
8}

在 HCL 中,==操作员检查两侧值的平等性,在这里它检查instance.region是否等于fra1。如果是,则检查通过并将instance转换并添加到输出中,否则将被省略。此代码的输出将与前一个例子相同,因为所有Dropplet实例都位于fra1区域,根据test_droplet资源定义。

因为在下一节中,您将以不同的方式创建资源,请通过运行以下命令来摧毁当前部署的资源:

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

当被要求完成过程时输入

我们已经研究了for循环,它的语法,以及在输出中使用的例子,现在您将了解条件符号以及它们如何与计数一起使用。

指令和条件

在之前的部分中,您已经看到了计数密钥以及它是如何工作的,现在您将了解三位条件操作员,您可以在Terraform代码中的其他地方使用它们,以及它们如何与计数一起使用。

ternary 操作员的语法是:

1condition ? value_if_true : value_if_false

'condition' 是一个计算为 boolean (true 或 false) 的表达式,如果条件是 true,则表达式会评估为 'value_if_true'。

三重运算的主要用途是根据变量的内容启用或禁用单个资源创建,这可以通过将比较结果(10)转移到所需资源上的计数键来实现。

如果您使用三重运算器从列表或集合中提取单个元素,则可以使用函数. 如果该集合是空的,则返回null

让我们添加一个名为create_droplet的变量,它将控制是否会创建一个Droplet。

1nano variables.tf

添加突出的线条:

 1[label terraform-flexibility/variables.tf]
 2variable "droplet_names" {
 3  type    = list(string)
 4  default = ["first", "second", "third", "fourth"]
 5}
 6
 7variable "create_droplet" {
 8  type = bool
 9  default = true
10}

此代码定义了类型为boolcreate_droplet变量,保存并关闭文件。

然后,要更改 Droplet 声明,打开 `droplets.tf’ 进行编辑:

1nano droplets.tf

修改你的文件如下:

1[label terraform-flexibility/droplets.tf]
2resource "digitalocean_droplet" "test_droplet" {
3  count  = var.create_droplet ? 1 : 0
4  image  = "ubuntu-20-04-x64"
5  name   =  "test_droplet"
6  region = "fra1"
7  size   = "s-1vcpu-1gb"
8}

对于,您使用三重运算符返回1如果create_droplet变量是真的,或0如果是假的,这将导致没有提供Dropplets。

通过运行该变量设置为 false 来计划项目执行计划:

1terraform plan -var "do_token=${DO_PAT}" -var "create_droplet=false"

您将收到以下输出:

1[secondary_label Output]
2Changes to Outputs:
3  + ip_addresses = {}
4
5You can apply this plan to save these new output values to the Terraform state, without changing any real infrastructure.

由于create_droplet被传输为false,因此实例的数目0,不会创建Dropplets,因此不会有 IP 地址输出。

您已经审查了如何与计数键一起使用三级条件运算器,以便在选择是否部署所需资源时提供更高的灵活性。

明确设置资源依赖性

在为您的项目创建执行计划时,Terraform 检测资源之间的依赖链,并默认地排序它们,以便它们以适当的顺序构建。

然而,当一个资源,为了提供,需要访问控制设置已经部署在云提供商时,没有明确的迹象表明Terraform它们是相关的。

depends_on密钥在每个资源上可用,用于指定特定资源之间隐藏的依赖链接. 隐藏的依赖关系是在一个资源依赖另一个人的行为时形成的,而不使用其声明中的任何数据,这将促使Terraform以一种方式连接它们。

以下是如何在代码中指定depends_on的示例:

 1resource "digitalocean_droplet" "droplet" {
 2  image  = "ubuntu-20-04-x64"
 3  name   = "web"
 4  region = "fra1"
 5  size   = "s-1vcpu-1gb"
 6
 7  depends_on = [
 8    # Resources...
 9  ]
10}

它接受其他资源的引用列表,不接受任意表达。

depends_on应谨慎使用,并且仅在所有其他选项都耗尽时使用,其使用意味着您试图声明的内容正在超越Terraform自动依赖检测系统的界限;这可能意味着该资源明确依赖于比它需要的更多资源。

您现在已经了解了如何使用depends_on键明确设置资源的额外依赖性,以及何时应该使用它。

结论

在本文中,我们讨论了 HCL 的功能,这些功能可以提高代码的灵活性和可扩展性,例如计数用于指定要部署的资源实例数量,以及为每一个作为跨集数据类型和定制实例的先进方式。

您还了解了条件和三级操作员,以及如何使用它们来控制资源是否会被部署,虽然Terraform的自动依赖分析系统非常有能力,但可能需要使用depends_on键手动指定资源依赖。

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

Published At
Categories with 技术
comments powered by Disqus