Harbor

Hạ tầng theo quy mô

Ba mức hạ tầng từ một VPS đến Kubernetes nhiều region: thành phần, sơ đồ, chi phí ước lượng mỗi tháng, đội vận hành cần có và các tín hiệu cho biết đã đến lúc lên mức tiếp theo.

14 phút đọcHạ tầng theo quy mô

Một lỗi phổ biến trong phỏng vấn và cả ngoài đời: dựng hạ tầng cho 50 triệu người dùng khi sản phẩm mới có 5 nghìn. Hạ tầng thừa tốn tiền, tốn người vận hành và làm chậm việc ra tính năng. Building Microservices cũng cảnh báo việc dựng cho quy mô khổng lồ ngay từ đầu là nguy hiểm, vì lúc đầu ta chưa biết sản phẩm có thành công không, và việc phải đổi kiến trúc khi tải tăng là dấu hiệu thành công chứ không phải thất bại.1 Bài này chia hạ tầng thành ba mức. Mỗi mức có thành phần, chi phí và đội ngũ riêng. Ngưỡng giữa các mức khớp với Máy tính hạ tầng:

MứcNgưỡng (ước lượng)Hình dạngChi phí mỗi tháng (ước lượng)Đội vận hành
1 · Khởi đầu≤ 50.000 DAU và đỉnh < 300 req/s1–2 máy hoặc serverless container, một Postgres20–150 USDDev tự lo
2 · Tăng trưởngĐỉnh < 20.000 req/sLB, container tự scale, Postgres HA + replica, Redis, queue, CDN1.000–15.000 USD1–3 người lo hạ tầng
3 · Quy mô lớnĐỉnh ≥ 20.000 req/sKubernetes nhiều zone/region, shard, KafkaTừ vài chục nghìn USD trở lênSRE và platform riêng

Các ngưỡng DAU, req/s, chi phí và quy mô đội trong bảng là quy tắc ước lượng của khoá học, không có trong sách.2 Chi phí thay đổi nhiều theo nhà cung cấp, region và cách dùng. Hãy coi các khoảng trên là thứ tự độ lớn để trình bày; giá cloud cụ thể chưa có sách trong thư viện.3

Mức 1 · Khởi đầu

Mục tiêu ở mức này là ra sản phẩm nhanh và không mất dữ liệu. Chấp nhận downtime ngắn khi có sự cố.

Cách 1: một VPS và Docker Compose. Một máy 2–4 vCPU · 4–8 GB chạy Nginx (hoặc Caddy để có HTTPS tự động), app Node.js và Postgres trong Docker Compose. Rẻ nhất, dễ hiểu nhất. Đánh đổi: Building Microservices ghi nhận nhiều service chung một host làm giảm chi phí và đơn giản việc quản lý host lúc đầu, nhưng một sự cố host kéo theo nhiều service và việc giám sát, scale riêng từng service khó hơn.4

Cách 2: serverless container và database managed. Cloud Run, App Runner hoặc Azure Container Apps cho API, cộng một Postgres managed nhỏ (2 vCPU · 8 GB hoặc nhỏ hơn). Không phải quản lý máy, tự scale theo tải và có thể về 0 khi không có request. Hướng này gần với platform as a service mà Building Microservices mô tả: làm việc ở mức trừu tượng cao hơn một host, nền tảng lo chạy và có thể scale giúp, đổi lại bạn nhường quyền kiểm soát.5 Chi tiết sản phẩm cụ thể (Cloud Run, App Runner…) chưa có sách trong thư viện.6

Đang vẽ sơ đồ…

File docker-compose.yml rút gọn cho cách 1:

services:
  app:
    image: myapp:latest
    env_file: .env
    restart: unless-stopped
    depends_on: [db]
  db:
    image: postgres:16
    volumes: ["pgdata:/var/lib/postgresql/data"]
    restart: unless-stopped
  caddy:
    image: caddy:2
    ports: ["80:80", "443:443"]
volumes:
  pgdata:

Những việc không được bỏ qua dù đang ở mức 1:

  • Backup: pg_dump hoặc snapshot hằng ngày đẩy ra object storage ở nơi khác, giữ ít nhất 7–30 ngày. Database managed thường có sẵn point-in-time recovery. Sách nhắc rằng dữ liệu an toàn (durability) và dịch vụ sẵn sàng (availability) là hai việc khác nhau với giải pháp khác nhau: có bản sao dữ liệu chưa có nghĩa DB đang chạy.7 Thời gian giữ 7–30 ngày là khuyến nghị của khoá học.2
  • Thử khôi phục: backup chưa từng restore thử thì chưa chắc dùng được (khuyến nghị vận hành của khoá học).2
  • App stateless: file lên object storage, session ở DB hoặc JWT. Node.js Design Patterns nêu điều kiện tiên quyết để scale ngang là mỗi instance không giữ thông tin chung trên bộ nhớ hay đĩa cục bộ, ví dụ session phải nằm ở kho dùng chung. Việc này giúp lên mức 2 không phải viết lại.8
  • Giám sát tối thiểu: uptime check từ bên ngoài và cảnh báo khi đĩa gần đầy.9

Lưu ý: Rủi ro chính của mức 1 là một máy chết thì dịch vụ dừng. Điều này chấp nhận được khi người dùng còn ít, miễn là dữ liệu có backup.

Mức 2 · Tăng trưởng

Ở mức này người dùng bắt đầu phàn nàn khi hệ thống chậm hoặc sập. Mục tiêu chuyển sang: không có điểm chết đơn lẻ, deploy không downtime, và biết sự cố trước khi người dùng báo.

Thành phần:

  • Load balancer (ALB, Cloud Load Balancing) phía trước, kết thúc TLS. Load balancer phân phối request tới nhiều instance, loại instance không khoẻ, và là cách đơn giản nhất để bỏ điểm chết đơn lẻ của một service HTTP đồng bộ.10
  • API container tự scale: Cloud Run, ECS Fargate hoặc Kubernetes managed (EKS, GKE). Scale theo CPU khoảng 60% hoặc theo số request (quy tắc của khoá học). Tối thiểu 2 instance ở 2 zone: Building Microservices khuyên trải dịch vụ qua nhiều availability zone vì nhà cung cấp không bảo đảm một node hay một zone.11
  • Postgres managed HA: primary và standby ở zone khác, failover tự động, cộng 1–2 read replica. Có PgBouncer hoặc proxy kết nối. Primary ghi, replica phục vụ đọc và giữ bản sao dữ liệu; replicate bất đồng bộ nên đọc từ replica có thể cũ.12 Chi tiết PgBouncer chưa có sách trong thư viện.6
  • Redis managed cho cache, session, rate limit.
  • Queue managed (SQS, Pub/Sub, hoặc BullMQ) và worker riêng cho job nền: hệ thống kiểu worker cùng xử lý một hàng việc hợp với việc bất đồng bộ như tạo thumbnail, gửi email, báo cáo, và hợp với tải có đỉnh.13 Grokking cũng nêu queue giúp tách việc chậm khỏi đường đi chính và hấp thụ đỉnh tải.14
  • CDN và object storage cho ảnh, file, tài nguyên tĩnh: CDN phục vụ từ proxy gần người dùng, giảm độ trễ và giảm tải cho origin.15
  • Observability: metric, log tập trung, trace cơ bản, cảnh báo theo latency p95 và tỉ lệ lỗi.9
  • CI/CD và staging: mỗi merge chạy test, build image, deploy staging, rồi deploy production kiểu rolling hoặc blue-green. Blue/green và canary là kỹ thuật tách deploy khỏi release để giảm rủi ro.16
Đang vẽ sơ đồ…

Building Microservices ch.6 mô tả mô hình immutable server: mọi thay đổi đều đi qua build pipeline để tạo máy mới, tránh "configuration drift" khi ai đó sửa tay trên máy chạy.17 Ch.8 nhấn mạnh khi số host tăng thì phải gom log về một chỗ và dùng correlation ID để truy một request qua nhiều tiến trình.9 Ở mức 2 bạn chưa cần microservices. Một monolith chia module tốt, chạy nhiều instance, vẫn là lựa chọn hợp lý (nhận định của khoá học, phù hợp với cảnh báo "đừng dựng cho quy mô lớn từ đầu" của Building Microservices).1

Mẹo: Ở mức 2, chi phí lớn nhất thường là database và băng thông ra ngoài. Tối ưu truy vấn, thêm cache và đặt CDN trước khi mua máy DB lớn hơn.

Mức 3 · Quy mô lớn

Đây là quy mô hàng chục triệu người dùng, đỉnh hàng chục nghìn req/s trở lên. Một database, một zone hoặc một đội không còn gánh nổi.

  • Kubernetes nhiều zone, thường nhiều region gần người dùng. Mỗi region tự phục vụ được khi region khác lỗi. Building Microservices nói AWS chia thành region và availability zone, và có tổ chức còn chạy nhiều region để tăng độ sẵn sàng.11 Kubernetes cụ thể chưa có sách trong thư viện.6
  • Dữ liệu chia shard (Citus, Vitess) hoặc dùng DB phân tán (Cassandra, DynamoDB, Spanner). Sharding chia dữ liệu cho nhiều node, mỗi node giữ một phần, để xử lý lượng dữ liệu và truy vấn tăng.18 Xem Sharding.
  • Kafka làm xương sống sự kiện: service phát sự kiện, nhiều consumer đọc độc lập, đọc lại được khi thêm tính năng. Xem Kafka.19
  • Tách service theo phần có tải khác nhau hoặc đội khác nhau: scale cube gọi đây là trục y, tách theo chức năng, trục có ảnh hưởng lớn nhất lên kiến trúc và cách quản lý phát triển.20
  • SRE và on-call: SLO cho từng service, error budget, runbook, trực sự cố luân phiên, diễn tập failover định kỳ. Grokking nhấn mạnh đội vận hành cần được luyện sẵn cho sự cố hiếm.21 Khái niệm error budget và vai trò SRE chưa có sách trong thư viện.22
Đang vẽ sơ đồ…

Grokking ch.39 phân tích vài sự cố lớn và rút ra những bài học áp dụng trực tiếp ở mức này. Trong sự cố Facebook, việc khôi phục mất khoảng sáu giờ vì các công cụ nội bộ nhiều khả năng phụ thuộc vào hạ tầng DNS đang sập, nên phải can thiệp thủ công, mà các lớp bảo mật vật lý và số khiến việc đó chậm; sách rút ra bài học về phụ thuộc ẩn, đội vận hành sẵn sàng và giữ thiết kế đơn giản.23 Trong sự cố AWS Kinesis, thêm một ít máy vào fleet làm số thread vượt giới hạn hệ điều hành; sách nêu hướng giảm số server (dùng máy mạnh hơn) để mỗi server giữ ít thread hơn, cùng bài học về kiểm thử và đội vận hành được huấn luyện.24 Bài học chung: tìm phụ thuộc ẩn, chuẩn bị đội vận hành cho sự cố hiếm, và cân nhắc nhiều region (nhận định cuối là của khoá học).

Trong phỏng vấn: Khi vẽ kiến trúc mức 3, nói luôn về vận hành: ai trực, SLO là gì, failover region thử bao lâu một lần. Đây là phần nhiều ứng viên bỏ qua.

Tín hiệu cần lên mức

Đừng lên mức vì đọc blog của công ty lớn. Lên mức khi có số liệu:

Tín hiệuĐo bằng gìHướng xử lý
CPU database thường trên 60–70% dù đã tối ưu truy vấnMetric DB, slow query logCache, read replica, rồi máy lớn hơn, rồi shard
Downtime vượt mục tiêu (99,9% ≈ 43,8 phút/tháng25)Uptime check, SLOThêm HA: nhiều instance, nhiều zone
Một máy hoặc một zone sập kéo theo cả hệ thốngPostmortem sự cốBỏ điểm chết đơn lẻ
Deploy một phần làm ảnh hưởng phần khácTần suất rollbackTách module hoặc service, pipeline riêng
p95 tăng theo giờ cao điểmAPM, traceAutoscaling, queue để làm phẳng đỉnh
Dữ liệu một node vượt 1–2 TBDung lượng đĩaPartition, lưu trữ lạnh, rồi shard
Đỉnh vượt 300 req/s hoặc 20.000 req/sMetric LBTheo ngưỡng mức ở bảng đầu bài

Các ngưỡng CPU 60–70%, 1–2 TB và 300 / 20.000 req/s trong bảng là quy tắc ước lượng của khoá học.2 Building Microservices ch.11 gọi đây là câu hỏi "How Much Is Too Much?": mức chịu lỗi và tốc độ cần có do người dùng hệ thống quyết định; autoscaling hay blue/green có thể là thừa với hệ thống báo cáo chạy hai lần mỗi tháng hay wiki nội bộ.26 Một app nội bộ 200 người dùng không cần multi-region (ví dụ của khoá học theo cùng tinh thần).

Sai lầm hay gặp

Sai lầm hay gặp: Bắt đầu bằng Kubernetes tự dựng và microservices cho sản phẩm chưa có người dùng. Đội dành phần lớn thời gian cho hạ tầng thay vì sản phẩm.1

  • Bỏ qua backup ở mức 1 vì "chưa có ai dùng". Dữ liệu đầu tiên của khách hàng là dữ liệu quan trọng nhất.
  • Lên mức 2 nhưng vẫn một zone. Có load balancer và nhiều instance nhưng tất cả cùng một zone thì một sự cố zone vẫn làm sập toàn bộ.11
  • Tự vận hành Kafka, Elasticsearch, Postgres ở mức 2 khi chưa có người chuyên. Dùng dịch vụ managed cho đến khi hoá đơn đủ lớn để trả lương một đội platform.
  • Không có staging. Mọi thay đổi cấu hình hạ tầng thử thẳng trên production.

Liên kết với các bài khác

Nguồn trích dẫn

  1. Building Microservices (Sam Newman) (file .zip, tải về giải nén) · ch.11 Microservices at Scale · mục "Scaling" › "Starting Again" (tr. 221–222). ↩ ↩2 ↩3

  2. Quy tắc ước lượng của khoá học, xem bài Chọn server. Không phải số liệu trích từ sách; cần load test với ứng dụng thật. ↩ ↩2 ↩3 ↩4

  3. Chưa có nguồn trong thư viện: giá cloud thay đổi theo nhà cung cấp và thời điểm, không sách nào trong thư viện nêu; khoảng chi phí chỉ là thứ tự độ lớn minh hoạ. ↩

  4. Building Microservices (file .zip, tải về giải nén) · ch.6 Deployment · mục "Service-to-Host Mapping" › "Multiple Services Per Host" và "Single Service Per Host" (tr. 116–120). ↩

  5. Building Microservices (file .zip, tải về giải nén) · ch.6 Deployment · mục "Service-to-Host Mapping" › "Platform as a Service" (tr. 120–121). ↩

  6. Chưa có nguồn trong thư viện: Cloud Run, ECS, Kubernetes, PgBouncer, Docker Compose, Caddy là sản phẩm cụ thể mà thư viện không có sách; bài chỉ nêu vai trò cơ bản. ↩ ↩2 ↩3

  7. Building Microservices (file .zip, tải về giải nén) · ch.11 Microservices at Scale · mục "Scaling Databases" › "Availability of Service Versus Durability of Data" (tr. 222). ↩

  8. Node.js Design Patterns 2e (file .zip, tải về giải nén) · ch.10 Scalability and Architectural Patterns · mục "Cloning and load balancing" (tr. 391). ↩

  9. Building Microservices (file .zip, tải về giải nén) · ch.8 Monitoring · mục "Logs, Logs, and Yet More Logs..." (tr. 158) và "Correlation IDs" (tr. 162). ↩ ↩2 ↩3

  10. Building Microservices (file .zip, tải về giải nén) · ch.11 Microservices at Scale · mục "Scaling" › "Load Balancing" (tr. 219–220). ↩

  11. Building Microservices (file .zip, tải về giải nén) · ch.11 Microservices at Scale · mục "Scaling" › "Spreading Your Risk" (tr. 217–218). ↩ ↩2 ↩3

  12. Grokking Modern System Design · ch.9 Databases · bài "Data Replication", mục "Single leader/primary-secondary replication" và "Synchronous versus asynchronous replication". ↩

  13. Building Microservices (file .zip, tải về giải nén) · ch.11 Microservices at Scale · mục "Scaling" › "Worker-Based Systems" (tr. 220–221). ↩

  14. Grokking Modern System Design · ch.17 Distributed Messaging Queue · bài "System Design: The Distributed Messaging Queue", mục "Motivation". ↩

  15. Grokking Modern System Design · ch.11 Content Delivery Network (CDN) · bài "System Design: Content Delivery Network (CDN)", mục "Problem statement"; bài "Introduction to a CDN", mục "Proposed solution". ↩

  16. Building Microservices (file .zip, tải về giải nén) · ch.7 Testing · mục "Separating Deployment from Release" (blue/green deployment) và "Canary Releasing" (tr. 148–150). ↩

  17. Building Microservices (file .zip, tải về giải nén) · ch.6 Deployment · mục "Custom Images" › "Immutable Servers" (tr. 113). ↩

  18. Grokking Modern System Design · ch.9 Databases · bài "Data Partitioning", mục "Why do we partition data?" và "Sharding". ↩

  19. Chưa có nguồn trong thư viện: thư viện không có sách về Kafka; chỉ nêu ý tưởng cơ bản, chi tiết ở bài Kafka. ↩

  20. Node.js Design Patterns 2e (file .zip, tải về giải nén) · ch.10 Scalability and Architectural Patterns · mục "The three dimensions of scalability" (tr. 388–390). ↩

  21. Grokking Modern System Design · ch.39 Spectacular Failures · các mục "Lessons learned" (Ready operations team) của bài Facebook và bài AWS Kinesis. ↩

  22. Chưa có nguồn trong thư viện: SLO, error budget và vai trò SRE không có sách trong thư viện; chỉ nêu như khái niệm vận hành cơ bản. ↩

  23. Grokking Modern System Design · ch.39 Spectacular Failures · bài "Facebook, WhatsApp, Instagram, Oculus Outage", mục "Analysis" và "Lessons learned". ↩

  24. Grokking Modern System Design · ch.39 Spectacular Failures · bài "AWS Kinesis Outage Affecting Many Organizations", mục "Sequence of events", "Analysis" và "Lessons learned" (Reducing number of servers). ↩

  25. Grokking Modern System Design · ch.4 Non-functional System Characteristics · bài "Availability", mục "Measuring availability", bảng "The Nines of Availability". ↩

  26. Building Microservices (file .zip, tải về giải nén) · ch.11 Microservices at Scale · mục "How Much Is Too Much?" (tr. 206–207). ↩