簡介
Cloud NAT (Network Address Translation) 是一款區域性、分散式、由軟體定義的代管服務,允許沒有外部 IP 位址的 Google Cloud 資源(包括 Compute Engine VM、私有 GKE 節點、Cloud Run for Anthos 工作負載、Serverless VPC Access 連接器)發起對外的網際網路連線,以及存取特定的 Google APIs。它只執行 Source NAT (SNAT) 與對應的回應轉譯;它從不接受未經請求的入站連線,這個特性讓它同時成為連線工具與縱深防禦邊界。Cloud NAT 實作於 Andromeda 網路虛擬化堆疊內、與您的 VM 位於同一台主機,因此資料平面完全分散,沒有 NAT VM、appliance、或單租戶閘道需要規劃容量、修補、或擴充。
一個 Cloud NAT 閘道必定屬於單一區域與單一 VPC 網路,您必須將它附加到該區域內的 Cloud Router。Cloud Router 並不為 Cloud NAT 執行 BGP;它儲存設定、對執行轉譯的 Andromeda 主機代理程式進行設定下發、並回報每台 VM 的連接埠保留情況。每個閘道可以服務該區域內所有或部分子網域,可以只為主要 IP 範圍或同時為主要與別名 IP 範圍設定 NAT,並可根據子網域堆疊類型承載 IPv4、IPv6 或 IPv4 加 NAT64 的流量。本章節將深入說明運作機制、IP 分配模式、連接埠行為、日誌、丟包原因、疑難排解流程與考試陷阱,足以應付 PCNE Cloud NAT 整段 blueprint。
Cloud NAT 運作機制(區域代管 NAT)
分散式資料平面(Andromeda)
Cloud NAT 不是一台閘道 VM,也不是 proxy。當私有 VM 將封包送往公開目的地時,VM 所在主機上的 Andromeda 虛擬交換器會將封包的 IPv4 來源從 VM 內部位址改寫為閘道擁有的其中一個 NAT IP、從該 VM 保留的範圍中挑選一個來源連接埠、並在主機端的連線表中記錄此 5-tuple。回程流量在同一台主機上反向翻譯。因為每台主機獨立翻譯,資料平面隨 VM 數量水平擴充,沒有中心瓶頸或單點故障。
Cloud Router 控制平面
您在目標區域建立 Cloud Router(例如 gcloud compute routers create nat-router --region=us-central1 --network=prod-vpc),再以 gcloud compute routers nats create 附加 NAT 閘道。Cloud Router 是設定錨點:告訴整個機隊哪些子網域可用、套用哪一種 IP 分配模式、連接埠分配參數為何、要套用哪些逾時設定。單一 Cloud Router 可承載多個 NAT 閘道,但這些閘道的子網域選擇不可重疊。
區域與每 VPC 範圍
位於 us-central1 的 Cloud NAT 閘道只服務該 VPC 中、主要內部 IP 屬於 us-central1 子網域的資源。它無法為其他區域、其他 VPC、對等互連 VPC、或透過 Cloud VPN/Cloud Interconnect 抵達的內部部署網路執行轉譯。多區域的私有工作負載因此需要每個區域各一個閘道。
Cloud NAT 是 Google 代管的區域 Source NAT 服務,將私有 Google Cloud 資源的內部 IPv4/IPv6 位址轉譯為附加在 Cloud Router 上的公用 NAT IP,提供對外網際網路出口,同時不讓該資源接受任何入站網際網路連線。
自動 vs 手動 IP 分配
自動分配 NAT IP
使用 --nat-external-ip-pool=auto 時,Google 會隨閘道連接埠需求增減自動配置與釋放外部 IPv4 位址。自動分配是最簡單的模式、無需操作者介入即可有效擴充,但 NAT IP 本身並不穩定:Google 可能輪換它們,您也無法將它們預先註冊到第三方 API 白名單、合作夥伴 SaaS、或要求固定來源 IP 白名單的銀行端點。
手動 IP 分配
使用 --nat-external-ip-pool=ADDRESS1,ADDRESS2,... 搭配已保留的靜態區域外部 IP,您可以明確指定 Cloud NAT 要使用哪些公用 IP 作為來源。當外部廠商要求 IP 白名單或來源 IP 稽核軌跡時,手動模式是必選的。代價是必須做容量規劃:每個手動 IP 最多支援 64,512 個來源連接埠(65,536 減去 1024 個保留的 well-known port),所以您必須保留足夠的位址以涵蓋尖峰並發流量除以每 VM 連接埠配額。
如何選擇
背景工作負載(拉套件、容器映像、公開資料集)來源 IP 無關緊要時用自動分配。對接金流、SWIFT/FIX 端點、有 IP 白名單的廠商 API、或法遵要求已知出口 IP 的場景,必須用手動分配。手動模式也適合在刪除並重建閘道後仍希望保有同一組 NAT IP 的情境,因為未保留的自動 IP 無法保證會再回來。
手動 NAT IP 分配透過 --nat-external-ip-pool 將特定保留的靜態外部位址綁定到閘道上。這是唯一能保證合作夥伴系統繼續接受您出口流量的方法;自動分配的 IP 可能被 Google 在無預警情況下輪換,絕不可用於需要法遵的對外連線。
動態連接埠分配(Dynamic Port Allocation, DPA)
靜態連接埠分配預設值
預設情況下,每台 VM 在每個 NAT IP 上會保留固定數量的來源連接埠。預設最低為每台 VM 64 個連接埠,且歷史上是靜態的:即使閘道有閒置連接埠,每台 VM 也只拿到設定的下限。靜態分配可預測,但對閒置 VM 浪費連接埠,又會把瞬間需要數千個並發連線的 chatty VM 餓死。
DPA 運作方式
動態連接埠分配(以 --enable-dynamic-port-allocation 搭配 --min-ports-per-vm 與 --max-ports-per-vm 啟用)讓 Cloud NAT 隨需求在最小與最大值之間調整每台 VM 的連接埠保留量。閒置時 64 個連接埠的 VM 可以在流量尖峰時暴增到例如 32,768 個,然後在活動下降後釋放。DPA 對於 crawler、ETL job、對外 webhook 等突發型工作負載,能顯著降低 OUT_OF_RESOURCES 丟包。
調校 Min 與 Max
最小值必須是介於 32 與 32,768 之間的 2 的次方;最大值必須是介於 64 與 65,536 之間的 2 的次方,且嚴格大於最小值。一個典型的生產調校是 --min-ports-per-vm=64 --max-ports-per-vm=32768,一般用途節點適用;對 fan-out 極大的主機(例如跑連線池吃緊服務的私有 GKE 節點)可將最大值提高到 65,536。
私有 GKE 叢集請啟用動態連接埠分配並把 --max-ports-per-vm 設為 65536。GKE 節點上跑很多 Pod,這些 Pod 共用節點的 NAT 連接埠保留量;單一 chatty Pod 就可能把節點預設的 64 個連接埠耗盡,觸發 OUT_OF_RESOURCES 丟包,對應用團隊來說看起來就是莫名其妙的網路不穩。
Endpoint-Independent Mapping (EIM)
預設:Endpoint-Dependent Mapping
預設情況下 Cloud NAT 使用 endpoint-dependent mapping:分配給流量的 (NAT IP, NAT port) 同時取決於來源與目的,所以同一台 VM 連往兩個不同目的地時,可能會從兩個不同的外部連接埠出去。這樣可以最大化連接埠重用,但會破壞依賴 UDP hole punching 或 STUN 型 NAT traversal 的協定,包含許多 WebRTC 與 VoIP 場景。
啟用 EIM
啟用 --enable-endpoint-independent-mapping 後,Cloud NAT 會為來自同一個內部 (VM IP, VM port) 的所有對外流量使用相同的 (NAT IP, NAT port),無論目的地為何。搭配 endpoint-independent filtering,這讓對等端可以透過 STUN 學到外部 mapping,再從不同的目的地端送封包進來——這正是 WebRTC NAT traversal 的基礎。
取捨
EIM 消耗更多連接埠,因為每個內部 (VM IP, VM port) 在 age out 之前都會永久占用一個外部 mapping,所以通常必須把 EIM 與動態連接埠分配以及較高的 --max-ports-per-vm 一起使用。EIM 只支援 UDP;TCP 不論此 flag 為何,永遠使用 endpoint-dependent mapping。
Endpoint-Independent Mapping 只對 UDP 有效。啟用 --enable-endpoint-independent-mapping 對 TCP 流量完全沒作用,所以聲稱 EIM「修好」某個 TCP 協定問題的說法,代表真正的根因另有其因。在指責或調整 EIM 前,先在 NAT 日誌中確認協定。
NAT 日誌與可觀測性
兩個獨立日誌流
Cloud NAT 將兩類日誌發布到 Cloud Logging,資源類型為 nat.googleapis.com/nat_gateway。Translation 日誌(TRANSLATIONS_ONLY)為每筆成功的新連線發出一筆記錄,包含來源 VM、目的、NAT IP、NAT 連接埠。Error 日誌(ERRORS_ONLY)在 Cloud NAT 丟棄連線時發出記錄,內含 vm_ip、endpoint 以及結構化丟包原因(例如 OUT_OF_RESOURCES)。ALL 同時啟用兩者;nat_logging 出於成本考量預設停用。
啟用日誌
使用 gcloud compute routers nats update NAT_NAME --router=ROUTER --region=REGION --enable-logging --log-filter=ALL,或指定 ERRORS_ONLY 只擷取失敗——後者能保持日誌量低,但仍可標出耗盡事件。日誌是計費的 Cloud Logging entries,所以高流量閘道通常從 ERRORS_ONLY 開始。
Cloud Monitoring 指標
Cloud NAT 暴露多個指標,包括 router.googleapis.com/nat/port_usage、nat/allocated_ports、nat/sent_bytes_count、nat/dropped_sent_packets_count、nat/new_connections_count。對 port_usage 接近閘道上限、以及任何非零的 dropped_sent_packets_count 且原因為 OUT_OF_RESOURCES 設警示。這些信號能在使用者察覺前就抓到連接埠耗盡。
丟包原因與 OUT_OF_RESOURCES
OUT_OF_RESOURCES
Cloud NAT 最常見的丟包原因是 OUT_OF_RESOURCES,意思是 VM 在當下的協定下已達當前已配置的連接埠上限,而 Cloud NAT 沒有更多連接埠可以擴展。修法為:調高 --min-ports-per-vm、以更高的 --max-ports-per-vm 啟用動態連接埠分配、新增更多 NAT IP 以擴大整個閘道的連接埠池、或縮短逾時讓關閉的 flow 更快釋放連接埠。
ENDPOINT_INDEPENDENT_CONFLICT
啟用 EIM 後,來自不同 VM 的兩個流量可能會嘗試為相同的內部連接埠取得相同的外部 (IP, port);Cloud NAT 會以 ENDPOINT_INDEPENDENT_CONFLICT 丟掉其中一個。新增更多 NAT IP 可降低碰撞機率。
其他原因
其他被記錄的丟包原因包括 NAT_ALLOCATION_FAILED(閘道完全配不到任何連接埠)以及流量超過 idle / established 逾時時的協定特定丟包。每筆丟包記錄都帶有犯規 VM 與目的,所以可直接對應到應用程式日誌。
OUT_OF_RESOURCES 是 Cloud NAT 標準的連接埠耗盡丟包原因。修復順序:啟用動態連接埠分配、調高 --max-ports-per-vm(上限 65,536)、新增更多 NAT IP(每個 IP 最多增加 64,512 個來源連接埠)、再縮短 --tcp-established-idle-timeout 與 --udp-idle-timeout。
逾時調校與連接埠保留
預設逾時
Cloud NAT 套用各協定的 idle 逾時:TCP established 1200 秒、TCP transitory 30 秒、TCP time-wait 120 秒、UDP 30 秒、ICMP 30 秒。連接埠在其 idle 逾時到期前都會為該 flow 保留;長逾時因此會把連接埠對短期突發工作負載鎖死。
何時縮短逾時
例如把 --tcp-established-idle-timeout 降到 600 秒,可讓長壽但低度使用的 TCP 連線釋放連接埠的速度快約一倍,在連接埠壓力大的閘道上可避開 OUT_OF_RESOURCES。不要把逾時設低於合法長連線(資料庫連線池、長壽 message broker 連線)的 keepalive 間隔,否則會切斷正常 session。
連接埠保留數學
閘道上可用的總連接埠 =(NAT IP 數量)× 64,512。每 VM 最小連接埠 = --min-ports-per-vm。閘道在下限時可服務的最大並發 VM 數 = 總連接埠 ÷ 每 VM 最小連接埠。例如 2 個 NAT IP、每 VM 最小 1024 個連接埠,可在下限時支援 2 × 64,512 ÷ 1024 = 126 台 VM;超過後在自動模式下會自動配置更多 IP,否則開始丟包。
IPv6 與 NAT64
Cloud NAT for IPv6
在雙堆疊與純 IPv6 子網域上,您可以使用 --nat64=ENABLED 或將閘道設為對 IPv6 prefix 進行 source 翻譯,附加 IPv6 模式的 Cloud NAT 閘道。原生 IPv6 端點因此可以像 IPv4 端點一樣透過代管 NAT 對外。
NAT64 翻譯
NAT64 讓純 IPv6 VM能存取公開網際網路上的純 IPv4 目的地。Cloud NAT 將 IPv6 來源翻譯為 IPv4 NAT IP,並將 IPv4 目的地嵌入 DNS64 給 VM 的 IPv6 prefix 中。這對仍需要消費傳統 IPv4 SaaS API 的純 IPv6 工作負載至關重要。
設定注意
NAT64 要求子網域堆疊類型包含 IPv6,且閘道要支援 IPv6。搭配 IPv6 版的 Private Google Access,您可以建構純 IPv6 的私有子網域,其 VM 可同時觸及 Google APIs(透過 PGA)與 IPv4 網際網路端點(透過 NAT64),完全不必持有外部 IPv6 位址。
NAT64 是唯一會改變 address family 的 Cloud NAT 翻譯類型。它將 IPv6 來源映射到 IPv4 NAT IP,讓純 IPv6 VM 能觸及純 IPv4 公開服務。請搭配 DNS64(由 Google 中繼資料解析器提供),讓只有 A record 的舊服務能以合成的 AAAA record 形式被存取。
Cloud Router 相依與設定
為何需要 Cloud Router
每個 Cloud NAT 閘道都附加在 Cloud Router 上,因為 Google 把 Router 當作可程式化的控制平面重用:它儲存閘道設定、把配置下發到 Andromeda 代理程式、並透過監控回報每 VM 的連接埠配置。即使 Cloud NAT 本身不需要 BGP session,Cloud Router 物件仍必須存在於同一區域與 VPC。
與其他服務共用 Router
單一 Cloud Router 可同時支援 Cloud NAT、Cloud VPN 的動態路由、Cloud Interconnect VLAN attachment 的 BGP session。共用可節省成本,但您必須以最嚴苛的租戶為基準調校 BGP keepalive 與 ASN。
常見 gcloud 模式
gcloud compute routers create prod-router \
--region=us-central1 --network=prod-vpc
gcloud compute addresses create prod-nat-ip-1 prod-nat-ip-2 \
--region=us-central1
gcloud compute routers nats create prod-nat \
--router=prod-router --region=us-central1 \
--nat-external-ip-pool=prod-nat-ip-1,prod-nat-ip-2 \
--nat-all-subnet-ip-ranges \
--enable-dynamic-port-allocation \
--min-ports-per-vm=64 --max-ports-per-vm=32768 \
--enable-logging --log-filter=ERRORS_ONLY
與 Private Google Access 整合
PGA 解決什麼
Private Google Access (PGA) 讓私有 VM 在沒有外部 IP、也不需要 Cloud NAT 的情況下存取 Google APIs 與服務(*.googleapis.com、gcr.io、storage.googleapis.com)。PGA 在子網域層級啟用(--enable-private-ip-google-access),透過將預設路由 0.0.0.0/0 指向 default-internet-gateway 並搭配 Google CIDR 的特殊私有路由處理,讓 API 流量走 Google 內部網路。
PGA 與 Cloud NAT 如何共存
同一子網域同時設定 PGA 與 Cloud NAT 時,要送往 Google APIs 的流量走 PGA 路徑(不做 NAT 翻譯、不消耗 NAT 連接埠),其他流量走 Cloud NAT。這種切分讓 Cloud NAT 閘道的連接埠預算保留給真正第三方網際網路流量,也減少了量大得多的 Google API 呼叫造成的翻譯成本。
Private Service Connect 替代方案
Private Service Connect endpoint 提供更緊密的替代方案:一個專案內的內部 IP 位址,能解析到 Google APIs 或合作夥伴服務,完全不必走網際網路。當您需要穩定的內部 IP 並為 Google APIs 提供每 VPC DNS 時用 PSC;只想要 Google API 出口而不希望花 NAT 連接埠時用 PGA。
任何同時承載私有 VM 與 Cloud NAT 出口路徑的子網域,都請啟用 Private Google Access。Google API 呼叫(Cloud Storage、Pub/Sub、BigQuery 客戶端函式庫、容器登錄拉取)就會完全繞過 NAT 閘道,把連接埠留給真正的第三方網際網路出口,順便縮減 NAT 日誌帳單。
Cloud NAT 在無伺服器與 GKE 的應用
私有 GKE 叢集
私有 GKE node pool 沒有外部 IP,任何可達網際網路的出口都依賴 Cloud NAT,例如從公開 registry 拉取映像(在未鏡像到 Artifact Registry 時)或呼叫第三方 API。從 NAT 角度每個節點就是一台 Compute Engine VM,所以 DPA 調校至關重要,因為單一節點可能託管數十個 Pod 共用該節點的連接埠預算。
Serverless VPC Access
Cloud Run、Cloud Functions、App Engine 透過 Serverless VPC Access 連接器接入 VPC。將出口設為 all-traffic 後可強制這些工作負載的對外流量走 VPC,此時 Cloud NAT 為連接器流量做翻譯。這是無伺服器呼叫需要固定來源 IP 的廠商 API 的標準模式。
Cloud Run 直接 VPC 出口
Cloud Run 直接 VPC 出口(無需連接器)將 Pod 直接掛入 VPC,並一樣使用 Cloud NAT 對外。手動 IP 分配在此可為廠商白名單釘上已知來源 IP。
考試重點與常見陷阱
陷阱:入站 NAT
Cloud NAT 只執行 Source NAT;從不接受入站連線。需要將公開存取導向私有後端時,請用外部 HTTP(S) Load Balancer、Network Load Balancer、或 Identity-Aware Proxy TCP tunneling。
陷阱:混合雲出口
透過 Cloud VPN 或 Cloud Interconnect 送往內部部署目的地的流量不會經過 Cloud NAT。Cloud NAT 只攔截 next hop 為 default-internet-gateway 的流量。混合雲出口的翻譯需求請在內部部署端設定,或使用廠商虛擬 appliance。
陷阱:子網域選擇
--nat-all-subnet-ip-ranges 涵蓋該 VPC 區域目前所有子網域,新增的子網域只在保留此 flag 時才會自動納入。改用 --nat-custom-subnet-ip-ranges 後,之後必須逐一列舉子網域,這是「新子網域沒有網路」工單常見的根因。
陷阱:每區域範圍
NAT 閘道絕不跨區域。多區域的私有工作負載需要每區域各一個 Cloud Router 與 Cloud NAT 閘道,各自擁有自己的 NAT IP 與連接埠預算。
白話文解釋
比喻一:高級公寓的大門櫃台
想像一棟保全嚴格的高級公寓。住戶(私有 VM)可以從大門走出去辦事(對外網際網路),門房(Cloud NAT)用公寓的地址(NAT IP)幫住戶簽出。當有東西寄回來時,門房只能交給原本送出該請求的住戶。陌生人從街上沒辦法叫門房幫他送到 7B 戶——他根本沒有方法主動接觸。這就是 Source NAT:公寓的單一街道地址替每位住戶的房號擋掉外界的目光,同時還是讓他們可以叫外送。
比喻二:飯店總機與分機線路
一棟 500 房的飯店只有一個對外電話號碼(NAT IP),卻只有 64,512 條對外幹線。當 312 房撥外線時,總機為該通電話保留一條幹線(NAT port)。靜態連接埠分配下,每個房間不論用不用都被永久指定 64 條幹線,於是會議房瞬間用完、空房卻把線路囤著。動態連接埠分配就是經理告訴總機「忙的人多給幹線、掛電話就收回來」。當需求超過全棟幹線你會聽到「線路忙線中」——這就是 OUT_OF_RESOURCES。修法不是再租一個對外電話號碼(增加 NAT IP),就是讓忙的房間借更多幹線(調高 --max-ports-per-vm)。
比喻三:信件轉送服務 vs 郵局信箱
Private Google Access 就像 Google 校園內部的專屬快遞路線:要寄信給 Cloud Storage 或 BigQuery 的 VM 把信交給內部快遞,那封信從未碰到公共郵政系統。Cloud NAT 是街角的一般郵局,處理離開校園的信件,並把回信地址蓋上 NAT IP。NAT64 則是櫃台後那位雙語譯員,把 IPv6 信件改寫成 IPv4 信封以便派送給老派收件人。把 Cloud Storage 請求送進郵局(Cloud NAT)能用,但會浪費郵票(NAT 連接埠);開啟 PGA 等於告訴 VM「凡是寄給 Google 的,請走快遞」。
常見問題 (FAQs)
Cloud NAT 會消耗 VM CPU 或頻寬嗎?
不會。翻譯發生在 Andromeda host networking 堆疊、VM 之外。沒有每 VM 的 CPU 或記憶體成本、沒有透過 NAT VM 的流量繞行,頻寬只受 VM 自身對外上限與閘道整體連接埠預算的限制。
可以把 Cloud NAT 用於私有 GKE 叢集嗎?
可以,而且是建議模式。私有 GKE 節點沒有外部 IP;Cloud NAT 讓它們能從公開 registry 拉取容器映像並呼叫第三方 API。請務必啟用動態連接埠分配並調高 --max-ports-per-vm,因為每個節點要把連接埠預算分給很多 Pod。
要怎麼讓出口 IP 固定,以便廠商加入白名單?
用手動 IP 分配。以 gcloud compute addresses create ... --region=REGION 保留一個或多個區域靜態外部 IPv4,然後用 --nat-external-ip-pool=ADDRESS_NAMES 附加。不要為加白名單的出口用自動分配,因為 Google 可能輪換自動分配的 IP。
Cloud NAT 與 Private Google Access 差別何在?
Cloud NAT 為任意外部目的地透過 Source NAT 提供一般網際網路出口。Private Google Access 透過 Google 內部網路直接存取 Google APIs(*.googleapis.com、Cloud Storage、BigQuery 等),不做翻譯、不消耗 NAT 連接埠。兩者可在同一子網域共存、服務互補的目的地。
為什麼只在尖峰時才看到 OUT_OF_RESOURCES 丟包?
尖峰把一個或多個 VM 推過當下已配置的連接埠上限。若用靜態分配,請調高 --min-ports-per-vm。若用動態連接埠分配,請調高 --max-ports-per-vm 讓 VM 能暴增更高,或新增更多 NAT IP 以擴大整個閘道的連接埠池。也請確認長 TCP idle 逾時是否把連接埠卡住。
Cloud NAT 能為透過 Cloud VPN 送往內部部署資料中心的流量做翻譯嗎?
不能。Cloud NAT 只翻譯路由 next hop 為 default-internet-gateway 的流量。透過 Cloud VPN 或 Cloud Interconnect 送往內部部署 CIDR 的流量完全繞過 Cloud NAT。混合流量若需要來源 IP 翻譯,請在內部部署端做。
啟用 Endpoint-Independent Mapping 會影響 TCP 效能嗎?
不會。EIM 只對 UDP 有效。不論 EIM flag 為何,Cloud NAT 中的 TCP 永遠使用 endpoint-dependent mapping。請僅在 WebRTC、STUN 等 UDP-based NAT-traversal 場景啟用 EIM。