Terraform是一種開源基礎設施及程式碼(IaC)的工具,可提供一致的CLI(命令列介面)工作流來管理數百個雲服務,將雲API編碼為宣告性的配置檔案進行管理。
本文建立一個管理AWS Lightsail例項的例子來入門Terraform的使用。
安裝Terraform CLI
要使用Terramform,首先要在本地系統安裝Terraform命令列工具。HashiCorp提供了預編譯好的二進位制分發包,可以通過(https://www.terraform.com/dow...) 直接下載相應平臺的二進位制包,解壓後放到相應的執行路徑。也可以通過一些軟體包管理工具安裝,例如在Linux/OS X上通過LinuxBrew/HomeBrew進行安裝,在Windows上通過Chocolatey進行安裝。
這裡我們示例在Linux上是使用LinuxBrew進行安裝
> brew install terraform
安裝完成後,可以檢視其版本
❯ terraform -version
Terraform v1.0.11
on linux_amd64
使用-help
檢視其可用命令,安裝成功後,我們就可以使用Terraform來建立相應的基礎設施專案了。
AWS賬號準備
本文將通過建立一個管理AWS Lightsial例項的專案來嘗試Terraform,因此需要一個AWS賬號,以及在本地環境安裝和配置好AWS CLI工具的訪問憑據。
安裝和配置AWS CLI,請參考其文件 (https://docs.aws.amazon.com/c...) 。 配置完成之後,可以在本地命令列終端訪問相應的AWS資源。
建立並初始化Terraform專案
Terraform在本地通過資料夾來管理一個基礎設施專案的宣告性程式碼,例如我們在本地建立一個資料夾
> mkdir mylightsail
> cd mylightsail/
進入資料夾後,建立一個以 .tf 作為字尾的檔案,例如 main.tf
> touch main.tf
然後使用編輯器開啟檔案進行編輯,寫入以下程式碼塊
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.65"
}
}
}
# Configure the AWS Provider
provider "aws" {
region = "ap-southeast-1"
}
其中 terraform/required_providers
塊定義了該專案需要的 Provider,Terraform是通過不同的Provider來管理相應的基礎設施資源的,可到 (https://registry.terraform.io) 來查詢需要的Providers,例如GCP,Azure以及阿里雲等的Providers。這裡因為我們要管理的資源是AWS Lightsail例項,所以使用了Hashicorp官方提供的 hashicorp/aws 。
provider "aws"
部分配置了該Provider的一些可選項,例如這裡配置了區域為 ap-southeast-1 ,因此請確保上面配置的AWS訪問憑據能夠操作該區域的資源。
也就是這裡我們定義了我們需要使用的Provider及其相應的選項配置,接下來我們需要使用 terraform init
命令來初始化專案
> terraform init
Initializing provider plugins...
...
Terraform has been successfully initialized!
初始化將會從 (https://registry.terraform.io/) 下載相應的Provider外掛到 .terramorm/providers/ 目錄,供接下來的命令使用。
同時,會生成一個 .terraform.lock.hcl 的檔案來記錄使用的具體Provider版本,其功能類似於NPM的package-lock檔案,可將其提交到程式碼版本管理倉庫,其他協作的成員就可以保持使用相同的外掛版本。
建立基礎設施資源
完成專案的初始化之後,我們就可以編寫需要建立的資源宣告性配置,可以直接將相應的配置寫入 main.tf 檔案,也可以另外建立新的以 .tf
作為字尾的檔案,這裡我們建立一個新的名為 resources.tf 的檔案,並寫入我們需要的資源的定義
## LightSail Resources
resource "aws_lightsail_static_ip" "Example-sig-ip" {
name = "Example-EIP"
}
resource "aws_lightsail_instance" "Example-sig" {
name = "Example-Sig"
availability_zone = "ap-southeast-1c"
blueprint_id = "ubuntu_20_04"
bundle_id = "nano_2_0"
key_pair_name = "LightsailDefaultKeyPair"
tags = {
Example = ""
}
}
resource "aws_lightsail_static_ip_attachment" "Example-sig-ip-attache" {
static_ip_name = aws_lightsail_static_ip.Example-sig-ip.id
instance_name = aws_lightsail_instance.Example-sig.id
}
resource "aws_lightsail_instance_public_ports" "Example-sig-public-ports" {
instance_name = aws_lightsail_instance.Example-sig.name
port_info {
protocol = "tcp"
from_port = 0
to_port = 65535
cidrs = [
"0.0.0.0/0"
]
}
port_info {
protocol = "udp"
from_port = 0
to_port = 65535
cidrs = [
"0.0.0.0/0"
]
}
}
定義資源的格式為 resource "[provider_resource _type]" "resource_name"
,第一個引數為相應Provider支援的資源型別名稱,第二個引數為自己定義的資源名稱(可用於其他資源引用)。例如,我們首先定義了一個Lightsail的靜態IP資源,其中引數 name
指定了AWS資源的名稱。
上面的定義中,我們宣告瞭以下資源
- 一個Lightsail靜態IP地址
- 一個Lightsail計算例項,並繫結名為
LightsailDefaultKeyPair
的SSH金鑰 - 靜態IP地址和計算例項的繫結
- 例項的開放的網路埠組(類似於AWS EC2例項的安全組定義)
儲存檔案之後,我們可以使用 terraform fmt
命令來格式化檔案格式,以及 terraform validate
來檢查是否有語法錯誤。
定義好我們想要的資源之後,我們先通過命令 terraform plan
命令來執行計劃,檢視具體的執行更改(plan不會實際操作相應的資源)
❯ 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:
# aws_lightsail_instance.Example-sig will be created
+ resource "aws_lightsail_instance" "Example-sig" {
+ arn = (known after apply)
+ availability_zone = "ap-southeast-1c"
+ blueprint_id = "ubuntu_20_04"
+ bundle_id = "nano_2_0"
+ cpu_count = (known after apply)
+ created_at = (known after apply)
+ id = (known after apply)
+ ipv6_address = (known after apply)
+ ipv6_addresses = (known after apply)
+ is_static_ip = (known after apply)
+ key_pair_name = "LightsailDefaultKeyPair"
+ name = "Example-Sig"
+ private_ip_address = (known after apply)
+ public_ip_address = (known after apply)
+ ram_size = (known after apply)
+ tags = {
+ "Example" = ""
}
+ tags_all = {
+ "Example" = (known after apply)
}
+ username = (known after apply)
}
# aws_lightsail_instance_public_ports.Example-sig-public-ports will be created
+ resource "aws_lightsail_instance_public_ports" "Example-sig-public-ports" {
+ id = (known after apply)
+ instance_name = "Example-Sig"
+ port_info {
+ cidrs = [
+ "0.0.0.0/0",
]
+ from_port = 0
+ protocol = "tcp"
+ to_port = 65535
}
+ port_info {
+ cidrs = [
+ "0.0.0.0/0",
]
+ from_port = 0
+ protocol = "udp"
+ to_port = 65535
}
}
# aws_lightsail_static_ip.Example-sig-ip will be created
+ resource "aws_lightsail_static_ip" "Example-sig-ip" {
+ arn = (known after apply)
+ id = (known after apply)
+ ip_address = (known after apply)
+ name = "Example-EIP"
+ support_code = (known after apply)
}
# aws_lightsail_static_ip_attachment.Example-sig-ip-attache will be created
+ resource "aws_lightsail_static_ip_attachment" "Example-sig-ip-attache" {
+ id = (known after apply)
+ instance_name = (known after apply)
+ ip_address = (known after apply)
+ static_ip_name = (known after apply)
}
Plan: 4 to add, 0 to change, 0 to destroy.
+
表示將要增加的資源,(know after apply)的意思是要在具體只想(apply)之後,AWS根據定義建立相應資源之後才會返回的具體值。接下來就可以使用 terraform apply
來具體執行操作了,執行成功之後,會生成 .terraform/terraform.state 檔案來記錄執行後的資源狀態,也可以通過命令 terraform show
命令來檢視
❯ terraform show
# aws_lightsail_instance.Example-sig:
resource "aws_lightsail_instance" "Example-sig" {
arn = "arn:aws:lightsail:ap-southeast-1:090767794770:Instance/21cb0ea5-e814-4307-8606-01348d98be15"
availability_zone = "ap-southeast-1c"
blueprint_id = "ubuntu_20_04"
bundle_id = "nano_2_0"
cpu_count = 1
created_at = "2021-11-08T05:49:05Z"
id = "Example-Sig"
ipv6_address = "2406:da18:8ae:4b02:1f2:4ff1:daa1:6a8c"
ipv6_addresses = [
"2406:da18:8ae:4b02:1f2:4ff1:daa1:6a8c",
]
is_static_ip = true
key_pair_name = "LightsailDefaultKeyPair"
name = "Example-Sig"
private_ip_address = "172.26.45.249"
public_ip_address = "54.220.33.133"
ram_size = 0.5
tags = {
"Example" = ""
}
tags_all = {
"Example" = ""
}
username = "ubuntu"
}
# aws_lightsail_instance_public_ports.Example-sig-public-ports:
resource "aws_lightsail_instance_public_ports" "Example-sig-public-ports" {
id = "Example-Sig-987241840"
instance_name = "Example-Sig"
port_info {
cidrs = [
"0.0.0.0/0",
]
from_port = 0
protocol = "tcp"
to_port = 65535
}
port_info {
cidrs = [
"0.0.0.0/0",
]
from_port = 0
protocol = "udp"
to_port = 65535
}
}
# aws_lightsail_static_ip.Example-sig-ip:
resource "aws_lightsail_static_ip" "Example-sig-ip" {
arn = "arn:aws:lightsail:ap-southeast-1:090767794770:StaticIp/3f0298e0-efeb-4429-9574-156fef12a48f"
id = "Example-EIP"
ip_address = "54.220.33.133"
name = "Example-EIP"
support_code = "313963776615/54.220.33.133"
}
# aws_lightsail_static_ip_attachment.Example-sig-ip-attache:
resource "aws_lightsail_static_ip_attachment" "exmaple-sig-ip-attache" {
id = "Example-EIP"
instance_name = "Example-Sig"
ip_address = "54.220.33.133"
static_ip_name = "Example-EIP"
}
之後我們就可以通過更新資源定義檔案,然後執行 plan & apply
來更新雲上的資源了,如果資源不需要了,我們也可以通過 terraform destroy
一條命令來銷燬所有資源。
總結
本文以管理簡單的AWS Lightsail資源為例,展示瞭如何使用Terraform來管理雲上的資源。通過一宣告性的程式碼來定義我們需要的資源,同時資源定義程式碼可以通過版本管理工具進行版本化管理,進一步實現IaC的工作方式。
這麼我們使用的是Terraform的本地執行模式,除了在本地執行之外,Terraform還提供了執行後端(Backend)的功能,就可以將執行放到雲上的一些執行環境,資源狀態的管理也將會維護在Backend端,方便實現CI/CD Pipeline,以及GitOps的方式。其中Hashicorp的Terraform Cloud就是一個Backend。下一篇文章將示例將該專案放到Terraform Cloud上去執行。
【同時釋出在 Terraform初探:管理AWS Lightsail例項】