我們進到 IaC 的世界了~那…前面在 AWS 手動建立的各種 resource 怎麼辦?
有兩個選項:
全部砍掉重新用 terraform 寫!
把手動建立的 resource import 進 terraform
哪個比較容易呢……?
不好說。
重新用 terraform 寫就要查 terraform resource 的 reference,一點一點把前面手動建立的東西寫出來跟測試,就是用 terraform 把前面做的事情再做一次。這個作法容易踩到的問題是除非了解 AWS web console 幫你做了什麼,不然會在找到對應的 resource 及設定上花不少時間。好處是這樣寫出來並且測試過的 terraform configuration 往往不會有太大問題。
import 是你把現有會動的 resource import 進 terraform,好處是可以保留已經會動的 infrastructure (有時候就是會有各種原因例如宇宙射線太強所以我們不能砍掉重來…) ,問題是可能以為已經 import 完所有 resource,但實際還是有缺,到了新的乾淨環境才發現怎麼這個不會動、那個不會動的東缺西缺。
這邊筆者用 import 把前面手動建立的 infrastructure 加進 terraform,之後就能用 terraform 繼續修改 cloud resource。 (其實是以為 import 比較簡單,結果根本沒有。)
terraform 在 1.5 版推出 import block 功能,可以用 import block 來定義要 import 的 resource,還會自動產生 terraform configuration!
沒這個功能前,要 import 手動建立的 resource 都要先寫出 resource block ⇒ 用 terraform import
⇒ plan 看差異 ⇒ 手動補上 resource block 的參數 ⇒ 直到沒有 changes(說是沒有 changes 但有時候還是可能被 default value 陰到)
1.5 推出 import block 後,可以把 import resource 的操作合併進 plan/apply 的流程,而且不用在那裡用 plan 看差異、補參數。雖然還是會遇到一些 error,但整體來說比原本的 import 方式好多了~
接下來讓我們把前面手動建立的 resource 們都 import 進來吧!
先定義 import block,syntax 如下:
import {
id = [resource 在 cloud 上的 identifier]
to = [terraform 內 resource 的 id]
}
我們從 ECR repository 開始,id 是 resource 在 cloud 上的 identifier,每種 resource 都不一樣,這裡要參考 resource 文件 aws_ecr_repository 中的 import。ECR repository 的 id 是它的名稱,也就是 my-app
:
import {
to = aws_ecr_repository.repo
id = "my-app"
}
import block 的 to
則是打算產生的 resource block 跟它在 terraform 裡的 id,這邊我們 import 的是 aws_ecr_repository
並且把它的 resource id 訂為 repo
。
接下來用 plan 指令產生要 import 的 resource 的 configuration:
$ terraform plan -generate-config-out=generated.tf
執行後會看到這樣的畫面:
產生的 configuration 會在 generated.tf
裡:
# __generated__ by Terraform
# Please review these resources and move them into your main configuration files.
# __generated__ by Terraform from "my-app"
resource "aws_ecr_repository" "repo" {
force_delete = null
image_tag_mutability = "MUTABLE"
name = "my-app"
tags = {}
tags_all = {}
encryption_configuration {
encryption_type = "AES256"
kms_key = null
}
image_scanning_configuration {
scan_on_push = false
}
}
把它搬到 main.tf
,現在 main.tf
長這樣:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
required_version = "~> 1.5"
}
provider "aws" {
profile = "my"
region = "ap-northeast-1"
}
import {
id = "my-app"
to = aws_ecr_repository.repo
}
resource "aws_ecr_repository" "repo" {
force_delete = null
image_tag_mutability = "MUTABLE"
name = "my-app"
tags = {}
tags_all = {}
encryption_configuration {
encryption_type = "AES256"
kms_key = null
}
image_scanning_configuration {
scan_on_push = false
}
}
接著正式 import:
$ terraform apply
看到熟悉的畫面,terraform 準備 import:
輸入 yes 後 resource 順利 import:
我們可以用 terraform plan
查看目前的 terraform configuration 跟 AWS 上的 infrastructure 有沒有什麼不同:
兩邊是一致的!
這就是用 import block 進行 import resource 跟產生 terraform configuration 的方式,接下來我們要把所有前面我們手動建立的 resource 都 import 進來。