《Terraform 101 從入門(mén)到實(shí)踐》這本小冊(cè)在南瓜慢說(shuō)官方網(wǎng)站和GitHub兩個(gè)地方同步更新,書(shū)中的示例代碼也是放在GitHub上,方便大家參考查看。
初聞不知Terraform,再聞已是云中人。
什么叫基礎(chǔ)設(shè)施即代碼?
在以前,當(dāng)我們需要把應(yīng)用部署在服務(wù)器時(shí),需要購(gòu)買(mǎi)多臺(tái)服務(wù)器和機(jī)房、組裝交換機(jī)和網(wǎng)絡(luò)、不間斷電源UPS等。隨著云時(shí)代的到來(lái),我們可以在IaaS(Infrastructure as a Service)平臺(tái)直接購(gòu)買(mǎi)所有的基礎(chǔ)設(shè)施,包括服務(wù)器、專(zhuān)用網(wǎng)絡(luò)、DNS、負(fù)載均衡等,而你只需要專(zhuān)注于應(yīng)用層面即可。
IaaS(Infrastructure as a Service)的意思是基礎(chǔ)設(shè)施即服務(wù),它是云服務(wù)的基礎(chǔ)。著名的IaaS廠商有亞馬遜、微軟、谷歌和阿里云等。
云廠商為我們解決了許多運(yùn)維問(wèn)題:我們不再需要自己管理物理機(jī)器,而且能夠根據(jù)需要隨時(shí)創(chuàng)建和銷(xiāo)毀云機(jī)器,還能根據(jù)業(yè)務(wù)和性能要求指定創(chuàng)建服務(wù)器的配置和數(shù)量。這種便利對(duì)于創(chuàng)業(yè)型的小公司和個(gè)人開(kāi)發(fā)者尤其重要。
隨時(shí)公司業(yè)務(wù)的良好發(fā)展,所需要的硬件資源越來(lái)越多,架構(gòu)越來(lái)越復(fù)雜。通過(guò)界面操作手工創(chuàng)建服務(wù)器、數(shù)據(jù)庫(kù)等資源的方式帶來(lái)越來(lái)越多的問(wèn)題。首先,只要是人工操作,都會(huì)有失誤的可能,沒(méi)有人能保證自己不會(huì)犯錯(cuò);而人工操作在軟件行業(yè)發(fā)生事故的案例屢見(jiàn)不鮮。其次,為保證正確率,人工操作一般只能串行,資源多的時(shí)候時(shí)間會(huì)很長(zhǎng)。最后,如果我需要根據(jù)開(kāi)發(fā)環(huán)境的配置再創(chuàng)建一個(gè)測(cè)試環(huán)境和生產(chǎn)環(huán)境,人工操作可能會(huì)造成差異和錯(cuò)誤。
因此,對(duì)于這種復(fù)雜需要,最佳的方式是通過(guò)代碼來(lái)創(chuàng)建所有硬件資源。這種思想就是基礎(chǔ)設(shè)施即代碼(Infrastructure as Code,很簡(jiǎn)稱IaC),通過(guò)代碼與定義、部署、更新和銷(xiāo)毀基礎(chǔ)設(shè)施。把硬件映射為軟件,而開(kāi)發(fā)和運(yùn)維人員通過(guò)管理代碼來(lái)管理硬件。
IaC的好處有:
- 自動(dòng)化:與軟件代替人工,實(shí)現(xiàn)自動(dòng)化,減少風(fēng)險(xiǎn)和安全問(wèn)題;
- 效率高:軟件可以并行創(chuàng)建資源,大大提高效率;
- 記錄與追蹤:通過(guò)代碼與執(zhí)行情況,記錄硬件變更,出問(wèn)題也可以追溯;
- 重用與復(fù)制:抽取公共模塊實(shí)現(xiàn)重用,如創(chuàng)建一個(gè)Kubernetes集群的資源可以封裝成一個(gè)模塊。
最終,實(shí)現(xiàn)快速安全地應(yīng)用部署交付(Devivery)。
IaC工具
在IaC這方面的優(yōu)秀工具還是非常多的,而且不同的工具完成不同的職責(zé),下面列出一些比較常見(jiàn)的工具:
| 圖標(biāo) | 工具名 | GitHub STAR數(shù) |
|---|---|---|
| <img src="https://pkslow.oss-cn-shenzhen.aliyuncs.com/images/other/terraform-101/pictures/01.introduction/logo.ansible.png" width="40"> | Ansible | 50.9k |
| <img src="https://pkslow.oss-cn-shenzhen.aliyuncs.com/images/other/terraform-101/pictures/01.introduction/logo.terraform.png" width="80"> | Terraform | 30.2k |
| <img src="https://pkslow.oss-cn-shenzhen.aliyuncs.com/images/other/terraform-101/pictures/01.introduction/logo.vagrant-logo.png" width="80"> | Vagrant | 23k |
| <img src="https://pkslow.oss-cn-shenzhen.aliyuncs.com/images/other/terraform-101/pictures/01.introduction/logo.chef.png" width="40"> | Chef | 6.8k |
| <img src="https://pkslow.oss-cn-shenzhen.aliyuncs.com/images/other/terraform-101/pictures/01.introduction/logo.puppet.jpg" width="40"> | Puppet | 6.4k |
| <img src="https://pkslow.oss-cn-shenzhen.aliyuncs.com/images/other/terraform-101/pictures/01.introduction/logo.aws-cf.png" width="40"> | AWS CloudFormation | |
| <img src="https://pkslow.oss-cn-shenzhen.aliyuncs.com/images/other/terraform-101/pictures/01.introduction/logo.azure-resource-manager.jpg" width="40"> | Azure Resource Manager | |
| <img src="https://pkslow.oss-cn-shenzhen.aliyuncs.com/images/other/terraform-101/pictures/01.introduction/logo.google-deployment-manager.jpg" width="40"> | Google Cloud Deployment Manager |
其中,Ansible在配置自動(dòng)化應(yīng)該是領(lǐng)頭羊的地位。而Terraform則在服務(wù)開(kāi)通上的事實(shí)標(biāo)準(zhǔn)。這里并不想給各個(gè)工具做具體介紹,感興趣的可以去官網(wǎng)或GitHub了解。
注:有些文章或書(shū)籍會(huì)把Docker和Kubernetes也列為IaC工具,它們的主要職責(zé)是在容器與服務(wù)編排方面。
Terraform隆重登場(chǎng)
Terraform是什么
我們的主角Terraform終于登場(chǎng)了。它是由HashiCorp公司研發(fā)的開(kāi)源的IaC工具,它是由GO語(yǔ)言編寫(xiě)的,可以在各個(gè)平臺(tái)上運(yùn)行,支持Linux、Mac、Windows等。它簡(jiǎn)單易用,即使沒(méi)有太多代碼經(jīng)驗(yàn)的人,也能讀懂Terraform的配置代碼HCL。
HCL,即HashiCorp Configuration Language,是HashiCorp公司開(kāi)發(fā)的配置語(yǔ)言。后續(xù)我們會(huì)介紹一些常用語(yǔ)法。
Terraform是一個(gè)安全高效的用于對(duì)基礎(chǔ)設(shè)施進(jìn)行創(chuàng)建和變更且進(jìn)行版本控制的工具。它支持私有云和公有云,如AWS、Azure、GCP和阿里云等。它的官方網(wǎng)站為https://www.terraform.io。
特性
主要特性有:
- 基礎(chǔ)設(shè)施即代碼:通過(guò)配置語(yǔ)言HCL來(lái)描述基礎(chǔ)設(shè)施,也讓代碼更好地共享和重用。
- 變更計(jì)劃:在實(shí)際變更前可以根據(jù)代碼和狀態(tài)生成即將要發(fā)生變更的計(jì)劃,它能告訴你將要生成、改變和銷(xiāo)毀哪些資源。這可以在執(zhí)行變更前再做最好的檢查,為基礎(chǔ)設(shè)施提供多一層保護(hù)。
- 資源視圖:可以根據(jù)依賴關(guān)系創(chuàng)建出資源視圖,可以直觀地查看整個(gè)基礎(chǔ)設(shè)施的關(guān)系。
- 自動(dòng)化:無(wú)須人工干預(yù)就可以完成變更。
版本號(hào)
截至2021年12月02日,Terraform的最新版本為1.0.11,而它在2021年6月8日才正式發(fā)布1.0.0版本??梢?jiàn)Terraform是如此年輕且有活力。而在Terraform還不是1.0.0版本的時(shí)候,已經(jīng)有大量公司在生產(chǎn)環(huán)境上使用了。
架構(gòu)與原理
Terraform是一個(gè)由Go語(yǔ)言編寫(xiě)的程序,它會(huì)讀取HCL語(yǔ)言編寫(xiě)的配置文件,然后將變更信息通過(guò)RPC與插件通信,由插件調(diào)用云廠商的API完成變更操作。這就是Terraform的工作原理,架構(gòu)圖如下:

基本概念
Terraform core:Terraform的核心組件,類(lèi)似于指揮官,負(fù)責(zé)解析配置、管理狀態(tài)、模塊等核心功能。
插件Plugin:完成具體變更的組件,因?yàn)門(mén)erraform支持多種平臺(tái),它并沒(méi)有把對(duì)所有平臺(tái)的支持都放到核心組件中實(shí)現(xiàn),而是通過(guò)插件的方式來(lái)提供這些功能。需要對(duì)接什么平臺(tái),就加入什么平臺(tái)的插件,非常方面。
模塊module:可以將完成特定功能的HCL封裝成一個(gè)模塊,以實(shí)現(xiàn)代碼復(fù)用。類(lèi)似于其它編程語(yǔ)言中的函數(shù)或方法。有入?yún)⒑统鰠?,一切都可自定義。
狀態(tài)state:狀態(tài)存在專(zhuān)門(mén)的狀態(tài)文件里,它是作用是記錄實(shí)際基礎(chǔ)設(shè)施的狀態(tài)。當(dāng)再次執(zhí)行變更請(qǐng)求時(shí),Terraform會(huì)讀取狀態(tài)文件,判斷是否真的需要變更實(shí)際的基礎(chǔ)設(shè)施。如果狀態(tài)文件記錄的狀態(tài)與HCL描述的一致,就不用再執(zhí)行變更操作了。
初體驗(yàn)
下載安裝
Terraform就是一個(gè)二進(jìn)制的程序,只要下載并添加到PATH中去就可以了。各個(gè)系統(tǒng)的安裝方式?jīng)]有太大差異。這里以Mac系統(tǒng)為例,做個(gè)簡(jiǎn)單介紹。
下載程序:
可以直接到官網(wǎng)界面(https://www.terraform.io/downloads.html)去下載,請(qǐng)根據(jù)自己的系統(tǒng)選擇對(duì)應(yīng)的文件:

下載后進(jìn)行解壓,并將該程序添加到環(huán)境變量中。
比如我的Terraform放在路徑/Users/larry/Software/terraform中,則添加到環(huán)境變量的命令如下:
export PATH=$PATH:/Users/larry/Software/terraform
為了讓它一直生效,我把上面命令放在home目錄下的.bash_profile文件中。
檢查是否安裝成功如下:
$ terraform version
Terraform v1.0.11
on darwin_amd64
如果在純終端的環(huán)境下,也可以通過(guò)命令進(jìn)行下載和解壓,命令如下:
# 下載安裝包
$ wget https://releases.hashicorp.com/terraform/1.0.11/terraform_1.0.11_darwin_amd64.zip
# 解壓
$ unzip terraform_1.0.11_darwin_amd64.zip
最簡(jiǎn)單的任務(wù):創(chuàng)建一個(gè)文件
Terraform的主要應(yīng)用場(chǎng)景是云服務(wù)的基礎(chǔ)設(shè)施管理,但為了讓大家能快速的接觸與體驗(yàn)Terraform,我會(huì)先選擇最簡(jiǎn)單的一個(gè)插件來(lái)入門(mén),以免需要太多的環(huán)境設(shè)置。我們的任務(wù)是創(chuàng)建一個(gè)文本文件,內(nèi)容由我們來(lái)指定??梢酝ㄟ^(guò)插件hashicorp/local來(lái)完成。
在當(dāng)前目錄創(chuàng)建一個(gè)main.tf文件,完整的代碼如下:
terraform {
required_version = "= v1.0.11"
required_providers {
local = {
source = "hashicorp/local"
version = "= 2.1.0"
}
}
}
resource "local_file" "terraform-introduction" {
content = "Hi guys, this the tutorial of Terraform from pkslow.com"
filename = "${path.module}/terraform-introduction-by-pkslow.txt"
}
然后執(zhí)行下面命令:
$ terraform init
Initializing the backend...
Initializing provider plugins...
- Finding hashicorp/local versions matching "2.1.0"...
- Installing hashicorp/local v2.1.0...
- Installed hashicorp/local v2.1.0 (signed by HashiCorp)
Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
看命令的輸出結(jié)果可以知道,Terraform會(huì)自動(dòng)幫我們?nèi)ハ螺d對(duì)應(yīng)版本的插件hashicorp/local,并做一些初始化的操作。
接著我們通過(guò)命令terraform plan來(lái)查看將要執(zhí)行的變更計(jì)劃:
$ terraform plan
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# local_file.terraform-introduction will be created
+ resource "local_file" "terraform-introduction" {
+ content = "Hi guys, this the tutorial of Terraform from pkslow.com"
+ directory_permission = "0777"
+ file_permission = "0777"
+ filename = "./terraform-introduction-by-pkslow.txt"
+ id = (known after apply)
}
Plan: 1 to add, 0 to change, 0 to destroy.
輸出日志中會(huì)提示需要?jiǎng)?chuàng)建、改變和銷(xiāo)毀多少資源。
Plan: 1 to add, 0 to change, 0 to destroy
這里表示會(huì)創(chuàng)建一個(gè)資源。
廢話少說(shuō),我們直接執(zhí)行變更:
$ terraform apply
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# local_file.terraform-introduction will be created
+ resource "local_file" "terraform-introduction" {
+ content = "Hi guys, this the tutorial of Terraform from pkslow.com"
+ directory_permission = "0777"
+ file_permission = "0777"
+ filename = "./terraform-introduction-by-pkslow.txt"
+ id = (known after apply)
}
Plan: 1 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value:
會(huì)讓你確認(rèn)是否執(zhí)行變更,如果是,則輸入yes。我們直接輸入yes并按回車(chē)。
Enter a value: yes
local_file.terraform-introduction: Creating...
local_file.terraform-introduction: Creation complete after 0s [id=f63c7933c953ea2d03820d1ec35a80c718bd4777]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
成功執(zhí)行,創(chuàng)建了文件。
$ ls -l
total 24
-rw-r--r-- 1 larry staff 344 Dec 3 00:01 main.tf
-rwxr-xr-x 1 larry staff 55 Dec 3 00:13 terraform-introduction-by-pkslow.txt
-rw-r--r-- 1 larry staff 921 Dec 3 00:13 terraform.tfstate
上面還有一個(gè)tfstate文件,是用來(lái)記錄狀態(tài)的,以后會(huì)詳細(xì)講這塊內(nèi)容。
查看一下文件內(nèi)容:
$ cat terraform-introduction-by-pkslow.txt
Hi guys, this the tutorial of Terraform from pkslow.com
與我們預(yù)期的內(nèi)容一致。
如果再次執(zhí)行apply會(huì)不會(huì)再次創(chuàng)建一個(gè)文件呢?還是創(chuàng)建失敗,因?yàn)槲募汛嬖冢?/p>
帶著這樣的問(wèn)題,我們?cè)賵?zhí)行一次:
$ terraform apply
local_file.terraform-introduction: Refreshing state... [id=f63c7933c953ea2d03820d1ec35a80c718bd4777]
No changes. Your infrastructure matches the configuration.
Terraform has compared your real infrastructure against your configuration and found no differences, so no changes are needed.
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
發(fā)現(xiàn)提示不需要變更,不會(huì)執(zhí)行任何操作。
大家可以思考一下為什么,答案會(huì)在后面章節(jié)揭曉。
現(xiàn)在我不需要這個(gè)文件呢,通過(guò)destroy命令可以刪除:
$ terraform destroy
local_file.terraform-introduction: Refreshing state... [id=f63c7933c953ea2d03820d1ec35a80c718bd4777]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
- destroy
Terraform will perform the following actions:
# local_file.terraform-introduction will be destroyed
- resource "local_file" "terraform-introduction" {
- content = "Hi guys, this the tutorial of Terraform from pkslow.com" -> null
- directory_permission = "0777" -> null
- file_permission = "0777" -> null
- filename = "./terraform-introduction-by-pkslow.txt" -> null
- id = "f63c7933c953ea2d03820d1ec35a80c718bd4777" -> null
}
Plan: 0 to add, 0 to change, 1 to destroy.
Do you really want to destroy all resources?
Terraform will destroy all your managed infrastructure, as shown above.
There is no undo. Only 'yes' will be accepted to confirm.
Enter a value: yes
local_file.terraform-introduction: Destroying... [id=f63c7933c953ea2d03820d1ec35a80c718bd4777]
local_file.terraform-introduction: Destruction complete after 0s
Destroy complete! Resources: 1 destroyed.
一樣需要你確認(rèn)是否真的需要?jiǎng)h除,輸入yes回車(chē)即可。
到這里,就已經(jīng)真正地帶大家體驗(yàn)了一下Terraform是如何工作的,介紹了它的整個(gè)流程,也就是Terraform官網(wǎng)所說(shuō)的Write, Plan, Apply。希望大家能真正動(dòng)手實(shí)踐,包括后續(xù)的實(shí)驗(yàn),這跟學(xué)編程語(yǔ)言是一樣的。
最后,對(duì)于本次實(shí)驗(yàn)我想提幾點(diǎn):
- 其中的plan命令不是必須的,它是展示即將發(fā)生的變更,你可以直接apply也是可以的;
- 可以通過(guò)plan命令輸出計(jì)劃文件,然后apply的時(shí)候指定計(jì)劃文件;
- 命令apply和destroy可以不必交互式輸入yes,通過(guò)添加參數(shù)
-auto-approve即可。