《Terraform 101 從入門到實踐》這本小冊在南瓜慢說官方網(wǎng)站和GitHub兩個地方同步更新,書中的示例代碼也是放在GitHub上,方便大家參考查看。
Terraform支持的公有云有很多,如AWS、Azure、Google、Alibaba等。將Terraform應(yīng)用于公有云,才最能發(fā)揮其強(qiáng)大的功能。
初始化GCP項目
創(chuàng)建一個新項目
首先我們需要初始化一個GCP項目。GCP給開發(fā)者提供了免費試用的服務(wù),我們可以在不花錢的情況下學(xué)習(xí)GCP的功能。
要使用GCP,我們需要創(chuàng)建一個項目,它所有的資源都是在項目之下管理的:

創(chuàng)建Service Account
在實際開發(fā)中,我們不能使用自己的賬號在做操作,最好的方式是創(chuàng)建一個服務(wù)賬號(Service Account),這應(yīng)該也是所有云平臺都推薦的方式。創(chuàng)建位置如下:

輸入賬號名字:

選擇角色,為了方便,我直接選擇Owner,會擁有所有權(quán)限,但實際應(yīng)用肯定不能這樣,要做好隔離:

創(chuàng)建密鑰文件
對于Service Account,不是通過用戶名密碼來授權(quán)的,而是通過密鑰文件,創(chuàng)建如下:

選擇新建一個密鑰,并格式為json。創(chuàng)建后,會自動下載key文件。
設(shè)置gcloud SDK
Key文件拿到后,我們可以設(shè)置環(huán)境變量:GOOGLE_APPLICATION_CREDENTIALS:
$ export GOOGLE_APPLICATION_CREDENTIALS=/Users/larry/Software/google-cloud-sdk/pkslow-admin-for-all.json
激活Service Account:
$ gcloud auth activate-service-account admin-for-all@pkslow.iam.gserviceaccount.com --key-file=${GOOGLE_APPLICATION_CREDENTIALS}
設(shè)置SDK的項目ID:
$ gcloud config set project pkslow
檢查一下設(shè)置是否正確:
$ gcloud auth list
Credentialed Accounts
ACTIVE ACCOUNT
* admin-for-all@pkslow.iam.gserviceaccount.com
To set the active account, run:
$ gcloud config set account `ACCOUNT`
$ gcloud config list
[core]
account = admin-for-all@pkslow.iam.gserviceaccount.com
disable_usage_reporting = True
project = pkslow
Your active configuration is: [default]
使用gcloud創(chuàng)建Pub/Sub
SDK設(shè)置好后,就可以使用了,我們使用它來創(chuàng)建Pub/Sub試試。創(chuàng)建主題和訂閱:
$ gcloud pubsub topics create pkslow-test
Created topic [projects/pkslow/topics/pkslow-test].
$ gcloud pubsub subscriptions create pkslow-sub --topic=pkslow-test
Created subscription [projects/pkslow/subscriptions/pkslow-sub].
檢查是否創(chuàng)建成功:
$ gcloud pubsub topics list
---
name: projects/pkslow/topics/pkslow-test
$ gcloud pubsub subscriptions list
---
ackDeadlineSeconds: 10
expirationPolicy:
ttl: 2678400s
messageRetentionDuration: 604800s
name: projects/pkslow/subscriptions/pkslow-sub
pushConfig: {}
topic: projects/pkslow/topics/pkslow-test
在瀏覽器查看,發(fā)現(xiàn)已經(jīng)成功創(chuàng)建了:

Terraform創(chuàng)建Pub/Sub
下載Terraform插件
我們需要安裝GCP的Terraform插件來管理GCP資源:
# 設(shè)置插件目錄
$ export TERRAFORM_PLUGIN=/Users/larry/Software/terraform/plugins
# 創(chuàng)建目錄
$ mkdir -p ${TERRAFORM_PLUGIN}/registry.terraform.io/hashicorp/google/4.0.0/darwin_amd64
$ cd ${TERRAFORM_PLUGIN}/registry.terraform.io/hashicorp/google/4.0.0/darwin_amd64
# 下載
$ wget https://releases.hashicorp.com/terraform-provider-google/4.0.0/terraform-provider-google_4.0.0_darwin_amd64.zip
# 解壓
$ unzip terraform-provider-google_4.0.0_darwin_amd64.zip
準(zhǔn)備Terraform代碼
需要提供Terraform代碼理管理Pub/Sub,更多細(xì)節(jié)請參考: Terrafrom GCP.
版本文件version.tf:
terraform {
required_version = "= 1.0.11"
required_providers {
google = {
source = "hashicorp/google"
version = "= 4.0.0"
}
}
}
主文件main.tf:
provider "google" {
project = "pkslow"
}
resource "google_pubsub_topic" "pkslow-poc" {
name = "pkslow-poc"
}
resource "google_pubsub_subscription" "pkslow-poc" {
name = "pkslow-poc"
topic = google_pubsub_topic.pkslow-poc.name
labels = {
foo = "bar"
}
# 20 minutes
message_retention_duration = "1200s"
retain_acked_messages = true
ack_deadline_seconds = 20
expiration_policy {
ttl = "300000.5s"
}
retry_policy {
minimum_backoff = "10s"
}
enable_message_ordering = true
}
初始化和變更
指定插件目錄初始化:
$ terraform init -plugin-dir=${TERRAFORM_PLUGIN}
使變更生效,就會在GCP上創(chuàng)建對應(yīng)的資源:
$ terraform apply -auto-approve
如果沒有發(fā)生錯誤,則意味著創(chuàng)建成功,我們檢查一下:
$ gcloud pubsub topics list
---
name: projects/pkslow/topics/pkslow-poc
$ gcloud pubsub subscriptions list
---
ackDeadlineSeconds: 20
enableMessageOrdering: true
expirationPolicy:
ttl: 300000.500s
labels:
foo: bar
messageRetentionDuration: 1200s
name: projects/pkslow/subscriptions/pkslow-poc
pushConfig: {}
retainAckedMessages: true
retryPolicy:
maximumBackoff: 600s
minimumBackoff: 10s
topic: projects/pkslow/topics/pkslow-poc
注意:我們并沒有提供任何密碼或密鑰,那Terraform怎么可以直接操作我的GCP資源呢?因為它會根據(jù)環(huán)境變量GOOGLE_APPLICATION_CREDENTIALS來獲取。
發(fā)送和接收消息
我們通過gcloud來發(fā)送消息到Pub/Sub上:
$ gcloud pubsub topics publish pkslow-poc --message="www.pkslow.com"
messageIds:
- '3491736520339885'
$ gcloud pubsub topics publish pkslow-poc --message="Larry Deng"
messageIds:
- '3491738650256958'
$ gcloud pubsub topics publish pkslow-poc --message="Hi, pkslower"
messageIds:
- '3491739306095970'
從Pub/Sub拉取消息:
$ gcloud pubsub subscriptions pull pkslow-poc --auto-ack

我們還能在GCP界面上監(jiān)控對應(yīng)的隊列,十分方便:

通過Google Cloud Storage(GCS)管理Terraform的狀態(tài)State
管理Terraform狀態(tài)文件的最佳方式是通過云端的統(tǒng)一的存儲,如谷歌云就用GCS。
首先要創(chuàng)建一個Bucket:
$ gsutil mb -p pkslow -l us-west1 -b on gs://pkslow-terraform
Creating gs://pkslow-terraform/...
$ gsutil ls gs://
gs://pkslow-terraform/
然后在Terraform文件中配置對應(yīng)的信息:
terraform {
backend "gcs" {
bucket = "pkslow-terraform"
prefix = "state/gcp/pubsub"
}
}
初始化后,就會在Bucket上創(chuàng)建對應(yīng)的目錄:
$ terraform init -plugin-dir=${TERRAFORM_PLUGIN}
變更生效:
$ terraform apply -auto-approve
我們在瀏覽器查看一下,發(fā)現(xiàn)已經(jīng)成功狀態(tài)了對應(yīng)的狀態(tài)文件:

通過遠(yuǎn)程的云端,不僅可以存入狀態(tài)文件,也可以從狀態(tài)文件讀取數(shù)據(jù),如一些輸出變量。比如模塊A創(chuàng)建了一個VM,而我們可能通過這種方式獲取它的IP,以便在其它模塊使用。大致的配置如下:
data "terraform_remote_state" "foo" {
backend = "gcs"
config = {
bucket = "terraform-state"
prefix = "prod"
}
}
resource "template_file" "bar" {
template = "${greeting}"
vars {
greeting = "${data.terraform_remote_state.foo.greeting}"
}
}