
你有沒有遇過這種情況:某台 VM 的設定跟其他台不一樣,但沒人記得誰改的、什麼時候改的、為什麼改的?當你用手動點擊在 cloud console 上建資源,每一次部署都是一次不可重現的實驗。
先講結論
IaC 的價值不是「更快」,而是「可預期」。相同的 code 一定產出相同的基礎設施,所有變更都有版本紀錄,出問題能回滾。Terraform 管資源建立、Ansible 管服務配置、GitOps 管部署審核——每個工具有自己的守備範圍,不要混用。
Terraform:宣告你要什麼,它幫你建
Terraform 是目前最主流的 IaC 工具。你寫一份 .tf 檔案描述「我要一個 VPC、一台 RDS、一個 Load Balancer」,terraform plan 告訴你會發生什麼變更,terraform apply 執行變更。
terraform {
required_version = ">= 1.5.0"
backend "s3" {
bucket = "iac-state-prod"
key = "network/vpc.tfstate"
region = "ap-northeast-1"
}
}
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
tags = { Name = "prod-vpc" }
}幾個紀律:
- State 永遠不要放本機。用 S3 + DynamoDB lock,確保加密
- 模組化——每個模組只做一件事,用版本號鎖定
- 不要 hardcode region——用變數傳入
- 禁止人工手動修改 state——那是潘朵拉的盒子
Ansible:建完資源之後的事
Terraform 建 VM,但 VM 裡面要裝什麼?Nginx 怎麼設定?SSL 憑證怎麼放?這些是 Ansible 的工作。
- name: Configure Nginx
hosts: web
become: yes
tasks:
- name: Install nginx
apt: { name: nginx, state: present }
- name: Copy config
template: { src: nginx.conf.j2, dest: /etc/nginx/nginx.conf }
- name: Restart nginx
service: { name: nginx, state: restarted }兩者的分工要清楚:Terraform 管「有什麼資源」,Ansible 管「資源裡跑什麼」。不要用 Terraform 去做服務配置,也不要用 Ansible 去建 cloud 資源。
Drift:IaC 最大的敵人
Drift 就是「實際狀態跟 code 描述的狀態不一致」。最常見的原因:有人在半夜緊急到 AWS console 上直接改了設定。
改的當下問題解決了,但從此以後 terraform plan 永遠會出現 diff,沒人敢 apply 因為不確定會不會炸掉那次手動修改。
對策:
- 定期跑
terraform plan做 drift detection - 所有手動修改都要回補 PR
- 設定 drift 告警
如果 IaC 跟現實不一致,那 IaC 就只是一份過期的文件。
Policy as Code:防呆比修 bug 便宜
OPA 或 Sentinel 讓你用 code 定義「什麼是不允許的」:
package terraform.security
deny[msg] {
input.resource_type == "aws_s3_bucket"
input.public_read == true
msg := "S3 bucket must not be public"
}「S3 不能開公開」、「VM 不能用 m5.4xlarge 以上」、「所有資源必須有 cost-center tag」——這些規則寫進 policy,在 plan 階段就擋住,比上線後才發現省事一百倍。
GitOps:Git 是唯一真相
GitOps 的核心原則是所有變更都透過 PR。沒有人可以直接 terraform apply——PR 開出來,CI 自動跑 plan,reviewer 看過 plan 結果,approve 之後由機器人 apply。
這不只是流程管理,是防呆機制。你不會相信有多少 outage 是因為有人在 terminal 裡手殘按了 apply。
延伸閱讀
- Terraform Best Practices
- GitOps Principles
- OPA Policy Design
IaC 不是一個工具,是一種紀律。跟寫程式碼一樣——你的基礎設施需要 code review、版本控制、測試。差別只在於 bug 炸的不是你的 app,是你的整個環境。