Использование динамического распределения портов Cloud NAT

1. Обзор

Динамическое распределение портов (DPA) — это новая функция Cloud NAT. При включенном DPA Cloud NAT динамически масштабирует выделение портов для экземпляров в зависимости от их потребностей. DPA настроен с минимальными и максимальными ограничениями портов, поэтому он никогда не уменьшает количество портов ниже минимального и не увеличивает масштаб за пределы максимального. Это позволяет некоторым экземплярам за шлюзами NAT динамически увеличивать количество подключений без необходимости выделять дополнительные порты всем экземплярам за Cloud NAT.

Без DPA всем экземплярам за Cloud NAT выделяется одинаковое количество портов независимо от использования, как определено параметром minPortsPerVm .

Для получения дополнительной информации просмотрите раздел документации о NAT DPA .

Что вы узнаете

  • Как настроить шлюз Cloud NAT при подготовке к DPA.
  • Как проверить распределение портов без DPA.
  • Как включить и настроить DPA для шлюза NAT.
  • Как наблюдать за эффектами DPA, запуская параллельные выходные соединения.
  • Как добавить правила NAT к шлюзу NAT с включенным DPA.
  • Как просмотреть поведение DPA с помощью правил, запустив исходящие подключения к нескольким местам назначения.

Что вам понадобится

  • Базовые знания Google Compute Engine.
  • Базовые знания сетевых технологий и TCP/IP.
  • Базовые знания командной строки Unix/Linux.
  • Полезно пройти экскурсию по сетям в Google Cloud, например, по лаборатории «Сеть в Google Cloud» .
  • Проект Google Cloud с включенным альфа-доступом.
  • Понимание основ Cloud NAT.

2. Использование Google Cloud Console и Cloud Shell.

Для взаимодействия с GCP на протяжении всей лабораторной работы мы будем использовать как Google Cloud Console, так и Cloud Shell.

Облачная консоль Google

Доступ к облачной консоли можно получить по адресу https://console.cloud.google.com .

75eef5f6fd6d7e41.png

Самостоятельная настройка среды

  1. Войдите в Google Cloud Console и создайте новый проект или повторно используйте существующий. Если у вас еще нет учетной записи Gmail или Google Workspace, вам необходимо ее создать .

96a9c957bc475304.png

b9a10ebdf5b5a448.png

a1e3c01a38fa61c2.png

  • Имя проекта — это отображаемое имя для участников этого проекта. Это строка символов, не используемая API Google, и вы можете обновить ее в любое время.
  • Идентификатор проекта должен быть уникальным для всех проектов Google Cloud и неизменяемым (нельзя изменить после его установки). Cloud Console автоматически генерирует уникальную строку; обычно тебя не волнует, что это такое. В большинстве лабораторий кода вам потребуется указать идентификатор проекта (обычно он обозначается как PROJECT_ID ), поэтому, если он вам не нравится, создайте другой случайный идентификатор или попробуйте свой собственный и посмотрите, доступен ли он. Затем он «замораживается» после создания проекта.
  • Существует третье значение — номер проекта , который используют некоторые API. Подробнее обо всех трех этих значениях читайте в документации .
  1. Затем вам необходимо включить выставление счетов в Cloud Console, чтобы использовать облачные ресурсы/API. Прохождение этой лаборатории кода не должно стоить много, если вообще стоит. Чтобы отключить ресурсы и не платить за выставление счетов за пределами этого руководства, следуйте инструкциям по «очистке», которые можно найти в конце лаборатории кода. Новые пользователи Google Cloud имеют право на участие в программе бесплатной пробной версии стоимостью 300 долларов США .

Запустить Cloud Shell

Хотя Google Cloud можно управлять удаленно с вашего ноутбука, в этой лаборатории вы будете использовать Google Cloud Shell , среду командной строки, работающую в облаке.

В консоли GCP щелкните значок Cloud Shell на верхней правой панели инструментов:

bce75f34b2c53987.png

Подготовка и подключение к среде займет всего несколько минут. Когда все будет готово, вы должны увидеть что-то вроде этого:

f6ef2b5f13479f3a.png

Эта виртуальная машина оснащена всеми необходимыми инструментами разработки. Он предлагает постоянный домашний каталог объемом 5 ГБ и работает в Google Cloud, что значительно повышает производительность сети и аутентификацию. Всю работу в этой лабораторной работе можно выполнять с помощью простого браузера.

3. Настройка лаборатории

В ходе этой лабораторной работы вы будете использовать проект и создадите два облака VPC с подсетью в каждом. Вы зарезервируете внешние IP-адреса, а затем создадите и настроите шлюз Cloud NAT (с облачным маршрутизатором), два экземпляра производителя, а также два экземпляра потребителя. После проверки поведения Cloud NAT по умолчанию вы включите динамическое распределение портов и проверите его поведение. Наконец, вы также настроите правила NAT и понаблюдаете за взаимодействием между DPA и правилами NAT.

Обзор сетевой архитектуры:

a21caa6c333909d8.png

4. Зарезервируйте внешние IP-адреса.

Давайте зарезервируем все внешние IP-адреса для использования в этой лабораторной работе. Это поможет вам написать все соответствующие правила NAT и брандмауэра как в потребительском, так и в продюсерском VPC.

Из 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-производителе, будут предлагать службу выхода в Интернет с использованием двух общедоступных IP-адресов «адрес производителя-1» и «адрес производителя-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

Далее давайте создадим правила брандмауэра VPC, чтобы IP-адреса NAT могли достигать экземпляров производителя через порт 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.

Чтобы быстро предоставить инстансам все необходимое программное обеспечение, мы создадим инстансы со сценарием запуска, который устанавливает nginx с помощью менеджера пакетов Debian APT.

Чтобы иметь возможность писать правила 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. Настройка потребительского VPC, облачного NAT и экземпляров.

Теперь, когда вы создали службу-производитель, пришло время создать потребительский VPC и его шлюз Cloud NAT.

После создания VPC и подсети мы добавим простое правило входящего брандмауэра, чтобы разрешить IAP для диапазонов исходных IP-адресов TCP. Это позволит нам подключаться по SSH к потребительским экземплярам напрямую с помощью gcloud.

Затем мы создадим простой шлюз Cloud NAT в режиме ручного выделения и связанный с ним зарезервированный адрес «nat-address-1». В последующих частях лабораторной работы мы обновим конфигурацию шлюза, чтобы включить динамическое распределение портов, а позже добавим собственные правила.

Сначала давайте создадим 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

Далее давайте создадим правила брандмауэра VPC, чтобы адреса диапазонов 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, нам необходимо сначала создать экземпляр облачного маршрутизатора (мы используем частный номер 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-адреса производителей, чтобы иметь возможность позже ссылаться на них внутри экземпляра. Из 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-адреса обоих производителей и заполним их как переменные среды.

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"`

Затем попробуйте подключиться к обоим экземплярам производителя, чтобы убедиться, что мы можем успешно связаться с ними.

<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 и устанавливает минимальное выделение портов для каждой виртуальной машины равным 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, фактически удваивая выделение на каждом этапе, мы видим таймауты соединения, выделенные вокруг степеней 2 между 64 и 1024.

Поскольку мы установили для maxPortsPerVM значение 1024, мы не ожидаем, что сможем поддерживать более 1024 подключений. Мы можем проверить это, повторно запустив цикл скручивания со счетчиком, превышающим 1024 (после ожидания 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 никогда не масштабировать выделение портов сверх 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 это было нелегко, и это подчеркивает возможности DPA для Cloud NAT.

Если вы подождите 2 минуты, прежде чем повторно запустить команду get-nat-mapping-info , вы заметите, что consumer-instance-1 вернулся к минимальному значению, составляющему всего 64 выделенных порта. Иллюстрирует способность DPA не только увеличивать выделение портов, но и освобождать их, когда они не используются, для потенциального использования другими экземплярами за тем же шлюзом NAT.

9. Проверьте правила Cloud NAT с помощью DPA

Недавно мы также выпустили функцию правил NAT для Cloud NAT, позволяющую клиентам писать правила, использующие определенные IP-адреса NAT для определенных внешних мест назначения. Для получения дополнительной информации обратитесь к странице документации по правилам NAT.

В этом упражнении мы наблюдаем взаимодействие между правилами DPA и NAT. Давайте сначала определим правило NAT для использования nat-address-2 при доступе к producer-address-2 .

Запустите следующую команду 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

Обратите внимание, что теперь у нас есть дополнительные порты, выделенные (также 64, указанный минимум) специально для nat-address-2 в иерархии ruleMappings .

Что же произойдет, если экземпляр откроет множество подключений к месту назначения, указанному правилом 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

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

Как вы можете видеть выше, IP-адрес NAT по умолчанию для consumer-instance-1 (IP для nat-address-1 ) по-прежнему имеет только 64 выделенных порта, но IP-адрес правила NAT (IP для nat-address-2 ) имеет 1024 порта. выделено. При этом consumer-instance-2 сохранял выделение по умолчанию 64 портов для всех IP-адресов NAT.

В качестве упражнения вы можете проверить обратный случай. Позвольте Cloud NAT освободить все дополнительные порты, затем запустите цикл скручивания для producerip1 и посмотрите, как это повлияет на выходные данные 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].

Удалите правила брандмауэра 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!

Что вы покрыли

  • Как настроить шлюз Cloud NAT при подготовке к DPA.
  • Как проверить распределение портов без DPA.
  • Как включить и настроить DPA для шлюза NAT.
  • Как наблюдать за эффектом DPA, запуская параллельные выходные соединения.
  • Как добавить правила NAT к шлюзу NAT с включенным DPA.
  • Как просмотреть поведение DPA с помощью правил, запустив исходящие подключения к нескольким местам назначения.

Следующие шаги

©Google, Inc. или ее дочерние компании. Все права защищены. Не распространяйте.