記錄把本地 Terraform State 文件轉移到 AWS S3 的過程與注意事項
前言
最近我在玩 Terraform 與 AWS,一開始在手動建置 Terraform 時 state 沒有上 Git,是先存在 local,但隨著我後來將建置流程改交由 GitHub Actions 自動化後,state 就不能繼續放在 local 了,必須要找個 remote 來存放,才有辦法讓 GitHub Actions 使用。
(在實務情境中,公司也會因為需多人協作開發而有轉存 remote 的需求)
對於 state 存放 remote 的問題,Terraform 官方有一個設定方式 — Backend,以下我會分享如何將 loacl 的 state 文件轉交由 Terraform Backend 存放的過程。
Terraform Backend
Terraform Backend 是 Terraform 用來儲存與管理 state file 的機制
於 local 第一次運行 terraform apply 時,如果沒有特別指定要儲存在哪裏的話,他會 Default 於當前目錄 Create 一個 terraform.tfstate 文件
terraform.tfstate 文件是用來記錄 Terraform 管理之設施的當前狀態,會隨著每次 apply 更新設施狀態後更改文件內容
因為他裡面有可能會包含很多敏感的資訊,所以不能 push 上 Git 存放
如果你是個人專案,並且只有自己一個人管理 Terraform,存在 local 沒問題
若一旦須交由其他人管理 ( GitHub Actions 或是團隊其他人 ) ,存在 local 就會難以共享,此時就須要考慮 remote 的解決方案了
Terraform 有支援多種 Backend,這裡列出幾個比較知名的
| local (Default) | Consul | S3 | Azurerm | GCS | |
| remote | ❌ | ✅ | ✅ | ✅ | ✅ |
| 儲存位置 | 當前目錄 | HashiCorp Consul KV | AWS S3 | Azure Blob Storage | GCP Cloud Storage |
| lock 支援 | ❌ | ✅ | ✅ | ✅ | ✅ |
| lock 機制 | --- | Session lock | s3 原生 state lock | Blob lease | Object generation lock |
表格中可以看到,除了 local 以外,大多數其他 remote backend 都有支援 lock
lock 機制是為了防止多人同時編輯同一個文件造成衝突
有支援 lock 機制的,terraform 在執行時,會先檢查有無 lock 才會繼續往下做
有 lock 住的話,若沒有設置超時等待,在執行 terraform plan 會出現這種異常訊息 Error acquiring the state lock
上述的各種 remote backend 實作方式可參考官方教學:
因為我最近都在玩 AWS,所以這裡我會採用 AWS 的解決方案 — 使用 AWS S3 當作 state 的 remote 存放點
Create state 儲存用的 S3
這裡選擇一般用途就好,並輸入你想要取的 S3 Name
其他設定大多都使用 Default 就好不用更改~
不過在 Terraform 官方文件中,建議 S3 要開啟版本控制
所以這裡要選擇「啟用」
設定好後就可以 Create 了
編寫 Terraform 腳本
就參照 Terraform 官方文件說的寫就好了
比較需要注意的是
🔶 啟用 lock 機制
設定 use_lockfile = true 才能夠啟用 S3 原生的 lock 機制,要能 lock 的話一定要設置
🔶 啟用檔案加密
因為 state 文件裡面有可能夾帶很多敏感資料,建議一定要加密
AWS 解決方案的加密方式有 3 種:
- SSE-S3 (Default):由 S3 自動管理加密的 Key
- KMS:自行添加 KMS Key 管理,能做更多 Policy 的存取設定
- SSE-C:設定客戶自己的 Key,這個 Key 不會由 AWS 管理,由客戶自己管
設定 encrypt = true 可以啟用檔案加密,預設的話會是用 S3 的 SSE-S3 方式加密
如果要用 KMS 加密的話,要再多設定 kms_key_id = "your-key"
🔶 不能使用 variables 填充這裡的內容
這裡跟其他 Terraform 設定比較不一樣的是,在 backend 區塊中,是不能用 variables 的
因為 backend 是在 terraform init 階段初始化的,而 variables 是在之後的 plan、apply 階段才解析
ex:bucket = var.bucket_name 不可以❌❌
執行 Terraform 命令搬移
開始執行 terraform init
此時,你會看到在 S3 隨即被添加了一個 lock 檔案
在添加 backend.tf 更改 state 儲存位置前,若有先執行過 terraform apply 命令,此時 local 會有一份既有的 state 文件,記錄著當前的最新狀態
所以他會跳出這個對話訊息
問你要不要將 local 的 state 文件複製到 S3,你就回 yes 就好
接下來他就會開始複製 state
看到綠色這段提示,代表 backend s3 設定沒有問題
init 執行完後,state 即同步過去了(lock 檔案隨即被刪除)
之後的每一次 Terraform 資源異動,都會改存取 S3 裡面的 state 文件了~~
END





