Mở đầu — vì sao bài này quan trọng
Hãy tưởng tượng bạn vừa thuê một tòa nhà văn phòng lớn trong khu đô thị cloud. Bạn có thể dựng bàn ghế (máy chủ), lắp máy chủ cơ sở dữ liệu, chạy ứng dụng… nhưng nếu tòa nhà đó không có tường, không có cửa khóa, ai đi ngoài đường cũng bước thẳng vào phòng kế toán của bạn được, thì mọi thứ bên trong đều vô nghĩa. VPC (Virtual Private Cloud) chính là "bức tường và hệ thống cửa khóa" đó — nó là nền tảng mạng ảo mà gần như mọi thứ bạn triển khai trên cloud sẽ nằm bên trong.
Ở những bài trước, chúng ta đã nói về compute (máy ảo, container, serverless) và storage. Nhưng có một sự thật mà nhiều bạn mới học cloud hay bỏ qua: 90% các sự cố bảo mật và "sao ứng dụng không kết nối được database" đều bắt nguồn từ việc cấu hình mạng sai. Một EC2 instance không SSH vào được, một Lambda không gọi được RDS, một website không ra được Internet — tất cả đều là câu chuyện của VPC.
Bài này sẽ trang bị cho bạn tư duy nền tảng nhất về networking trong cloud: cách một mạng ảo được cô lập, cách chia nhỏ nó, cách định tuyến (routing) và kiểm soát luồng dữ liệu. Đây là kiến thức mà bất kỳ DevOps, backend engineer hay cloud architect nào cũng phải nắm chắc trước khi động tới những chủ đề phức tạp hơn như VPC Peering, Transit Gateway hay multi-region (các bài sau). Nắm vững VPC, bạn sẽ tự tin đọc được sơ đồ hạ tầng của bất kỳ hệ thống nào.
Khái niệm cốt lõi
VPC là gì?
VPC là một mạng ảo được cô lập logic dành riêng cho tài khoản cloud của bạn, chạy bên trong hạ tầng chung của nhà cung cấp (AWS, GCP, Azure). "Cô lập logic" nghĩa là dù máy chủ vật lý của bạn có thể nằm cùng một dàn server với hàng nghìn khách hàng khác, mạng của bạn hoàn toàn tách biệt — không ai nhìn thấy hay chạm được vào lưu lượng của bạn nếu bạn không cho phép.
Trên AWS nó tên là VPC, trên Google Cloud là VPC Network, trên Azure là Virtual Network (VNet). Tên khác nhau nhưng bản chất và các thành phần rất giống nhau.
CIDR block — dải địa chỉ IP của bạn
Khi tạo VPC, việc đầu tiên bạn làm là chọn một CIDR block — dải địa chỉ IP riêng tư mà toàn bộ tài nguyên trong VPC sẽ dùng. Ví dụ phổ biến nhất: 10.0.0.0/16.
Con số /16 gọi là "prefix length", cho biết bao nhiêu bit đầu là cố định. Với /16, bạn có 16 bit cố định và 16 bit còn lại tự do — tức khoảng 65.536 địa chỉ IP (từ 10.0.0.0 đến 10.0.255.255). Nhớ quy tắc đơn giản: số càng nhỏ (/16) thì mạng càng lớn; số càng lớn (/24) thì mạng càng nhỏ (256 địa chỉ).
Bạn nên dùng các dải IP riêng tư (private) theo chuẩn RFC 1918:
10.0.0.0/8172.16.0.0/12192.168.0.0/16
10.0.0.0/24 (chỉ 256 IP) cho VPC production vì nghĩ "chắc không bao giờ cần nhiều". Sáu tháng sau khi scale lên, họ hết IP, phải tạo VPC mới và migrate toàn bộ — mất gần 2 tuần. /16 là mặc định hợp lý cho hầu hết trường hợp.Subnet — chia nhỏ mạng thành các "khu"
Một VPC lớn được chia thành các subnet (mạng con) nhỏ hơn, mỗi subnet là một phần của CIDR tổng. Ví dụ với VPC 10.0.0.0/16, bạn có thể chia:
10.0.1.0/24— Public subnet (256 IP)10.0.2.0/24— Private subnet10.0.3.0/24— Database subnet
- Public subnet: subnet có đường ra Internet trực tiếp qua Internet Gateway (IGW). Đây là nơi đặt những tài nguyên cần "tiếp xúc" với thế giới bên ngoài: load balancer, bastion host, web server public.
- Private subnet: subnet KHÔNG có đường ra Internet trực tiếp. Đây là nơi đặt những thứ nhạy cảm: application server, database. Chúng vẫn có thể ra Internet để tải update thông qua NAT Gateway, nhưng Internet không thể chủ động gọi vào chúng.
ap-southeast-1a và một public subnet khác ở ap-southeast-1b (region Singapore, gần Việt Nam nhất). Chủ đề HA/Multi-AZ sẽ được đào sâu ở Bài 31, ở đây bạn chỉ cần hiểu subnet gắn chặt với AZ.Route Table — bản đồ định tuyến
Route Table trả lời câu hỏi: "Gói tin muốn đi đến đích X thì đi đường nào?". Mỗi subnet được gắn với một route table.
Ví dụ một route table đơn giản của public subnet:
| Destination | Target |
|---|---|
10.0.0.0/16 | local |
0.0.0.0/0 | igw-xxxx (Internet Gateway) |
0.0.0.0/0 (mọi địa chỉ khác) thì đẩy ra Internet Gateway. Chính dòng thứ hai này biến một subnet thành "public". Nếu private subnet, thay vì trỏ tới IGW, bạn trỏ 0.0.0.0/0 tới NAT Gateway.Internet Gateway và NAT Gateway
- Internet Gateway (IGW): cổng cho lưu lượng hai chiều giữa VPC và Internet. Gắn vào VPC. Có nó, tài nguyên trong public subnet mới ra/vào Internet được.
- NAT Gateway: cho phép tài nguyên trong private subnet chủ động ra Internet (ví dụ
apt update, gọi API bên ngoài) nhưng Internet không thể chủ động vào. NAT Gateway được đặt trong public subnet. Đây là cơ chế bảo vệ database và app server khỏi bị tấn công trực tiếp.
Security Group và Network ACL — hai lớp tường lửa
VPC có hai lớp kiểm soát luồng dữ liệu, và các bạn mới rất hay nhầm:
- Security Group (SG): tường lửa ở cấp instance (gắn vào từng máy ảo, ENI). Nó stateful — nghĩa là nếu bạn cho phép request vào, response đi ra tự động được phép, không cần khai báo. SG chỉ có luật "allow", không có luật "deny".
- Network ACL (NACL): tường lửa ở cấp subnet. Nó stateless — bạn phải khai báo cả chiều vào lẫn chiều ra. NACL có cả luật allow và deny.
Tình huống thực tế
Tình huống 1: Sàn TMĐT triển khai kiến trúc 3 tầng trên VPC
Một công ty thương mại điện tử giả định tên ChợViệt, doanh thu ~50 tỷ/năm, quyết định chuyển hệ thống lên AWS region Singapore (ap-southeast-1). Kiến trúc web 3 tầng của họ được thiết kế trên một VPC 10.0.0.0/16 như sau:
- Public subnet (
10.0.1.0/24,10.0.2.0/24ở 2 AZ): chứa Application Load Balancer và NAT Gateway. - Private subnet — App (
10.0.11.0/24,10.0.12.0/24): chứa các EC2 chạy backend Laravel. - Private subnet — DB (
10.0.21.0/24,10.0.22.0/24): chứa RDS MySQL.
Bài học rút ra: Bằng cách đặt database trong private subnet và ràng buộc Security Group theo tầng, ngay cả khi một hacker chiếm được một App server, họ vẫn không thể quét ra database từ bên ngoài, và database không bao giờ lộ ra Internet. Đây là mô hình chuẩn mực mà bạn nên thuộc nằm lòng.
Tình huống 2: Fintech và bài toán chồng lấn CIDR khi sáp nhập
Một công ty fintech tại Hà Nội mua lại một startup nhỏ hơn. Cả hai đều chạy trên AWS. Vấn đề: cả hai VPC đều chọn CIDR mặc định 10.0.0.0/16 — trùng nhau hoàn toàn. Khi đội kỹ thuật muốn kết nối hai hệ thống bằng VPC Peering để chia sẻ dữ liệu, họ nhận ra không thể làm được: khi hai VPC có dải IP chồng lấn, routing không thể phân biệt gói tin 10.0.1.5 là thuộc VPC nào.
Kết quả: đội bên bị mua phải quy hoạch lại toàn bộ mạng, đổi VPC sang 10.1.0.0/16, và migrate dần từng service trong 3 tuần với nhiều downtime ngoài giờ.
Bài học rút ra: Ngay từ ngày đầu, hãy quy hoạch dải CIDR ở cấp tổ chức. Ví dụ: production 10.0.0.0/16, staging 10.1.0.0/16, dev 10.2.0.0/16. Đừng để mỗi team tự chọn CIDR ngẫu nhiên. Việc chồng lấn CIDR là một trong những "nợ kỹ thuật" tốn kém nhất để sửa về sau. (Chủ đề Landing Zone & Account Strategy ở Bài 39 sẽ nói sâu hơn về quy hoạch này.)
Tình huống 3: "Vì sao Lambda của tôi timeout khi gọi database?"
Một kỹ sư backend ở Đà Nẵng viết một Lambda function để đọc dữ liệu từ RDS. Trên môi trường dev nó chạy tốt, nhưng khi gắn Lambda vào private subnet để truy cập RDS, function bắt đầu timeout mỗi khi gọi ra API thanh toán của bên thứ ba (VNPay).
Nguyên nhân: khi đưa Lambda vào private subnet, nó mất kết nối Internet mặc định. Route table của private subnet đó không có đường 0.0.0.0/0 trỏ tới NAT Gateway, nên mọi request ra Internet đều "rơi vào hư không" và timeout sau 30 giây.
Cách sửa: thêm một NAT Gateway ở public subnet, rồi cập nhật route table của private subnet để 0.0.0.0/0 → NAT Gateway. Lambda ngay lập tức gọi được VNPay.
Bài học rút ra: Private subnet không tự nhiên có Internet. Bất cứ khi nào một tài nguyên trong private subnet cần gọi ra ngoài (API bên thứ ba, tải package), bạn phải đi qua NAT Gateway. Khi debug lỗi kết nối, luôn kiểm tra route table trước tiên.
Hướng dẫn từng bước
Dưới đây là quy trình dựng một VPC chuẩn với public + private subnet (áp dụng tương tự cho AWS/GCP/Azure, ví dụ minh họa theo AWS):
- Tạo VPC với CIDR block
10.0.0.0/16. Ghi rõ tên và region (ví dụap-southeast-1Singapore).
- Tạo các subnet. Tạo ít nhất 2 public subnet ở 2 AZ khác nhau (
10.0.1.0/24,10.0.2.0/24) và 2 private subnet (10.0.11.0/24,10.0.12.0/24). Trải trên nhiều AZ để đảm bảo HA.
- Tạo Internet Gateway và attach vào VPC.
- Tạo NAT Gateway đặt trong một public subnet, cấp cho nó một Elastic IP.
- Cấu hình Route Table cho public subnet: thêm route
0.0.0.0/0 → Internet Gateway. Associate route table này với các public subnet.
- Cấu hình Route Table cho private subnet: thêm route
0.0.0.0/0 → NAT Gateway. Associate với các private subnet.
- Tạo Security Group theo nguyên tắc least privilege: chỉ mở đúng port cần thiết (443 cho web, 3306 cho MySQL từ App SG…). Không bao giờ mở
0.0.0.0/0cho port SSH (22) hay database.
- Kiểm thử: launch một EC2 test trong private subnet, thử
ping 8.8.8.8hoặccurl https://google.comđể xác nhận NAT hoạt động; thử kết nối từ App tới DB để xác nhận Security Group đúng.
Lỗi thường gặp & mẹo
- CIDR quá nhỏ / chồng lấn: như đã kể ở tình huống 2. Luôn quy hoạch CIDR cấp tổ chức và chọn
/16cho VPC production.
- Mở SSH/RDP ra
0.0.0.0/0: đây là lỗi bảo mật kinh điển. Bot quét Internet sẽ tìm thấy port 22 mở trong vài phút. Chỉ cho phép SSH từ IP văn phòng hoặc dùng bastion host / SSM Session Manager.
- Quên NAT Gateway cho private subnet: dẫn tới timeout khi gọi API ngoài (tình huống 3). Nhớ kiểm tra route table.
- Đặt database trong public subnet: tuyệt đối tránh. Database phải luôn ở private subnet.
- Nhầm lẫn Security Group (stateful) và NACL (stateless): với SG bạn chỉ cần khai báo chiều vào; với NACL phải khai báo cả vào lẫn ra, nếu quên chiều ra sẽ bị chặn response mà không hiểu vì sao.
- Mẹo chi phí: NAT Gateway tính phí theo giờ + theo GB dữ liệu đi qua, khá đắt (có thể vài chục USD/tháng mỗi cái). Với môi trường dev, cân nhắc dùng một NAT Gateway chung, hoặc VPC Endpoint để truy cập S3/DynamoDB mà không cần đi qua NAT (tiết kiệm đáng kể). Chủ đề Cost Management ở Bài 30.
- Mẹo đặt tên: đặt tên subnet rõ ràng theo chức năng và AZ, ví dụ
chợviệt-prod-public-1a,chợviệt-prod-db-1b. Sáu tháng sau bạn sẽ cảm ơn chính mình.
Bài tập thực hành
- Thiết kế trên giấy: Cho VPC
10.0.0.0/16. Hãy phân bổ CIDR cho: 2 public subnet, 2 private-app subnet, 2 private-db subnet (mỗi loại trải trên 2 AZ). Viết ra route table tương ứng cho mỗi nhóm subnet.
- Tính toán CIDR: Một subnet
/24chứa được bao nhiêu địa chỉ IP khả dụng? (Gợi ý: tổng 256, nhưng cloud provider thường "giữ lại" 5 địa chỉ). Nếu bạn cần một subnet chứa khoảng 500 host thì nên chọn prefix nào?
- Thực hành trên cloud (nếu có tài khoản free tier): Dựng một VPC với 1 public + 1 private subnet, 1 EC2 ở mỗi subnet. SSH vào EC2 public (bastion), từ đó SSH tiếp vào EC2 private. Xác nhận EC2 private ra được Internet qua NAT nhưng không nhận kết nối trực tiếp từ ngoài.
- Debug tình huống: Một App server trong private subnet không gọi được API bên ngoài. Hãy liệt kê theo thứ tự 4 thứ bạn sẽ kiểm tra để tìm nguyên nhân.
Tóm tắt
VPC là nền tảng mạng ảo cô lập nơi gần như mọi tài nguyên cloud của bạn cư trú. Những điểm cốt lõi cần nhớ:
- VPC = mạng ảo riêng tư, xác định bằng một CIDR block (ví dụ
10.0.0.0/16). Chọn dải đủ lớn và quy hoạch để tránh chồng lấn. - Subnet chia VPC thành các khu, mỗi subnet gắn với một AZ. Public subnet ra Internet qua Internet Gateway; private subnet ẩn khỏi Internet và ra ngoài (nếu cần) qua NAT Gateway.
- Route Table quyết định lưu lượng đi đâu — chính nó biến một subnet thành public hay private.
- Security Group (stateful, cấp instance) và Network ACL (stateless, cấp subnet) là hai lớp tường lửa. Áp dụng nguyên tắc least privilege.
- Mô hình chuẩn: đặt load balancer ở public subnet, app và database ở private subnet, ràng buộc Security Group theo từng tầng.