代碼編寫階段的術語和概念
在了解了模板編寫、Terraform 配置文件目錄和 HashiCorp 語言 HCL 之后,本文主要介紹在 Terraform 工作流的代碼編寫階段你會遇到的一些常見術語和概念。
資源(Resources)
資源(Resources)是定義基礎設施組件的代碼塊,通常定義在 main.tf 文件中。資源通過關鍵字 resource 來標識,其后跟具體的資源類型和自定義名稱。資源類型取決于你在配置文件中定義的提供商(Provider)。在花括號內是指定資源類型的參數,你需要在這里指定資源配置所需的輸入。
resource "resource_type" "resource_name" {
# 指定資源類型的參數(Argument)
}
Terraform 使用資源類型和資源名稱來標識一個基礎設施元素。關鍵字 resource 將代碼塊識別為云基礎設施的組件。資源類型是 alicloud_oss_bucket,這代表阿里云的資源。術語 resource 是 Terraform 特有的,不能自定義;資源類型根據定義的提供商而變化;example-bucket 代表在當前 Terraform 配置中的資源名稱。Terraform 使用資源類型和資源名稱一起作為資源在當前 Terraform 配置中的標識符。
resource "alicloud_oss_bucket" "example-bucket" {
bucket = "my-bucket-xxxx" # 指定一個全局唯一的 Bucket 名稱
}
下面這個示例聲明了阿里云為提供者,并展示了兩個阿里云的資源塊:一個 OSS Bucket 和一個虛擬交換機。參數根據定義的資源類型而不同。對于資源 alicloud_oss_bucket,你只需指定 Bucket 名稱即可成功創建資源。對于 alicloud_vswitch 資源,你必須指定所屬 VPC 的 ID(vpc_id)、網段(cidr_block)、所屬可用區(zone_id),名稱,標簽等其他參數是可選的。
resource "alicloud_oss_bucket" "example-bucket" {
bucket = "my-bucket-xxxxx"
}
resource "alicloud_vswitch" "main_vswitch" {
vpc_id = "vpc-abc12345"
cidr_block = "10.0.1.0/24"
zone_id = "cn-hangzhou-k"
vswitch_name = "main-vswitch"
}
如果資源復雜,資源配置代碼較長,可以按照資源類型單獨使用一個獨立的 .tf 文件來存放,例如,用于 ECS 實例、OSS Bucket 和數據庫的配置可以分別放在 instance.tf,oss.tf 和 database.tf 中。
提供商(Provider)
提供商實現了每一種可配置的資源類型;如果沒有提供商,Terraform 將無法管理任何類型的基礎設施。提供商通常定義在 providers.tf 文件中,你需要指定包含提供商定義的 Terraform 塊。當聲明了提供商后,Terraform 通過 init 命令自動下載提供商插件。
terraform {
required_providers {
alicloud = {
source = "aliyun/alicloud"
version = "1.225.0"
}
}
}
provider "alicloud" {
# 配置你的阿里云憑據和地域信息
# 出于安全考慮,建議不要在這個文件中直接包含你的阿里云AccessKey和SecretKey,推薦使用環境變量或其它安全方式設置憑據:
# export ALICLOUD_ACCESS_KEY="<你的阿里云Access Key>"
# export ALICLOUD_SECRET_KEY="<你的阿里云Secret Key>"
region = "cn-hangzhou"
}
提供商將具體的管理資源的 API 編排為 Terraform 資源,并管理資源與 API 之間的交互。提供商配置屬于 Terraform 配置的根模塊。alicloud 是要配置的本地提供商名稱,為了確保本地名稱配置正確,必須在 required_providers 塊中包含提供商。source 參數用于指定你打算使用的提供商的全局源地址。在上面的示例中,source 參數被賦值為 Terraform Registry 站點的地址 aliyun/alicloud。version 參數用于指定提供商的其中一個版本,該參數是可選的,但建議使用。version 參數將提供商限制在特定版本或版本范圍內,以防止下載可能包含非兼容更改的新提供商。如果未指定版本,Terraform 會在初始化期間自動下載最新版本的提供商。
值得注意的是,由于歷史原因,阿里云提供商 alicloud 支持兩個 source 值:aliyun/alicloud 和 hashicorp/alicloud。兩者的實現完全一致。更多信息,詳見Terraform 概覽。
access_key,secret_key,region 等參數是專用于配置阿里云 Provider 的。如果 Terraform 配置中沒有包含 provider 塊,Terraform 會假定一個空的默認配置,并且 access_key,secret_key,region 默認會從環境變量中獲取。如果環境變量中沒有指定 region,默認將使用 cn-beijing。更多阿里云 Provider 的配置參數,詳見 Provider 官網。
變量(Variables)
變量用于參數化你的 Terraform 配置。輸入變量作為參數供給 Terraform 使用,使其允許在無需更改源配置代碼的情況下輕松定制和共享配置。一旦定義了變量,在 Terraform 運行時可以有多種不同的方式來設置其值:環境變量、CLI 參數、鍵值文件等。你可以在運行時或在一個以 .tfvars 擴展名結尾的文件中以 K-V 的形式定義資源屬性。
借助參數,你可以輕松地將屬性與 Terraform 執行計劃分離。在這個示例中,main.tf 聲明了一個專有網絡 VPC,vpc_name 屬性在 variables.tf 文件中被聲明為變量,因此該屬性已經被參數化,你可以在運行時定義這些變量的值或者將其定義到一個 tfvars 文件中。更多關于變量的內容,詳見Variable 介紹。
輸出(Outputs)
outputs.tf 文件保存了資源的輸出值。由 Terraform 管理的每個資源實例都可以導出屬性,這些屬性的值可在 Terraform 配置的其他地方被引用。如果需要,輸出值是用來暴露這些信息的方法。
一些資源屬性在創建時被計算出來。例如,某些資源的連接地址或者 VSwitch 的 ID 會在資源創建時生成。VSwitch 的計算屬性 ID 是創建其他資源(如 ECS 實例,RDS 實例等)對象所需的。通過輸出值,你可以輸出這些信息并使其可訪問。
output "vswitch_id" {
value = alicloud_vswitch.main_vswitch.id
}
output 關鍵字后的標簽是名稱,必須是一個有效的標識符。在根模塊中,此名稱會顯示給查看者。在子模塊中,它可以用于訪問該值。value 參數接受一個表達式,該表達式返回結果給用戶。
狀態(State)
Terraform 在狀態文件中保存它管理的資源的狀態。默認情況下,狀態文件是存儲在本地,但它也可以遠端存儲。在團隊協作場景中,遠端存儲通常是首選方法。
{
"version": 4,
"terraform_version": "1.7.1",
"serial": 168,
"lineage": "46c0889c-f4ff-d1fd-2109-364f97e55c06",
"outputs": {
"vswitch_id": {
"value": "vsw-bp1ev5ei73c7y5ib887v1",
"type": "string"
}
},
"resources": [
{
"mode": "managed",
"type": "alicloud_vswitch",
"name": "main_vswitch",
"provider": "provider[\"registry.terraform.io/hashicorp/alicloud\"]",
"instances": [
{
"schema_version": 0,
"attributes": {
"availability_zone": "cn-hangzhou-k",
"cidr_block": "10.0.1.0/24",
"create_time": "2024-06-23T07:53:48Z",
"description": "",
"enable_ipv6": null,
"id": "vsw-bp1ev5ei73c7y5ib887v1",
...
需要注意的是,不要修改或觸碰此文件,它是自動創建和更新的,一旦狀態文件損壞,將會導致繼續執行 Terraform 失敗或者重復創建新的資源。更多狀態介紹,詳見Terraform State 介紹。
模塊(Modules)
Terraform 模塊是一組位于單個目錄中的 Terraform 配置文件,即使是一個包含了一個或多個 .tf 文件的單一目錄的簡單配置也被視為一個模塊。模塊是 Terraform 中代碼復用的主要方法,它們通過指定可以檢索代碼的源來重復使用。源可以是本地的也可以是遠程的。你可以使用來自 HashiCorp 模塊注冊中心的開源模塊或創建你自己的模塊。