Files
sys-analysis-design/sa-output/e-commerce/02-architecture/adr/ADR-017_iac-terraform.md
Canhchimlac 343ad8bbbc save
2026-09-15 16:02:30 +07:00

168 lines
11 KiB
Markdown

# ADR-017 — Công cụ Infrastructure as Code — Terraform
*Tên file: `adr/ADR-017_iac-terraform.md`*
| | |
|---|---|
| **Status** | `Proposed` |
| **Date** | 2026-09-15 |
| **Người quyết** | Tech Lead + Ops/SRE (hạ tầng — `decision-radar.md §5`) — chưa ký thật |
| **Người đề xuất** | SA (qua skill `sa-2-architecture`, hoạt động `adr`) |
| **Điểm radar** | **7/10** *(chấm theo `decision-radar.md §2`, kế thừa nguyên ước lượng đã ghi ở `INF_e-commerce_v1.0.md §11`: Chi phí đảo ngược=2 (>4 tuần — đổi công cụ sau khi đã có code Terraform thật cho toàn bộ hạ tầng tốn nhiều tuần viết lại + rủi ro thao tác chuyển đổi state) · Bán kính ảnh hưởng=2 (toàn bộ tài nguyên AWS của dự án) · Chạm `QAS` Must=1 (gián tiếp — nền tảng hiện thực hoá mọi `QAS` hạ tầng, không phải chính nó là một `QAS`) · Ràng buộc dài hạn=2 (chuẩn IaC nội bộ ≥1 năm) · Tranh cãi=0 → **7 ⇒ `ADR` bắt buộc**, dưới ngưỡng 8, không bắt buộc POC)* |
| **Supersedes** | — |
| **Superseded by** | — |
| **Liên quan** | `CON-05` · `INF_e-commerce_v1.0.md §11` · `OQ-060` · `DEC-30` |
> ⚠️ **ADR bất biến sau khi `Accepted`.** Muốn đổi quyết định thì viết ADR mới có
> `Supersedes: ADR-017` và đổi trạng thái bản cũ thành `Superseded by`. Không sửa nội dung ADR
> đã `Accepted`, không xoá ADR đã `Rejected`.
---
## 0. Ghi chú Preflight & ngoại lệ gate
Viết cùng lượt với `ADR-014`/`ADR-015`/`ADR-016` dưới ngoại lệ gate ghi ở `DEC-31` (tiếp nối
`DEC-01…30`) — xem `ADR-014 §0` cho bối cảnh đầy đủ. Riêng `ADR-017`: hiện thực hoá đề xuất đã ghi
ở `INF_e-commerce_v1.0.md §11` (duyệt từng phần, `DEC-30`).
---
## 1. Bối cảnh
Trước khi `sa-3-enablement` (GĐ3) viết code hạ tầng thật, cần chốt công cụ Infrastructure as Code
(IaC) chính cho toàn dự án — tránh tình trạng mỗi thành phần hạ tầng dùng một công cụ khác nhau,
không ai review/audit được nhất quán. `INF_e-commerce_v1.0.md §11` đã đề xuất Terraform và đánh
dấu đây là quyết định thiết lập tiền lệ (radar ước lượng ~7, đạt ngưỡng `ADR` bắt buộc), yêu cầu
SA viết `ADR` chính thức ở hoạt động `adr`.
**Ràng buộc đang chi phối:**
| Nguồn | Nội dung |
|---|---|
| `CON-05` | Năng lực đội (kỹ năng lập trình cho hạ tầng — TypeScript/Python cho CDK, hay chỉ cần HCL của Terraform) chưa xác nhận rõ |
| `D9` (`design-rules.md`) | Mọi con số hạ tầng phải quy ra tiền, có nguồn, và cấu hình phải tái lập được — công cụ IaC là nền tảng để đạt điều này |
**Cái đã biết chắc / cái còn là giả định:**
| Điều | 🟢 Đã kiểm chứng / 🔴 Giả định | Bằng chứng |
|---|---|---|
| Terraform có cộng đồng module lớn cho ECS/RDS/ElastiCache (AWS) | 🟢 Đã kiểm chứng — thực tế công khai của hệ sinh thái Terraform | `INF §11` |
| Đội có đủ kỹ năng TypeScript/Python để dùng AWS CDK hiệu quả | 🔴 Giả định chưa xác nhận | `CON-05`, `OQ-060` |
| Đội có đủ kỹ năng HCL (ngôn ngữ cấu hình của Terraform) hoặc học được nhanh hơn một ngôn ngữ lập trình đầy đủ | 🔴 Giả định — Terraform HCL thường được coi là dễ tiếp cận hơn với đội chưa quen lập trình hạ tầng, nhưng chưa xác nhận với đội thật | `OQ-060` |
## 2. Phương án đã cân nhắc
### PA-1 — Terraform *(chọn)*
| | |
|---|---|
| **Mô tả** | HashiCorp Terraform, dùng HCL để định nghĩa hạ tầng, quản lý state qua backend (đề xuất S3 + DynamoDB lock) |
| **Ưu** | Đa cloud-agnostic hơn CDK (dù hiện chỉ dùng AWS — giữ tuỳ chọn mở cho tương lai); cộng đồng module lớn cho ECS/RDS/ElastiCache; không khoá vào một ngôn ngữ lập trình cụ thể (HCL là ngôn ngữ khai báo riêng, không cần biết TypeScript/Python) |
| **Nhược** | HCL là một ngôn ngữ riêng cần học, dù thường được coi là dễ tiếp cận hơn ngôn ngữ lập trình đầy đủ; cần thiết lập backend state (S3 + DynamoDB lock) — thêm một phần hạ tầng nhỏ |
| **Chi phí đảo ngược** | Cao (>4 tuần) nếu đổi công cụ sau khi đã có code Terraform thật cho toàn bộ hạ tầng — viết lại + rủi ro thao tác trong lúc chuyển đổi state |
### PA-2 — AWS CDK
| | |
|---|---|
| **Mô tả** | Định nghĩa hạ tầng bằng ngôn ngữ lập trình đầy đủ (TypeScript/Python), compile ra CloudFormation |
| **Ưu** | Tích hợp sâu với AWS, cho phép dùng logic lập trình (vòng lặp, hàm) trực tiếp khi định nghĩa hạ tầng |
| **Nhược** | Cần kỹ năng TypeScript/Python cho hạ tầng — `CON-05` chưa xác nhận đội có; khoá vào AWS (dù hiện tại dự án chỉ dùng AWS, việc khoá vào một hãng làm giảm tuỳ chọn multi-cloud tương lai nếu cần) |
| **Chi phí đảo ngược** | Cao — tương tự PA-1, đổi sau khi đã có code thật tốn nhiều tuần |
### PA-3 — AWS CloudFormation (native)
| | |
|---|---|
| **Mô tả** | Dùng trực tiếp CloudFormation (JSON/YAML), không qua công cụ trung gian |
| **Ưu** | Không cần công cụ bên thứ ba, tích hợp gốc với AWS Console/CLI |
| **Nhược** | Cú pháp JSON/YAML kém module hoá hơn Terraform/CDK; cộng đồng module tái sử dụng nhỏ hơn; quản lý state kém linh hoạt hơn (CloudFormation tự quản lý state, không có backend tách rời như Terraform S3+DynamoDB, khó tách theo môi trường/nhóm tài nguyên để giảm blast radius) |
| **Chi phí đảo ngược** | Trung bình-cao — viết lại theo cấu trúc module hoá tốt hơn sau này |
### Bảng so sánh
| Tiêu chí | PA-1 (Terraform) | PA-2 (CDK) | PA-3 (CloudFormation) |
|---|---|---|---|
| Phù hợp năng lực đội hiện tại (`CON-05`, chưa xác nhận kỹ năng lập trình) | 🟡 Cần học HCL (thường dễ hơn) | 🔴 Cần TypeScript/Python | 🟡 Cần học JSON/YAML CloudFormation |
| Đa cloud-agnostic (giữ tuỳ chọn tương lai) | ✅ | ❌ Khoá vào AWS | ❌ Khoá vào AWS |
| Cộng đồng module tái sử dụng (ECS/RDS/ElastiCache) | ✅ Lớn | 🟡 Trung bình | 🔴 Nhỏ hơn |
| Tách state theo môi trường/nhóm tài nguyên (giảm blast radius) | ✅ Linh hoạt (backend riêng) | 🟡 Qua CDK stack | 🔴 Kém linh hoạt hơn |
## 3. Quyết định
> **Chọn PA-1 — Terraform làm công cụ Infrastructure as Code chính cho toàn dự án.**
**Vì sao:** Cân bằng tốt nhất giữa năng lực đội chưa xác nhận rõ (`CON-05`, không đòi hỏi kỹ năng
lập trình đầy đủ như CDK), hệ sinh thái module tái sử dụng lớn cho đúng các dịch vụ AWS đã chọn
(ECS/RDS/ElastiCache), và khả năng tách state để giảm blast radius (yêu cầu (h) của `INF §11`).
**Phạm vi áp dụng:** Toàn bộ hạ tầng AWS của dự án — network, data, compute — trong mọi môi trường
(dev/stg/prod).
### Điều kiện chuyển `Proposed → Accepted`
| Điều kiện | Ai xác nhận | Trạng thái hiện tại |
|---|---|---|
| Tech Lead xác nhận công cụ IaC (Terraform) cho P2 | Tech Lead | Mở (`OQ-060` chưa đóng) |
| Ops/SRE xác nhận năng lực vận hành Terraform (đào tạo nếu cần) | Ops/SRE | Mở |
| Thiết lập backend state (S3 + DynamoDB lock) thành công ở dev/stg | Ops/SRE | Chưa chạy — GĐ3 |
## 4. Phương án bị loại và lý do
| Phương án | Loại vì | Gắn với | Điều kiện nào thì xét lại |
|---|---|---|---|
| PA-2 — AWS CDK | Cần kỹ năng TypeScript/Python cho hạ tầng mà `CON-05` chưa xác nhận đội có; khoá vào AWS làm giảm tuỳ chọn multi-cloud tương lai dù hiện chưa cần | `CON-05` | Xét lại nếu đội xác nhận có kỹ năng lập trình mạnh (TypeScript/Python) và muốn tích hợp logic lập trình phức tạp trực tiếp vào định nghĩa hạ tầng |
| PA-3 — CloudFormation | Cộng đồng module nhỏ hơn, kém tái sử dụng, quản lý state kém linh hoạt hơn so với Terraform (backend S3+DynamoDB tách rời) | `INF §11` (yêu cầu tách state theo môi trường/nhóm) | Xét lại nếu tổ chức có chính sách bắt buộc chỉ dùng công cụ AWS gốc (không có ở dự án này hiện tại) |
## 5. Hệ quả
**Hệ quả tích cực**
- Module hoá tốt, tách state theo môi trường/nhóm tài nguyên — giảm blast radius khi
`terraform apply`
- Drift detection dễ tích hợp CI (`terraform plan` định kỳ, `FIT-34`)
- Không khoá vào một ngôn ngữ lập trình cụ thể — giảm rào cản với đội chưa xác nhận kỹ năng
TypeScript/Python
**Hệ quả tiêu cực phải sống chung**
- Cần đào tạo Terraform/HCL cho đội nếu chưa quen (`TCO §5`)
- Cần thiết lập và vận hành backend state riêng (S3 + DynamoDB lock) — thêm một phần hạ tầng nhỏ
cần quản lý (quyền truy cập, backup state)
**Cái quyết định này khoá lại**
| Muốn đổi về sau thì | Tốn |
|---|---|
| Đổi công cụ IaC sau khi đã có code Terraform thật cho toàn bộ hạ tầng | Viết lại toàn bộ + rủi ro thao tác trong lúc migrate state — nhiều tuần |
**Việc phát sinh**
| Việc | Chủ | Hạn | Ghi ở đâu |
|---|---|---|---|
| Viết Terraform module thật cho network/data/compute | Ops/SRE + Dev (GĐ3) | Trước go-live | `03-enablement/AGD_e-commerce.md` (chưa tồn tại) |
| Thiết lập backend state (S3 + DynamoDB lock) | Ops/SRE | Trước khi viết module thật | GĐ3 |
| Viết `FIT-34`/`FIT-35`/`FIT-36` thật | Ops/SRE (GĐ3) | GĐ3 | `03-enablement/FIT_e-commerce.md` |
## 6. Cách kiểm chứng quyết định này được tuân thủ
| Cách kiểm | Công cụ | Chạy ở đâu | `FIT` |
|---|---|---|---|
| Drift detection — hạ tầng thật khớp Terraform state | `terraform plan` định kỳ / driftctl | CI, hàng ngày | `FIT-34` *(đã đề xuất ở `INF §11`)* |
| Tag policy — mọi tài nguyên có đủ 4 tag bắt buộc | AWS Config rule / OPA | CI + AWS Config liên tục | `FIT-35` *(đã đề xuất ở `INF §11`)* |
| Đúng cấu trúc hạ tầng (2 ECS service GD/HT + 1 Payment, đúng SG cô lập) | Terraform plan review + AWS Config | CI/CD | `FIT-36` *(đã đề xuất ở `INF §11`)* |
## 7. Điều kiện xét lại
| Dấu hiệu | Ngưỡng | Ai theo dõi |
|---|---|---|
| Đội xác nhận có kỹ năng TypeScript/Python mạnh và muốn logic lập trình phức tạp trong định nghĩa hạ tầng | Ý kiến chính thức từ Tech Lead sau khi đội đã dùng Terraform một thời gian | Tech Lead |
| Nhu cầu multi-cloud thật sự phát sinh | Có quyết định kinh doanh mở rộng ngoài AWS | PO + Tech Lead |
## 8. Tham chiếu
- POC: Không bắt buộc (radar 7/10, dưới ngưỡng 8)
- Bài đo: `FIT-34`/`FIT-35`/`FIT-36` (ứng viên GĐ3, đã đề xuất ở `INF §11`)
- Tài liệu ngoài: —
- Thảo luận: `INF_e-commerce_v1.0.md §11` (phát hiện + đề xuất), `OQ-060`, `DEC-30`