目錄
這篇整理 Terraform 在 Durable Queue 架構中的責任,以及 configuration、state 和 AWS real infrastructure 三者如何維持一致。
Configuration、State 與 Real Infrastructure
Terraform configuration
└─ 描述 desired state
Terraform state
└─ 記錄 Terraform 管理了哪些 real resources
AWS
└─ 實際存在的 infrastructureterraform plan
↓
比較 configuration、state 與 provider 讀到的 real infrastructure
↓
計算需要建立、修改或刪除的 actionsState 不是單純的 cache;它保存 Terraform resource address 與 real provider object 之間的 mapping。
Terraform State 為什麼敏感?
即使 input variable 宣告:
sensitive = true也只代表 Terraform 會在 CLI output 中隱藏它,不代表:
- Value 被加密。
- Value 不會寫入 state。
- Remote backend 的讀取者看不到它。
若 secret value 被傳入 resource attributes,它仍可能以明文存在 terraform.tfstate。
因此 state 必須被當作 sensitive data 管理:
- 不 commit 到 Git。
- Remote backend 啟用 encryption。
- 嚴格限制 backend IAM permissions。
- 把能讀 state 的 CI runner 納入 threat model。
Remote Backend 擴大了 Security Boundary
Local development 時,.env 和 local state 都只在開發者電腦;導入 remote backend 和 CI 後,更多 identities 可能接觸 state:
GitHub Actions Runner
↓ terraform init / plan / apply
S3 Backend
↓
Terraform StateGitHub deployment role 必須能讀寫 state object,能使用該 role 的 workload 因此也是 state security boundary 的一部分。
- Store Terraform state in a backend that supports encryption
- Strictly control who can access your Terraform backend
For example, if you’re using S3 as a backend, you’ll want to configure an IAM policy that solely grants access to the S3 bucket for production to a small handful of trusted devs (or perhaps solely just the CI server you use to deploy to prod). — https://www.gruntwork.io/blog/a-comprehensive-guide-to-managing-secrets-in-your-terraform-code
Terraform 與 Secrets Manager 的責任
核心原則是:
Terraform 建立空的保險箱與誰能打開它;secret value 從 Terraform 之外注入。
Terraform
├─ 建立 Secrets Manager secret container
├─ 建立 IAM access policy
└─ 把 secret identifier 提供給 workload
Out-of-band process
└─ put-secret-value這樣可以讓 actual secret value 不經過 .tf 和 Terraform state。
Terraform Template 與 Shell Interpolation
user_data template 中可能同時出現兩種 ${...}:
- Terraform interpolation。
- Shell variable expansion。
user_data = <<-EOF
# Terraform 解析
echo "Region: ${var.aws_region}"
# Terraform 輸出 literal ${USER},交給 shell 解析
echo "User: $${USER}"
EOF$${...} 會 escape Terraform interpolation,讓輸出保留 ${...} 給 shell runtime 使用。
這個區分很重要,因為同一份 user_data 同時經過:
Terraform template rendering
↓
EC2 user_data
↓
Shell executionState 遺失與 terraform import
若 AWS resources 還存在,但 Terraform state 遺失:
Terraform configuration:有
Terraform state:沒有
AWS resources:有terraform import 的作用是把既有 AWS object 和 Terraform resource address 建立 mapping:
- 寫入 state。
- 不修改 AWS resource。
- 不自動修改
.tfconfiguration。
完成 import 後仍要執行 terraform plan。理想驗收結果是:
No changes這表示 configuration、state 和 AWS real infrastructure 三者一致。
Bootstrap Infrastructure (雞生蛋蛋生雞問題)
Remote backend 的 S3 bucket 本身也需要被建立,形成 bootstrap 問題:Terraform 的 state bucket 在一開始還不存在。
常見流程是:
Local bootstrap state
↓
建立 S3 backend
↓
terraform init -migrate-state
↓
後續使用 remote state若 bootstrap state 最後放在它自己管理的 bucket 中,日常操作可以正常運作,但完整 destroy 時必須先處理 state migration,避免刪除 bucket 的同時失去 Terraform 自己的管理記錄。
CI/CD 中的 Terraform Permission Boundary
首次建立 infrastructure 和日常 deployment 是不同工作:
Bootstrap / Infrastructure Administration
└─ 建立 VPC、IAM、RDS、ASG、ECR、State Backend
Incremental Deployment
└─ Push image、更新 Launch Template、啟動 ASG refresh日常 CD role 不必具有建立所有 infrastructure 的權限。限制它只能做 incremental deployment,可以縮小 credential 被濫用時的 blast radius。
詳細部署流程見 Continuous Integration and Delivery 基本觀念 與 Continuous Integration and Delivery 實作紀錄。