Terraform 相關概念及函數
一 Metadata
Metadata是Terraform支持的內置元參數,可以在 provider,resource,data塊中使用。本章節主要介紹 resource塊支持的元參數,主要包括:
depends_on:用于指定資源的依賴項
count:用于創建多個相同配置的資源
for_each:用于根據映射、字符串集合創建多個資源
provider:用于選擇非默認的 provider
lifecycle:用于定制資源的生命周期
1.1 depends_on
在同一個 Terraform 配置文件中可以包含多個資源。通過在資源中引用其他資源的屬性值,Terraform可以自動推斷出資源的依賴關系。然而,某些資源的依賴關系對于Terraform是不可見的,這就需要使用 depends_on 來創建顯式依賴。我們可以使用 depends_on 來更改資源的創建順序或執行順序,使其在所依賴資源之后處理。depends_on 的表達式是依賴資源的地址列表。例如我們在遠程操作一臺ECS服務器之前,需要為其綁定EIP或配置NAT規則。
resource "huaweicloud_compute_instance" "myinstance" { ... } resource "huaweicloud_vpc_eip" "myeip" { ... } resource "huaweicloud_compute_eip_associate" "associated" { public_ip = huaweicloud_vpc_eip.myeip.address instance_id = huaweicloud_compute_instance.myinstance.id } resource "null_resource" "provision" { depends_on = [huaweicloud_compute_eip_associate.associated] provisioner "remote-exec" { connection { # 通過公網地址訪問 ECS host = huaweicloud_vpc_eip.myeip.address ... } inline = [ ... ] } }
1.2 count
默認情況下,Terraform的 resource塊只配置一個資源。當我們需要創建多個相同的資源時,如果配置多個獨立的 resource塊就顯得很冗余,且不利于維護。我們可以使用 count 或 for_each 參數在同一個 resource塊中管理多個相同的資源。在同一個 resource塊中不能同時使用count 和 for_each 參數。示例如下:
resource "huaweicloud_evs_volume" "volumes" { count = 3 size = 20 volume_type = "SSD" availability_zone = "cn-north-4a" }
我們通過如上配置創建了3個相同的云硬盤(EVS)。在很多情況下,Provider 要求創建資源的某些參數具有唯一性,這時我們可以使用 “count.index” 屬性來進行區分,這是一個從0開始計數的索引值。
resource "huaweicloud_vpc" "vpcs" { count = 2 name = "myvpc_${count.index}" cidr = "192.168.0.0/16" }
我們通過如上配置創建了兩個VPC,名字分別為 myvpc_0 和 myvpc_1,它們具有相同的CIDR值。如果進一步修改CIDR值,我們可以聲明一個string列表用于存儲不同VPC的CIDR值,然后通過 count.index 去訪問列表元素。
variable "name_list" { type = list(string) default = ["vpc_demo1", "vpc_demo2"] } variable "cidr_list" { type = list(string) default = ["192.168.0.0/16", "172.16.0.0/16"] } resource "huaweicloud_vpc" "vpcs" { count = 2 name = var.name_list[count.index] cidr = var.cidr_list[count.index] }
使用 count 創建的資源需要通過索引值進行訪問,格式為:<資源類型>.<名稱>[索引值]
# 訪問第一個VPC > huaweicloud_vpc.vpcs[0] # 訪問第一個VPC的ID > huaweicloud_vpc.vpcs[0].id # 訪問所有VPC的ID > huaweicloud_vpc.vpcs[*].id
1.3 for_each
for_each 在功能上與 count 相似,for_each 使用鍵值對或字符串集合的形式快速地將值填入到對應的屬性中,不僅可以優化腳本結構也有利于理解多實例間的關系。
在使用映射類型表達時,我們可以使用 “each.key” 和 “each.value” 來訪問映射的鍵和值。以創建VPC為例,通過 for_each 中的鍵值對,我們可以靈活配置VPC的名稱和CIDR。
resource "hauweicloud_vpc" "vpc" { for_each = { vpc_demo1 = "192.168.0.0/16" vpc_demo2 = "172.16.0.0/16" } name = each.key cidr = each.value }
在使用字符串集合類型表達時,“each.key” 等同于 “each.value”,我們一般使用 each.key表示,另外,可以通過 toset() 函數將定義的 list 類型進行轉化
resource "huaweicloud_networking_secgroup" "mysecgroup" { for_each = toset(["secgroup_demo1", "secgroup_demo2"]) name = each.key } # 通過變量表示 for _each variable "secgroup_name" { type = set(string) } resource "huaweicloud_networking_secgroup" "mysecgroup" { for_each = var.secgroup_name name = each.key }
使用 for_each 創建的資源需要通過鍵名進行訪問,格式為:<資源類型>.<名稱>[鍵名]
# 訪問 vpc_demo1 > huaweicloud_vpc.vpcs["vpc_demo1"] # 訪問 vpc_demo1 的ID > huaweicloud_vpc.vpcs["vpc_demo1"].id
由于 count 和 for_each 都可用于創建多個資源,建議參考以下規則進行選擇:
1、如果資源實例的參數完全或者大部分一致,建議使用count;
2、如果資源的某些參數需要使用不同的值并且這些值不能由整數派生,建議使用 for_each;
1.4 provider
在Terraform中,我們可以使用 provider塊創建多個配置,其中一個 provider塊為默認配置,其它塊使用 “alias” 標識為非默認配置。在資源中使用元參數 provider 可以選擇非默認的 provider塊。例如我們需要在不同的地區管理資源,首先需要聲明多個 provider塊:
provider "huaweicloud" { region = "cn-north-1" ... } provider "huaweicloud" { alias = "guangzhou" region = "cn-south-1" ... }
示例中我們聲明了北京和廣州的華為云provider,并對廣州地區的provider增加了別名。我們在資源中使用元參數 provider 來選擇非默認的 provider塊,其格式為:
resource "huaweicloud_networking_secgroup" "mysecgroup" { # 使用非默認 provider塊名,對應非默認provider塊的別名(alias) provider = huaweicloud.guangzhou ... }
華為云Provider 支持在Resource中指定region參數,可以在不同的地區創建資源。相比 alias + provider 的方式,這種方式更加靈活簡單。
provider "huaweicloud" { region = "cn-north-1" ... } resource "huaweicloud_vpc" "example" { region = "cn-south-1" name = "terraform_vpc" cidr = "192.168.0.0/16" }
1.5 lifecycle
每個資源實例都具有創建 、更新和銷毀三個階段,在一個資源實例的生命周期過程中都會經歷其中的2至3個階段。通過元參數 lifecycle 可以對資源實例的生命周期過程進行改變,lifecycle 支持以下參數:
默認情況下,當我們需要改變資源中不支持更新的參數時,Terraform會先銷毀已有實例,再使用新配置的參數創建新的對象進行替換。當我們將 create_before_destroy 參數設置為 true 時,Terraform將先創建新的實例,再銷毀之前的實例。這個參數可以適用于保持業務連續的場景,由于新舊實例會同時存在,需要提前確認資源實例是否有唯一的名稱要求或其他約束。
lifecycle { create_before_destroy = true }
當我們將 prevent_destroy 參數設置為true時,Terraform將會阻止對此資源的刪除操作并返回錯誤。這個元參數可以作為一種防止因意外操作而重新創建成本較高實例的安全措施,例如數據庫實例。如果要刪除此資源,需要將這個配置刪除后再執行 destroy 操作。
lifecycle { prevent_destroy = true }
默認情況下,Terraform plan/apply 操作將檢測云上資源的屬性和本地資源塊中的差異,如果不一致將會調用更新或者重建操作來匹配配置。我們可以用 ignore_changes 來忽略某些參數不進行更新或重新。ignore_changes 的值可以是屬性的相對地址列表,對于 Map 和 List 類型,可以使用索引表示法引用,如 tags[“Name”],list[0] 等。
resource "huaweicloud_rds_instance" "myinstance" { ... lifecycle { ignore_changes = [ name, ] } }
此時,Terraform 將會忽略對 name 參數的修改。除了列表之外,我們也可以使用關鍵字 all 忽略所有屬性的更新。
resource "huaweicloud_rds_instance" "myinstance" { ... lifecycle { ignore_changes = all } }
二 常用函數
2.1 cocat與flatten 區別
Concat 接受兩個或多個列表并將它們組合成單個列表。
> concat(["a", ""], ["b", "c"]) [ "a", "", "b", "c", ]
flatten
flatten 接受一個列表并將任何列表元素替換為列表內容的扁平序列。
> flatten([["a", "b"], [], ["c"]]) ["a", "b", "c"]
2.2 lookup 和 element
lookup
> lookup({a="ay", b="bee"}, "a", "what?") ay > lookup({a="ay", b="bee"}, "c", "what?") what?
element
# element 從列表中檢索單個元素。 > element(["a", "b", "c"], 1) b # 如果給定的索引大于列表的長度,則通過將索引取模列表的長度來“環繞”索引: > element(["a", "b", "c"], 3) a > element(["a", "b", "c"], length(["a", "b", "c"])-1) c
2.3 Merge
Merge 接受任意數量的映射或對象,并返回包含來自所有參數的合并元素集的單個映射或對象。如果多個給定的映射或對象定義了相同的鍵或屬性,那么參數序列中后面的那個將優先。如果參數類型不匹配,則在應用合并規則之后,結果類型將是與屬性類型結構匹配的對象。
> merge({a="b", c="d"}, {e="f", c="z"}) { "a" = "b" "c" = "z" "e" = "f" } > merge({a="b"}, {a=[1,2], c="z"}, {d=3}) { "a" = [ 1, 2, ] "c" = "z" "d" = 3 }
三 表達式
如果 var.list 是所有具有屬性 id 的對象的列表,則可以使用以下 for 表達式生成 id 列表:
[for o in var.list : o.id] var.list[*].id var.list[*].interfaces[0].name [for o in var.list : o.interfaces[0].name]
參考鏈接
https://support.huaweicloud.com/basics-terraform/terraform_0015.html
https://cloud.tencent.com/document/product/1213/67049
https://www.terraform.io/language/functions/merge
虛擬私有云 VPC
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。