Cấu Hình, Giám Sát & Tối Ưu Cloud NAT
Tại Sao Cấu Hình Timeout Quan Trọng
Timeout trong Cloud NAT không chỉ là thông số "thử chỉnh xem sao". Mỗi giá trị timeout kiểm soát bao lâu Cloud NAT giữ một connection tracking entry sau khi connection đó kết thúc hoặc im lặng. Giá trị quá cao → port bị giữ lâu → pool cạn kiệt. Giá trị quá thấp → connection tracking entry bị xóa sớm → valid connections bị drop.
Hiểu từng loại timeout từ cơ chế giúp bạn chỉnh đúng mà không gây side effects.
Connection Timeout Mechanics
TCP Timeouts: Ba Trạng Thái Khác Nhau
Cloud NAT phân biệt ba trạng thái của TCP connection, mỗi cái có timeout riêng:
1. TCP Established Idle Timeout (tcp-established-idle-timeout)
Connection đang ở trạng thái ESTABLISHED nhưng không có packet nào trong thời gian này → Cloud NAT xóa tracking entry.
- Giá trị mặc định: 1.200 giây (20 phút)
- Phạm vi cấu hình: 300 giây đến 9.000 giây
- Tại sao dài: TCP connections có thể "ngủ" hợp lệ (idle database connection, long-polling HTTP connections, gRPC bidirectional streams). Xóa quá sớm gây drop connections đang active.
2. TCP Transitory Idle Timeout (tcp-transitory-idle-timeout)
Connection trong trạng thái half-open (SYN gửi nhưng chưa nhận SYN-ACK) hoặc kết nối vừa bắt đầu nhưng chưa complete handshake.
- Giá trị mặc định: 30 giây
- Phạm vi cấu hình: 10 giây đến 300 giây
- Tại sao ngắn: Nếu TCP handshake không hoàn thành sau 30 giây, nhiều khả năng destination unreachable hoặc bị block. Không cần giữ tracking entry lâu.
3. TCP TIME_WAIT Timeout (tcp-time-wait-timeout)
Connection đã fully closed (FIN/ACK exchange hoàn thành) nhưng Cloud NAT chưa cho phép tái sử dụng cùng 5-tuple.
- Giá trị mặc định: 120 giây (sẽ giảm xuống 30 giây từ tháng 9/2026 theo Google)
- Phạm vi cấu hình: 5 giây đến 120 giây
- Đây là giá trị quan trọng nhất để tune khi gặp port exhaustion từ short-lived connections
Tại Sao TCP TIME_WAIT Tồn Tại
TIME_WAIT là cơ chế bảo vệ từ TCP specification (RFC 793). Mục đích:
Ngăn "ghost packets": Packet cũ từ connection đã đóng có thể vẫn đang trên đường. Nếu cùng 5-tuple được reuse ngay lập tức, packet cũ có thể nhầm vào connection mới, gây corruption dữ liệu.
Đảm bảo phía kia nhận FIN/ACK: TCP TIME_WAIT ở phía active close (bên gửi FIN trước) đảm bảo rằng nếu final ACK bị mất và phía kia retransmit FIN, bên này vẫn có thể respond.
Trong kernel TCP stack, TIME_WAIT thường là 2× MSL (Maximum Segment Lifetime) = 2 × 60s = 120s. Cloud NAT default đồng bộ với giá trị này.
Khi nào có thể giảm TIME_WAIT:
- Application của bạn không sensitive với ghost packets (nhiều UDP-based hoặc idempotent HTTP APIs)
- Destination servers hỗ trợ TCP RST để clear half-open connections
- Bạn muốn aggressively reuse ports cho high-throughput scenarios
# Giảm TCP TIME_WAIT timeout:
gcloud compute routers nats update NAT_GATEWAY_NAME \
--router=ROUTER_NAME \
--region=REGION \
--tcp-time-wait-timeout=30s # safe minimum cho hầu hết workloads
# hoặc --tcp-time-wait-timeout=5s cho aggressive reuseUDP và ICMP Timeouts
UDP (udp-idle-timeout)
UDP không có connection state (connectionless protocol), nhưng Cloud NAT vẫn cần tracking để route return traffic. Tracking dựa trên "luồng UDP" — cùng source/destination 4-tuple.
- Mặc định: 30 giây sau khi không có UDP packet nào trong luồng
- Phạm vi: 30 giây đến 300 giây
- Với DNS queries (short-lived UDP): 30 giây là quá đủ
- Với VoIP hoặc game UDP streams (continuous but with gaps): có thể cần tăng lên 60–120 giây
ICMP (icmp-idle-timeout)
ICMP echo (ping) được track theo cặp request/response.
- Mặc định: 30 giây
- Phạm vi: 30 giây đến 300 giây
- Ít khi cần tune — ICMP thường không chiếm nhiều ports
Bảng Tổng Hợp Timeouts
| Loại | Mặc định | Min | Max | Khi Nào Tune |
|---|---|---|---|---|
| TCP Established Idle | 1.200s (20m) | 300s | 9.000s | Nếu có nhiều long-lived idle TCP connections |
| TCP Transitory | 30s | 10s | 300s | Hiếm khi cần tune |
| TCP TIME_WAIT | 120s | 5s | 120s | Khi gặp exhaustion từ short-lived connections |
| UDP | 30s | 30s | 300s | Nếu có UDP streams với gaps dài |
| ICMP | 30s | 30s | 300s | Không cần tune trong hầu hết cases |
NAT Rules: Phân Tách Traffic Theo Destination
Khi Nào Cần NAT Rules
Mặc định, tất cả traffic qua Cloud NAT đều dùng chung một pool NAT IPs. Điều này tạo ra risk: traffic volume lớn từ một loại workload có thể cạn kiệt port và ảnh hưởng các workloads quan trọng khác.
NAT Rules cho phép route traffic đến các destinations khác nhau qua các NAT IP pools khác nhau:
Không có NAT Rules:
Traffic đến payment.example.com ─┐
Traffic đến cdn.example.com ─┤─→ Shared NAT IP pool
Traffic đến logs.example.com ─┘
Với NAT Rules:
Traffic đến payment.example.com ─→ Dedicated IP pool (2 IPs, allowlisted)
Traffic đến cdn.example.com ─→ High-volume pool (5 IPs)
Traffic đến logs.example.com ─→ Default pool (remaining IPs)Cấu Trúc NAT Rule
Mỗi NAT rule có:
- Rule number: priority (1–65.000), thấp hơn = được evaluate trước
- Match condition: CEL expression xác định traffic nào áp dụng rule này
- Action: NAT IP pool nào dùng cho traffic này
# Tạo NAT rule cho payment gateway traffic:
gcloud compute routers nats rules create 1 \
--nat=NAT_GATEWAY_NAME \
--router=ROUTER_NAME \
--region=REGION \
--match="destination.ip == '203.0.113.1' || destination.ip == '203.0.113.2'" \
--source-nat-active-ips=projects/PROJECT/regions/REGION/addresses/payment-nat-ipMatch conditions hỗ trợ:
destination.ip == 'x.x.x.x'inIpRange(destination.ip, '203.0.113.0/24')destination.ip != 'x.x.x.x'- Kết hợp với
&&,||
Traffic không khớp bất kỳ rule nào sẽ đi qua default rule (dùng default NAT IP pool).
Use Case: Allowlisting Destination Với Fixed IPs
Một số third-party services (payment processors, compliance APIs) yêu cầu bạn allowlist source IPs phía họ. Điều này đòi hỏi traffic đến họ luôn xuất phát từ một set IP cố định, không phải bất kỳ IP nào trong auto-allocated pool.
# Reserve static IPs cho payment gateway:
gcloud compute addresses create payment-nat-ip-1 --region=REGION
gcloud compute addresses create payment-nat-ip-2 --region=REGION
# NAT Rule: traffic đến payment processor luôn dùng 2 IPs này:
gcloud compute routers nats rules create 100 \
--nat=GKE_NAT \
--router=GKE_ROUTER \
--region=REGION \
--match="inIpRange(destination.ip, '10.100.200.0/24')" \
--source-nat-active-ips=payment-nat-ip-1,payment-nat-ip-2Lợi ích: traffic thông thường có thể dùng auto-allocated IPs (dynamic), nhưng payment traffic luôn xuất phát từ 2 IPs cố định mà bạn đã allowlist với payment processor.
NAT Rules Kết Hợp Dynamic Port Allocation
DPA và NAT Rules hoạt động cùng nhau: mỗi NAT rule có pool IP riêng và DPA được áp dụng cho từng pool độc lập. Traffic "nặng" và traffic "quan trọng" cạnh tranh port trong pools khác nhau, không ảnh hưởng lẫn nhau.
Metrics Quan Trọng Cần Monitor
port_usage
compute.googleapis.com/nat/port_usageĐo số NAT source ports hiện tại đang được sử dụng bởi mỗi VM. Đây là metric quan trọng nhất để phát hiện nguy cơ exhaustion trước khi xảy ra.
Cách đọc:
- So sánh với
min-ports-per-vm(static) hoặcmax-ports-per-vm(dynamic) - Nếu nhiều VMs đang ở gần maximum → nguy cơ exhaustion
- Trend quan trọng hơn absolute value: nếu đang tăng dần → cần action
Alert recommendation:
# Alert khi bất kỳ VM nào dùng > 80% max allocation:
fetch gce_instance
| metric 'compute.googleapis.com/nat/port_usage'
| group_by 1m, [max_usage: max(value.port_usage)]
| every 1m
| condition max_usage > 3277 # 80% of 4096 maxdropped_sent_packets_count
compute.googleapis.com/nat/dropped_sent_packets_countSố packet bị drop khi cố gắng gửi qua Cloud NAT. Phân loại theo reason:
OUT_OF_RESOURCES: VM hết ports — đây là port exhaustionENDPOINT_INDEPENDENCE_CONFLICT: EIM conflict (chỉ khi EIM bật)NAT_ALLOCATION_FAILED: Không phân bổ được NAT IP cho VM
# Query drop rate theo reason:
fetch gce_instance
| metric 'compute.googleapis.com/nat/dropped_sent_packets_count'
| align rate(1m)
| every 1m
| group_by [metric.reason], [drop_rate: aggregate(value.dropped_sent_packets_count)]Alert recommendation: Bất kỳ drop OUT_OF_RESOURCES nào > 0/phút trong 5 phút liên tiếp → PagerDuty.
nat_allocation_failed
compute.googleapis.com/nat/nat_allocation_failedBinary metric: 0 = bình thường, 1 = Cloud NAT không thể phân bổ IP cho một hoặc nhiều VMs.
Đây là signal nghiêm trọng nhất — cần immediate response.
# Alert khi nat_allocation_failed > 0:
fetch nat_gateway
| metric 'compute.googleapis.com/nat/nat_allocation_failed'
| align next_older(1m)
| every 1m
| condition val() > 0sent_packets_count và received_packets_count
compute.googleapis.com/nat/sent_packets_count
compute.googleapis.com/nat/received_packets_countVolume metrics để baseline traffic pattern. Hữu ích để:
- Tính drop rate = drops / sent_packets (normalize theo traffic volume)
- Phát hiện traffic spikes bất thường
- Correlate với application metrics
Normalized Drop Rate
Absolute drop count không đủ context. Nếu bình thường gửi 1M packets/phút và drop 1.000 → 0.1% là có thể acceptable. Nếu chỉ gửi 10K packets/phút và drop 1.000 → 10% là thảm họa.
# MQL: Drop rate normalized theo traffic:
fetch nat_gateway
| { metric 'compute.googleapis.com/nat/dropped_sent_packets_count'
; metric 'compute.googleapis.com/nat/sent_packets_count' }
| align rate(1m)
| every 1m
| group_by [resource.gateway_name],
[drop_rate: (t_0 / (t_0 + t_1)) * 100]Cloud NAT Logging
Cơ Chế Logging
Cloud NAT có thể log từng connection translation — bao gồm cả successful translations và dropped connections. Log được ghi vào Cloud Logging.
Mỗi log entry chứa:
{
"connection": {
"src_ip": "10.0.0.5",
"src_port": 52340,
"dest_ip": "142.250.1.1",
"dest_port": 443,
"protocol": "TCP"
},
"endpoint": {
"vm_name": "gke-cluster-node-abc123",
"zone": "us-central1-a"
},
"gateway_identifiers": {
"gateway_name": "gke-nat",
"router_name": "gke-router",
"region": "us-central1"
},
"allocation_status": "OK", // hoặc "DROPPED"
"nat_ip": "34.100.200.50",
"nat_port": 44001
}Filter Levels và Cost Implications
NAT logging có thể rất expensive — đặc biệt với cluster GKE có traffic cao. Có ba filter options:
| Filter | Log gì | Chi phí tương đối |
|---|---|---|
ALL | Mọi translation (success + failed) | Rất cao |
TRANSLATIONS_ONLY | Chỉ successful translations | Cao |
ERRORS_ONLY | Chỉ failed/dropped | Thấp |
Recommendation production:
- Mặc định:
ERRORS_ONLY— đủ để debug exhaustion, chi phí thấp - Khi debug cụ thể: tạm thời chuyển sang
ALLcho 1 gateway và tắt sau khi xong - Không dùng
ALLliên tục cho high-traffic GKE clusters
# Cấu hình ERRORS_ONLY logging:
gcloud compute routers nats update NAT_GATEWAY_NAME \
--router=ROUTER_NAME \
--region=REGION \
--enable-logging \
--log-filter=ERRORS_ONLY
# Hoặc tắt logging:
gcloud compute routers nats update NAT_GATEWAY_NAME \
--router=ROUTER_NAME \
--region=REGION \
--no-enable-loggingQuery Logs Hữu Ích
Tìm top destinations bị drop:
resource.type="nat_gateway"
jsonPayload.allocation_status="DROPPED"Nhóm theo jsonPayload.connection.dest_ip và jsonPayload.connection.dest_port để xác định destination nào gây ra nhiều drop nhất.
Tìm VM nào bị drop nhiều nhất:
resource.type="nat_gateway"
jsonPayload.allocation_status="DROPPED"Nhóm theo jsonPayload.endpoint.vm_name.
Correlate với application logs: Timestamp từ NAT drop log có thể được correlate với application error logs trong cùng thời điểm để xác nhận causal relationship.
Connection Pooling và Keep-Alive Patterns
Tại Sao Connection Pooling Là Giải Pháp Dài Hạn
Mọi giải pháp "thêm NAT IP" hoặc "tăng port" chỉ là delay nếu root cause là application behavior tạo quá nhiều short-lived connections. Connection pooling giải quyết tận gốc.
Nguyên tắc: thay vì mở connection mới cho mỗi request, maintain một pool connections sẵn sàng tái sử dụng:
Không có pooling:
Request 1 → TCP connect → Send → TCP close → TIME_WAIT 120s
Request 2 → TCP connect → Send → TCP close → TIME_WAIT 120s
...
Request N → Out of ports (phantom shortage từ TIME_WAIT)
Với connection pool (10 connections):
Startup: mở 10 TCP connections, giữ ESTABLISHED
Request 1 → borrow connection từ pool → Send → return to pool
Request 2 → borrow connection từ pool → Send → return to pool
...
Request N → vẫn dùng 10 connections (không tăng port usage)HTTP/HTTPS: Keep-Alive và HTTP/2
Với HTTP/1.1: bật Connection: keep-alive header để reuse TCP connections. Với HTTP/2: multiplexing built-in — nhiều requests chia sẻ một TCP connection.
gRPC: mỗi gRPC channel là một HTTP/2 connection với multiplexing. Dùng một channel cho mỗi service, không tạo channel per-request.
Database Connection Pooling
Với PostgreSQL, MySQL: dùng pooler như PgBouncer (transaction mode) thay vì để application tự quản lý connections. Với Cloud SQL: Cloud SQL Auth Proxy tự handle connection pooling.
Không có pooler: 100 app instances × 10 connections = 1.000 database connections
Với PgBouncer: 100 app instances → PgBouncer → 20 database connections
→ Giảm 98% port usage phía database sideMột Ví Dụ Minh Họa: "Connection Spike" Do Health Check
Anti-pattern thực tế: Load balancer health checks. Nếu GKE service có nhiều replicas và mỗi replica nhận health check từ nhiều health check IPs với timeout ngắn (health check không dùng keep-alive), đây tạo ra hàng trăm short-lived TCP connections mỗi phút. Nhân với số replicas và số GKE nodes...
Giải pháp: cấu hình health check dùng keep-alive nếu protocol cho phép, hoặc tăng health check interval để giảm tần suất.
Checklist Operational Cloud NAT
Khi Tạo Cloud NAT Mới
- [ ] Xác định NAT scope:
--nat-all-subnet-ip-rangesnếu GKE VPC-native - [ ] Chọn port allocation mode: DPA cho hầu hết GKE workloads
- [ ] Cấu hình
min-ports-per-vmphù hợp (≥ 1.024 cho GKE nodes) - [ ] Cấu hình
tcp-time-wait-timeout=30s(baseline safe) - [ ] Bật logging với
ERRORS_ONLY - [ ] Tạo alerting policies cho
dropped_sent_packets_countvànat_allocation_failed
Khi Nghi Ngờ Port Exhaustion
- [ ] Kiểm tra
dropped_sent_packets_countmetric với breakdown theoreason - [ ] Kiểm tra
port_usageđể tìm VM nào đang ở near-max - [ ] Nếu bật logging: query logs tìm DROPPED entries và nhóm theo destination
- [ ] Kiểm tra
netstat -an | awk '{print $6}' | sort | uniq -ctrên VM bị nghi - [ ] Xác nhận
nat_allocation_failedđể biết IP-level hay port-level failure
Tuning Decision Tree
Có drop OUT_OF_RESOURCES không?
└─ Có:
├─ Dynamic Port Allocation đã bật chưa?
│ └─ Chưa: Bật DPA trước
├─ max-ports-per-vm đã ở mức reasonable?
│ └─ 512 hoặc thấp hơn: Tăng lên 4.096 hoặc 8.192
├─ tcp-time-wait-timeout = 120s?
│ └─ Có: Giảm xuống 30s
└─ Vẫn còn drop: Thêm NAT IP