NAT Gateway vs NAT Instance: Chọn Giải Pháp Nào Cho Private Subnet Trên AWS?
Bạn vừa dựng xong một private subnet, các EC2 instance bên trong cần tải bản cập nhật từ internet nhưng không được phép nhận kết nối từ bên ngoài vào — đây là bài toán NAT cổ điển trên AWS. Câu hỏi thực tế là: dùng NAT Gateway được quản lý hoàn toàn bởi AWS, hay tự vận hành một EC2 instance làm NAT? Câu trả lời không đơn giản là 'dùng cái nào rẻ hơn' — nó phụ thuộc vào yêu cầu vận hành, khả năng kiểm soát traffic, và ngân sách thực tế của bạn.
TL;DR — NAT Gateway vs NAT Instance
| Tiêu chí | NAT Gateway | NAT Instance |
|---|---|---|
| Quản lý hạ tầng | AWS quản lý hoàn toàn | Bạn tự quản lý EC2 |
| Tính sẵn sàng cao | Tích hợp sẵn trong một AZ | Phải tự thiết kế HA |
| Băng thông | Scale tự động (xem AWS docs) | Giới hạn bởi instance type |
| Security Group | Không áp dụng trực tiếp | Áp dụng đầy đủ |
| Port forwarding | Không hỗ trợ | Hỗ trợ qua iptables |
| Chi phí | Tính theo giờ + data processed | Tính theo EC2 instance type |
| Phù hợp nhất | Production workload, ít ops overhead | Chi phí thấp, cần tùy chỉnh sâu |
NAT Hoạt Động Như Thế Nào Trong VPC?
Khi một EC2 instance trong private subnet gửi request ra internet, nó không có public IP để nhận response về. NAT (Network Address Translation) giải quyết điều này bằng cách thay thế source IP của packet bằng một public IP, sau đó chuyển tiếp response về đúng instance gốc dựa trên bảng trạng thái kết nối.
Cả NAT Gateway lẫn NAT Instance đều phải nằm trong public subnet — tức là subnet có route đến Internet Gateway. Private subnet sau đó có route mặc định (0.0.0.0/0) trỏ đến NAT device này.
10.0.1.5"] -->|"0.0.0.0/0"| RouteTable["Route Table
Private Subnet"] RouteTable --> NATDev["NAT Device
Public Subnet"] NATDev -->|"Elastic IP"| IGW["Internet Gateway"] IGW --> Internet["Internet"] Internet -->|"Response"| IGW IGW --> NATDev NATDev -->|"Connection Table Lookup"| PrivInst
- Private Instance gửi packet ra ngoài — source IP là private IP (ví dụ 10.0.1.5).
- Route Table của Private Subnet có entry
0.0.0.0/0 → nat-device, packet được chuyển đến NAT device. - NAT Device (Gateway hoặc Instance) thay source IP bằng Elastic IP của nó, ghi nhớ mapping trong connection table.
- Internet Gateway chuyển packet ra internet với public IP.
- Response từ internet về đúng Elastic IP, NAT device tra bảng trạng thái và forward về đúng private instance.
NAT Gateway — Giải Pháp Managed Của AWS
NAT Gateway là dịch vụ được AWS quản lý hoàn toàn. Bạn tạo nó trong một public subnet, gán một Elastic IP, và cập nhật route table của private subnet. Không có EC2 instance nào để patch, không có SSH key nào để quản lý.
Tạo NAT Gateway bằng AWS CLI
Trước tiên cần có một Elastic IP allocation ID:
# Cấp phát Elastic IP
aws ec2 allocate-address \
--domain vpc \
--region us-east-1
# Tạo NAT Gateway trong public subnet
aws ec2 create-nat-gateway \
--subnet-id subnet-0abc123456789def0 \
--allocation-id eipalloc-0abc123456789def0 \
--region us-east-1
Sau khi NAT Gateway ở trạng thái available, cập nhật route table của private subnet:
# Thêm route mặc định trỏ đến NAT Gateway
aws ec2 create-route \
--route-table-id rtb-0abc123456789def0 \
--destination-cidr-block 0.0.0.0/0 \
--nat-gateway-id nat-0abc123456789def0 \
--region us-east-1
Kiểm tra trạng thái NAT Gateway
aws ec2 describe-nat-gateways \
--nat-gateway-ids nat-0abc123456789def0 \
--query 'NatGateways[0].{State:State,PublicIP:NatGatewayAddresses[0].PublicIp}' \
--region us-east-1
Điểm cần lưu ý với NAT Gateway
NAT Gateway là per-AZ resource. Nếu bạn có private subnet ở nhiều Availability Zone, bạn cần một NAT Gateway riêng cho từng AZ để tránh cross-AZ traffic và đảm bảo tính sẵn sàng. Đây là chi phí ẩn mà nhiều người bỏ qua khi so sánh với NAT Instance.
Nghĩ về NAT Gateway như một managed load balancer — bạn không cần lo về server bên dưới, nhưng bạn vẫn phải thiết kế đúng topology để tránh single point of failure ở tầng AZ.
NAT Instance — Tự Vận Hành EC2 Làm NAT
NAT Instance là một EC2 instance thông thường chạy AMI đặc biệt (hoặc bạn tự cấu hình IP forwarding và iptables), đặt trong public subnet, và hoạt động như một router cho private subnet. AWS từng cung cấp AMI amzn-ami-vpc-nat nhưng hiện tại khuyến nghị sử dụng NAT Gateway cho production. Bạn vẫn có thể tự cấu hình một Amazon Linux 2 instance làm NAT nếu có nhu cầu cụ thể.
Cấu hình EC2 Instance làm NAT
Bước quan trọng nhất thường bị bỏ qua: tắt Source/Destination Check trên instance. Mặc định, EC2 drop packet nếu source hoặc destination IP không phải của chính nó — đây chính xác là điều NAT cần làm, nên phải tắt check này đi.
# Tắt Source/Destination Check — bắt buộc cho NAT Instance
aws ec2 modify-instance-attribute \
--instance-id i-0abc123456789def0 \
--no-source-dest-check \
--region us-east-1
Sau đó, trên instance, bật IP forwarding và cấu hình iptables masquerade:
🔽 Click để xem cấu hình IP forwarding và iptables trên Amazon Linux 2
# Bật IP forwarding tạm thời
sudo sysctl -w net.ipv4.ip_forward=1
# Bật IP forwarding vĩnh viễn
echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.conf
# Cấu hình iptables MASQUERADE
# Thay eth0 bằng interface thực tế của instance
sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
# Lưu iptables rules để tồn tại qua reboot
sudo service iptables save
Cập nhật route table của private subnet trỏ đến instance ID (không phải ENI):
aws ec2 create-route \
--route-table-id rtb-0abc123456789def0 \
--destination-cidr-block 0.0.0.0/0 \
--instance-id i-0abc123456789def0 \
--region us-east-1
IAM Policy cho người quản trị NAT Instance
Nếu team của bạn cần quyền modify Source/Destination Check và quản lý route table, đây là policy tối thiểu cần thiết:
🔽 Click để xem IAM Policy mẫu
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ec2:ModifyInstanceAttribute",
"ec2:DescribeInstances"
],
"Resource": "arn:aws:ec2:us-east-1:123456789012:instance/i-0abc123456789def0"
},
{
"Effect": "Allow",
"Action": [
"ec2:CreateRoute",
"ec2:ReplaceRoute",
"ec2:DeleteRoute",
"ec2:DescribeRouteTables"
],
"Resource": "arn:aws:ec2:us-east-1:123456789012:route-table/rtb-0abc123456789def0"
}
]
}
So Sánh Chi Tiết: Khi Nào Dùng Cái Nào?
hoặc deep inspection?"} Q1 -->|"Không - Dev/Test"| Q3{"Chi phí là ưu tiên?"} Q2 -->|"Không"| NATGW["✅ NAT Gateway
Recommended"] Q2 -->|"Có"| NATI1["⚙️ NAT Instance
với iptables"] Q3 -->|"Có"| NATI2["⚙️ NAT Instance
t3.micro/small"] Q3 -->|"Không"| NATGW
Trường hợp nên dùng NAT Gateway
- Production workload cần uptime cao mà không muốn tự vận hành HA
- Team nhỏ, ít ops bandwidth để patch và monitor EC2
- Throughput cao và không thể bị giới hạn bởi instance type
- Compliance yêu cầu giảm thiểu attack surface — NAT Gateway không có SSH, không có OS để exploit
Trường hợp nên dùng NAT Instance
- Dev/test environment, chi phí là ưu tiên hàng đầu
- Cần port forwarding hoặc deep packet inspection — NAT Gateway không hỗ trợ
- Cần chạy thêm dịch vụ trên cùng instance (ví dụ: bastion host kiêm NAT)
- Cần kiểm soát hoàn toàn traffic log ở tầng OS
Bẫy Thực Tế: Khi NAT Instance Âm Thầm Gây Ra Sự Cố
Đây là pattern lỗi mình đã gặp nhiều lần: private instance không ra được internet, nhưng ping đến NAT instance từ private subnet thì thành công. CloudWatch không có gì bất thường. Log ứng dụng chỉ thấy connection timeout.
Chẩn đoán ban đầu thường là Security Group của NAT instance — kiểm tra inbound rule cho phép traffic từ private subnet CIDR, outbound rule cho phép ra internet. Mọi thứ trông ổn.
Nguyên nhân thực sự: Source/Destination Check vẫn đang bật. Instance nhận packet từ private subnet (source IP là 10.0.1.5), nhưng vì Source/Destination Check bật, nó drop packet ngay tại network layer trước khi iptables có cơ hội xử lý. Security Group không liên quan gì ở đây — đây là check ở tầng thấp hơn.
# Xác nhận Source/Destination Check đang ở trạng thái nào
aws ec2 describe-instances \
--instance-ids i-0abc123456789def0 \
--query 'Reservations[0].Instances[0].NetworkInterfaces[0].SourceDestCheck' \
--region us-east-1
# Kết quả phải là: false
# Nếu là true, chạy lệnh modify bên trên
Insight: Security Group là tầng kiểm soát truy cập, còn Source/Destination Check là tầng kiểm soát routing. Hai tầng này độc lập nhau — cả hai phải đúng thì NAT Instance mới hoạt động.
Kiến Trúc Multi-AZ Với NAT Gateway
Đây là điểm mà nhiều kiến trúc bị thiết kế sai ngay từ đầu. Một NAT Gateway duy nhất trong một AZ tạo ra single point of failure ở tầng AZ — nếu AZ đó có sự cố, toàn bộ private instance ở các AZ khác mất kết nối ra ngoài nếu route table của chúng trỏ về NAT Gateway đó.
Elastic IP A"] PrivA["Private Subnet A
Route: 0.0.0.0/0 → NATGW-A"] end subgraph AZB["Availability Zone B"] PubB["Public Subnet B"] NATGWB["NAT Gateway B
Elastic IP B"] PrivB["Private Subnet B
Route: 0.0.0.0/0 → NATGW-B"] end IGW["Internet Gateway"] Internet["Internet"] PubA --> NATGWA NATGWA --> IGW PubB --> NATGWB NATGWB --> IGW IGW --> Internet PrivA --> NATGWA PrivB --> NATGWB
- Mỗi AZ có NAT Gateway riêng trong public subnet tương ứng.
- Route table của private subnet trong AZ-A trỏ đến NAT Gateway trong AZ-A — không cross-AZ.
- Nếu AZ-A có sự cố, private subnet AZ-B vẫn hoạt động bình thường qua NAT Gateway của AZ-B.
- Cross-AZ traffic bị loại bỏ — giảm chi phí data transfer và giảm latency.
Giám Sát NAT Gateway Với CloudWatch
NAT Gateway tự động publish metrics lên CloudWatch. Các metric quan trọng cần theo dõi:
# Xem bytes processed qua NAT Gateway trong 1 giờ qua
aws cloudwatch get-metric-statistics \
--namespace AWS/NATGateway \
--metric-name BytesOutToDestination \
--dimensions Name=NatGatewayId,Value=nat-0abc123456789def0 \
--start-time $(date -u -d '1 hour ago' +%Y-%m-%dT%H:%M:%SZ) \
--end-time $(date -u +%Y-%m-%dT%H:%M:%SZ) \
--period 3600 \
--statistics Sum \
--region us-east-1
Với NAT Instance, bạn phải tự cấu hình monitoring — VPC Flow Logs là cách thực tế nhất để có visibility tương đương:
# Bật VPC Flow Logs cho subnet chứa NAT Instance
aws ec2 create-flow-logs \
--resource-type Subnet \
--resource-ids subnet-0abc123456789def0 \
--traffic-type ALL \
--log-destination-type cloud-watch-logs \
--log-group-name /vpc/nat-instance-flows \
--deliver-logs-permission-arn arn:aws:iam::123456789012:role/FlowLogsRole \
--region us-east-1
NAT Gateway vs NAT Instance — Kết Luận Và Bước Tiếp Theo
Với hầu hết production workload trên AWS, NAT Gateway là lựa chọn mặc định hợp lý — không phải vì nó rẻ hơn, mà vì nó loại bỏ một lớp vận hành mà team thường không có bandwidth để làm đúng. NAT Instance vẫn có chỗ đứng trong môi trường dev/test hoặc khi bạn cần tính năng mà NAT Gateway không cung cấp như port forwarding.
Dù chọn giải pháp nào, hãy thiết kế đúng topology multi-AZ ngay từ đầu — refactor route table sau khi production đang chạy tốn công hơn nhiều so với làm đúng từ lúc khởi tạo.
- Tham khảo: AWS VPC NAT Gateway Documentation
- Tham khảo: AWS VPC NAT Instance Documentation
- Bài liên quan: Thiết kế VPC multi-tier với public/private subnet trên AWS
- Bài liên quan: VPC Flow Logs — giám sát network traffic trong môi trường production
Glossary — Thuật Ngữ Chính
| Thuật ngữ | Giải thích |
|---|---|
| NAT (Network Address Translation) | Kỹ thuật thay thế địa chỉ IP trong packet header, cho phép nhiều thiết bị dùng chung một public IP. |
| Elastic IP | Địa chỉ IPv4 tĩnh do AWS cấp phát, gắn với tài khoản cho đến khi bạn release — không thay đổi khi instance restart. |
| Source/Destination Check | Cơ chế mặc định của EC2 drop packet nếu instance không phải source hoặc destination thực sự — phải tắt khi dùng NAT Instance. |
| Internet Gateway (IGW) | Thành phần VPC cho phép traffic giữa VPC và internet — NAT device phải nằm trong subnet có route đến IGW. |
| VPC Flow Logs | Tính năng capture metadata của IP traffic đến/đi từ network interface trong VPC, lưu vào CloudWatch Logs hoặc S3. |
Nhận xét
Đăng nhận xét