depneds_on
在resouce文档中,我们提及了 depends_on。使用 depends_on 元参数来处理 Terraform 无法自动推断的隐藏资源或模块依赖关系。仅当某个资源或模块依赖于另一个资源的行为,但在其参数中不访问该资源的任何数据时,才需要显式指定依赖关系。
depends_on 的表达式是依赖资源的地址列表。例如需要搭建一台ecs和mysql实例的小型服务端,mysql实例必须在ecs创建成功后才能部署。根据上述要求,具体实现如下:
resource "ctyun_ecs" "ecs_example" {
...
}
resource "ctyun_mysql_instance" "mysql_example" {
depends_on = [ctyun_ecs.ecs_example]
...
}count
默认情况下,resource 块会根据定义创建一个相应的云资源。但是,您希望需要同时创建多个类似的对象(例如相配置的ecs实例),无需为每个资源单独编写 resource 块。Terraform 有两种方法可以实现这一功能: count 和 for_each。
如果 resource 块包含一个 count 值为整数的参数,Terraform 将创建那么多实例。
resource "ctyun_ecs" "ecs_example" {
count = 3
instance_name = "tf-ecs-${count.index}"
...
}上述示例可以创建 3 个 ctyun_ecs 资源。但按照要求,ecs 示例的名称是不允许相同的,可以利用 ${count.index} 对每个资源进行标记区分,这是一个从0开始计数的索引值,避免重复。除名称以外,还可以通过${count.index}访问数组,具体示例如下:
# 1. 创建2个vpc,名称分别为vpc_examples_0,和vpc_examples_1,并且我希望vpc的cidr分别不同
# 2. 定义一个variable,用于存储不同的cidr
variable "cidr_list" {
type = list(string)
default = ["192.168.0.0/16", "172.16.0.0/16"]
}
# 3. 创建2个名称不同,cidr不同的vpc
resource "ctyun_vpc" "vpc_examples" {
count = 2
name = "vpc_examples_${count.index}"
cidr = var.cidr_list[count.index]
...
}count创建的资源引用方式本文也介绍下,为区分借助 count 创建的资源实例。实例的引用由索引标识,从0开始。具体引用方法如下:
<RESOURCE TYPE>.<NAME>指的是引用资源块,借用上述vpc示例,想要引用vpc资源块可以表示为:ctyun_vpc.vpc_examples<RESOURCE TYPE>.<NAME>[INDEX]指的是引用具体单个实例,如果我先引用并输入第二个vpc实例的id,可以定义为:
output "vpc0_id" {
value = ctyun_vpc.vpc_examples[1].id
}count 和 for_each 这两个元参数无法同时在一个 resource 块中使用。所以关于 count 和 for_each 的抉择,可以根据如下准则去确定:
如果您的实例几乎相同,
count则是合适的。如果它们的某些参数不能直接简单的遍历获取到,则使用for_each更合理。
我们可以使用 for 语句解释 count 和 for_each 的区别:
# count = 10
for (int i = 0; i < 10; i++){
resource块
}
# for_each
regions = ["华东1", "华北2", "华南2", "西南1",...]
for (int i = 0; i < length(regions); i++){
region = regions[i]
resource 块
}for_each
元参数 for_each 与 count 相似,可以同时创建多个配置相似的云资源。for_each 参数通过遍历一组集合,利用集合中每个元素为 resouce 块创建相应属性的实例,每个实例都会单独创建、更新或销毁。
for_each 利用字符串集合创建资源示例
resource "ctyun_mysql_account" "account_examples" {
for_each = toset( ["Todd", "James", "Alice", "Dottie"] )
name = each.key
}for_each 利用 map 创建资源示例
resource "ctyun_vpc" "vpc_examples" {
for_each = {
vpc_1 = "192.168.0.0/16"
vpc_2 = "172.16.0.0/16"
}
name = each.key
cidr = each.value
}上述示例出现了 each.key 和 each.value 两个属性,当 for_each 遍历的是集合,而并非 map 时,each.value = each.key
for_each 使用限制:
map的键(或一组字符串的所有值)必须是***已知值***
for_each的 key 不能取uuid、bcrypt或timestamp这类函数的结果for_each不能取敏感值进行遍历
for_each 的引用:
利用 for_each 创建资源实例组后,Terraform 会区分块本身和与其关联的多个资源。实例由提供给 的值中的映射键(或集合成员)标识 for_each。
<RESOURCE TYPE>.<NAME>(例如ctyun_vpc.vpc_examples)可以引用资源块。<RESOURCE TYPE>.<NAME>[KEY](例如ctyun_vpc.vpc_examples["vpc_1"])可以引用个别实例
provider
利用 alias 参数可以支持云平台的多个region,用于提供多资源池,多场景高可用的需求。可以通过创建多个 provider 声明块实现。对于每个额外的非默认配置,请使用 alias 元参数提供额外的名称段。例如:
# 默认provider配置;以 `ctyun_` 开头的资源将使用
# 它作为默认值,并且可以将其引用为 `ctyun`。
provider "ctyun" {
region_id = "200000002368"
az_name = "cn-xinan1-xn1A-public-ctcloud"
}
# 华北2的provider配置;资源可以将其引用为 `ctyun.huabei2`。
provider "ctyun" {
alias = "huabei2"
region_id = "200000001852"
az_name = "cn-huabei2-tj1A-public-ctcloud"
}上述示例中声明了西南1和华北2资源池的provider,并对华北2资源池增加了别名,在资源中使用元参数 provider 来选择非默认的 provider块,其格式为:<ctyun>.<alias>
# 创建vpc,指定vpc创建在华北2资源池
resource "ctyun_vpc" "vpc_test" {
provider = ctyun.huabei2
name = "tf-vpc"
cidr = "192.168.0.0/16"
description = "terraform测试使用"
enable_ipv6 = true
}lifecycle
每个资源实例都具有创建 、更新和销毁三个阶段,在一个资源实例的生命周期过程中都会经历其中的2至3个阶段。通过元参数 lifecycle 可以对资源实例的生命周期过程进行改变,元参数 lifecycle 适用于 resource 块中,关键字为 lifecycle,支持以下参数:
create_before_destroy
默认情况下,当需要改变资源中不支持更新的参数时,Terraform会先销毁已有实例,再使用新配置的参数创建新的对象进行替换。当您将create_before_destroy 参数设置为 true 时,Terraform将先创建新的实例,再销毁之前的实例。这个参数可以适用于保持业务连续的场景,由于新旧实例会同时存在,需要提前确认资源实例是否有唯一的名称要求或其他约束。
lifecycle {
create_before_destroy = true
} prevent_destroy
当您将 prevent_destroy 参数设置为true时,Terraform将会阻止对此资源的删除操作并返回错误。这个元参数可以作为一种防止因意外操作而重新创建成本较高实例的安全措施,例如数据库实例。如果要删除此资源,需要将这个配置删除后再执行 destroy 操作。
lifecycle {
prevent_destroy = true
} ignore_changes
默认情况下,Terraform plan/apply 操作将检测云上资源的属性和本地资源块中的差异,如果不一致将会调用更新或者重建操作来匹配配置。您可以用 ignore_changes 来忽略某些参数不进行更新或重建。ignore_changes 的值可以是属性的相对地址列表,对于 Map 和 List 类型,可以使用索引表示法引用,如 tags["Name"],list[0] 等。
resource "ctyun_ecs" "ecs_examples" {
...
lifecycle {
ignore_changes = [
instance_name,
]
}
} 此时,Terraform 将会忽略对 instance_name 参数的修改。除了列表之外,您也可以使用关键字 all 忽略所有属性的更新。
resource "ctyun_ecs" "ecs_examples" {
...
lifecycle {
ignore_changes = all
}
} replace_triggered_by
Terraform 1.2版本新增,当任何引用项发生更改时,替换资源。
resource "ctyun_ecs" "ecs_examples" {
# ...
lifecycle {
replace_triggered_by = [
ctyun_vpc.vpc_example.id
]
}
}