4.9 KiB
Terraform boundary
Terraform은 VM만 정의하는 도구가 아니라 provider가 노출하는 API 객체의 desired state를 선언하고 plan/apply하는 framework입니다. 이 저장소에는 machine/cloud provider가 없으므로 서버, 네트워크, k3s 설치를 Terraform이 소유하지 않습니다. 현재 적용 범위는 Vault API 객체뿐입니다.
도구별 소유권
| 대상 | 소유 도구 | 이유 |
|---|---|---|
| Kubernetes manifest와 rollout | Argo CD | Git revision을 지속적으로 reconcile |
| Vault mount, auth, policy, role, Transit key, DB connection | Terraform Vault provider | API 객체의 plan과 state ownership 필요 |
| Vault init/unseal, initial secret seed | 승인된 operator runbook | 일회성 ceremony와 secret material을 state에서 제외 |
| KV secret payload | 외부 secret authority/operator | Git과 Terraform state에 값이 남지 않아야 함 |
| VM, network, k3s | 현재 소유자 없음 | 실제 provider와 lifecycle이 정해지지 않음 |
Kubernetes와 Helm을 Terraform에 다시 넣지 않습니다. 같은 object를 Argo CD와 Terraform이 동시에 소유하면 두 reconciler가 충돌합니다. 반대로 Terraform을 Argo hook에서 실행하면 cluster reconciliation이 Vault state lock과 privileged credential lifecycle까지 떠안게 됩니다.
State 경계
vault-foundation
creates delegation
| |
v v
vault-workloads vault-database
runtime access PostgreSQL integration
vault-foundation은 mount, Kubernetes auth와 위임 policy/login role을 소유합니다. Routine CI apply 대상이 아닙니다.vault-workloads는 runtime ACL/Kubernetes role과 애플리케이션 Transit key만 소유합니다.vault-database는 실제 PostgreSQL이 준비된 뒤 connection과 migration dynamic role만 소유합니다.
위임받은 state는 자기 runner policy나 login role을 만들지 않습니다.
State 간 이름은 checked-in contract로 공유하며 terraform_remote_state로
다른 state snapshot을 읽지 않습니다.
Policy HCL이 정확한 API path를 허용하므로 kv, database, transit,
kubernetes, project-auth-jwt, auth-system-postgres-dev 같은 보안
경계 이름은 각 root의 local contract로 고정합니다. 변수로 한쪽만
override해 plan은 성공하지만 권한이 어긋나는 상태를 허용하지 않습니다.
이 이름을 바꿀 때는 foundation policy, delegated root와 runtime consumer를
하나의 migration 설계에서 함께 변경합니다.
Mount, Kubernetes auth와 선택적 CI JWT auth에는 prevent_destroy를
적용합니다. 입력 누락이 기존 auth mount 삭제로 이어지지 않으며, 실제
제거는 consumer/token inventory를 거친 별도 decommission revision에서만
보호를 명시적으로 해제합니다.
실행 계약
- Remote backend는 encryption, versioning, locking과 root별 access control을 제공해야 합니다.
terraform-plan이 만든 saved plan을 검토하고, 같은PLAN_FILE만terraform-apply가 사용합니다.- Plan은 sensitive artifact로 취급하며 apply 성공 후 제거합니다.
- Provider token과 PostgreSQL password는 Terraform 1.11 이상의 ephemeral variable/write-only argument로 실행 시점에 다시 주입합니다.
- Delegated runner token은 짧은 TTL, no-default-policy와 정확한 object path만 사용합니다. Capability 확인, self lookup과 명시적 self revoke에 필요한 세 self-service API만 별도로 허용합니다.
- Foundation, workloads, database apply는 서로 다른 승인 단계입니다.
두 번째 클러스터 또는 machine IaC
두 번째 클러스터가 생겨도 state를 합치지 않습니다. Cluster별 backend와 Vault instance ownership이 독립이면 같은 세 root contract를 reusable module로 승격합니다. 실제 VM/network provider, account, failure domain과 destroy/backup 책임이 정해졌을 때만 다음처럼 별도 machine root를 추가합니다.
iac/terraform/live/<cluster>/machine
iac/terraform/live/<cluster>/vault-foundation
iac/terraform/live/<cluster>/vault-workloads
iac/terraform/live/<cluster>/vault-database
Machine root output을 읽기 위해 Vault state 전체를 공유하지 않습니다. 필요한 endpoint는 명시적 configuration contract나 최소 권한의 별도 configuration store로 전달합니다.