# INF — Infrastructure & Deployment Design — e-commerce | | | |---|---| | **Version** | 1.1 | | **Date** | 2026-09-15 | | **Author** | SA (qua skill `sa-2-architecture`, chế độ `go`, hoạt động `inf`) | | **Status** | 🟡 Draft *(duyệt từng phần — xem `Approved by`; AG2 cần cả ba vai trò Tech Lead/Security/Ops-SRE ký, mới có một chữ ký thay có điều kiện — **chưa đủ điều kiện chuyển `🔵 Approved`**)* | | **Approved by** | Tech Lead: **Điều phối dự án** (uỷ quyền, chế độ chạy thử — ký thay theo ngoại lệ `DEC-01`, **không phải chữ ký Tech Lead thật**) — duyệt **từng phần** bản v1.0 · 2026-09-15: chấp nhận topology AWS `ap-southeast-1`, bảng đối chiếu `INF↔TCO` (§10), HA/auto-scaling split ECS Nhóm Giao dịch/Nhóm Hỗ trợ A 2/2 – B 6/4 (`ASM-42`, `OQ-055` giữ mở), kế hoạch diễn tập DR 3 kịch bản (ngày thật `OQ-056` chờ Ops/SRE — điều kiện tiên quyết AG2), observability, CI/CD blue-green (`ADR-016` ứng viên), network/egress, IaC Terraform (`ADR-017` ứng viên). Chốt **TẠM** `OQ-058`: giữ nguyên `TCO` — **KHÔNG** thêm replica Redis ở kịch bản A, chấp nhận SPOF với hành vi fail-closed theo `FAIL` — `OQ-058` **giữ nguyên mở**, chờ PO xác nhận cuối. Đồng ý để SA viết `ADR-016`/`ADR-017` (`Proposed`) cùng `ADR-014`/`ADR-015` ở lượt hoạt động `adr` kế tiếp. `OQ-054` (cross-region snapshot Payment vs `ADR-009`) **giữ nguyên mở**. **KHÔNG ký thay Ops/SRE** — header `Approved by → Ops/SRE` giữ `—`. Security: **—** *(chưa ký)* · Ops/SRE: **—** *(chưa ký)*. `Confidence` giữ 🔴; Status giữ 🟡 Draft; AG2 chưa ký. | | **Source** | `02-architecture/SAD_e-commerce_v1.0.md` v1.3 §4, §7, §10, §11 (`OQ-026/027`, `ASM-22/23`) · `02-architecture/QAS_e-commerce_v1.0.md` §A3 (`QAS-002/005/006/007/008/009/013/014`) · `02-architecture/ASR_e-commerce_v1.0.md` §B2 (`ASR-001/002/005/006/007/009/010/011/012/013/014`) · `02-architecture/FAIL_e-commerce_v1.0.md` v1.1 §1, §3, §7, §10 (`FM-01…13`, `OQ-035/036/037/039`) · `02-architecture/DAT_e-commerce_v1.0.md` §7.2, §8.2, §9, §11 (`OQ-045/046`) · `02-architecture/SEC_e-commerce_v1.0.md` §1, §2.4, §5, §6 (`OQ-048…053`, `DEC-28`) · `02-architecture/adr/ADR-005…006, 009…012_*.md` · `01-context/TCO_e-commerce_v1.0.md` §3.1–§3.2 · `01-context/CTX_e-commerce_v1.0.md` §3 (`CON-04/05/08`) · `01-context/ARISK_e-commerce_v1.0.md` §6 (`POC-01/POC-02`) · `00-index/OQ_e-commerce.md` (`OQ-008/020/022/026/027/036/046/050`) · `00-index/DEC_e-commerce.md` (`DEC-01…28`) · `e-commerce/docs/sections/09-van-hanh-kiem-thu.md` §9.3–§9.5 *(chỉ tái dùng khung CI/CD/rollback/RTO-RPO của tài liệu P1 gốc — điều chỉnh lại cho kiến trúc P2: 2 ECS service + Payment thay vì ~10 microservice, bỏ Kafka/MSK/OpenSearch)* | | **Scope** | Toàn sàn e-commerce theo P2 (`SAD v1.3 §7` deployment view): hạ tầng AWS `ap-southeast-1`, HA/DR, scale, observability, CI/CD, kế hoạch diễn tập DR trước AG2. Hoạt động 7/9 của `sa-2-architecture` — không sửa `SAD`/`ICD`/`DAT`/`SEC`/`FAIL`/`ADR` đã có | | **Confidence** | 🔴 Giả định chưa xác minh — theo yêu cầu điều phối, tiếp nối `Confidence` 🔴 của toàn bộ artifact GĐ2 trước đó. AG1 chưa ký thật; AG2 chưa tới hạn; `POC-01`/`POC-02`/diễn tập DR/diễn tập inject lỗi đều **chưa chạy**; mọi con số auto-scaling/pool/timeout hạ tầng dưới đây là **đề xuất SA chưa kiểm chứng**, gắn `OQ`/`ASM` tương ứng. | ## Change Log | Version | Date | Người sửa | Thay đổi | ADR/DEC | |---|---|---|---|---| | 1.0 | 2026-09-15 | SA (qua skill `sa-2-architecture`, chế độ `go`, hoạt động `inf`) | Bản đầu — hoạt động 7/9 của `sa-2-architecture`. Topology AWS `ap-southeast-1` (VPC/subnet/AZ, ALB+WAF, 2 ECS Fargate service Nhóm Giao dịch/Nhóm Hỗ trợ + Payment Service tách biệt, RDS chính Multi-AZ + RDS Payment, ElastiCache Redis, SQS FIFO+EventBridge+DLQ, S3+CloudFront, Secrets Manager/KMS, NAT) — đối chiếu từng dòng với `TCO §3.2` (bảng §10), phát hiện 1 điểm chưa khớp bản chất (cross-region snapshot Payment trong `TCO` vs "không multi-region" của `ADR-009`, ghi `OQ-054`), không tự sửa `TCO`/`ADR`. Đề xuất split ECS task Nhóm Giao dịch/Nhóm Hỗ trợ (A: 2/2, B: 6/4) khớp đúng tổng `TCO` (`OQ-055`, nối `OQ-026`). Thiết kế HA (Multi-AZ, health check, auto-scaling A→B theo `QAS-009`), DR (RPO≤15’/RTO≤1h theo `QAS-008`/`ADR-009`, backup/PITR, kế hoạch diễn tập DR 3 kịch bản kèm tiêu chí PASS/FAIL đo thật, đề xuất hạn trước AG2 — `OQ-022` ngày thật chờ Ops/SRE), observability (log/metric/trace/dashboard/alert theo `QAS-013`/`ADR-010`, DLQ 14 ngày + alert lag >5 phút theo `OQ-036`/`DEC-22`, on-call theo `CON-08` + `OQ-008`), CI/CD (pipeline build→test→scan→deploy, blue-green cho 3 ECS service, migration schema trong pipeline theo `OQ-045`), network/security group + egress đối tác ngoài (`OQ-057`), IaC (Terraform, đề xuất) + FIT ứng viên GĐ3 (`FIT-34…38`). Thêm `OQ-054…063`, `ASM-42…46`. Ghi ngoại lệ tiếp tục gate `DEC-29` (nối `DEC-28`). Đề xuất 2 `ADR` ứng viên mới (chiến lược triển khai blue-green, công cụ IaC) cho hoạt động `adr` kế tiếp — **không viết `ADR` ở lượt này** (ngoài phạm vi `inf`). `Confidence` 🔴 toàn bộ. | `DEC-29` | | 1.0 | 2026-09-15 | Điều phối dự án (thay mặt Tech Lead, ngoại lệ `DEC-01`) — tác vụ **sign/approve** | Duyệt **từng phần**: ghi nhận nội dung topology AWS `ap-southeast-1`, bảng đối chiếu `INF↔TCO` (§10), HA/auto-scaling split ECS GD/HT A 2/2 – B 6/4 (`ASM-42`, `OQ-055`), kế hoạch diễn tập DR 3 kịch bản (`OQ-022`/`OQ-056`, ngày thật chờ Ops/SRE — điều kiện tiên quyết AG2), observability, CI/CD blue-green (`ADR-016` ứng viên), network/egress, IaC Terraform (`ADR-017` ứng viên). Chốt **TẠM** `OQ-058`: giữ `TCO`, **KHÔNG** thêm replica Redis ở kịch bản A, chấp nhận SPOF với fail-closed theo `FAIL` — `OQ-058` giữ nguyên mở, chờ PO. Đồng ý viết `ADR-016`/`ADR-017` (`Proposed`) cùng `ADR-014`/`ADR-015` ở lượt `adr` kế tiếp. `OQ-054` (cross-region snapshot vs `ADR-009`) giữ nguyên mở. **KHÔNG ký thay Ops/SRE** — header `Approved by → Ops/SRE` giữ `—`. Security chưa ký. Không đổi nội dung chuyên môn nào của tài liệu. `Confidence` giữ 🔴; Status giữ 🟡 Draft; AG2 chưa ký. Ghi thêm `DEC-30`. | `DEC-30` | | 1.1 | 2026-09-15 | SA (qua skill sa-2-architecture, chế độ `go`, hoạt động `adr`) | **Chỉ link ADR, không đổi nội dung.** `ADR-016` (blue-green qua AWS CodeDeploy) và `ADR-017` (IaC Terraform), cả hai `Proposed`, vừa được viết theo đề xuất đã duyệt TẠM ở `DEC-30` — thay các dòng "chưa viết, ngoài phạm vi `inf`" ở §7.2 và §11 bằng đường dẫn thật; cập nhật bảng Truy vết §13. `OQ-056`/`OQ-020` (điều kiện `Accepted` `ADR-016`) và `OQ-060` (điều kiện `Accepted` `ADR-017`) giữ nguyên mở. Không sửa nội dung chuyên môn nào khác của `INF`. Ghi `DEC-31` (tiếp nối `DEC-01…30`). | `ADR-016`, `ADR-017`, `DEC-31` | > Sơ đồ thắng về **quan hệ và luồng** (ai gọi ai, theo thứ tự nào). > Bảng/văn bản thắng về **ràng buộc và con số** (số task, ngưỡng scale, RTO/RPO, retention). > Mâu thuẫn ngoài hai loại trên là lỗi tài liệu, phải sửa chứ không phải chọn bên (`D12`). --- ## 0. Ghi chú Preflight & ngoại lệ gate AG1 chưa được ký chính thức; AG2 (gate của chính GĐ2) càng chưa tới hạn. Theo `SKILL.md`: hoạt động 1 (`QAS`) → 2 (`ASR`) → 3 (`SAD`) đã hoàn tất và được duyệt từng phần (`DEC-12/14/16`); `ICD`/`DAT`/`SEC`/`FAIL`/`ADR` (hoạt động 4, 5, 6, 8, 9) cũng đã chạy và duyệt từng phần (`DEC-17…28`) — điều kiện đầu vào cho `inf` đã đủ. Người dùng (vai điều phối dự án chạy thử) đã được cảnh báo lại AG1/AG2 chưa qua và **khẳng định muốn tiếp tục**. Ghi ngoại lệ tại: > **DEC-29 (SA)** — Tiếp tục `sa-2-architecture` (hoạt động 7 — `INF`) cho e-commerce trong khi > AG1 chưa ký thật và AG2 chưa tới hạn — tiếp nối `DEC-01…28`. > **Quyết định:** Dựng `INF` (topology, HA/DR, scale, observability, CI/CD, network/security, > IaC) dựa trên `SAD §7` + `TCO §3.2` đã duyệt từng phần, giữ `Confidence 🔴` cho tới khi: (a) > AG1 ký thật, (b) `POC-01`/`POC-02` chạy xong, (c) diễn tập DR (`QAS-008`/`ADR-009`) và diễn tập > inject lỗi (`QAS-013`/`ADR-010`) chạy xong PASS, (d) `OQ-010`/`OQ-026`/`OQ-027` (số đội thật, > khớp `TCO`, vị trí Identity) được Tech Lead/Ops trả lời. > **Người quyết:** Điều phối dự án (đại diện PO, dự án chạy thử). > **Radar (ước lượng):** ~4 — chi phí đảo ngược thấp (tài liệu hạ tầng sửa được qua version mới, > chưa là Terraform code thật) · bán kính ảnh hưởng: hoạt động `sa-3-enablement` phụ thuộc `INF` > này, nhưng bản thân *việc ghi tài liệu dưới ngoại lệ* thì nhỏ · chạm `QAS-008/009/013` Must > trực tiếp (đang thiết kế hạ tầng hiện thực hoá) nhưng chưa cam kết thi công (chưa IaC thật) · > không ràng buộc dài hạn tự thân · không tranh cãi mới → **ghi `DEC-nn`, không cần `ADR`** > (`decision-radar.md §1–§2`). > **Hệ quả nếu không chấp nhận ngoại lệ:** dừng GĐ2 ở hoạt động `fail`, không có `INF` để `AGD`/ > `FIT` (GĐ3) và Ops dùng làm đầu vào chuẩn bị go-live — chậm tiến độ chạy thử tương ứng thời gian > xử lý các `OQ` đang mở, đặc biệt `OQ-022` (lịch diễn tập DR, điều kiện tiên quyết AG2). 🔴 **Nhắc quan trọng:** chưa `POC-01`/`POC-02`, chưa diễn tập DR, chưa diễn tập inject lỗi — mọi con số auto-scaling/ngưỡng cảnh báo/kích thước instance dưới đây là **mục tiêu thiết kế**, không phải kết quả đã đo. `AGD`/`FIT`/`IaC` thật (Terraform) là công việc của `sa-3-enablement`, ngoài phạm vi tài liệu này. --- ## 1. Tóm tắt | | | |---|---| | **Cloud / vùng** | AWS `ap-southeast-1` (Singapore) — kế thừa `TCO §3` (`ASM-11`); ràng buộc lãnh thổ VN (`CON-06`/NĐ13) chưa xác nhận cần cư trú dữ liệu trong nước (`OQ-007` Pháp chế, `CTX`) | | **Mô hình chạy** | ECS Fargate — 3 service triển khai: **Nhóm Giao dịch**, **Nhóm Hỗ trợ**, **Payment** (`ADR-001` Proposed, `ADR-012` Proposed) | | **Chịu được mất gì** | 1 AZ (Multi-AZ toàn bộ compute/data); **không** chịu được mất toàn vùng `ap-southeast-1` ở MVP (`ADR-009` PA-1) | | **RTO / RPO** | Nhóm giao dịch cốt lõi (Payment/Cart&Order/Identity): **RPO ≤15 phút / RTO ≤1 giờ** (`QAS-008`/`ADR-009`) · **chưa từng diễn tập** — kế hoạch diễn tập ở §5.4, `OQ-022` | | **Chi phí/tháng ở tải dự kiến** | Kịch bản A: **≈ $2.409/tháng (≈ 60,2 triệu VND)** · Kịch bản B: **≈ $5.862/tháng (≈ 146,6 triệu VND)** — khớp `TCO §3.2`, xem đối chiếu §10 | | **Điểm chưa khớp `TCO` phát hiện ở lượt này** | 1 điểm bản chất (`OQ-054` — cross-region snapshot Payment trong `TCO` vs quyết định "không multi-region" của `ADR-009`) — không tự sửa, xem §10 | --- ## 2. Môi trường | Môi trường | Mục đích | Cấu hình so với prod | Dữ liệu | Ai truy cập được | |---|---|---|---|---| | dev | Phát triển, tích hợp nhanh | ~15–20% Production (đề xuất SA, chưa xác nhận — `TCO §3.2` chỉ gộp chung "non-prod ~35%") | Dữ liệu sinh (seed script) | Dev team | | stg | **Đo `QAS`**, UAT, integration test với sandbox đối tác | ~35% Production theo `TCO §3.2` — **KHÔNG cùng công suất prod** (xem cảnh báo dưới) | Ẩn danh hoá (không PII/KYC thật, theo `SEC §5`) | Dev + QA + Tech Lead; Ops/SRE cho diễn tập DR/chaos | | prod | Vận hành thật | 100% (§3, §9) | Thật | Ops/SRE + Admin qua IAM role có audit; không ai truy cập DB Production trực tiếp trừ khẩn cấp có phê duyệt (kế thừa `docs/09 §9.3.2`) | 🔴 **Câu hỏi bắt buộc đã trả lời một phần:** stg chạy ở **~35% công suất** RDS/ECS so với prod (`r6g.xlarge`/`t4g.medium` giảm size — cụ thể chưa chốt kích cỡ instance stg, `OQ-062`). Điều này làm sai lệch trực tiếp việc đo `QAS-002` (checkout p95 ≤3s) và `QAS-006` (RDS gộp) nếu chạy thẳng trên stg với cấu hình thu nhỏ — **`POC-01`/`POC-02` phải chạy trên cấu hình instance PROD thật** (`ARISK §6` đã ghi rõ "cấu hình instance thật", không phải stg thu nhỏ) để không tự lừa mình theo đúng cảnh báo `SKILL.md` mục 7. | `QAS` cần đo | Đo được trên stg (cấu hình thu nhỏ)? | Nếu không, đo ở đâu | Sai số ước tính | |---|---|---|---| | `QAS-002` (checkout p95 ≤3s) | 🟡 Một phần — đo được luồng logic/timeout, nhưng số tuyệt đối không đại diện | Staging với **cấu hình tạm nâng lên bằng prod** trong cửa sổ chạy `POC`/load test, hạ lại sau | Không định lượng được nếu không nâng cấu hình — biên độ RDS nhỏ hơn có thể khiến p95 đo được cao hơn thực tế 20–50% (ước lượng, chưa đo) | | `QAS-005`/`QAS-006` (`POC-01`/`POC-02`) | ❌ Không — `ARISK §6` đã quy định rõ chạy trên "cấu hình instance thật" | Staging, **nâng tạm** lên đúng cấu hình prod (`r6g.xlarge`, SQS FIFO thật) chỉ trong thời gian chạy POC | N/A — đây chính là lý do `POC` phải chạy đúng cấu hình, không phải trên bản thu nhỏ | | `QAS-008` (DR drill) | ✅ Có — diễn tập DR chạy trên staging trước, không cần đúng size (đo RTO/RPO theo tỷ lệ, quy trình là chính, không phải hiệu năng tuyệt đối) | — | Thấp — quy trình failover không phụ thuộc kích cỡ instance | | `QAS-013` (alert ≤1 phút) | ✅ Có — chaos/inject lỗi không phụ thuộc kích cỡ instance | — | Thấp | --- ## 3. Sơ đồ triển khai *Mức: **Deployment view**, bổ sung chi tiết VPC/subnet/AZ so với `SAD §7` (SAD chưa thiết kế ranh giới mạng con chi tiết — ghi rõ ở `SAD §10` "thuộc hoạt động `inf`"). Vùng: AWS `ap-southeast-1`, 2 AZ (`ap-southeast-1a`, `ap-southeast-1b`).* ```mermaid flowchart TB subgraph INTERNET["Internet"] Users["Guest/Customer/Seller/Admin"] ExtPay["VNPay · Momo"] ExtShip["GHN · GHTK"] ExtNotif["Email/SMS Provider"] end subgraph VPC["VPC — ap-southeast-1 (đề xuất CIDR 10.0.0.0/16, chưa chốt)"] subgraph AZa["AZ a (ap-southeast-1a)"] subgraph PubA["Public subnet A"] WAFa["WAF"] ALBa["ALB (node A)"] NATa["NAT Gateway A"] end subgraph AppA["Private subnet A — ứng dụng"] GDa["ECS task — Nhóm Giao dịch"] HTa["ECS task — Nhóm Hỗ trợ"] PAYa["ECS task — Payment (SG riêng)"] end subgraph DataA["Private subnet A — dữ liệu"] RDSMa[("RDS chính — writer/AZ a")] RDSPa[("RDS Payment — writer/AZ a")] Redisa[("Redis — primary")] end end subgraph AZb["AZ b (ap-southeast-1b)"] subgraph PubB["Public subnet B"] ALBb["ALB (node B)"] NATb["NAT Gateway B"] end subgraph AppB["Private subnet B — ứng dụng"] GDb["ECS task — Nhóm Giao dịch"] HTb["ECS task — Nhóm Hỗ trợ"] PAYb["ECS task — Payment (SG riêng)"] end subgraph DataB["Private subnet B — dữ liệu"] RDSMb[("RDS chính — standby/AZ b (+ read replica, chỉ kịch bản B)")] RDSPb[("RDS Payment — standby/AZ b")] Redisb[("Redis — replica, chỉ kịch bản B — SPOF ở kịch bản A, §4.3")] end end CM["AWS Cloud Map / ECS Service Connect\n(service discovery GD↔HT nội bộ)"] SQS[("SQS FIFO + EventBridge + DLQ")] S3[("S3 (asset/KYC)")] CF["CloudFront"] SM["Secrets Manager"] KMS["KMS (CMK)"] end Users -->|"1 · HTTPS, sync"| WAFa Users -->|"1 · HTTPS, sync"| ALBb WAFa -->|"2 · HTTPS, sync"| ALBa ALBa -->|"3 · HTTP, sync"| GDa ALBa -->|"3 · HTTP, sync"| HTa ALBa -->|"3 · HTTP, sync, SG riêng"| PAYa ALBb -->|"3 · HTTP, sync"| GDb ALBb -->|"3 · HTTP, sync"| HTb ALBb -->|"3 · HTTP, sync, SG riêng"| PAYb GDa -->|"4 · Service Connect, sync, JWT (SEC PA-3)"| HTa GDa -.->|"4 · cross-AZ nếu cần"| HTb CM -.-> GDa CM -.-> HTa GDa -->|"5 · SQL, sync"| RDSMa HTa -->|"5 · SQL, sync"| RDSMa PAYa -->|"6 · SQL, sync"| RDSPa RDSMa -.->|"sync replication, Multi-AZ"| RDSMb RDSPa -.->|"sync replication, Multi-AZ"| RDSPb GDa -->|"7 · cache, sync"| Redisa Redisa -.->|"replication, chỉ kịch bản B"| Redisb GDa -->|"8 · publish, async"| SQS PAYa -->|"8b · publish, async"| SQS SQS -->|"9 · consume, async"| HTa SQS -->|"9 · consume, async"| HTb GDa -->|"10 · S3 API, sync"| S3 CF --> S3 GDa -.->|"secret fetch"| SM PAYa -.->|"secret fetch"| SM SM -.-> KMS RDSMa -.-> KMS S3 -.-> KMS GDa -.->|"egress qua NAT"| NATa --> ExtNotif HTa -.->|"egress qua NAT"| NATa --> ExtShip PAYa -.->|"egress qua NAT"| NATa --> ExtPay ``` **Legend:** ▭ tài nguyên compute · hình trụ = data store · nét liền = đường gọi đồng bộ hoặc kết nối trực tiếp có nhãn giao thức · nét đứt = quan hệ hạ tầng (replication, service discovery, lấy secret, egress qua NAT) · ranh giới `VPC` = ranh giới mạng ngoài cùng · ranh giới `AZ a`/`AZ b` = ranh giới sẵn sàng · Payment (`PAYa`/`PAYb`) có **security group riêng**, không chung với Nhóm Giao dịch/Nhóm Hỗ trợ (`ASR-002`). 🔴 **Quyết định mới của `INF` (giải quyết khoảng trống `SAD §7`/`OQ-028`):** cơ chế kết nối thật giữa Nhóm Giao dịch ↔ Nhóm Hỗ trợ (`IF-021`/`IF-022`) là **AWS Cloud Map + ECS Service Connect** (service discovery gốc của ECS, không cần thêm cụm/sidecar mesh) — **không dùng App Mesh** (đúng lưu ý `SAD §7` v1.2 "không tự thêm hạ tầng mới ngoài phạm vi" và khớp `SEC OQ-050`/`DEC-28` đã chọn TẠM PA-3 service JWT ở tầng ứng dụng, không cần mTLS hạ tầng). Xác thực giữa 2 service dùng **service JWT** (`SEC §2.4`, chờ `ADR-015` ở hoạt động `adr` kế tiếp — ngoài phạm vi `inf`). Đây là quyết định cấu hình mạng (radar ước lượng ~3 — đảo ngược thấp, đổi sang App Mesh sau này là bổ sung không phải viết lại), **không cần `ADR`**, ghi `DEC-nn` là đủ (`decision-radar.md §2`) — xem §12 Decisions. **Bảng thành phần:** | Thành phần | Môi trường | Số bản *(A / B — `TCO §3.2`)* | Cấu hình | Vùng/AZ | Ranh giới tin cậy | |---|---|---|---|---|---| | WAF + ALB | Prod | Managed (Multi-AZ, không đếm instance) | OWASP Core Rule Set (`SEC TB1`) | 2 AZ | Internet → VPC | | **ECS Fargate — Nhóm Giao dịch** *(mới tách khỏi dòng gộp `TCO`, §10)* | Prod | **A: 2 tasks × 1vCPU/2GB · B: 6 tasks × 1vCPU/2GB** *(đề xuất SA — `OQ-055`, chờ Tech Lead/Ops)* | Auto-scaling riêng theo `ASR-014` (§4.2) | Multi-AZ (private subnet ứng dụng) | VPC nội bộ — cùng SG với Nhóm Hỗ trợ trừ port dành cho Service Connect | | **ECS Fargate — Nhóm Hỗ trợ** | Prod | **A: 2 tasks × 1vCPU/2GB · B: 4 tasks × 1vCPU/2GB** *(đề xuất SA — `OQ-055`)* | Auto-scaling riêng, ngưỡng khác Nhóm Giao dịch (§4.2) | Multi-AZ | VPC nội bộ | | ECS Fargate — Payment | Prod | A: 2 tasks × 0,5vCPU/1GB · B: 4 tasks × 0,5vCPU/1GB *(khớp `TCO` nguyên trạng, không đổi)* | SG/IAM riêng hoàn toàn | Multi-AZ (private subnet riêng) | Cao nhất — PCI-DSS SAQ A (`ASR-002`) | | RDS chính | Prod | A: `r6g.xlarge` Multi-AZ · B: `r6g.2xlarge` Multi-AZ + 1 read replica (chỉ Catalog đọc, `DAT §7.2`/`OQ-046`) | schema-per-module (`ADR-006`) | Multi-AZ | Chỉ Nhóm Giao dịch/Nhóm Hỗ trợ | | RDS Payment | Prod | A: `t4g.medium` Multi-AZ · B: `r6g.large` Multi-AZ | Tách biệt hoàn toàn (`ADR-002`) | Multi-AZ | Chỉ Payment | | ElastiCache Redis | Prod | **A: `r6g.large` × 1 node — KHÔNG có replica (SPOF, §4.3)** · B: `r6g.xlarge` × 1 + 1 replica (HA) | Session/ownership/giỏ hàng | A: 1 AZ (SPOF) · B: Multi-AZ | Chỉ Nhóm Giao dịch | | SQS FIFO + EventBridge + DLQ | Prod | Managed | Message group = `seller_id`; DLQ riêng mỗi queue, retention **14 ngày** (`OQ-036`/`DEC-22`, TẠM) | Managed | Publish (GD/Payment) vs consume (HT) | | S3 + CloudFront | Prod | Managed | KMS SSE, versioning cho bucket KYC | Managed | Public (asset) vs private (KYC) | | Secrets Manager + KMS | Prod | Managed | DB credentials, API key đối tác, JWT signing key — mỗi module 1 secret riêng (`SEC §6`) | Managed | Theo IAM task role, cô lập theo module | | NAT Gateway | Prod | 2 (1/AZ) | | 2 AZ | Egress duy nhất cho private subnet ra đối tác ngoài | | Non-prod (dev/stg) | Dev/Stg | ~35% Production compute/RDS (`TCO §3.2`) | Cấu hình thu nhỏ (§2) — **cần nâng tạm khi chạy `POC`/đo `QAS`** | `ap-southeast-1`, **VPC/account riêng** (đề xuất, `OQ-062`) | Tách biệt hoàn toàn với Production | --- ## 4. Tính sẵn sàng (HA) ### 4.1 Cơ chế chuyển đổi theo thành phần | Thành phần | Chịu được mất | Cơ chế chuyển đổi | Thời gian chuyển *(ước tính, chưa đo)* | Tự động? | Đã thử chưa | |---|---|---|---|---|---| | ECS Fargate (GD/HT/Payment) | 1 task, 1 AZ | ALB health check (interval 15s, unhealthy threshold 3 lần) loại task lỗi; ECS scheduler khởi task mới ở AZ còn lại | ~1–3 phút *(`ASM-45`, chưa đo)* | ✅ | ☐ | | ALB | 1 AZ | Managed Multi-AZ, tự động | N/A (không downtime) | ✅ | N/A (AWS managed) | | RDS chính / RDS Payment | 1 AZ (mất writer) | RDS Multi-AZ synchronous replication → failover tự động sang standby | Theo SLA AWS công khai ~60–120s *(chưa tự đo)* | ✅ | ☐ — nằm trong kế hoạch diễn tập §5.4 (kịch bản 2) | | ElastiCache Redis — kịch bản B | 1 node (có replica) | Multi-AZ với automatic failover (ElastiCache) | ~60s theo tài liệu AWS *(`ASM-44`, chưa tự đo)* | ✅ | ☐ | | **ElastiCache Redis — kịch bản A** | **KHÔNG chịu được mất node — SPOF** | Node mới được ElastiCache tự khởi tạo lại (nếu bật snapshot) hoặc cache rỗng | ~5–10 phút để node mới sẵn sàng *(ước tính, chưa đo)*; dữ liệu cache mất hoàn toàn (không phải source of truth, `D7`) nhưng ownership-check/session Guest phụ thuộc Redis (`ADR-007`) → **có gián đoạn dịch vụ trong lúc chờ**, xem §4.3 | ✅ (tạo lại node) / ❌ (không failover, vì không có replica) | ☐ | | SQS FIFO + EventBridge | Managed, đa AZ nội tại | AWS quản lý hoàn toàn | N/A | ✅ | N/A | | NAT Gateway | 1 AZ | 2 NAT Gateway (1/AZ), route table theo AZ | N/A (route riêng theo AZ, không có "chuyển đổi" — mỗi AZ dùng NAT của chính nó) | ✅ (theo thiết kế) | ☐ | ### 4.2 Auto-scaling — kịch bản A → B (`QAS-009`, `ASR-014`) 🔴 Toàn bộ ngưỡng dưới đây là **đề xuất SA**, chưa Tech Lead/Ops xác nhận, chưa đo tải thật (`POC-01`/`POC-02` mới đo throughput SQS/RDS, chưa đo hành vi auto-scaling ECS) — ghi `OQ-055`. | Nhóm | Metric | Ngưỡng kích hoạt scale-out | Ngưỡng scale-in | Min task | Max task | Thời gian scale *(ước tính)* | |---|---|---|---|---|---|---| | **Nhóm Giao dịch** (Catalog/Cart&Order/Identity) | Target tracking: `ALBRequestCountPerTarget` **và** CPU (lấy giá trị kích hoạt sớm hơn) | CPU > 60% trong 3 phút, hoặc request/target > ngưỡng tương ứng ~2.000 concurrent/task *(suy từ `QAS-009` A=2.000 concurrent/2 task)* | CPU < 30% trong 10 phút | **2** (kịch bản A) | **12** *(2× kịch bản B=6, dự phòng đột biến ×2 chưa kiểm chứng — khớp "Ngoài phạm vi" `SAD §10`)* | Cooldown scale-out 60s, scale-in 300s *(đề xuất, chưa đo)* | | **Nhóm Hỗ trợ** (Seller/Commission/Promotion/Review/Notification/Shipping) | CPU + độ trễ (age) tin nhắn SQS đang chờ xử lý (consumer lag) | CPU > 70% trong 5 phút, hoặc `ApproximateAgeOfOldestMessage` > 60s | CPU < 30% trong 15 phút | **2** | **8** | Cooldown scale-out 90s, scale-in 300s | | Payment | CPU (ít nhạy tải hơn vì COD đồng bộ nhẹ, VNPay/Momo đã bất đồng bộ theo `ADR-013`) | CPU > 65% trong 3 phút | CPU < 30% trong 10 phút | **2** (A) | **4** (B, khớp `TCO`, không mở rộng thêm vì PCI-DSS scope hẹp) | Cooldown tương tự Nhóm Giao dịch | 🔴 **`ASR-014` yêu cầu scale riêng Nhóm Giao dịch** — bảng trên đáp ứng bằng 2 auto-scaling policy độc lập (2 ECS service riêng, đúng `OQ-026` đã chốt TẠM). Nếu Tech Lead/Ops xác nhận ngược lại ở `OQ-026` (chỉ 1 service gộp), toàn bộ bảng này phải viết lại thành 1 policy chung. **Giới hạn trên và nút thắt kế tiếp** *(kịch bản tải ×3 của `TCO`)* | Thứ tự | Thành phần nghẽn trước | Ở mức tải nào | Cách gỡ | Chi phí | |---|---|---|---|---| | 1 | RDS chính (đọc + ghi gộp, `ADR-006`) | Khi CPU RDS > 75% liên tục — có thể xảy ra trước khi ECS chạm max task, vì RDS là tài nguyên chung không scale ngang tự động | Tách read replica thêm (đã có 1 ở kịch bản B) hoặc tách Catalog ra RDS riêng (theo điều kiện xét lại `ADR-006 §7`) | Instance lớn hơn hoặc thêm replica — chưa ước tính, ngoài `TCO` hiện tại | | 2 | Message group SQS FIFO của 1 seller volume cao (`ADR-005 §7`) | Khi 1 seller vượt trần throughput riêng của group đó | Theo dõi/cảnh báo riêng theo seller (chưa thiết kế — việc phát sinh của `ADR-005`, xem §6.4) | Không phát sinh chi phí hạ tầng, chỉ engineering effort | | 3 | ECS Nhóm Giao dịch chạm max=12 | Tải vượt kịch bản B ×2 (~20.000 concurrent) | Nâng max, đánh giá lại kiến trúc (ngoài phạm vi thiết kế hiện tại theo `SAD §10`) | Cần TCO mới | ### 4.3 Điểm hỏng đơn (SPOF) còn lại | Thành phần | Vì sao chưa dự phòng | Rủi ro | Kế hoạch | |---|---|---|---| | **ElastiCache Redis kịch bản A (1 node, không replica)** | `TCO §3.2` kịch bản A chỉ tính 1 node để tiết kiệm chi phí (`ASM-11`) — chưa có yêu cầu HA ở mức tải thấp | Mất node → gián đoạn ownership-check/session Guest (`ADR-007`) cho tới khi node mới sẵn sàng (~5–10 phút ước tính); **không mất dữ liệu nghiệp vụ** (Redis không phải source of truth, `D7`) nhưng có gián đoạn dịch vụ | `OQ-058` — hỏi PO/Ops có chấp nhận rủi ro này ở kịch bản A hay muốn thêm 1 replica ngay (chi phí +~$92/tháng ước tính theo đơn giá `TCO §3.1`, chưa xác nhận) | | VPC/region `ap-southeast-1` | `ADR-009` chọn PA-1 — không multi-region ở MVP, vì chi phí chưa có trong ngân sách | Mất toàn vùng → toàn hệ thống down, RTO thực tế vượt xa 1 giờ (khôi phục sang region khác là dự án riêng) | Đã ghi trong `ADR-009 §5` "Cái quyết định này khoá lại" — chấp nhận có ý thức, xét lại khi PO duyệt ngân sách multi-region | | NAT Gateway (theo AZ) | Mỗi AZ có NAT riêng — nếu AZ đó down, task trong AZ đó cũng down theo (không phải NAT là nguyên nhân chính) | Trùng với SPOF "mất 1 AZ" đã có cơ chế chuyển đổi ở §4.1 — không phải SPOF độc lập | Không cần kế hoạch riêng | | Cấu hình DNS/Route53 (chưa thiết kế) | Chưa có trong phạm vi `SAD`/`INF` lượt này — domain/SSL đã có ở `TCO §4` nhưng cấu hình failover DNS chưa thiết kế | Nếu ALB endpoint đổi mà không có health-check DNS, có thể kéo dài downtime khi có sự cố tầng ngoài ALB (hiếm, vì ALB tự Multi-AZ) | Ghi nhận — mức độ ưu tiên thấp vì ALB đã Multi-AZ, không phải SPOF cấp bách | 🔴 Hệ thống nào cũng còn SPOF — liệt kê ra là chuyên nghiệp; giả vờ không có mới là vấn đề. --- ## 5. Khôi phục thảm hoạ (DR) ### 5.1 Mục tiêu và cơ chế khôi phục | | | |---|---| | **Nhóm phạm vi** | Payment, Cart & Order, Identity & Access — "nhóm giao dịch cốt lõi" (`ASR-010`) | | **Kịch bản thảm hoạ tính tới** | Mất 1 AZ · hỏng RDS primary (dữ liệu lỗi logic, không phải mất AZ) · xoá nhầm dữ liệu · mất Redis. **Không tính** mất toàn vùng (`ADR-009` PA-1) | | **RTO mục tiêu** | **≤ 1 giờ** (nguồn: `QAS-008`, kế thừa nguyên trạng từ `SAD.md §5.3.2`/`§9.5.2` gốc — **chưa phải SLA hợp đồng đã ký với PO**, xem `CTX DRV-05`) | | **RPO mục tiêu** | **≤ 15 phút** (nguồn: `QAS-008`) | | **Cách khôi phục** | RDS Multi-AZ tự động failover (mất AZ, §4.1) hoặc PITR restore (hỏng dữ liệu logic/xoá nhầm) — xem runbook §5.3 | | **RTO đo được thực tế** | 🔴 **Chưa đo** — chưa từng diễn tập | | **Lần diễn tập gần nhất** | 🔴 **Chưa từng** — xem kế hoạch §5.4 | | **Tần suất diễn tập đề xuất** | 2 lần/năm sau lần đầu (kế thừa đề xuất `ADR-009 §6`), điều chỉnh theo kết quả | ### 5.2 Backup & PITR | Data store | Cơ chế | Tần suất/độ trễ | Retention | Cross-AZ | Cross-region | |---|---|---|---|---|---| | RDS chính | Automated Backup + PITR (WAL continuous archiving) | Continuous (đạt RPO ≤15 phút — cần xác nhận tần suất archive log thật đủ nhanh, `OQ-055` mở rộng) | Đề xuất 7 ngày (chưa chốt — khác với con số 35 ngày ở tài liệu P1 gốc `docs/09 §9.5.3`, cần Tech Lead xác nhận số cho P2, `OQ-059-b` gộp vào `OQ-045` phạm vi migration/backup) | ✅ (Multi-AZ synchronous) | ❌ — `TCO §3.2` có dòng "cross-region snapshot (Payment)" nhưng **mâu thuẫn với `ADR-009` PA-1**, xem `OQ-054` | | RDS Payment | Automated Backup + PITR | Continuous | Đề xuất 7 ngày, riêng biệt khỏi RDS chính (`ADR-002`) | ✅ | ❌ — cùng `OQ-054` | | ElastiCache Redis | Không PITR (cache, không phải source of truth, `D7`) — chỉ snapshot định kỳ tuỳ chọn để giảm thời gian "cache lạnh" sau sự cố | N/A (không cần RPO cho cache) | N/A | Chỉ kịch bản B (replica) | ❌ | | S3 (KYC, asset) | Versioning bật cho bucket KYC (khôi phục object bị xoá/ghi đè nhầm) | Continuous (mỗi write là 1 version) | Đề xuất giữ version cũ 90 ngày rồi chuyển lifecycle sang Glacier | N/A (S3 tự đa AZ) | 🔴 Chưa chốt — chỉ cần nếu Pháp chế/Security yêu cầu (`OQ-007`), chưa có trong `TCO` | | SQS FIFO/EventBridge DLQ | Retention **14 ngày** (`OQ-036`/`DEC-22`, TẠM) | N/A | 14 ngày | Managed | Managed | ### 5.3 Runbook failover (tóm tắt — chi tiết đầy đủ thuộc tài liệu vận hành `sa-3-enablement`) 1. **Xác định phạm vi sự cố** — service nào bị ảnh hưởng, dữ liệu mất từ thời điểm nào (dựa trên CloudWatch alarm đã cấu hình ở §6, đối chiếu `QAS-013`). 2. **Mất 1 AZ:** không can thiệp thủ công cho ECS/ALB/RDS Multi-AZ (tự động, §4.1) — Ops xác nhận qua dashboard, không chặn nghiệp vụ trừ khi failover RDS vượt ngưỡng bất thường. 3. **Hỏng RDS primary do lỗi dữ liệu logic (không phải mất AZ):** dùng PITR restore về thời điểm trước sự cố lên instance mới; **không mở lại luồng thanh toán cho tới khi đối soát xong** (kế thừa nguyên tắc `docs/09 §9.5.3` bước 5 — ưu tiên đúng đắn tài chính hơn tốc độ). 4. **Mất Redis (kịch bản A, không replica):** chấp nhận gián đoạn ownership-check/session Guest trong lúc ElastiCache tạo node mới; **không cần restore dữ liệu** (cache, không phải nguồn sự thật) — khi node mới lên, hệ thống tự "làm nóng lại" cache theo truy vấn thực tế. 5. **Xác minh toàn vẹn tài chính** trước khi mở lại Payment (đối chiếu `ReconciliationLog`, kế thừa nguyên tắc `docs/09 §9.5.3`). 6. **Thông báo & escalation** theo `QAS-013`/`CON-08` — xem §6.5. 🔴 Runbook đầy đủ (lệnh thao tác cụ thể, ai bấm nút gì) là sản phẩm của `sa-3-enablement` (`AGD`), tài liệu này chỉ định khung quy trình. ### 5.4 Kế hoạch diễn tập DR — điều kiện tiên quyết AG2 (`OQ-022`, `DEC-12`) 🔴 **Đây là mục quan trọng nhất của `INF`** — `ADR-009`/`QAS-008` đều ghi rõ "RTO/RPO chưa diễn tập là RTO/RPO trên giấy". Ba kịch bản dưới đây **phải chạy trước khi ký AG2**; ngày thật vẫn chờ Ops/SRE xác nhận (`OQ-022`), nhưng kế hoạch (kịch bản, bước, tiêu chí PASS/FAIL, ai làm, môi trường) đã đủ chi tiết để lên lịch ngay khi có Ops/SRE. | # | Kịch bản | Môi trường | Các bước | Tiêu chí PASS | Tiêu chí FAIL | Ai làm | Công cụ | |---|---|---|---|---|---|---|---| | DR-1 | **Mất 1 AZ** (giả lập bằng cách chặn traffic tới AZ đó, không thật sự tắt AZ AWS) | Staging (nâng tạm lên cấu hình gần prod), sau đó lặp lại ở Production giờ thấp điểm nếu DR-1 PASS ở staging | 1) Đo baseline (p95 checkout, uptime) trước khi bắt đầu. 2) Dùng AWS Fault Injection Simulator hoặc chặn route table/SG để cô lập 1 AZ khỏi traffic. 3) Quan sát ALB tự loại AZ lỗi, ECS scheduler khởi task mới ở AZ còn lại, RDS Multi-AZ failover (nếu writer nằm ở AZ bị cô lập). 4) Đo thời gian từ lúc cô lập tới lúc hệ thống phục vụ bình thường trở lại (RTO thực đo). 5) Đo lượng dữ liệu/giao dịch bị ảnh hưởng trong cửa sổ đó (RPO thực đo — kỳ vọng 0 vì đây là mất AZ, không mất dữ liệu, RDS Multi-AZ đồng bộ). 6) Khôi phục traffic bình thường, xác nhận không còn task "mồ côi" | RTO đo được ≤ 1 giờ; RPO đo được = 0 (không mất giao dịch nào vì Multi-AZ đồng bộ); không lỗi 5xx kéo dài > 5 phút liên tục trong lúc chuyển đổi | RTO > 1 giờ, hoặc mất giao dịch, hoặc lỗi 5xx > 5 phút liên tục | Ops/SRE chủ trì, Tech Lead quan sát/xác nhận số liệu | AWS Fault Injection Simulator hoặc thao tác Security Group/Route table thủ công; CloudWatch dashboard đo thời gian thực | | DR-2 | **Mất RDS primary** (giả lập bằng reboot-with-failover hoặc force failover qua AWS Console/CLI) | Staging trước, Production giờ thấp điểm nếu PASS ở staging (khuyến nghị **không** chạy DR-2 thật trên Production writer chính cho tới khi DR-1 và DR-2 đã PASS ở staging ≥1 lần) | 1) Đo baseline. 2) Trigger `aws rds reboot-db-instance --force-failover` (hoặc tương đương) trên RDS chính (staging trước). 3) Đo thời gian từ lúc trigger tới lúc ứng dụng (Nhóm Giao dịch/Nhóm Hỗ trợ) ghi/đọc thành công trở lại (RTO). 4) Kiểm tra giao dịch đang xử lý tại thời điểm failover có bị mất/trùng không (RPO + kiểm tra idempotency `ADR-004`). 5) Lặp lại riêng cho RDS Payment | RTO đo được ≤ 1 giờ (kỳ vọng thực tế thấp hơn nhiều — Multi-AZ failover thường < 2 phút theo AWS SLA công khai, nhưng phải **đo thật**, không giả định); RPO đo được ≤ 15 phút; không giao dịch nào bị double-write/mất do idempotency đã có (`ADR-004`) | RTO > 1 giờ, RPO > 15 phút, hoặc phát hiện giao dịch bị mất/trùng không được idempotency bắt | Ops/SRE + DBA chủ trì, Tech Lead xác nhận số liệu | AWS CLI/Console, CloudWatch, `ReconciliationLog` (kiểm tra sau) | | DR-3 | **Mất Redis** (giả lập bằng xoá node hoặc force-failover ElastiCache) | Staging trước | 1) Đo baseline. 2) Xoá/force-failover node Redis. 3) Quan sát hành vi ownership-check/session Guest khi Redis không sẵn sàng (`ADR-007` — có fallback gọi thẳng Identity & Access không, hay lỗi hoàn toàn?). 4) Đo thời gian tới khi node mới sẵn sàng và cache "nóng lại". 5) Với kịch bản A (không replica): đo downtime dịch vụ thực tế trong lúc chờ node mới | Xác nhận có đường fallback (không phải lỗi cứng hoàn toàn) khi Redis mất — nếu không có fallback, đây là **phát hiện quan trọng cần ghi `ARISK` mới**, không phải điều kiện PASS/FAIL đơn thuần | Hệ thống lỗi cứng hoàn toàn (không phục vụ được request nào) khi Redis mất, không có fallback nào | Ops/SRE + Tech Lead (backend module `CMP-02`/`CMP-04`) | Xoá node thủ công qua AWS Console (staging), theo dõi log ứng dụng | **Hạn đề xuất:** trong vòng 2 tuần kể từ khi Ops/SRE được xác định (`OQ-008`) và trước khi trình AG2 — đây là **đề xuất của SA**, ngày thật vẫn là `OQ-022`, chờ Ops/SRE xác nhận lịch cụ thể. **Kết quả diễn tập ghi vào:** `ARISK_e-commerce_v1.0.md` (mục mới, theo đúng cách `POC-01`/`POC-02` đã ghi) — không ghi trực tiếp vào `INF` này để tránh phải bump version mỗi lần có kết quả mới; `INF` sẽ dẫn chiếu khi có. --- ## 6. Quan sát được (Observability) ### 6.1 Log / Metric / Trace | Loại | Công cụ | Ghi gì | Giữ bao lâu | Ai đọc | Chi phí/tháng | |---|---|---|---|---|---| | Log | CloudWatch Logs (managed, khớp `ADR-010` PA-1) | Request log (không PII thô — log-scrubber mask `email`/`phone`/`account_number` theo `SEC §5.1`), application log theo `correlation_id` = header `X-Request-Id` (`ICD OQ-031`, đề xuất Tech Lead xác nhận tên header) | Đề xuất 30 ngày hot (CloudWatch) rồi archive S3 Glacier 90 ngày thêm (🔴 chưa chốt, `OQ-059`) | Dev + Ops/SRE (không unrestricted — theo IAM role) | Trong `TCO §3.2` dòng "Observability" (~$357 A / ~$1.033 B) | | Metric | CloudWatch Metrics | CPU/memory ECS, connection/CPU RDS, cache hit ratio Redis, SQS `ApproximateAgeOfOldestMessage`/`NumberOfMessagesSent`, ALB 5xx rate, target response time | 15 tháng (CloudWatch mặc định cho metric đã aggregate) | Ops/SRE, dashboard chia sẻ Tech Lead | Trong dòng Observability trên | | Trace | AWS X-Ray | Luồng checkout xuyên `ALB→GD→(HT/Payment)→RDS/SQS`, tỉ lệ lấy mẫu đề xuất 10% (100% cho request lỗi) — **chưa chốt tỉ lệ**, `OQ-059` | Mặc định X-Ray 30 ngày | Dev + Ops/SRE khi debug latency | Trong dòng Observability trên | | **Cộng** | | | | | **≈ $357/tháng (A) · ≈ $1.033/tháng (B)** — khớp `TCO §3.2` | **Correlation id:** header request `X-Request-Id` (đề xuất SA ở `ICD OQ-031`) — ALB/API Gateway sinh nếu client không gửi, map 1-1 vào `traceId` (X-Ray) và field `correlation_id` trong mọi dòng log ứng dụng, xuyên suốt Nhóm Giao dịch → Nhóm Hỗ trợ → Payment → SQS consumer. **Chưa Tech Lead xác nhận tên header** — nếu đổi, chỉ cần đổi tên field, không ảnh hưởng kiến trúc. ### 6.2 Dashboard đề xuất | Dashboard | Đối tượng xem | Nội dung chính | |---|---|---| | "Sức khoẻ giao dịch cốt lõi" | Ops/SRE, Tech Lead | 5xx rate + p95 latency của Payment/Cart&Order/Identity, uptime rolling 30 ngày (đối chiếu ngân sách lỗi `QAS-007`), auto-scaling hiện tại (task count vs max) | | "Message backbone" | Ops/SRE | SQS lag theo message group (đặc biệt seller volume cao, `ADR-005 §7`), DLQ depth, EventBridge fan-out lag | | "Chi phí" | PO/Tech Lead | Chi phí AWS thực tế theo dịch vụ, đối chiếu `TCO §3.2` hàng tháng (rà chênh lệch >20% — chuẩn bị cho `CONF` GĐ4) | ### 6.3 Cảnh báo | Cảnh báo | Điều kiện | Mức | Báo cho ai | `QAS` | |---|---|---|---|---| | 5xx tăng đột biến — Nhóm giao dịch cốt lõi | Health check fail liên tục **> 1 phút** cho Payment/Cart&Order/Identity | Trang (page) 24/7 | On-call theo `CON-08`/`OQ-008` (§6.5) | `QAS-013` | | p95 checkout vượt ngưỡng | p95 `POST /v1/checkout` > 3s liên tục 5 phút | Trang giờ hành chính, escalate nếu kéo dài | On-call | `QAS-002` | | SQS lag / DLQ | `ApproximateAgeOfOldestMessage` > **5 phút** (`OQ-036`/`DEC-22`, TẠM) | Vé giờ hành chính, trang nếu ảnh hưởng nhóm cốt lõi | Ops/SRE theo domain consumer (chưa phân công cụ thể tên người — `OQ-036` phần "ai xử lý" vẫn mở) | `QAS-005`, `FM-09/10` | | Message group riêng lẻ nghẽn (1 seller volume cao) | Lag riêng 1 message group > 5s kéo dài > 5 phút | Vé giờ hành chính | Ops/SRE | `ADR-005 §7` | | RDS CPU/connection pool | CPU > 75% > 3 lần/tuần giờ cao điểm, hoặc connection pool exhaust | Trang nếu exhaust, vé nếu CPU cao | DBA/Ops | `ADR-006 §7` | | Circuit breaker mở (FM-01/02/03/04/12/13) | Bất kỳ lần mở nào (`FAIL §3.1`) | Vé, trang nếu mở > 5 phút liên tục | On-call theo module | `QAS-002` | | Chi phí AWS bất thường | Chi phí ngày > 150% trung bình 7 ngày trước | Vé giờ hành chính | Ops/PO | `TCO §3.2` | 🔴 **Cảnh báo không ai xử lý là cảnh báo sẽ bị tắt tiếng.** Mọi cảnh báo trên cần một người nhận thật (§6.5) — hiện chưa có tên cụ thể vì `OQ-008` (số người Ops) còn mở. ### 6.4 Error budget (`QAS-007`) | | | |---|---| | Mục tiêu | 99,9%/tháng cho Catalog/Checkout/Payment/Identity (`QAS-007`) ⇒ ngân sách lỗi **43 phút/tháng** | | Loại trừ | Bảo trì có báo trước **≤ 2 giờ/tháng** (`OQ-020`/`DEC-12`, TẠM — chưa PO xác nhận số cuối) | | Theo dõi | Dashboard "Sức khoẻ giao dịch cốt lõi" (§6.2), tính rolling 30 ngày | | Ràng buộc lên CI/CD | Chiến lược deploy (§7) phải **không** tự tiêu tốn ngân sách lỗi — chọn blue-green/rolling zero-downtime, không chọn "deploy có downtime ngắn" dù chỉ vài giây mỗi lần (tích luỹ nhiều lần release/tháng có thể ăn hết 43 phút) | ### 6.5 Vận hành thường ngày & on-call | Việc | Ai làm | Tần suất | Tài liệu | |---|---|---|---| | Trực sự cố (on-call) | Ops/SRE theo `CON-08`: **ca hành chính + escalation 24/7 cho sự cố nghiêm trọng ảnh hưởng nhóm giao dịch cốt lõi** — số người/nội bộ hay thuê ngoài **chưa xác nhận** (`OQ-008`, mở) | Liên tục | Escalation chain: on-call → Tech Lead → PO (thứ tự đề xuất, chưa xác nhận) | | Vá bảo mật (SCA/dependency) | Dev + Ops (theo cảnh báo Trivy/Snyk ở CI/CD, §7) | Theo phát hiện, ưu tiên Critical/High trong 7 ngày (đề xuất, chưa chốt SLA) | `SEC §7` | | Kiểm tra backup khôi phục được | Ops/SRE | Theo tần suất diễn tập DR (§5.4) | §5 | | Rà chi phí | Ops/PO | Hàng tháng, đối chiếu `TCO §3.2` | §10 | **Năng lực đội vận hành** *(từ `CON-05`/`CON-08`)*: số người/kỹ năng thật **chưa xác nhận** (`OQ-008`) — thiết kế trên giả định "đủ người trực ca hành chính + escalation 24/7 khi cần", theo đúng `CON-08`. Nếu đội thật nhỏ hơn giả định "team MVP chuẩn" (`DEC-02`), khả năng đáp ứng ngưỡng ack ≤15 phút (`QAS-013`) và tần suất diễn tập DR 2 lần/năm có thể không khả thi — đây là đánh đổi PO/PM phải quyết (`D10`), không phải SA tự chọn giả định lạc quan hơn thực tế đội. Chi phí đào tạo/ tuyển dụng nếu thiếu người: xem `TCO §5`/`ASM-14`. --- ## 7. CI/CD ### 7.1 Pipeline build → test → scan → deploy *Điều chỉnh từ khung `docs/09 §9.3.1` (viết cho kiến trúc P1, ~10 microservice + Kafka) sang P2 (3 đơn vị triển khai: Nhóm Giao dịch, Nhóm Hỗ trợ, Payment) — bỏ bước liên quan Kafka/MSK/ OpenSearch, thêm bước scan theo `SEC §7`.* ```mermaid flowchart LR Commit["Commit / PR"] --> Build["Build\n(container image/service, tag = commit SHA)"] Build --> Unit["Unit test\n(coverage gate — ngưỡng chưa chốt, OQ-060)"] Unit --> SAST["SAST\n(SonarQube/Semgrep)"] SAST --> SCA["SCA/container scan\n(Trivy image + Snyk dependency)"] SCA --> Migration["Schema migration dry-run\n(Flyway — OQ-045, mỗi schema module riêng)"] Migration --> Integration["Integration test\n(Staging, sandbox VNPay/Momo/GHN/GHTK — ARISK-03/04)"] Integration --> DeployDev["Deploy → Dev\n(auto)"] DeployDev --> DeployStg["Deploy → Staging\n(auto sau Dev pass)"] DeployStg --> UAT["UAT + Performance/Security test\n(k6, security regression FIT-29..33)"] UAT --> Approval["Phê duyệt thủ công\n(Product Owner + Tech Lead — tách vai trò)"] Approval --> DeployProd["Deploy → Production\n(blue-green, §7.2)"] ``` **Ngưỡng chặn:** | Bước | Chặn nếu | Nguồn | |---|---|---| | Unit test | Coverage giảm so với baseline hoặc test đỏ (ngưỡng % cụ thể chưa chốt cho P2 — `docs/09` đề xuất 70%/50% cho P1, cần Tech Lead xác nhận lại cho P2, `OQ-060`) | `docs/09 §9.1.1` (tham khảo) | | SAST | Phát hiện lỗ hổng theo policy đã cấu hình (SonarQube quality gate) | `SEC §7` | | SCA/container scan | **Trivy/Snyk phát hiện Critical/High chưa có ngoại lệ được phê duyệt** — chặn deploy (khớp yêu cầu người duyệt) | `SEC §7`, `docs/09 §9.3.1` | | Migration dry-run | Migration không tương thích ngược (không theo expand-contract, `DAT §8.2`) — kiểm tra tự động một phần (linter script), phần còn lại cần review thủ công | `DAT §8.2`, `OQ-045` | | Integration test | Fail idempotency webhook (`ADR-004`), fail contract `ICD` | `ICD`, `ADR-004` | | UAT/Security regression | FR Must không Pass; `FIT-29…33` (secret scan, service-authn, webhook signature, audit completeness, TLS/HSTS) đỏ | `SEC §11` | | Deploy Production | Thiếu phê duyệt thủ công (PO + Tech Lead, tách vai trò người phê duyệt/người deploy) | `docs/09 §9.3.2` | ### 7.2 Chiến lược deploy — zero/low-downtime | | Quyết định | Vì sao | |---|---|---| | **Chiến lược** | **Blue-green (AWS CodeDeploy cho ECS)** cho cả 3 service (Nhóm Giao dịch, Nhóm Hỗ trợ, Payment) | Tương thích ngân sách lỗi chặt (43 phút/tháng, `QAS-007`) — rolling update vẫn có short window request có thể chạm task đang tắt, blue-green chuyển traffic dứt điểm sau health check pass, rollback tức thời (chuyển lại traffic) nếu phát hiện lỗi sau khi đã live | | Thời gian downtime cho phép | **0** theo thiết kế (blue-green không có cửa sổ mất traffic nếu health check đúng) — nằm gọn trong ngân sách lỗi `QAS-007` | | | **Cách rollback** | Chuyển traffic ALB về target group cũ (green→blue) — tức thời (giây), không cần redeploy | CodeDeploy hỗ trợ sẵn | | Migration schema | **Expand-contract** (thêm cột/bảng trước, xoá sau — kế thừa nguyên tắc `docs/09 §9.5.1`/`DAT §8.2`) — chạy trước bước deploy code mới trong pipeline (§7.1), tương thích ngược để rollback code không gặp schema mới không hiểu | `DAT §8.2`, `OQ-045` (công cụ Flyway/Liquibase chưa chốt) | | Cờ tính năng (feature flag) | 🔴 Chưa chốt công cụ (LaunchDarkly/tự xây bảng config) — đề xuất SA: bảng config đơn giản trong RDS chính (schema `platform`), không cần SaaS bên thứ ba ở MVP; dùng cho rollout tính năng rủi ro cao (đổi luồng thanh toán/hoa hồng, theo `docs/09 §9.3.2`) | `OQ-060` | | Ai được bấm deploy Production | Tech Lead (thực hiện) sau khi PO phê duyệt (tách vai trò — segregation of duties) | `docs/09 §9.3.2` | 🔴 Chiến lược deploy blue-green cho toàn bộ 3 service là quyết định thiết lập tiền lệ (radar ước lượng ~6 — đảo ngược trung bình, bán kính toàn hệ thống, chạm trực tiếp `QAS-007` Must, ràng buộc một release, không tranh cãi) — theo `decision-radar.md §2`, đạt ngưỡng `ADR` bắt buộc. Xem [`adr/ADR-016_blue-green-deploy-aws-codedeploy.md`](adr/ADR-016_blue-green-deploy-aws-codedeploy.md) (`Proposed`). Điều kiện `Accepted`: Ops/SRE xác nhận năng lực vận hành CodeDeploy + chạy thử blue-green/rollback thành công ở staging (`OQ-056`), PO xác nhận số cuối `OQ-020`. ### 7.3 Phân quyền Production & secret trong pipeline | Hạng mục | Thiết kế | |---|---| | CI/CD → AWS | **OIDC federation** (GitHub Actions/GitLab CI ↔ AWS IAM role tạm thời) — không dùng access key dài hạn nhúng pipeline (kế thừa `docs/09 §9.3.2`) | | Secret trong pipeline | Lấy từ **AWS Secrets Manager** tại thời điểm chạy (`SEC §6`), không lưu trong biến môi trường CI dạng plaintext lâu dài, không commit vào repo — quét rò rỉ bằng Gitleaks/TruffleHog (`SEC FIT-29`) | | Audit CI/CD | Log ai trigger deploy, phiên bản nào, thời điểm nào — audit trail hạ tầng, khác `audit_log` nghiệp vụ (`DAT`) | --- ## 8. Network & Security groups ### 8.1 Security group theo thành phần | SG | Áp dụng cho | Inbound | Outbound | |---|---|---|---| | `sg-alb` | ALB | 443 từ Internet (0.0.0.0/0, qua WAF) | 80/443 tới `sg-ecs-gd`, `sg-ecs-ht`, `sg-ecs-pay` | | `sg-ecs-gd` | ECS Nhóm Giao dịch | 80 từ `sg-alb`; port Service Connect từ `sg-ecs-ht` (nội bộ) | 5432 tới `sg-rds-main`; 6379 tới `sg-redis`; 443 tới SQS/EventBridge/S3/Secrets Manager (qua VPC endpoint hoặc NAT); port Service Connect tới `sg-ecs-ht` | | `sg-ecs-ht` | ECS Nhóm Hỗ trợ | 80 từ `sg-alb`; port Service Connect từ `sg-ecs-gd` | 5432 tới `sg-rds-main`; 443 tới SQS/EventBridge/S3/Secrets Manager; 443 tới NAT (egress GHN/GHTK/Email-SMS) | | `sg-ecs-pay` | ECS Payment — **cô lập, không chung SG với GD/HT** (`ASR-002`) | 80 từ `sg-alb` **chỉ route Payment** | 5432 tới `sg-rds-payment` (chỉ SG này); 443 tới NAT (egress VNPay/Momo); 443 tới Secrets Manager (chỉ secret của Payment) | | `sg-rds-main` | RDS chính | 5432 từ `sg-ecs-gd`, `sg-ecs-ht` | — | | `sg-rds-payment` | RDS Payment | 5432 **chỉ từ** `sg-ecs-pay` | — | | `sg-redis` | ElastiCache Redis | 6379 **chỉ từ** `sg-ecs-gd` | — | 🔴 **Không có SG nào cho phép Nhóm Hỗ trợ/Payment kết nối trực tiếp RDS Payment hoặc Redis** — đúng nguyên tắc cô lập `ASR-002`/`ADR-002` và "chủ duy nhất" `D7`. ### 8.2 Private subnet cho dữ liệu RDS chính, RDS Payment, ElastiCache Redis đặt **hoàn toàn trong private subnet** (không route public), không có Elastic IP, không truy cập được từ Internet — chỉ qua ECS task trong cùng VPC. Đúng yêu cầu (f). ### 8.3 Egress tới đối tác ngoài (VNPay/Momo/GHN/GHTK/Email-SMS) | Đối tác | Qua NAT Gateway? | IP allowlist đối tác yêu cầu? | Static outbound IP cần thiết? | |---|---|---|---| | VNPay | ✅ (từ `sg-ecs-pay`) | 🔴 **Chưa xác nhận** — chưa có tài liệu tích hợp/sandbox thật (`CON-04`, `ARISK-03`) | Nếu VNPay yêu cầu allowlist IP nguồn: NAT Gateway đã có Elastic IP cố định theo AZ — đủ điều kiện kỹ thuật, chỉ cần đăng ký 2 IP (1/AZ) với VNPay | | Momo | ✅ (từ `sg-ecs-pay`) | 🔴 Chưa xác nhận | Tương tự — 2 Elastic IP NAT | | GHN | ✅ (từ `sg-ecs-ht`) | 🔴 Chưa xác nhận (`ARISK-04`) | Tương tự | | GHTK | ✅ (từ `sg-ecs-ht`) | 🔴 Chưa xác nhận | Tương tự | | Email/SMS Provider | ✅ (từ `sg-ecs-ht`, qua `CMP-09` Notification) | 🔴 Chưa chọn nhà cung cấp (`TCO OQ-016`) | Chưa xác định | 🔴 **`OQ-057` (mới):** VNPay/Momo/GHN/GHTK/Email-SMS có yêu cầu IP allowlist cho outbound traffic từ sàn không? Nếu có, cần đăng ký 2 Elastic IP (1/AZ, gắn NAT Gateway) với từng đối tác trước go-live — việc này **không phát sinh chi phí thêm** (Elastic IP đã tính trong giá NAT Gateway ở `TCO §3.1`) nhưng cần thời gian phối hợp hành chính với đối tác. Hỏi: Tech Lead (khi có tài liệu tích hợp thật từ 4 đối tác, cùng điều kiện với `ARISK-03/04`). --- ## 9. Chi phí — tham chiếu `TCO` Toàn bộ con số chi phí trong tài liệu này **tham chiếu nguyên trạng** `TCO_e-commerce_v1.0.md §3.1–§3.2` — không tính lại, không đổi đơn giá/tỷ giá (`ASM-11`/`ASM-12` vẫn 🔴 chưa xác minh, thuộc trách nhiệm `TCO`, không phải `INF`). Bảng đối chiếu chi tiết ở §10. --- ## 10. Đối chiếu với `TCO` *(bắt buộc theo `D9` — từng dòng)* | Hạng mục | `INF` §3/§4/§6 | `TCO §3.2` | Khớp | |---|---|---|---| | Compute — Nhóm Giao dịch + Nhóm Hỗ trợ (tổng) | A: 2+2=4 tasks×1vCPU/2GB · B: 6+4=10 tasks×1vCPU/2GB | A: ~4 tasks×1vCPU/2GB (gộp) · B: ~10 tasks×1vCPU/2GB (gộp) | ✅ **Khớp về tổng số** — split GD/HT là đề xuất mới của `INF` (`OQ-055`), chưa Tech Lead/Ops xác nhận nhưng không đổi tổng cost | | Compute — Payment | A: 2 tasks×0,5vCPU/1GB · B: 4 tasks×0,5vCPU/1GB | A: 2 tasks×0,5vCPU/1GB · B: 4 tasks×0,5vCPU/1GB | ✅ Khớp hoàn toàn | | CSDL (RDS chính + Payment) | A: `r6g.xlarge`+`t4g.medium` Multi-AZ · B: `r6g.2xlarge`+1 replica + Payment `r6g.large` | Giống hệt | ✅ Khớp | | Cache (Redis) | A: `r6g.large`×1 (không replica) · B: `r6g.xlarge`×1+1 replica | Giống hệt | ✅ Khớp — nhưng §4.3 mới **phát hiện và ghi rõ** hệ quả SPOF kịch bản A mà `TCO` không đề cập (không phải lỗi `TCO`, chỉ là `TCO` không có cột "rủi ro HA") | | Message broker (SQS/EventBridge) | Managed, ~750K msg/tháng (A) / ~2,25M msg/tháng (B) | Giống hệt | ✅ Khớp | | S3/CloudFront | ~500GB (A) / ~1,5TB (B) | Giống hệt | ✅ Khớp | | WAF/ALB/NAT | Giống `TCO` | Giống `TCO` | ✅ Khớp | | **Backup & DR** | Automated backup + PITR, **không cross-region** (theo `ADR-009` PA-1) | Dòng "Backup & DR" ghi **"Automated backup + cross-region snapshot (Payment)"**, ≈$30 (A)/≈$60 (B) | 🔴 **KHÔNG khớp bản chất** — xem `OQ-054` | | Observability | CloudWatch Logs/Metrics + X-Ray, ~$357 (A)/~$1.033 (B) | Giống hệt | ✅ Khớp | | Non-prod | ~35% Production | ~35% Production | ✅ Khớp về tỷ lệ; kích cỡ instance cụ thể của non-prod chưa chốt (`OQ-062`) | | **Tổng/tháng** | ≈ $2.409 (A) / ≈ $5.862 (B) | ≈ $2.409 (A) / ≈ $5.862 (B) | ✅ Khớp | 🔴 **`OQ-054` (mới) — phát hiện quan trọng nhất của mục đối chiếu này:** `TCO §3.2` tính một khoản nhỏ (~$30/A, ~$60/B) cho **"cross-region snapshot (Payment)"** trong dòng "Backup & DR", nhưng `ADR-009` (chiến lược HA/DR cho nhóm giao dịch cốt lõi, bao gồm Payment) đã chọn **PA-1 — không multi-region ở MVP**, với lý do rõ ràng "chưa có trong ngân sách đã duyệt". Hai khả năng: (1) khoản chi phí này trong `TCO` chỉ là **bản sao snapshot sang region khác** để phòng thảm hoạ tối hậu (không kèm hạ tầng compute/failover chủ động ở region đó) — nếu vậy, nó **không mâu thuẫn** với "không multi-region active-passive" của `ADR-009`, nhưng cần ghi rõ: khôi phục từ snapshot cross-region này (nếu dùng tới) sẽ **KHÔNG đạt RTO ≤1 giờ** đã cam kết (restore RDS từ snapshot qua region khác thường mất nhiều giờ) — đây là "van an toàn cuối cùng", không phải một phần của cam kết RTO/RPO chính; (2) hoặc khoản chi phí này là sai sót/thừa trong `TCO`, nên bỏ nếu PO/Ops xác nhận không cần. **Không tự sửa `TCO` hay `ADR-009`** — trình cả hai khả năng. **Hỏi:** Tech Lead + Ops/SRE + PO. **Hệ quả nếu chọn hướng (1):** giữ nguyên chi phí `TCO`, thêm 1 dòng rõ ràng vào `ADR-009`/`INF` rằng cross-region snapshot Payment là biện pháp phụ, không nằm trong cam kết RTO≤1h. **Hệ quả nếu chọn hướng (2):** `TCO §3.2` giảm ~$30–60/tháng (không đáng kể so với tổng, không đổi kết luận "P2 rẻ hơn P1"). --- ## 11. Infrastructure as Code (IaC) — đề xuất cho GĐ3 *Không viết code Terraform/CDK thật ở lượt này (thuộc `sa-3-enablement`) — chỉ chốt hướng và tiêu chí FIT ứng viên.* | | Đề xuất | Vì sao | |---|---|---| | Công cụ | **Terraform** | Đa cloud-agnostic hơn CDK (dù hiện chỉ dùng AWS), cộng đồng module lớn cho ECS/RDS/ElastiCache, không khoá vào 1 ngôn ngữ lập trình cụ thể (CDK cần TypeScript/Python) — phù hợp năng lực team chưa xác nhận rõ (`CON-05`) | | Cấu trúc state | Tách state theo môi trường (dev/stg/prod) và theo nhóm tài nguyên (network, data, compute) — giảm blast radius khi `terraform apply` | Giảm rủi ro 1 lệnh apply làm hỏng toàn bộ hạ tầng | | Drift detection | Chạy `terraform plan` định kỳ (đề xuất hàng ngày) trên CI, cảnh báo nếu có drift chưa giải thích | Đúng yêu cầu (h) — fitness function `FIT-34` | | Tag policy | Bắt buộc tag `Project`, `Environment`, `Owner`, `CostCenter` trên mọi tài nguyên — enforce bằng AWS Config rule hoặc Terraform Sentinel/OPA policy | Phục vụ rà chi phí (§6.2 dashboard "Chi phí") và audit | 🔴 Chọn Terraform làm công cụ IaC chính là quyết định thiết lập tiền lệ, ràng buộc dài hạn (đảo ngược tốn nhiều tuần nếu đổi công cụ sau khi đã có code thật) — radar ước lượng ~7, đạt ngưỡng `ADR` bắt buộc. Xem [`adr/ADR-017_iac-terraform.md`](adr/ADR-017_iac-terraform.md) (`Proposed`). Điều kiện `Accepted`: Tech Lead + Ops/SRE xác nhận công cụ (`OQ-060`) và năng lực vận hành. **`FIT` ứng viên cho GĐ3:** | `FIT` | Kiểm tra | Công cụ | Chạy ở đâu | |---|---|---|---| | `FIT-34` | Drift detection — hạ tầng thật khớp Terraform state | `terraform plan` định kỳ / driftctl | CI, hàng ngày | | `FIT-35` | 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-36` | Đúng 2 ECS service (GD/HT) + 1 Payment tồn tại, đúng SG cô lập theo §8.1 | Terraform plan review + AWS Config | CI/CD (trùng `ADR-012 FIT-16`, mở rộng thêm kiểm tra SG) | | `FIT-37` | Blue-green deploy tự động rollback khi health check fail sau khi chuyển traffic | CodeDeploy hook test | Staging, trước mỗi major release | | `FIT-38` | Pipeline chặn deploy khi Trivy/Snyk phát hiện Critical/High chưa có ngoại lệ | CI/CD test (giả lập lỗ hổng) | CI, định kỳ kiểm tra pipeline tự nó hoạt động đúng | --- ## 12. Quyết định ghi nhận ở mức `DEC` (không đạt ngưỡng `ADR`) | Quyết định | Radar ước lượng | Lý do không cần `ADR` | |---|---|---| | Cơ chế service discovery nội bộ GD↔HT: AWS Cloud Map + ECS Service Connect (không App Mesh) | ~3 | Đảo ngược thấp (đổi sang App Mesh sau là bổ sung, không viết lại), bán kính hẹp (chỉ ảnh hưởng cấu hình network nội bộ), không chạm `QAS` Must trực tiếp (latency thêm không đáng kể, kế thừa đường găng đã có timeout ở `FAIL`), không tranh cãi | | Auto-scaling metric: target tracking CPU + request count (không dùng custom metric phức tạp hơn ở bản đầu) | ~3 | Điều chỉnh được dễ dàng qua console/Terraform, không ràng buộc dài hạn | | Environment tách VPC/account riêng cho non-prod (đề xuất, `OQ-062`) | ~4 | Đảo ngược trung bình (tách account sau khi đã chạy chung tốn công di chuyển nhưng không phải viết lại code) — ghi `DEC`, không `ADR`, nhưng vẫn cần `OQ-062` xác nhận trước khi triển khai thật | --- ## 13. Truy vết | `INF` §/mục | `QAS` | `ASR` | `ADR` | `CMP` | `FM` | |---|---|---|---|---|---| | §3 Topology | `QAS-009` | `ASR-001`, `ASR-012`, `ASR-002` | `ADR-001`, `ADR-002`, `ADR-012` | `CMP-01…15` | — | | §4 HA/auto-scaling | `QAS-002`, `QAS-009` | `ASR-014`, `ASR-007` | `ADR-012` | `CMP-04`, `CMP-15` | — | | §5 DR | `QAS-008` | `ASR-010` | `ADR-009` | `CMP-02`, `CMP-04`, `CMP-11` | — | | §6 Observability | `QAS-013`, `QAS-007` | `ASR-011` | `ADR-010` | `CMP-02`, `CMP-04`, `CMP-11` | `FM-09`, `FM-10` | | §7 CI/CD | `QAS-007` | — | `ADR-016` | Toàn bộ `CMP` triển khai được | — | | §8 Network/Security | `QAS-010`, `QAS-011` | `ASR-002`, `ASR-007` | `ADR-002` | `CMP-01`, `CMP-11`, `CMP-14`, `CMP-15` | — | | §11 IaC | — | — | `ADR-017` | — | — | --- ## 14. Giả định & Ngoài phạm vi **Giả định** *(tiếp số toàn dự án, bắt đầu `ASM-42`)*: | ID | Giả định | Cách xác minh | Nếu sai | |---|---|---|---| | `ASM-42` | Split ECS task Nhóm Giao dịch/Nhóm Hỗ trợ đề xuất (A: 2/2, B: 6/4) phản ánh đúng ý `TCO §3.2` khi gộp thành 1 dòng "monolith" — tức là `TCO` đã tính đủ tiền cho *tổng* task bất kể chia thế nào | Tech Lead/Ops xác nhận ở `OQ-026`/`OQ-055` | Nếu `TCO` thực ra chỉ tính đủ cho 1 service duy nhất (không đủ overhead vận hành 2 service riêng — VD 2 load balancer target group, 2 service discovery entry): chi phí thực tế có thể cao hơn `TCO` một khoản nhỏ (không đáng kể theo kinh nghiệm AWS — ECS service không tính phí riêng, chỉ tính theo task) | | `ASM-43` | Auto-scaling target tracking (CPU 60%/70%, request count) đủ nhanh để bắt kịp tốc độ tăng tải thật của flash sale (chưa biết tốc độ tăng — `QAS-009` chỉ có 2 điểm A/B, không có đường cong tăng) | Đo thật trong `POC-01`/`POC-02` mở rộng hoặc diễn tập tải riêng cho auto-scaling (chưa có kế hoạch, đề xuất bổ sung ở GĐ3 `FIT`) | Nếu tải tăng nhanh hơn tốc độ scale (thường ECS Fargate cần 1-3 phút để task mới sẵn sàng): có thể có cửa sổ ngắn quá tải trước khi auto-scaling bắt kịp — cân nhắc pre-scale thủ công trước sự kiện flash sale đã biết trước lịch | | `ASM-44` | ElastiCache Multi-AZ (kịch bản B) failover tự động trong ~60 giây theo tài liệu công khai AWS | Diễn tập DR-3 (§5.4) đo thật | Nếu chậm hơn nhiều: tăng thời gian gián đoạn ownership-check, cần xét lại kiến trúc fallback (VD cache-aside với timeout ngắn gọi thẳng DB) | | `ASM-45` | ECS task thay thế sau khi 1 AZ down mất ~1-3 phút (health check + scheduler + container start) | Diễn tập DR-1 (§5.4) đo thật | Nếu lâu hơn: RTO tổng thể của nhóm giao dịch cốt lõi có nguy cơ tiệm cận giới hạn 1 giờ nhanh hơn dự kiến khi cộng dồn nhiều thành phần phục hồi tuần tự | | `ASM-46` | Cửa sổ bảo trì ≤2 giờ/tháng (`OQ-020`, TẠM) đủ cho mọi hoạt động deploy/migration định kỳ kể cả nâng cấp minor version RDS | PO xác nhận số cuối ở `OQ-020`; Ops theo dõi thực tế sau go-live | Nếu không đủ: một số bảo trì phải tính vào ngân sách lỗi 43 phút/tháng, giảm biên độ cho sự cố thật | **Ngoài phạm vi:** - IaC (Terraform) thật, `AGD` runbook chi tiết, `FIT` chạy trên CI thật — thuộc `sa-3-enablement`. - Multi-region active-passive — đã loại ở `ADR-009`, chỉ xét lại nếu PO duyệt ngân sách bổ sung. - OpenSearch — P2 hoãn dùng, kế thừa nguyên trạng `SAD §10`/`TCO §3.2` (không có trong `TCO` cho P2 kịch bản A/B, không thiết kế hạ tầng cho nó ở tài liệu này). - Cấu hình DNS/Route53 failover chi tiết, chứng chỉ SSL cụ thể — tham chiếu `TCO §4`, chưa thiết kế chi tiết ở `INF` này (mức độ ưu tiên thấp, ALB đã Multi-AZ). - Chi tiết connection pool/bulkhead theo con số cụ thể (`OQ-037` của `FAIL`) — chờ kết quả `POC-02`, `INF` chỉ ghi nhận đây là cấu hình cần thiết lập ở tầng RDS parameter group khi có số. - Giá cả/đơn giá AWS — không tính lại, tham chiếu nguyên trạng `TCO` (`ASM-11`/`ASM-12`). --- ## 15. Open Questions | ID | Câu hỏi | Hỏi ai | Từ ngày | Chặn gì | Hệ quả nếu trả lời ngược | |---|---|---|---|---|---| | `OQ-054` | `TCO §3.2` tính "cross-region snapshot (Payment)" (~$30/A, ~$60/B) trong dòng Backup & DR — có mâu thuẫn với `ADR-009` (chọn PA-1, không multi-region) không, hay đây chỉ là snapshot phụ không nằm trong cam kết RTO≤1h? | Tech Lead + Ops/SRE + PO | 2026-09-15 | §10 đối chiếu `TCO`; nội dung `ADR-009`/`INF §5.2` | Nếu là (1) snapshot phụ: giữ nguyên, chỉ cần ghi rõ nó không tính vào RTO cam kết. Nếu là (2) sai sót: `TCO` giảm ~$30-60/tháng, không đổi kết luận P2 rẻ hơn P1 | | `OQ-055` | Xác nhận split ECS task đề xuất giữa Nhóm Giao dịch/Nhóm Hỗ trợ (A: 2/2, B: 6/4) và ngưỡng auto-scaling (CPU 60%/70%, request count) — nối `OQ-026` | Tech Lead + Ops/SRE | 2026-09-15 | §4.2, §10; cấu hình Terraform thật ở GĐ3 | Nếu Tech Lead muốn tỷ lệ khác (VD 3/1 thay vì 2/2 ở kịch bản A): đổi bảng §3/§4, không đổi tổng chi phí `TCO` | | `OQ-056` | Nối `OQ-022` — lịch diễn tập DR thật (DR-1/2/3 ở §5.4) là ngày nào? SA đề xuất trong vòng 2 tuần kể từ khi xác định Ops/SRE, trước khi trình AG2 | Ops/SRE | 2026-09-15 | Điều kiện tiên quyết ký AG2 (`DEC-12`) | Không diễn tập trước AG2 ⇒ RTO/RPO vẫn "trên giấy", Security/Ops có thể từ chối ký AG2 với lý do chính đáng | | `OQ-057` | VNPay/Momo/GHN/GHTK/Email-SMS có yêu cầu IP allowlist cho traffic outbound từ sàn không? Nếu có, cần đăng ký 2 Elastic IP NAT với từng đối tác | Tech Lead (khi có tài liệu đối tác thật) | 2026-09-15 | §8.3; thời điểm phối hợp hành chính với đối tác trước go-live | Nếu không xử lý trước go-live và đối tác yêu cầu allowlist: toàn bộ traffic outbound bị chặn ở phía đối tác, phát hiện muộn ngay trước/sau go-live | | `OQ-058` | Chấp nhận ElastiCache kịch bản A không có replica (SPOF, §4.3) hay muốn thêm 1 replica ngay (chi phí ước tính +~$92/tháng theo đơn giá `TCO §3.1`, chưa xác nhận chính xác)? | PO + Ops/SRE | 2026-09-15 | §4.3; cấu hình ElastiCache thật ở GĐ3 | Giữ nguyên (chấp nhận SPOF): tiết kiệm chi phí nhưng có gián đoạn ownership-check khi mất node Redis (ước 5-10 phút, chưa đo). Thêm replica: tăng chi phí nhỏ, giảm rủi ro gián đoạn | | `OQ-059` | Xác nhận: (a) retention log CloudWatch/S3 archive, (b) tỉ lệ lấy mẫu X-Ray trace, (c) retention backup RDS (đề xuất 7 ngày, khác 35 ngày ở tài liệu P1 gốc) | Tech Lead + Ops/SRE | 2026-09-15 | §6.1, §5.2; chi phí lưu trữ thực tế | Retention ngắn hơn: giảm chi phí nhưng giảm khả năng điều tra sự cố cũ. Dài hơn: tăng chi phí lưu trữ | | `OQ-060` | Xác nhận công cụ IaC (Terraform, đề xuất) và ngưỡng coverage unit test cho P2 (đề xuất kế thừa 70%/50% từ tài liệu P1, cần xác nhận lại cho kiến trúc mới) | Tech Lead | 2026-09-15 | §11 (`ADR-017` ứng viên); §7.1 pipeline | Nếu chọn CDK thay Terraform: cần kỹ năng TypeScript/Python cho hạ tầng, ảnh hưởng `CON-05` (năng lực team) | | `OQ-061` | *(nối `OQ-037` của `FAIL`/`DAT`)* Kích thước connection pool RDS theo module (ghi checkout vs đọc catalog) và pool HTTP theo từng adapter đối tác ngoài — phụ thuộc kết quả `POC-02` chưa chạy | DBA + Tech Lead | 2026-09-15 | Cấu hình RDS parameter group thật ở GĐ3 | Pool sai kích thước: nghẽn checkout (quá nhỏ) hoặc lãng phí connection/cạn tổng pool RDS (quá lớn) | | `OQ-062` | Non-prod (dev/stg) nên tách VPC riêng trong cùng account hay tách hẳn AWS account riêng (đề xuất SA: account riêng theo AWS Organizations, best practice cô lập blast radius + rà chi phí)? | Tech Lead + Ops/SRE | 2026-09-15 | §2, §3 (bảng thành phần "Non-prod") | Account riêng: cô lập tốt hơn nhưng thêm chi phí quản lý cross-account (IAM, networking). Cùng account khác VPC: đơn giản hơn nhưng rủi ro cấu hình sai lan sang prod cao hơn | | `OQ-063` | *(nối `OQ-008`, không lặp lại — chỉ nhắc)* Đội Ops/SRE thật (nội bộ/thuê ngoài, quy mô) — chặn trực tiếp khả năng đáp ứng on-call §6.5 và tần suất diễn tập DR §5.4 | PM/SRE | 2026-09-12 *(đã mở từ `CTX`)* | §5.4, §6.5 | Xem `CTX OQ-008` — không lặp lại hệ quả ở đây | **Nhắc AG2:** cần **Tech Lead + Security + Ops/SRE ký**. `INF` là artifact cuối cùng cần Ops/SRE ký trực tiếp (`workflow.md §2`) — hoạt động còn lại của GĐ2 là `fail` (đã xong, `DEC-21/22`) và `adr` (12+1 ADR đã viết, cộng 2 ADR ứng viên mới từ `INF`: `ADR-016` blue-green, `ADR-017` Terraform, cộng `ADR-014`/`ADR-015` đang chờ từ `DAT`/`SEC`). --- ## Tự chấm ### ① Bảng tự chấm Gate AG2 *(`workflow.md §2` — dòng liên quan `INF`)* | # | Tiêu chí | ☐/✅ | Ghi chú | |---|---|---|---| | — | `ASR`/`QAS`/`SAD`/`ADR`/`ICD`/`DAT`/`SEC`/`FAIL` | ✅ *(đã đạt ở các hoạt động trước, duyệt từng phần)* | Xem artifact tương ứng | | 1 | `INF` — topology môi trường, HA/DR có **RTO/RPO bằng số**, chiến lược scale, observability | ✅ *(nội dung đầy đủ)* / 🔴 *(chưa đo thật)* | §3–§6: RTO≤1h/RPO≤15’ có số, HA Multi-AZ, scale A→B có ngưỡng, observability có log/metric/trace/dashboard/alert — nhưng **chưa diễn tập** (`OQ-022/056`), `Confidence` giữ 🔴 | | — | `sa-conformance` báo coverage `ASR → ADR/CMP` ≥ 100% | 🟡 Không đổi bởi `INF` | `INF` không tạo `ASR`/`CMP` mới, chỉ hiện thực hoá — coverage đã đạt 15/15 ở `SAD §4.3` | **Kết luận tự chấm (riêng phần `INF`):** Đủ nội dung theo checklist AG2 dòng `INF` — có RTO/RPO bằng số, kế hoạch diễn tập DR cụ thể (3 kịch bản, tiêu chí PASS/FAIL đo thật), auto-scaling có ngưỡng, observability đủ 3 trụ (log/metric/trace) + alert + error budget, CI/CD có pipeline đủ bước + chiến lược deploy zero-downtime, network/security group đầy đủ, đối chiếu `TCO` từng dòng (1 điểm chưa khớp bản chất đã ghi `OQ-054`, không tự sửa). **Chưa đủ điều kiện ký AG2** vì: (a) chưa diễn tập DR/inject lỗi thật, (b) `POC-01`/`POC-02` chưa chạy, (c) `OQ-008` (đội Ops thật) còn mở — ba điều này đều **ngoài khả năng của việc viết tài liệu**, cần hành động thật của Ops/SRE/Tech Lead. ### ② Checklist D1–D12 | # | Mục | ☐/✅ | Ghi chú | |---|---|---|---| | D1 | Một ADR một quyết định | N/A | `INF` không viết `ADR` mới ở lượt này — chỉ đề xuất 2 ứng viên (`ADR-016`, `ADR-017`) cho hoạt động `adr` kế tiếp, mỗi ứng viên đã tách đúng 1 quyết định | | D2 | Không NFR định tính | ✅ | Mọi ngưỡng (RTO/RPO, auto-scaling, alert, retention) đều có con số hoặc đánh dấu rõ "chưa chốt" kèm `OQ` | | D3 | Nêu phương án bị loại + lý do gắn `CON`/`QAS` | ✅ *(kế thừa)* | Deploy strategy: nêu rõ vì sao chọn blue-green thay vì rolling (gắn `QAS-007`); Service discovery: nêu rõ vì sao không chọn App Mesh (gắn giới hạn phạm vi đã ghi ở `SAD §7`); các phương án lớn khác (multi-region, message backbone, DB) đã có `ADR` riêng, `INF` chỉ hiện thực hoá | | D4 | Sơ đồ khai báo mức + legend | ✅ | §3 khai báo "Deployment view", có legend đầy đủ (ranh giới mạng, AZ, loại đường nối); §7.1 khai báo loại (pipeline flowchart) | | D5 | Interface có chủ/contract | N/A | Không phải phạm vi `INF` — đã có ở `ICD` | | D6 | Phụ thuộc ngoài process có timeout/retry | N/A | Đã có ở `FAIL` — `INF` chỉ bổ sung network/SG cho phép các phụ thuộc đó chạy được, không thiết kế lại timeout/retry | | D7 | Một chủ sở hữu dữ liệu | ✅ *(kế thừa)* | §5.2 Backup/PITR tôn trọng đúng ranh giới `ADR-002`/`ADR-006` (RDS chính vs RDS Payment tách biệt) | | D8 | Ràng buộc có FIT hoặc nhãn khuyến nghị | ✅ | §11 đề xuất `FIT-34…38`; các mục chưa có FIT (VD "ai xử lý DLQ theo domain") đánh dấu rõ "chưa chốt", không giả vờ đã có | | D9 | Con số hạ tầng quy ra tiền + nguồn; `INF` khớp `TCO` | ✅ *(1 điểm ngoại lệ đã ghi rõ)* | §10 đối chiếu từng dòng — khớp toàn bộ trừ 1 điểm bản chất (`OQ-054`), không tự sửa `TCO` | | D10 | Không quyết định thay người có thẩm quyền | ✅ | §4.3 (SPOF Redis kịch bản A — trình `OQ-058` kèm chi phí, không tự chọn), §5.2 (`OQ-054` — trình 2 khả năng, không tự sửa `TCO`/`ADR-009`), §7.2 (đề xuất blue-green nhưng đánh dấu cần `ADR-016` — không tự "Accepted") | | D11 | Có mục "Ngoài phạm vi" + `ASM-nn` | ✅ | §14 đầy đủ — `ASM-42…46` có cách xác minh/hệ quả | | D12 | Câu quy định thẩm quyền sơ đồ vs văn bản | ✅ | Có ngay sau Change Log | ### ③ Bảng đối chiếu với bộ BA | `BA` | Nội dung | `INF` tương ứng | Khớp? | Hành động | |---|---|---|---|---| | `docs/09 §9.5.2` (RTO/RPO gốc, kiến trúc P1) | Payment/Cart&Order/Identity: RPO≤15’/RTO≤1h; Commission&Payout/Seller: RPO≤1h/RTO≤4h; Catalog/Promotion/Shipping: RPO≤1h/RTO≤8h; Review/Notification/Audit: RPO≤24h/RTO≤24h | `INF §5.1` chỉ thiết kế DR cho nhóm giao dịch cốt lõi (khớp `ASR-010`/`QAS-008`, đúng phạm vi P2 hiện tại) | 🟡 Một phần | `INF` **chưa** thiết kế DR chi tiết cho Nhóm Hỗ trợ (Commission/Seller/Catalog/Promotion/Review/Notification) — ngoài phạm vi yêu cầu người duyệt lượt này (chỉ yêu cầu nhóm giao dịch cốt lõi); ghi nhận là khoảng trống cần bổ sung ở lượt `inf` tiếp theo hoặc trước AG2 nếu Ops/SRE yêu cầu | | `docs/09 §9.3.1` (CI/CD, kiến trúc P1, 10 microservice) | Pipeline build→test→SAST→SCA→integration→deploy dev/stg/prod, canary rollout | `INF §7.1` — điều chỉnh còn 3 đơn vị triển khai (không phải 10), bỏ Kafka-specific test, đổi canary→blue-green | ✅ Đã điều chỉnh đúng theo P2, không sao chép nguyên trạng P1 | Không cần hành động — đã ghi rõ trong Change Log là "điều chỉnh, không tái dùng nguyên trạng" | | `docs/09 §9.4.1` (Metrics/alert, kiến trúc P1) | Alert theo NFR-01…08, kênh PagerDuty/OpsGenie | `INF §6.3` — giữ cùng nguyên tắc alert (health check ≤1 phút, escalation 24/7) nhưng bỏ Kafka consumer lag (đổi thành SQS `ApproximateAgeOfOldestMessage`) | ✅ Đã điều chỉnh | Không cần hành động | | `QAS-008`/`ADR-009` (SA) | RPO≤15’/RTO≤1h, chưa diễn tập | `INF §5.4` — kế hoạch diễn tập cụ thể | ✅ | `INF` là nơi hiện thực hoá điều kiện `ADR-009 §3` đã đặt ra — không lệch | ### ④ Danh sách `OQ` mở kèm người phải trả lời, chặn gì Xem §15 (`OQ-054…063` mới) cộng các `OQ` còn mở từ toàn dự án — sổ đầy đủ tại `00-index/OQ_e-commerce.md`. Ba câu quan trọng nhất trước khi trình AG2: **`OQ-056`** (nối `OQ-022`, lịch diễn tập DR — điều kiện tiên quyết `DEC-12`), **`OQ-063`** (nối `OQ-008`, đội Ops thật — chặn cả on-call §6.5 lẫn khả năng thực hiện diễn tập DR §5.4), **`OQ-054`** (mâu thuẫn TCO/ADR-009 về cross-region snapshot Payment). **Nhắc:** `ADR-014` (outbox, theo `DAT`), `ADR-015` (service JWT, theo `SEC`), `ADR-016` (blue-green) và `ADR-017` (Terraform, theo `INF`) đã được viết ở lượt hoạt động `adr` kế tiếp — GĐ2 nay đủ 9/9 hoạt động, 17 `ADR` tổng cộng, tất cả `Proposed`. Cần chạy `sa-conformance` để cập nhật `DTM`/`ADL` và kiểm coverage trước khi trình AG2 (Tech Lead + Security + Ops/SRE ký).