上一篇《 玩轉阿裡雲Terraform(一):Terraform 是什麼 》介紹了 Terraform 的基本定義和特點之後,本文将着重介紹幾個Terraform中的關鍵概念。
Terraform 關鍵概念
在使用Terraform的過程中,通常接觸到很多名詞,如configuration,provider,resource,datasource,state,backend,provisioner等,本文将一一跟大家介紹這些概念。
Configuration:基礎設施的定義和描述
“基礎設施即代碼(Infrastructure as Code)”,這裡的Code就是對基礎設施資源的代碼定義和描述,也就是通過代碼表達我們想要管理的資源。
# VPC 資源
resource "alicloud_vpc" "vpc" {
name = "tf_vpc"
cidr_block = "172.16.0.0/16"
}
# VSwitch 資源
resource "alicloud_vswitch" "vswitch" {
vpc_id = alicloud_vpc.vpc.id
cidr_block = "172.16.1.0/24"
availability_zone = "cn-beijing-a"
}
對所有資源的代碼描述都需要定義在一個以
tf
結尾的檔案用于Terraform加載和解析,這個檔案我們稱之為“Terraform模闆”或者“Configuration”。
Provider:基礎設施管理元件
Terraform 通常用于對雲上基礎設施,如虛拟機,網絡資源,容器資源,存儲資源等的建立,更新,檢視,删除等管理動作,也可以實作對實體機的管理,如安裝軟體,部署應用等。
【Provider】是一個與Open API直接互動的後端驅動,Terraform 就是通過Provider來完成對基礎設施資源的管理的。不同的基礎設施提供商都需要提供一個Provider來實作對自家基礎設施的統一管理。目前Terraform目前支援超過160多種的providers,大多數雲平台的Provider插件均已經實作了,阿裡雲對應的Provider為
alicloud
。
!

在操作環境中,Terraform和Provider是兩個獨立存在的package,當運作Terraform時,Terraform會根據使用者模闆中指定的provider或者resource/datasource的标志自動的下載下傳模闆所用到的所有provider,并将其放在執行目錄下的一個隐藏目錄
.terraform
下。
provider "alicloud" {
version = ">=1.56.0"
region = "cn-hangzhou"
configuration_source = "terraform-alicloud-modules/classic-load-balance"
}
模闆中顯示指定了一個阿裡雲的Provider,并顯示設定了provider的版本為
1.56.0+
(預設下載下傳最新的版本),指定了需要管理資源的region,指定了目前這個模闆的辨別。
通常Provider都包含兩個主要元素 resource 和 data source。
Resource:基礎設施資源和服務的管理
在Terraform中,一個具體的資源或者服務稱之為一個resource,比如一台ECS 執行個體,一個VPC網絡,一個SLB執行個體。每個特定的resource包含了若幹可用于描述對應資源或者服務的屬性字段,通過這些字段來定義一個完整的資源或者服務,比如執行個體的名稱(name),執行個體的規格(instance_type),VPC或者VSwitch的網段(cidr_block)等。
定義一個Resource的文法非常簡單,通過
resource
關鍵字聲明,如下:
# 定義一個ECS執行個體
resource "alicloud_instance" "default" {
image_id = "ubuntu_16_04_64_20G_alibase_20190620.vhd"
instance_type = "ecs.sn1ne.large"
instance_name = "my-first-vm"
system_disk_category = "cloud_ssd"
...
}
- 其中
為資源類型(Resource Type),定義這個資源的類型,告訴Terraform這個Resource是阿裡雲的ECS執行個體還是阿裡雲的VPC。alicloud_instance
-
為資源名稱(Resource Name),資源名稱在同一個子產品中必須唯一,主要用于供其他資源引用該資源。default
- 大括号裡面的block塊為配置參數(Configuration Arguments),定義資源的屬性,比如ECS 執行個體的規格、鏡像、名稱等。
顯然這個Terraform模闆的功能為在阿裡雲上建立一個ECS執行個體,鏡像ID為
ubuntu_16_04_64_20G_alibase_20190620.vhd
,規格為
ecs.sn1ne.large
,自定義了執行個體名稱和系統盤的類型。
除此之外,在Terraform中,一個資源與另一個資源的關系也定義為一個資源,如一塊雲盤與一台ECS執行個體的挂載,一個彈性IP(EIP)與一台ECS或者SLB執行個體的綁定關系。這樣定義的好處是,一方面資源架構非常清晰,另一方面,當模闆中有若幹個EIP需要與若幹台ECS執行個體綁定時,隻需要通過Terraform的
count
功能就可以在無需編寫大量重複代碼的前提下實作綁定功能。
resource "alicloud_instance" "default" {
count = 5
...
}
resource "alicloud_eip" "default" {
count = 5
...
}
resource "alicloud_eip_association" "default" {
count = 5
instance_id = alicloud_instance.default[count.index].id
allocation_id = alicloud_eip.default[count.index].id
}
顯然這個Terraform模闆的功能為在阿裡雲上建立5個ECS執行個體和5個彈性IP,并将它們一一綁定。
Data Source:基礎設施資源和服務的查詢
對資源的查詢是運維人員或者系統最常使用的操作,比如,檢視某個region下有哪些可用區,某個可用區下有哪些執行個體規格,每個region下有哪些鏡像,目前賬号下有多少機器等,通過對資源及其資源屬性的查詢可以幫助和引導開發者進行下一步的操作。
除此之外,在編寫Terraform模闆時,Resource使用的參數有些是固定的靜态變量,但有些情況下可能參數變量不确定或者參數可能随時變化。比如我們建立ECS 執行個體時,通常需要指定我們自己的鏡像ID和執行個體規格,但我們的模闆可能随時更新,如果在代碼中指定ImageID和Instance,則一旦我們更新鏡像模闆就需要重新修改代碼。
在Terraform 中,Data Source 提供的就是一個查詢資源的功能,每個data source實作對一個資源的動态查詢,Data Souce的結果可以認為是動态變量,隻有在運作時才能知道變量的值。
Data Sources通過
data
// Images data source for image_id
data "alicloud_images" "default" {
most_recent = true
owners = "system"
name_regex = "^ubuntu_18.*_64"
}
data "alicloud_zones" "default" {
available_resource_creation = "VSwitch"
enable_details = true
}
// Instance_types data source for instance_type
data "alicloud_instance_types" "default" {
availability_zone = data.alicloud_zones.default.zones.0.id
cpu_core_count = 2
memory_size = 4
}
resource "alicloud_instance" "web" {
image_id = data.alicloud_images.default.images[0].id
instance_type = data.alicloud_instance_types.default.instance_types[0].id
instance_name = "my-first-vm"
system_disk_category = "cloud_ssd"
...
}
如上例子中的ECS Instance 沒有指定鏡像ImageID和執行個體規格,而是通過
data
引用,Terraform運作時将首先根據鏡像名稱字首選擇系統鏡像,如果同時有多個鏡像滿足條件,則選擇最新的鏡像。執行個體規格也是類似,在某個可用區下選擇2核4G的執行個體規格進行傳回。
State:儲存資源關系及其屬性檔案的資料庫
Terraform建立和管理的所有資源都會儲存到自己的資料庫上,這個資料庫不是通常意義上的資料庫(MySQL,Redis等),而是一個檔案名為
terraform.tfstate
的檔案,在Terraform 中稱之為
state
https://www.terraform.io/docs/state/index.html ,預設存放在執行Terraform指令的本地目錄下。這個
state
檔案非常重要,如果該檔案損壞,Terraform 将認為已建立的資源被破壞或者需要重建(實際的雲資源通常不會受到影響),因為在執行Terraform指令是,Terraform将會利用該檔案與目前目錄下的模闆做Diff比較,如果出現不一緻,Terraform将按照模闆中的定義重新建立或者修改已有資源,直到沒有Diff,是以可以認為Terraform是一個有狀态服務。
當涉及多人協作時不僅需要拷貝模闆,還需要拷貝
state
檔案,這無形中增加了維護成本。幸運的是,目前Terraform支援把
state
檔案放到遠端的存儲服務
OSS
上或者
consul
上,來實作
state
檔案和模闆代碼的分離。具體細節可參考
官方文檔Remote State或者關注後續文章的詳細介紹。
Backend:存放 State 檔案的載體
正如上節提到,Terraform 在建立完資源後,會将資源的屬性存放在一個
state
檔案中,這個檔案可以存放在本地也可以存放在遠端。存放
state
檔案的載體就是
Backend
Backend
分為本地(local)和遠端(remote)兩類,預設為本地。遠端的類型也非常多,目前官方網站提供的有13種,并且阿裡雲的
OSS就位列其中。
使用遠端的Backend,既可以降低多人協作時對state的維護成本,而且可以将一些敏感的資料存放在遠端,保證了資料的安全性。
Provisioner:在機器上執行操作的元件
Provisioner通常用來在本地機器或者登陸遠端主機執行相關的操作,如
local-exec
provisioner 用來執行本地的指令,
chef
provisioner 用來在遠端機器安裝,配置和執行chef client,
remote-exec
provisioner 用來登入遠端主機并在其上執行指令。
Provisioner 通常跟 Provider一起配合使用,provider用來建立和管理資源,provisioner在建立好的機器上執行各種操作。
小結
Terraform中涉及到的概念非常多,用法也多種多樣,本文隻是介紹了其中的幾個關鍵的概念,如果想要了解更多的概念,可以通路Terraform的官方網站。學習Terraform最好的方式是要多動手,使用terraform去實作和操作一些特定的場景,在不斷操作的過程中,持續解決遇到的問題可以幫助大家更快和更好的使用Terraform。
最後,歡迎大家關注 Terraform,關注阿裡雲 Provider,如有任何使用問題,可直接在
terraform-provider-alicloud送出您的問題,我們将盡快解決。