Cloud NAT の動的ポート割り当ての使用

1. 概要

動的ポート割り当て(DPA)は Cloud NAT の新機能です。DPA を有効にすると、Cloud NAT はインスタンスのポート割り当てを必要に応じて動的にスケールアップ/スケールダウンします。DPA では、ポートの最小数と最大数を設定して、ポート数が最小数を下回ったり、最大数を超えてスケールアップされたりすることはありません。これにより、NAT ゲートウェイの背後にある一部のインスタンスは、Cloud NAT の背後にあるすべてのインスタンスに追加のポートを割り当てることなく、接続数を動的にスケールアップできます。

DPA を使用しない場合、Cloud NAT の背後にあるすべてのインスタンスには、使用状況に関係なく、minPortsPerVm パラメータで定義された同じ数のポートが割り当てられます。

詳しくは、NAT DPA に関するドキュメントのセクション をご覧ください。

学習内容

  • DPA に備えて Cloud NAT ゲートウェイを設定する方法。
  • DPA なしでポート割り当てを検査する方法。
  • NAT ゲートウェイの DPA を有効にして構成する方法。
  • 下り(外向き)並列接続を実行して DPA の影響を確認する方法。
  • DPA を有効にした NAT ゲートウェイに NAT ルールを追加する方法。
  • 複数の宛先への下り(外向き)接続を実行して、ルールを使用した DPA の動作を確認する方法。

必要なもの

  • Google Compute Engine に関する基本的な知識
  • ネットワークと TCP/IP に関する基本的な知識
  • Unix / Linux コマンドラインに関する基本的な知識
  • Google Cloud のネットワーキング ツアー(Networking in Google Cloud ラボなど)を完了しておくことをおすすめします。
  • 「アルファ版にアクセスできる」 Google Cloud プロジェクト有効にします。
  • Cloud NAT の基本を理解していること。

2. Google Cloud コンソールと Cloud Shell の使用

このラボでは、GCP とやり取りするために Google Cloud コンソールと Cloud Shell の両方を使用します。

Google Cloud Console

Cloud コンソールには https://console.cloud.google.com からアクセスできます。

75eef5f6fd6d7e41.png

セルフペース型の環境設定

  1. Google Cloud Console にログインして、プロジェクトを新規作成するか、既存のプロジェクトを再利用します。Gmail アカウントも Google Workspace アカウントもまだお持ちでない場合は、アカウントを作成してください。

96a9c957bc475304.png

b9a10ebdf5b5a448.png

a1e3c01a38fa61c2.png

  • プロジェクト名は、このプロジェクトの参加者に表示される名称です。Google API では使用されない文字列で、いつでも更新できます。
  • プロジェクト ID は、すべての Google Cloud プロジェクトにおいて一意でなければならず、不変です(設定後は変更できません)。Cloud Console により一意の文字列が自動生成されます(通常は内容を意識する必要はありません)。ほとんどの Codelab では、プロジェクト ID を参照する必要があります(通常、プロジェクト ID は「PROJECT_ID」の形式です)。好みの文字列でない場合は、別のランダムな ID を生成するか、独自の ID を試用して利用可能であるかどうかを確認することができます。プロジェクトの作成後、ID は「フリーズ」されます。
  • 3 つ目の値として、一部の API が使用するプロジェクト番号があります。これら 3 つの値について詳しくは、こちらのドキュメントをご覧ください。
  1. 次に、Cloud のリソースや API を使用するために、Cloud Console で課金を有効にする必要があります。この Codelab の操作をすべて行って、費用が生じたとしても、少額です。このチュートリアルを終了した後に課金が発生しないようにリソースをシャットダウンするには、Codelab の最後にある「クリーンアップ」の手順を行います。Google Cloud の新規ユーザーは、300 米ドル分の無料トライアル プログラムをご利用いただけます。

Cloud Shell の起動

Google Cloud はノートパソコンからリモートで操作できますが、この Codelab では、Google Cloud Shell(Cloud 上で動作するコマンドライン環境)を使用します。

GCP Console で右上のツールバーにある Cloud Shell アイコンをクリックします。

bce75f34b2c53987.png

プロビジョニングと環境への接続にはそれほど時間はかかりません。完了すると、次のように表示されます。

f6ef2b5f13479f3a.png

この仮想マシンには、必要な開発ツールがすべて用意されています。永続的なホーム ディレクトリが 5 GB 用意されており、Google Cloud で稼働します。そのため、ネットワークのパフォーマンスと認証機能が大幅に向上しています。このラボでの作業はすべて、ブラウザから実行できます。

3. ラボの設定

このラボでは、プロジェクトを使用して 2 つの VPC を作成し、それぞれにサブネットを設定します。外部 IP アドレスを予約してから、1 つの Cloud NAT ゲートウェイ(Cloud Router を使用)、2 つのプロデューサー インスタンス、2 つのコンシューマ インスタンスを作成して構成します。Cloud NAT のデフォルトの動作を確認したら、動的ポートの割り当てを有効にして、その動作を検証します。最後に、NAT ルールを構成し、DPA と NAT ルールの相互作用を確認します。

ネットワーキング アーキテクチャの概要:

a21caa6c333909d8.png

4. 外部 IP アドレスを予約する

このラボで使用するすべての外部 IP アドレスを予約します。これにより、コンシューマ VPC とプロデューサー VPC の両方で、関連するすべての 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. プロデューサー VPC とインスタンスの設定。

次に、プロデューサー リソース用のリソースを作成します。プロデューサー VPC で実行されるインスタンスは、2 つのパブリック IP「producer-address-1」を使用してインターネットに接続するサービスを提供します。「producer-address-2」ををタップします。

まず、VPC を作成します。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 のプロデューサー インスタンスに到達できるように VPC ファイアウォール ルールを作成します。

Cloud Shell で 1 つ目のルールを作成します。

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

次のステップでは、2 つのプロデューサー インスタンスを作成します。

プロデューサー インスタンスはシンプルな nginx プロキシ デプロイを実行します。

必要なすべてのソフトウェアが含まれるインスタンスを迅速にプロビジョニングするには、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

次に、2 つ目のインスタンスを作成します。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. コンシューマ VPC、Cloud NAT、インスタンスの設定

プロデューサー サービスを作成したら、次はコンシューマ VPC とその Cloud NAT ゲートウェイを作成します。

VPC とサブネットを作成したら、TCP 送信元 IP 範囲の IAP を許可する単純な上り(内向き)ファイアウォール ルールを追加します。これにより、gcloud を使用してコンシューマ インスタンスに直接 SSH 接続できます。

次に、手動割り当てモードでシンプルな Cloud NAT ゲートウェイを作成し、予約済みアドレス「nat-address-1」を使用します。関連付けられていますCodelab の後半では、ゲートウェイの構成を更新して動的ポートの割り当てを有効にし、後でカスタムルールを追加します。

まず、VPC を作成します。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 のコンシューマ インスタンスに到達できるように VPC ファイアウォール ルールを作成します。

1 つ目のファイアウォール ルールについては、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.

デフォルトでは、minPortsPerVm を 64 に設定して Cloud NAT ゲートウェイが作成されます。

コンシューマ テスト インスタンスを作成します。後でインスタンス内で参照できるように、予約済みのプロデューサー 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 のデフォルトの動作を確認する

この時点で、コンシューマ インスタンスは、同じ予約済み IP「nat-address-1」を使用するデフォルトの Cloud NAT 動作を使用します。内部 IP アドレスを使用して通信できます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 は同じ外部 IP nat-address-1 からインスタンスごとに 64 個のポートを割り当てています。

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 を取得し、環境変数として設定します。

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 を実行して、プロデューサー インスタンスの 1 つへの多数の並列接続を作成してみましょう。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 がポートの割り当てを増やしている間、タイムアウトが長いアプリケーションは接続を正常に完了できるはずです。

この増加動作は、次のように 1,024 回の接続試行のループを実行すると、より明確になります。

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 の累乗で割り当てるため(ステップごとに割り当てを基本的に 2 倍にする)、64 ~ 1,024 の 2 の累乗付近で接続タイムアウトがハイライト表示されます。

maxPortsPerVM を 1024 に設定したため、1, 024 を超える接続は許容されないと考えられます。1,024 より大きいカウントで 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 に設定することで、VM ごとに 1, 024 を超えるポート割り当てをスケーリングしないように Cloud NAT に指示しています。

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 には 1, 024 個のポートが割り当てられていますが、consumer-instance-2 には 64 個のポートしか割り当てられていません。DPA が導入される前は簡単には実現できませんでしたが、Cloud NAT における DPA の力を浮き彫りにしています。

2 分待ってから get-nat-mapping-info コマンドを再実行すると、consumer-instance-1 が割り当てられた 64 ポートの最小値に戻っていることがわかります。DPA がポート割り当てを増やすだけでなく、使用していないときに解放して、同じ NAT ゲートウェイの背後にある他のインスタンスに使用される可能性があることを示しています。

9. DPA を使用して Cloud NAT ルールをテストする

また、Google は最近、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 ルールで指定された宛先に対して多数の接続を開くとどうなるでしょうか。Let's find out.(HONEY の節約額を確認してみましょう。)

インスタンスに 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)には 1,024 個のポートが割り当てられています。その間、consumer-instance-2 はすべての NAT IP に対してデフォルトの 64 ポートの割り当てを維持しました。

演習として、逆の場合も試してみましょう。Cloud NAT に余分なポートの割り当てをすべて解除させ、producerip1 に対して curl ループを実行して、get-nat-mapping-info の出力に対する影響を確認します。

10. クリーンアップ手順

定期的な請求が発生しないようにするため、この Codelab に関連付けられているリソースをすべて削除する必要があります。

まず、すべてのインスタンスを削除します。

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].

VPC ファイアウォール ルールを削除します。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].

最後に、VPC を削除します。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 ラボが完了しました。

学習した内容

  • DPA に備えて Cloud NAT ゲートウェイを設定する方法。
  • DPA なしでポート割り当てを検査する方法。
  • NAT ゲートウェイの DPA を有効にして構成する方法。
  • 下り(外向き)並列接続を実行して DPA の影響を確認する方法。
  • DPA を有効にした NAT ゲートウェイに NAT ルールを追加する方法。
  • 複数の宛先への下り(外向き)接続を実行して、ルールを使用した DPA の動作を確認する方法。

次のステップ

©Google, Inc. or its affiliates. All rights reserved. Do not distribute.