關於我想看漫畫卻不想看廣告這檔事 (12) —Terraform 入門 & 實戰

Seaweed
9 min readAug 28, 2021

--

話說回來,不知道各位先進在畫 AWS 架構圖的時候都怎麼選 icon 的

光個 EC2 icon 就可以多成這樣,到底是哪裡有毛病。

基本語法 & 佈署指令介紹

使用 Terraform 佈署雲端其實可以很簡單,下面是在 AWS 佈署一台 EC2 的範例程式碼:

可以發現程式碼本身比起說成程式碼,更像是設定檔。而這個設定檔便是最基本的 EC2 佈署程式。

關於裡面用到的關鍵字,其解釋如下

variable

就是定義變數,但這個變數只能用於啟動時輸入參數使用,無法在程式內改變,而使用 default 可以在當輸入沒有指定數值時為變數設定預設值。另外,要指定變數可以透過環境變數或者在同資料夾下放置 terraform.tfvars 來完成,格式如下:

關於使用環境變數指定變數的方法可以看這裡:

provider

就是提供功能的提供商設定,因為我們使用 AWS 的服務所以是 "aws" ,因此這裡的 "aws" 是不能改的(除非你不想用 aws)。另外,這裡的 provider 以及 resource 實際上是一套另外維護的專案,比如這邊用 aws 以及他的 resource,那這部份的功能就是 aws 這個 terraform provider 專案(類似 plugin)提供。因此如果各提供商沒有好好維護, provider 之間可能會有所衝突,甚至文件也會有不全的狀況。

不過大部份比較大的雲端都會把自己的 provider 像這樣開源(白◯)

所以只要是夠大的平台一般不用擔心會有事。

resource

用來實際定義要佈署的資源(比如一台 EC2 一台 RDS 一台 Lambda…等等),另外剛剛說過 provider 是廠商各自維護,因此 resource 則可以當作是 provider 提供的功能。每個雲端每個資源都會有不同的用法以及設定方法,所以關於有什麼選項以及設定方法麻煩看官方教學網站

output

其實就是印出變數或者中間產生的物件的值,比如 build 好之後輸出 EC2 的 public dns 名。挺好用的,只有 value 需要指定。

另外,實際用 Terraform 佈署之後應該還會看到 datalocalmodule ,這裡也一併介紹。

data

用需要動態產生資料時可用,比如要打包程式碼算 hash 的時候,或者要動態跟 aws 取得可用 ami (AWS 上的作業系統映像 ID)的時候。

module

別人打包的一組可用的 resource,基本上就是為了簡化重複的程式碼。這部份不由 provider 提供,需要另外指定 source 參數來使用。架構越寫越大之後如果能正確使用對可讀性有幫助。

關於 module 詳細可以看這裡:

.tf 檔(可以不只一個)跟 terraform.tfvars都寫好之後,就可以照以下方法佈署了:

$ terraform init
$ terraform plan -out dev.tfplan
$ terraform apply dev.tfplan

terraform.tfstate

另外特別注意, terraform 在佈署完成或失敗之後都會在資料夾下產生一個叫 terraform.tfstate 的檔案,這檔案非常重要,它被用來描述目前雲端的狀態。由於 terraform 不會隨時監視雲端,所以佈署後,不只這狀態檔不能丟,被佈署的雲端服務也基本不能以 terraform 之外的方式更動雲端

到這裡我們算是簡單看過 Terraform 的使用方法與結構了,接著開始針對 Terraform 上使用 AWS provider 做解釋。如果對 Terraform 其他 provider 還有興趣深入了解,可以看看官網(相比 AWS 真的寫得很好)。

另外這邊特別提一下,取得 var/locals/data/resource 的變數內容的方法其實在寫法上有些不同,詳細如下

# var
定義: var "foo" {}
取值: var.foo
# locals
定義: locals { foo="bar" }
取值: local.foo
# data
定義: data "aws_availability_zones" "available"
取值: data.aws_availability_zones.available.names
# resource
定義: resource "aws_vpc" "vpc"
取值: aws_vpc.vpc
另外,以上都可以根據回傳型態繼續深入取值,比如
陣列: data.aws_availability_zones.available.names[0]
物件: aws_vpc.vpc.id

AWS VPC 網路結構

一開始在部署 EC2 時遇到最大問題會是難以理解的 VPC 結構。為此本藻繪製一張(可能有點醜):建立一台可 ssh EC2 時需要的 VPC 架構圖。

特別注意:雖然 AWS 一開始會付預設可用 VPC,但為了之後能「真正地」部署出一套可用服務,我們必須理解 VPC 裡的架構。

VPC 的結構簡單來說就如上圖,說極端點這區分就像一個家用網路環境,以下介紹各個元件:

VPC

AWS 所定義的服務組單位,一個 VPC 可以通俗理解為一個資料中心。基本上所有網路資源都需要一個 VPC 才能運行,並且 VPC 之間被視為不同內網,一般也不能互相溝通。

Subnet

其實就是網段,但這裡需要另外注意的是,Subnet 定義時需要指定實體位置一個 availability zone,因為相比 VPC 只是個抽象的組合,Subnet 會決定服務實際放置的區域。關於 availibility zone 可以看以下:

補充一下:在 AWS 上也基本上是透過指定多個 Subnet(Availability zone 要不一樣) 給一個資源來做冗余化。

Security Group

這也是幾乎所有 AWS 資源都需要的東東,把它當防火牆就好,而且是 Windows 防火牆,差別只是在 AWS 上可以寫好一份重複指定給多個資源。然後 ingress 指傳入,egress 指傳出, port 指定為 0 就是允許所有 port。

補充:圖中只寫出 port 規則,但實際上還可以針對來源(ingress)・目的地(egress)/傳輸層協定(tcp/udp)來做特定的放行。

Internet Gateway

跟家裡連 wifi 時網路設定裡的 Gateway 87% 像,反正就是內部網路出口。

Route Table

與 Subnet 關聯,用來處理 Subnet 的「傳出」需求所對應的 Gateway,設定方法是一個網段指定一個 Internet Gateway但無法針對 Subnet 內的 IP/網段做 routing(本藻這麼覺得,歡迎指教)。另外,要讓一個 Route Table 被Subnet 使用時,得先寫好一份 Route Table 的 resource 然後透過 aws_route_table_association(Terraform 的話) 關聯至 Subnet

到此本藻算是介紹完基本的 VPC 概念了,雖然還有非常多的坑,但若能理解相信之後就算遇到,也能擁有解決問題與查資料解決吧。

實戰 — 基本 EC2 佈署

那麼我們就趕緊來實戰吧,先上程式碼:

真的是江湖一點訣,說破不值錢阿。正如所見,Terraform 程式碼也就只是把剛剛提到的架構圖該定義的定義好罷了。

關於各個 resource 裡面為啥要這樣填之類的,本藻覺得在這裡講會顯的過於冗長,而且也講不細,就請移步直接來看官方教學吧:

https://registry.terraform.io/providers/hashicorp/aws/latest/docs

他的教學真的寫得很好,善用這裡的搜尋可以幫到你。

阿對,至於佈署嘛…只要寫好 terraform.tfvars 後執行跟剛剛一樣的:

$ terraform init
$ terraform plan -out dev.tfplan
$ terraform apply dev.tfplan

這次 tfvars 需要多一個 key_name 表示要使用的 EC2 key pair,記得加上去。

結語

包含 Terraform 基本語法、AWS VPC 架構以及實戰的 Terraform 佈署 EC2。本篇都算是完整講完一輪了,雖然東西可能有點多,但希望沒有說的太快。

不過就算後續應用上真的遇到問題,因為 Terraform 佈署的部份是程式碼,所以其實很好查。這邊偏重於介紹基本架構方面的觀念,希望對各位之後的學習有幫助。

那麼這篇就說到這裡吧,下篇我們將會把漫畫閱讀器跟漫畫爬蟲都佈署到 EC2 上(用 Terraform),最後還是那句老話,若有興趣就敬請關注吧,再會。

下篇預告

單純開發者

不單純的EC2

暴打開發者的 AWS

下篇傳送門↓

--

--

Seaweed

最大的才能是行光合作用,朋友是矽藻的海藻。