使用 Cloud NAT 動態通訊埠分配

1. 總覽

動態通訊埠分配 (DPA) 是 Cloud NAT 的新功能。啟用 DPA 後,Cloud NAT 就能根據執行個體需求,動態擴充/縮減執行個體的通訊埠分配情形。DPA 設有通訊埠的下限與上限,因此絕對不會縮減通訊埠數量低於下限,或向上擴充至上限。這可讓 NAT 閘道背後的部分執行個體動態擴充連線數量,而不必將更多通訊埠分配給 Cloud NAT 後方的所有執行個體。

如果沒有 DPA,系統會根據 minPortsPerVm 參數的定義,為 Cloud NAT 後方的所有執行個體分配相同數量的通訊埠。

詳情請參閱 NAT DPA 的說明文件

課程內容

  • 如何設定 Cloud NAT 閘道,為 DPA 做好準備。
  • 如何在沒有 DPA 的情況下檢查通訊埠分配。
  • 如何為 NAT 閘道啟用及設定 DPA。
  • 如何透過執行平行輸出連線來觀察 DPA 的影響。
  • 如何將網路位址轉譯 (NAT) 規則新增至已啟用 DPA 的 NAT 閘道。
  • 如何透過執行輸出連線至多個目的地,利用規則查看 DPA 的行為。

軟硬體需求

  • Google Compute Engine 的基本知識
  • 基本的網路和 TCP/IP 知識
  • 基本的 Unix/Linux 指令列知識
  • 建議您先完成 Google Cloud 網路導覽,例如 Networking in Google Cloud 研究室。
  • 具有「Alpha 版存取權」的 Google Cloud 專案
  • 瞭解 Cloud NAT 基本概念

2. 使用 Google Cloud 控制台和 Cloud Shell

本研究室中會同時使用 Google Cloud 控制台和 Cloud Shell,以便與 GCP 互動。

Google Cloud Console

如要前往 Cloud 控制台,請前往 https://console.cloud.google.com

75eef5f6fd6d7e41.png

自修環境設定

  1. 登入 Google Cloud 控制台,建立新專案或重複使用現有專案。如果您還沒有 Gmail 或 Google Workspace 帳戶,請先建立帳戶

96a9c957bc475304.png

b9a10ebdf5b5a448.png

a1e3c01a38fa61c2.png

  • 「專案名稱」是這項專案參與者的顯示名稱。這是 Google API 不使用的字元字串,您可以隨時更新。
  • 所有 Google Cloud 專案的專案 ID 均不得重複,且設定後即無法變更。Cloud 控制台會自動產生一個不重複的字串。但通常是在乎它何在在大部分的程式碼研究室中,您必須參照專案 ID (通常稱為 PROJECT_ID),因此如果您不喜歡的話,請隨機產生一個,或者,您也可以自行嘗試看看是否可用。是「凍結」建立專案後
  • 還有第三個值,也就是部分 API 使用的專案編號。如要進一步瞭解這三個值,請參閱說明文件
  1. 接下來,您需要在 Cloud 控制台中啟用計費功能,才能使用 Cloud 資源/API。執行這個程式碼研究室並不會產生任何費用,如果有的話。如要關閉資源,以免產生本教學課程結束後產生的費用,請按照任「清除所用資源」操作請參閱本程式碼研究室結尾處的操作說明。Google Cloud 的新使用者符合 $300 美元免費試用計畫的資格。

啟動 Cloud Shell

雖然 Google Cloud 可以從筆記型電腦遠端操作,但在本程式碼研究室中,您將使用 Google Cloud Shell,這是一種在 Cloud 中執行的指令列環境。

在 GCP 控制台的右上方,按一下「Cloud Shell」圖示:

bce75f34b2c53987.png

佈建並連線至環境的作業只需幾分鐘的時間。完成後,您應該會看到類似下方的內容:

f6ef2b5f13479f3a.png

這部虛擬機器都裝載了您需要的所有開發工具。提供永久的 5 GB 主目錄,而且在 Google Cloud 中運作,大幅提高網路效能和驗證能力。這個研究室中的所有工作都可以透過瀏覽器完成。

3. 設定研究室

在這個研究室中,您將使用專案,並在每個專案中建立兩個有子網路的虛擬私有雲。您將保留外部 IP 位址,然後建立並設定 Cloud NAT 閘道 (有 Cloud Router)、兩個生產端執行個體和兩個用戶端執行個體。驗證預設 Cloud NAT 行為後,即可啟用動態通訊埠分配功能並驗證其行為。最後,您將設定網路位址轉譯 (NAT) 規則,並觀察 DPA 和 NAT 規則之間的互動。

網路架構總覽:

a21caa6c333909d8.png

4. 保留外部 IP 位址

保留在這個研究室中使用的所有外部 IP 位址。這有助於您在消費者和生產端的虛擬私有雲中,編寫所有相關 NAT 和防火牆規則。

透過 Cloud Shell:

gcloud compute addresses  create nat-address-1 nat-address-2 \
 producer-address-1 producer-address-2 --region us-east4

輸出:

Created [https://www.googleapis.com/compute/v1/projects/<Project ID>/regions/us-east4/addresses/nat-address-1].
Created [https://www.googleapis.com/compute/v1/projects/<Project ID>/regions/us-east4/addresses/nat-address-2].
Created [https://www.googleapis.com/compute/v1/projects/<Project ID>/regions/us-east4/addresses/producer-address-1].
Created [https://www.googleapis.com/compute/v1/projects/<Project ID>/regions/us-east4/addresses/producer-address-2].

填入保留為環境變數的 IP 位址。

export natip1=`gcloud compute addresses list --filter name:nat-address-1 --format="get(address)"`
export natip2=`gcloud compute addresses list --filter name:nat-address-2 --format="get(address)"`
export producerip1=`gcloud compute addresses list --filter name:producer-address-1 --format="get(address)"`
export producerip2=`gcloud compute addresses list --filter name:producer-address-2 --format="get(address)"`

預期不會有任何輸出內容,但為了確認地址填入正確,讓我們輸出所有環境變數的值。

env | egrep '^(nat|producer)ip[1-3]'

輸出:

producerip1=<Actual Producer IP 1>
producerip2=<Actual Producer IP 2>
natip1=<NAT IP 1>
natip2=<NAT IP 2>

5. 生產端虛擬私有雲與執行個體設定。

現在要為生產端資源建立資源。在生產端虛擬私有雲中運作的執行個體將使用兩個公開 IP「Producer-address-1」,提供面向網際網路的服務和「Producer-address-2」,直接在 Google Cloud 控制台實際操作。

首先來建立虛擬私有雲透過 Cloud Shell:

gcloud compute networks create producer-vpc --subnet-mode custom

輸出:

Created [https://www.googleapis.com/compute/v1/projects/<Project-ID>/global/networks/producer-vpc].
NAME      SUBNET_MODE  BGP_ROUTING_MODE  IPV4_RANGE  GATEWAY_IPV4
producer-vpc  CUSTOM       REGIONAL

Instances on this network will not be reachable until firewall rules
are created. As an example, you can allow all internal traffic between
instances as well as SSH, RDP, and ICMP by running:

$ gcloud compute firewall-rules create <FIREWALL_NAME> --network producer-vpc --allow tcp,udp,icmp --source-ranges <IP_RANGE>
$ gcloud compute firewall-rules create <FIREWALL_NAME> --network producer-vpc --allow tcp:22,tcp:3389,icmp

接著在 us-east4 中建立子網路透過 Cloud Shell:

gcloud compute networks subnets create prod-net-e4 \
   --network producer-vpc --range 10.0.0.0/24 --region us-east4

輸出:

Created [https://www.googleapis.com/compute/v1/projects/<Project ID>/regions/us-east4/subnetworks/prod-net-e4].
NAME         REGION    NETWORK       RANGE        STACK_TYPE  IPV6_ACCESS_TYPE  IPV6_CIDR_RANGE  EXTERNAL_IPV6_CIDR_RANGE
prod-net-e4  us-east4  producer-vpc  10.0.0.0/24  IPV4_ONLY

接著,請建立虛擬私有雲防火牆規則,允許網路位址轉譯 (NAT) IP 位址連上通訊埠 8080 的生產端執行個體。

透過 Cloud Shell 建立第一項規則:

gcloud compute firewall-rules create producer-allow-80 \
  --network producer-vpc --allow tcp:80 \
  --source-ranges $natip1,$natip2

輸出:

Creating firewall...⠹Created [https://www.googleapis.com/compute/v1/projects/<Project ID>/global/firewalls/producer-allow-80].
Creating firewall...done.
NAME                 NETWORK       DIRECTION  PRIORITY  ALLOW     DENY  DISABLED
producer-allow-80    producer-vpc  INGRESS    1000      tcp:80          False

接著要建立兩個生產端執行個體。

生產端執行個體會執行簡單的 nginx Proxy 部署作業。

為了快速佈建所有必要軟體的執行個體,我們將建立具有開機指令碼的執行個體,以使用 Debian APT 套件管理員安裝 nginx。

為了能夠寫入網路位址轉譯 (NAT) 規則,我們會以不同的保留 IP 位址佈建每個執行個體。

建立第一個執行個體。透過 Cloud Shell:

gcloud compute instances create producer-instance-1 \
--zone=us-east4-a --machine-type=e2-medium \
--network-interface=address=producer-address-1,network-tier=PREMIUM,subnet=prod-net-e4 \
--metadata startup-script="#! /bin/bash
sudo apt update
sudo apt install -y nginx
mkdir /var/www/html/nginx/
cat <<EOF > /var/www/html/nginx/index.html
<html><body><h1>This is producer instance 1</h1>
</body></html>
EOF"

輸出:

Created [https://www.googleapis.com/compute/v1/projects/<Project ID>/zones/us-east4-a/instances/producer-instance-1].
NAME                 ZONE        MACHINE_TYPE  PREEMPTIBLE  INTERNAL_IP  EXTERNAL_IP    STATUS
producer-instance-1  us-east4-a  e2-medium                  10.0.0.2     <Producer IP1>  RUNNING

接著建立第二個執行個體。透過 Cloud Shell:

gcloud compute instances create producer-instance-2 \
--zone=us-east4-a --machine-type=e2-medium \
--network-interface=address=producer-address-2,network-tier=PREMIUM,subnet=prod-net-e4 \
--metadata startup-script="#! /bin/bash
sudo apt update
sudo apt install -y nginx
mkdir /var/www/html/nginx/
cat <<EOF > /var/www/html/nginx/index.html
<html><body><h1>This is producer instance 2</h1>
</body></html>
EOF"

輸出:

Created [https://www.googleapis.com/compute/v1/projects/<Project ID>/zones/us-east4-a/instances/producer-instance-2].
NAME                 ZONE        MACHINE_TYPE  PREEMPTIBLE  INTERNAL_IP  EXTERNAL_IP    STATUS
producer-instance-2  us-east4-a  e2-medium                  10.0.0.3     <Producer IP2>  RUNNING

6. 設定用戶端虛擬私有雲、Cloud NAT 和執行個體

您已成功建立生產端服務,接著要建立消費者虛擬私有雲及其 Cloud NAT 閘道。

建立虛擬私有雲和子網路後,我們會新增簡單的輸入防火牆規則,允許 TCP 來源 IP 範圍的 IAP。這樣一來,我們就能直接使用 gcloud 透過 SSH 連線至用戶端執行個體。

接著,我們會在手動分配模式下建立簡易的 Cloud NAT 閘道,以及保留的位址「nat-address-1」相關聯的資源在程式碼研究室的後續部分中,我們會更新閘道設定,以啟用動態通訊埠分配功能,並在之後新增自訂規則。

首先來建立虛擬私有雲透過 Cloud Shell:

gcloud compute networks create consumer-vpc --subnet-mode custom

輸出:

Created [https://www.googleapis.com/compute/v1/projects/<Project ID>/global/networks/consumer-vpc].
NAME          SUBNET_MODE  BGP_ROUTING_MODE  IPV4_RANGE  GATEWAY_IPV4
consumer-vpc  CUSTOM       REGIONAL

Instances on this network will not be reachable until firewall rules
are created. As an example, you can allow all internal traffic between
instances as well as SSH, RDP, and ICMP by running:

$ gcloud compute firewall-rules create <FIREWALL_NAME> --network consumer-vpc --allow tcp,udp,icmp --source-ranges <IP_RANGE>
$ gcloud compute firewall-rules create <FIREWALL_NAME> --network consumer-vpc --allow tcp:22,tcp:3389,icmp

接著在 us-east4 中建立子網路透過 Cloud Shell:

gcloud compute networks subnets create cons-net-e4 \
   --network consumer-vpc --range 10.0.0.0/24 --region us-east4

輸出:

Created [https://www.googleapis.com/compute/v1/projects/<Project ID>/regions/us-east4/subnetworks/cons-net-e4].
NAME         REGION    NETWORK       RANGE        STACK_TYPE  IPV6_ACCESS_TYPE  IPV6_CIDR_RANGE  EXTERNAL_IPV6_CIDR_RANGE
cons-net-e4  us-east4  consumer-vpc  10.0.0.0/24  IPV4_ONLY

接著,請建立虛擬私有雲防火牆規則,允許 IAP 範圍位址傳送至通訊埠 22 的用戶執行個體。

針對第一個防火牆規則,從 Cloud Shell 執行下列指令:

gcloud compute firewall-rules create consumer-allow-iap \
  --network consumer-vpc --allow tcp:22 \
  --source-ranges 35.235.240.0/20

輸出:

Creating firewall...⠹Created [https://www.googleapis.com/compute/v1/projects/<Project-ID>/global/firewalls/consumer-allow-iap].
Creating firewall...done.
NAME                 NETWORK       DIRECTION  PRIORITY  ALLOW     DENY  DISABLED
consumer-allow-iap  consumer-vpc  INGRESS    1000      tcp:22        False

在建立 NAT 閘道之前,我們必須先建立 Cloud Router 執行個體 (我們會使用私人 ASN 編號,但與這個研究室的活動無關)。透過 Cloud Shell:

gcloud compute routers create consumer-cr \
--region=us-east4 --network=consumer-vpc \
 --asn=65501

輸出:

Creating router [consumer-cr]...done.
NAME         REGION       NETWORK
consumer-cr  us-east4  consumer-vpc

接著建立 NAT 閘道執行個體。透過 Cloud Shell:

gcloud compute routers nats create consumer-nat-gw \
    --router=consumer-cr \
    --router-region=us-east4 \
    --nat-all-subnet-ip-ranges \
    --nat-external-ip-pool=nat-address-1

輸出:

Creating NAT [consumer-nat-gw] in router [consumer-cr]...done.

請注意,系統會預設建立 Cloud NAT 閘道,並將 minPortsPerVm 設為 64

建立用戶測試執行個體。我們會在這裡填入預留生產端 IP,方便之後在執行個體中參照這些 IP。透過 Cloud Shell:

gcloud compute instances create consumer-instance-1 --zone=us-east4-a \
--machine-type=e2-medium --network-interface=subnet=cons-net-e4,no-address \
--metadata=producer-service-ip1=$producerip1,producer-service-ip2=$producerip2

gcloud compute instances create consumer-instance-2 --zone=us-east4-a \
--machine-type=e2-medium --network-interface=subnet=cons-net-e4,no-address \
--metadata=producer-service-ip1=$producerip1,producer-service-ip2=$producerip2

輸出:

Created [https://www.googleapis.com/compute/v1/projects/<Project ID>/zones/us-east4-a/instances/consumer-instance-1].
NAME                ZONE        MACHINE_TYPE  PREEMPTIBLE  INTERNAL_IP  EXTERNAL_IP  STATUS
consumer-instance-1  us-east4-a  e2-medium                  10.0.0.2                  RUNNING

Created [https://www.googleapis.com/compute/v1/projects/<Project ID>/zones/us-east4-a/instances/consumer-instance-2].
NAME                ZONE        MACHINE_TYPE  PREEMPTIBLE  INTERNAL_IP  EXTERNAL_IP  STATUS
consumer-instance-2  us-east4-a  e2-medium                  10.0.0.3                  RUNNING

7. 驗證預設的 Cloud NAT 行為

此時,取用端執行個體會使用預設的 Cloud NAT 行為,這個行為使用相同的預留 IP「nat-address-1」可用來與所有外部位址通訊Cloud NAT 也尚未啟用 DPA。

讓我們執行下列指令,驗證 Cloud NAT 已配置用戶端執行個體的通訊埠

gcloud  compute routers get-nat-mapping-info consumer-cr --region=us-east4

輸出內容範例

---
instanceName: consumer-instance-1
interfaceNatMappings:
- natIpPortRanges:
  - <NAT Consumer IP1>:1024-1055
  numTotalDrainNatPorts: 0
  numTotalNatPorts: 32
  sourceAliasIpRange: ''
  sourceVirtualIp: 10.0.0.2
- natIpPortRanges:
  - <NAT Consumer IP1>:32768-32799
  numTotalDrainNatPorts: 0
  numTotalNatPorts: 32
  sourceAliasIpRange: ''
  sourceVirtualIp: 10.0.0.2
---
instanceName: consumer-instance-2
interfaceNatMappings:
- natIpPortRanges:
  - <NAT Address IP1>:1056-1087
  numTotalDrainNatPorts: 0
  numTotalNatPorts: 32
  sourceAliasIpRange: ''
  sourceVirtualIp: 10.0.0.3
- natIpPortRanges:
  - <NAT Address IP1>:32800-32831
  numTotalDrainNatPorts: 0
  numTotalNatPorts: 32
  sourceAliasIpRange: ''
  sourceVirtualIp: 10.0.0.3

從上述輸出內容中可以看出,Cloud NAT 已為每個執行個體分配 64 個通訊埠,該通訊埠來自同一個外部 IP「nat-address-1

讓我們驗證在啟用 DPA 之前可以同時開啟的連線數量。

透過 SSH 登入第一個取用端執行個體。透過 Cloud Shell:

gcloud compute ssh consumer-instance-1 --zone=us-east4-a

您現在應該位於執行個體殼層。

輸出內容範例 (為求簡潔,完整輸出內容會截斷)

External IP address was not found; defaulting to using IAP tunneling.
...
...
<username>@consumer-instance-1:~$

在取用端執行個體中,先擷取兩個生產端 IP,並填入這些 IP 做為環境變數

export producerip1=`curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/producer-service-ip1" -H "Metadata-Flavor: Google"`

export producerip2=`curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/producer-service-ip2" -H "Metadata-Flavor: Google"`

接著嘗試對兩個生產端執行個體執行 curl 指令,確認可以成功連線。

<username>@consumer-instance-1:~$ curl http://$producerip1/nginx/
<html><body><h1>This is producer instance 1</h1>
</body></html>
<username>@consumer-instance-1:~$ curl http://$producerip2/nginx/
<html><body><h1>This is producer instance 2</h1>
</body></html>

現在,透過迴圈執行 curl,嘗試與其中一個生產端執行個體建立多個平行連線。提醒您,Cloud NAT 不允許在 2 分鐘內重複使用封閉通訊端。因此,只要能在 2 分鐘內反覆嘗試所有連線,我們就能以這種方式模擬平行連線。

在執行個體 SSH 工作階段中執行下列指令

while true; do for i in {1..64}; do curl -s -o /dev/null --connect-timeout 5 http://$producerip1/nginx/; if [ $? -ne 0 ] ; then echo -e "\nConnection # $i failed" ; else echo -en "\rConnection # $i successful"; fi; done; echo -e "\nLoop Done, Sleeping for 150s"; sleep 150; done

您應該可以順利開啟 64 個並行連線,指令碼應會顯示以下內容

Connection # 64 successful

Loop Done, Sleeping for 150s
Connection # 64 successful

Loop Done, Sleeping for 150s

要瞭解我們是否能超過 64 個平行連線,請先等待 2 分鐘,讓系統完全清除舊的通訊端。接著,將相同的單行程式碼調整成以下內容,然後重新執行

while true; do for i in {1..70}; do curl -s -o /dev/null --connect-timeout 5 http://$producerip1/nginx/; if [ $? -ne 0 ] ; then echo -e "\nConnection # $i failed" ; else echo -en "\rConnection # $i successful"; fi; done; echo -e "\nLoop Done, Sleeping for 150s"; sleep 150; done

您應該會看到以下輸出內容

Connection # 64 successful
Connection # 65 failed
Connection # 66 failed
Connection # 67 failed
Connection # 68 failed
Connection # 69 failed
Connection # 70 failed

Loop Done, Sleeping for 150s

這表示雖然前 64 個連線成功,但另外 6 個連線因通訊埠無法使用而失敗。

然後執行操作,結束 SSH 殼層,並在稍後啟用 DPA。

8. 啟用 DPA 並驗證行為

執行下列 gcloud 指令,啟用 DPA、將每個 VM 的通訊埠分配下限設為 64,並將通訊埠分配上限設為 1024。

gcloud alpha compute routers nats update consumer-nat-gw --router=consumer-cr \
--region=us-east4 --min-ports-per-vm=64 --max-ports-per-vm=1024 \
--enable-dynamic-port-allocation

這會輸出

Updating nat [consumer-nat-gw] in router [consumer-cr]...done.

現在,請重新執行 get-nat-mapping-info,確認兩個執行個體仍然分配到 64 個通訊埠

gcloud  compute routers get-nat-mapping-info consumer-cr --region=us-east4

輸出內容範例 (為求簡潔遭到截斷)

---
instanceName: consumer-instance-1
...
  - <NAT Consumer IP1>:1024-1055
  numTotalNatPorts: 32
...
- natIpPortRanges:
  - <NAT Consumer IP1>:32768-32799
  numTotalNatPorts: 32
...
---
instanceName: consumer-instance-2
...
  - <NAT Address IP1>:1056-1087
  numTotalNatPorts: 32
...
  - <NAT Address IP1>:32800-32831
  numTotalNatPorts: 32
...

由於執行個體未主動使用任何通訊埠,通訊埠分配方式沒有太大變化。

讓我們透過 SSH 回到執行個體:

gcloud compute ssh consumer-instance-1 --zone=us-east4-a

重新匯出生產端 IP 環境變數。

export producerip1=`curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/producer-service-ip1" -H "Metadata-Flavor: Google"`

export producerip2=`curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/producer-service-ip2" -H "Metadata-Flavor: Google"`

然後重新執行先前的迴圈,以模擬平行連線:

while true; do for i in {1..70}; do curl -s -o /dev/null --connect-timeout 5 http://$producerip1/nginx/; if [ $? -ne 0 ] ; then echo -e "\nConnection # $i failed" ; else echo -en "\rConnection # $i successful"; fi; done; echo -e "\nLoop Done, Sleeping for 150s"; sleep 150; done

現在應該會看到以下輸出內容

Connection # 64 successful
Connection # 65 failed

Connection # 66 failed
Connection # 70 successful
Loop Done, Sleeping for 150s

所以在這裡發生了什麼事?Cloud NAT 會提高通訊埠的分配量,但這會對整個網路層進行程式設計。因此,我們看到 1 至 3 次連線逾時,直到嘗試完成剩餘連線才會成功。

我們已針對 curl (5 秒) 指定積極逾時,不過當 DPA 增加通訊埠分配時,應用程式應能成功完成連線。

如果我們針對 1024 次連線嘗試執行迴圈,可更清楚瞭解這種增加行為

while true; do for i in {1..1024}; do curl -s -o /dev/null --connect-timeout 5 http://$producerip1/nginx/; if [ $? -ne 0 ] ; then echo -e "\nConnection # $i failed" ; else echo -en "\rConnection # $i successful"; fi; done; echo -e "\nLoop Done, Sleeping for 150s"; sleep 150; done

我們現在應該會看到

Connection # 64 successful
Connection # 65 failed

Connection # 66 failed
Connection # 129 successful
Connection # 130 failed

Connection # 131 failed
Connection # 258 successful
Connection # 259 failed

Connection # 260 failed
Connection # 515 successful
Connection # 516 failed

Connection # 1024 successful
Loop Done, Sleeping for 150s

由於 Cloud NAT 會分配通訊埠 2 的倍數 (基本上就是在每個步驟中將配置加倍),因此我們看到連線逾時被醒目顯示在 64 至 1024 之間。

我們將 maxPortsPerVM 設為 1024,因此可能會連線超過 1024 個連線。我們可以測試計數,方法是以高於 1024 的次數重新執行 curl 迴圈 (等待 2 分鐘後重設過時的通訊埠)。

while true; do for i in {1..1035}; do curl -s -o /dev/null --connect-timeout 5 http://$producerip1/nginx/; if [ $? -ne 0 ] ; then echo -e "\nConnection # $i failed" ; else echo -en "\rConnection # $i successful"; fi; done; echo -e "\nLoop Done, Sleeping for 150s"; sleep 150; done

輸出內容如預期顯示,從 1024 年開始的連線失敗

<truncated output>
...
Connection # 1028 successful
Connection # 1029 failed
Connection # 1030 failed
Connection # 1031 failed
Connection # 1032 failed
Connection # 1033 failed
Connection # 1034 failed
Connection # 1035 failed
...
Loop Done, Sleeping for 150s

藉由將 maxPortsPerVM 設為 1024,我們已指示 Cloud NAT 將每個 VM 的通訊埠分配範圍擴大至 1024 以上。

如果結束 SSH 工作階段並重新執行 get-nat-mapping-info 的速度夠快,可看到分配到的額外通訊埠

gcloud  compute routers get-nat-mapping-info consumer-cr --region=us-east4

然後觀察下列輸出內容

---
instanceName: consumer-instance-1
interfaceNatMappings:
- natIpPortRanges:
  - <NAT Address IP1>:1024-1055
  - <NAT Address IP1>1088-1119
  -<NAT Address IP1>:1152-1215
  - <NAT Address IP1>:1280-1407
  - <NAT Address IP1>:1536-1791
  numTotalDrainNatPorts: 0
  numTotalNatPorts: 512
  sourceAliasIpRange: ''
  sourceVirtualIp: 10.0.0.2
- natIpPortRanges:
  - <NAT Address IP1>:32768-32799
  - <NAT Address IP1>:32832-32863
  - <NAT Address IP1>:32896-32959
  - <NAT Address IP1>:33024-33151
  - <NAT Address IP1>:33536-33791
  numTotalDrainNatPorts: 0
  numTotalNatPorts: 512
  sourceAliasIpRange: ''
  sourceVirtualIp: 10.0.0.2
---
instanceName: consumer-instance-2
interfaceNatMappings:
- natIpPortRanges:
  - <NAT Address IP1>:1056-1087
  numTotalDrainNatPorts: 0
  numTotalNatPorts: 32
  sourceAliasIpRange: ''
  sourceVirtualIp: 10.0.0.3
- natIpPortRanges:
  - <NAT Address IP1>:32800-32831
  numTotalDrainNatPorts: 0
  numTotalNatPorts: 32
  sourceAliasIpRange: ''
  sourceVirtualIp: 10.0.0.3

請注意,consumer-instance-1 已分配 1024 個通訊埠,但 consumer-instance-2 只能分配 64 個通訊埠。在 DPA 之前,這是不可能做到的事,並準確展現了 Cloud NAT 資料保護主管機關的威力。

如果等待 2 分鐘後再重新執行 get-nat-mapping-info 指令,您會發現 consumer-instance-1 已回復為僅分配的 64 個通訊埠的最小值。在本次示範中,我們不僅要說明 DPA 提高通訊埠分配量的能力,也不會在並非用於相同 NAT 閘道的其他執行個體潛在使用時釋出這些配額。

9. 透過 DPA 測試 Cloud NAT 規則

我們最近也推出了 Cloud NAT 的網路位址轉譯 (NAT) 規則功能,可讓客戶編寫針對某些外部目的地使用特定網路位址轉譯 (NAT) IP 的規則。詳情請參閱 NAT 規則說明文件頁面

在本練習中,我們會觀察 DPA 和 NAT 規則之間的交互作用。首先,請定義在存取 producer-address-2 時,要使用 nat-address-2 的 NAT 規則。

執行下列 gcloud 指令,建立 NAT 規則

gcloud alpha compute routers nats rules create 100 \
 --match='destination.ip == "'$producerip2'"' \
 --source-nat-active-ips=nat-address-2 --nat=consumer-nat-gw \
 --router=consumer-cr --router-region=us-east4

您應該會看到以下輸出內容

Updating nat [consumer-nat-gw] in router [consumer-cr]...done.

現在,請重新執行 get-nat-mapping-info,查看新 NAT 規則的效果。

gcloud alpha compute routers get-nat-mapping-info consumer-cr --region=us-east4

輸出內容應會輸出下列內容

---
instanceName: consumer-instance-1
interfaceNatMappings:
- natIpPortRanges:
  - <NAT Address IP1>:1024-1055
  numTotalDrainNatPorts: 0
  numTotalNatPorts: 32
  ruleMappings:
  - natIpPortRanges:
    - <NAT Address IP2>:1024-1055
    numTotalDrainNatPorts: 0
    numTotalNatPorts: 32
    ruleNumber: 100
  sourceAliasIpRange: ''
  sourceVirtualIp: 10.0.0.2
- natIpPortRanges:
  - <NAT Address IP1>:32768-32799
  numTotalDrainNatPorts: 0
  numTotalNatPorts: 32
  ruleMappings:
  - natIpPortRanges:
    - <NAT Address IP2>:32768-32799
    numTotalDrainNatPorts: 0
    numTotalNatPorts: 32
    ruleNumber: 100
  sourceAliasIpRange: ''
  sourceVirtualIp: 10.0.0.2

請注意,現在我們已特別為 ruleMappings 階層下的 nat-address-2 分配額外的通訊埠 (也達到最低指定下限為 64)。

那麼,如果執行個體開啟多個連至 NAT 規則指定目的地的連線,會發生什麼事?讓我們一起來看看。

讓我們透過 SSH 回到執行個體:

gcloud compute ssh consumer-instance-1 --zone=us-east4-a

重新匯出生產端 IP 環境變數。

export producerip1=`curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/producer-service-ip1" -H "Metadata-Flavor: Google"`

export producerip2=`curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/producer-service-ip2" -H "Metadata-Flavor: Google"`

現在,請再次針對 producerip2 執行 curl 迴圈

while true; do for i in {1..1024}; do curl -s -o /dev/null --connect-timeout 5 http://$producerip2/nginx/; if [ $? -ne 0 ] ; then echo -e "\nConnection # $i failed" ; else echo -en "\rConnection # $i successful"; fi; done; echo -e "\nLoop Done, Sleeping for 150s"; sleep 150; done

輸出內容應如下所示

Connection # 64 successful
Connection # 65 failed

Connection # 66 failed
Connection # 129 successful
Connection # 130 failed

Connection # 131 failed
Connection # 258 successful
Connection # 259 failed

Connection # 260 failed
Connection # 515 successful
Connection # 516 failed

Connection # 1024 successful
Loop Done, Sleeping for 150s

基本上就是為先前的測試建立鏡像。讓我們結束執行個體的 SSH 工作階段,然後再次查看 nat 對應。

gcloud alpha compute routers get-nat-mapping-info consumer-cr --region=us-east4

輸出內容應會輸出下列內容

---
instanceName: consumer-instance-1
interfaceNatMappings:
- natIpPortRanges:
  - <NAT Address IP1>:1024-1055
  numTotalDrainNatPorts: 0
  numTotalNatPorts: 32
  ruleMappings:
  - natIpPortRanges:
    - <NAT Address IP2>:1024-1055
    - <NAT Address IP2>:1088-1119
    - <NAT Address IP2>:1152-1215
    - <NAT Address IP2>:1280-1407
    - <NAT Address IP2>:1536-1791
    numTotalDrainNatPorts: 0
    numTotalNatPorts: 512
    ruleNumber: 100
  sourceAliasIpRange: ''
  sourceVirtualIp: 10.0.0.2
- natIpPortRanges:
  - <NAT Address IP1>:32768-32799
  numTotalDrainNatPorts: 0
  numTotalNatPorts: 32
  ruleMappings:
  - natIpPortRanges:
    - <NAT Address IP2>:32768-32799
    - <NAT Address IP2>:32832-32863
    - <NAT Address IP2>:32896-32959
    - <NAT Address IP2>:33024-33151
    - <NAT Address IP2>:33280-33535
    numTotalDrainNatPorts: 0
    numTotalNatPorts: 512
    ruleNumber: 100
  sourceAliasIpRange: ''
  sourceVirtualIp: 10.0.0.2
---
instanceName: consumer-instance-2
interfaceNatMappings:
- natIpPortRanges:
  - <NAT Address IP1>:1056-1087
  numTotalDrainNatPorts: 0
  numTotalNatPorts: 32
  ruleMappings:
  - natIpPortRanges:
    - <NAT Address IP2>:1056-1087
    numTotalDrainNatPorts: 0
    numTotalNatPorts: 32
    ruleNumber: 100
  sourceAliasIpRange: ''
  sourceVirtualIp: 10.0.0.3
- natIpPortRanges:
  - <NAT Address IP1>:32800-32831
  numTotalDrainNatPorts: 0
  numTotalNatPorts: 32
  ruleMappings:
  - natIpPortRanges:
    - <NAT Address IP2>:32800-32831
    numTotalDrainNatPorts: 0
    numTotalNatPorts: 32
    ruleNumber: 100
  sourceAliasIpRange: ''
  sourceVirtualIp: 10.0.0.3

---
instanceName: consumer-instance-1
interfaceNatMappings:
- natIpPortRanges:
  - <NAT Address IP1>:1024-1055
  numTotalDrainNatPorts: 0
  numTotalNatPorts: 32
  ruleMappings:
  - natIpPortRanges:
    - <NAT Address IP2>:1024-1055
    numTotalDrainNatPorts: 0
    numTotalNatPorts: 32
    ruleNumber: 100
  sourceAliasIpRange: ''
  sourceVirtualIp: 10.0.0.2
- natIpPortRanges:
  - <NAT Address IP1>:32768-32799
  numTotalDrainNatPorts: 0
  numTotalNatPorts: 32
  ruleMappings:
  - natIpPortRanges:
    - <NAT Address IP2>:32768-32799
    numTotalDrainNatPorts: 0
    numTotalNatPorts: 32
    ruleNumber: 100
  sourceAliasIpRange: ''
  sourceVirtualIp: 10.0.0.2

如上方所示,consumer-instance-1 的預設 NAT IP ( nat-address-1 的 IP) 仍會分配到 64 個通訊埠,但 NAT 規則的 IP (nat-address-2 的 IP) 已分配 1024 個通訊埠。在所有網路位址轉譯 (NAT) IP 中,consumer-instance-2 保留了 64 個預設分配的通訊埠。

作為練習,您可以測試反向大小寫。讓 Cloud NAT 取消分配所有額外通訊埠,然後針對 producerip1 執行 curl 迴圈,並觀察 get-nat-mapping-info 輸出內容的影響

10. 清除步驟

為避免週期性費用,請刪除與本程式碼研究室相關聯的所有資源。

請先刪除所有執行個體。

透過 Cloud Shell:

gcloud compute instances delete consumer-instance-1 consumer-instance-2 \
 producer-instance-1 producer-instance-2 \
 --zone us-east4-a --quiet

預期的輸出內容:

Deleted [https://www.googleapis.com/compute/v1/projects/<Project Id>/zones/us-east4-a/instances/consumer-instance-1].
Deleted [https://www.googleapis.com/compute/v1/projects/<Project Id>/zones/us-east4-a/instances/consumer-instance-2].
Deleted [https://www.googleapis.com/compute/v1/projects/<Project Id>/zones/us-east4-a/instances/producer-instance-1].
Deleted [https://www.googleapis.com/compute/v1/projects/<Project Id>/zones/us-east4-a/instances/producer-instance-2].

接著,請刪除 Cloud Router。透過 Cloud Shell:

gcloud compute routers delete consumer-cr \
 --region us-east4 --quiet

您應該會看到以下輸出內容:

Deleted [https://www.googleapis.com/compute/v1/projects/<Project ID>/regions/us-east4/routers/consumer-cr].

釋出所有外部 IP 位址。透過 Cloud Shell:

gcloud compute addresses delete nat-address-1 \
 nat-address-2 producer-address-1 \
 producer-address-2 --region us-east4 --quiet

您應該會看到以下輸出內容:

Deleted [https://www.googleapis.com/compute/v1/projects/<Project ID>/regions/us-east4/addresses/nat-address-1].
Deleted [https://www.googleapis.com/compute/v1/projects/<Project ID>/regions/us-east4/addresses/nat-address-2].
Deleted [https://www.googleapis.com/compute/v1/projects/<Project ID>/regions/us-east4/addresses/nat-address-3].
Deleted [https://www.googleapis.com/compute/v1/projects/<Project ID>/regions/us-east4/addresses/producer-address-1].
Deleted [https://www.googleapis.com/compute/v1/projects/<Project ID>/regions/us-east4/addresses/producer-address-2].

刪除虛擬私有雲防火牆規則。透過 Cloud Shell:

gcloud compute firewall-rules delete consumer-allow-iap \
 producer-allow-80 --quiet

您應該會看到以下輸出內容:

Deleted [https://www.googleapis.com/compute/v1/projects/<Project ID>/global/firewalls/consumer-allow-iap].
Deleted [https://www.googleapis.com/compute/v1/projects/<Project ID>/global/firewalls/producer-allow-80].

刪除子網路。透過 Cloud Shell:

gcloud compute networks subnets delete cons-net-e4 \
 prod-net-e4 --region=us-east4 --quiet

您應該會看到以下輸出內容:

Deleted [https://www.googleapis.com/compute/v1/projects/<Project ID>/regions/us-east4/subnetworks/cons-net-e4].
Deleted [https://www.googleapis.com/compute/v1/projects/<Project ID>/regions/us-east4/subnetworks/prod-net-e4].

最後先刪除虛擬私有雲透過 Cloud Shell:

gcloud compute networks delete consumer-vpc \
 producer-vpc --quiet

您應該會看到以下輸出內容:

Deleted [https://www.googleapis.com/compute/v1/projects/<Project ID>/global/networks/consumer-vpc].
Deleted [https://www.googleapis.com/compute/v1/projects/<Project ID>/global/networks/producer-vpc].

11. 恭喜!

您已完成 Cloud NAT DPA 研究室!

涵蓋內容

  • 如何設定 Cloud NAT 閘道,為 DPA 做好準備。
  • 如何在沒有 DPA 的情況下檢查通訊埠分配。
  • 如何為 NAT 閘道啟用及設定 DPA。
  • 如何透過執行平行輸出連線來觀察 DPA 的影響。
  • 如何將網路位址轉譯 (NAT) 規則新增至已啟用 DPA 的 NAT 閘道。
  • 如何透過執行輸出連線至多個目的地,利用規則查看 DPA 的行為。

後續步驟

©Google, Inc. 或其關係企業。版權所有。請勿散佈。