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 с включенным режимом «Альфа-доступ».
- Понимание основ облачного NAT.
2. Использование консоли Google Cloud и Cloud Shell
Для взаимодействия с GCP в ходе этой лабораторной работы мы будем использовать как консоль Google Cloud, так и Cloud Shell.
Консоль Google Cloud
Доступ к консоли Cloud Console можно получить по адресу https://console.cloud.google.com .

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



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

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

Эта виртуальная машина оснащена всеми необходимыми инструментами разработки. Она предоставляет постоянный домашний каталог размером 5 ГБ и работает в облаке Google, что значительно повышает производительность сети и аутентификацию. Всю работу в этой лаборатории можно выполнять с помощью обычного браузера.
3. Подготовка лаборатории
Для этой лабораторной работы вы будете использовать проект и создадите две VPC с подсетью в каждой. Вы зарезервируете внешние IP-адреса, а затем создадите и настроите шлюз Cloud NAT (с Cloud Router), два экземпляра производителя, а также два экземпляра потребителя. После проверки поведения Cloud NAT по умолчанию вы включите динамическое распределение портов и проверите его работу. Наконец, вы также настроите правила NAT и понаблюдаете за взаимодействием между DPA и правилами NAT.
Обзор сетевой архитектуры:

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-адреса: «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
Далее создадим правила брандмауэра 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-шлюза необходимо сначала создать экземпляр 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-адреса производителей, чтобы иметь возможность ссылаться на них в дальнейшем внутри экземпляра. Из 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"`
Затем попробуйте выполнить команду 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, устанавливает минимальное количество выделяемых портов для каждой виртуальной машины на 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
Что же здесь произошло? Облачный 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 выделяет порты степенями двойки, по сути удваивая выделение на каждом шаге, мы видим, что таймауты соединения выделяются в диапазоне значений, кратных степеням двойки, от 64 до 1024.
Поскольку мы установили maxPortsPerVM равным 1024, мы не ожидаем, что сможем обработать более 1024 соединений. Мы можем проверить это, повторно запустив цикл curl с большим количеством соединений, чем 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
Установив значение параметра `set 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 для облачного 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"`
А теперь давайте снова запустим цикл curl для 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 освободит все лишние порты, затем запустите цикл curl для 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 с помощью правил, запуская исходящие соединения с несколькими пунктами назначения.
Следующие шаги
- Ознакомьтесь с нашей страницей документации по динамическому распределению портов.
- Поэкспериментируйте с настройкой таймаутов NAT и значений выделения портов для вашего приложения.
- Узнайте больше о сетевых технологиях на платформе Google Cloud.
©Google, Inc. или ее дочерние компании. Все права защищены. Распространение запрещено.