Usa la asignación de puertos dinámicos de Cloud NAT

1. Descripción general

La asignación dinámica de puertos (DPA) es una nueva función de Cloud NAT. Con la DPA habilitada, Cloud NAT aumenta o disminuye de forma dinámica las asignaciones de puertos para las instancias según sus necesidades. La DPA se configura con límites mínimos y máximos de puertos para que nunca reduzca la cantidad de puertos por debajo del mínimo ni la aumente por encima del máximo. Esto permite que algunas instancias detrás de las puertas de enlace de NAT aumenten de forma dinámica su recuento de conexiones sin tener que asignar más puertos a todas las instancias detrás de Cloud NAT.

Sin la DPA, a todas las instancias detrás de Cloud NAT se les asigna la misma cantidad de puertos, independientemente del uso, según lo define el parámetro minPortsPerVm .

Para obtener más información, consulta la sección de documentación sobre la DPA de NAT .

Qué aprenderás

  • Cómo configurar una puerta de enlace de Cloud NAT en preparación para la DPA
  • Cómo inspeccionar las asignaciones de puertos sin DPA
  • Cómo habilitar y configurar el DPA para una puerta de enlace NAT
  • Cómo observar los efectos de la DPA ejecutando conexiones de salida paralelas
  • Cómo agregar reglas NAT a una puerta de enlace NAT con la DPA habilitada
  • Cómo ver el comportamiento de la DPA con reglas ejecutando conexiones de salida a varios destinos

Requisitos

  • Conocimiento básico de Google Compute Engine
  • Conocimiento básico de herramientas de redes y TCP/IP
  • Conocimiento básico de la línea de comandos de Unix/Linux
  • Es útil haber completado un recorrido por las redes en Google Cloud, como el lab de Networking in Google Cloud.
  • Un proyecto de Google Cloud con el "Acceso alfa" habilitado
  • Comprensión de los conceptos básicos de Cloud NAT

2. Usa la consola de Google Cloud y Cloud Shell

Para interactuar con GCP, usaremos Google Cloud Console y Cloud Shell a lo largo de este lab.

Google Cloud Console

Puedes acceder a la consola de Cloud en https://console.cloud.google.com.

75eef5f6fd6d7e41.png

Configuración del entorno de autoaprendizaje

  1. Accede a Google Cloud Console y crea un proyecto nuevo o reutiliza uno existente. Si aún no tienes una cuenta de Gmail o de Google Workspace, debes crear una.

96a9c957bc475304.png

b9a10ebdf5b5a448.png

a1e3c01a38fa61c2.png

  • El Nombre del proyecto es el nombre visible de los participantes de este proyecto. Es una string de caracteres que no se utiliza en las API de Google y se puede actualizar en cualquier momento.
  • El ID del proyecto debe ser único en todos los proyectos de Google Cloud y es inmutable (no se puede cambiar después de configurarlo). Cloud Console genera automáticamente una string única, que, por lo general, no importa cuál sea. En la mayoría de los codelabs, debes hacer referencia al ID del proyecto (suele ser PROJECT_ID). Por lo tanto, si no te gusta, genera otro aleatorio o prueba con uno propio y comprueba si está disponible. Después de crear el proyecto, este ID se “congela” y no se puede cambiar.
  • Además, hay un tercer valor, el Número de proyecto, que usan algunas API. Obtén más información sobre estos tres valores en la documentación.
  1. A continuación, deberás habilitar la facturación en Cloud Console para usar las API o los recursos de Cloud. Ejecutar este codelab no debería costar mucho, tal vez nada. Si quieres cerrar los recursos para no se te facture más allá de este instructivo, sigue las instrucciones de “limpieza” que se encuentran al final del codelab. Los usuarios nuevos de Google Cloud son aptos para participar en el programa Prueba gratuita de USD 300.

Inicia Cloud Shell

Si bien Google Cloud y Spanner se pueden operar de manera remota desde tu laptop, en este codelab usarás Google Cloud Shell, un entorno de línea de comandos que se ejecuta en la nube.

En GCP Console, haga clic en el ícono de Cloud Shell en la barra de herramientas superior derecha:

bce75f34b2c53987.png

El aprovisionamiento y la conexión al entorno deberían tomar solo unos minutos. Cuando termine el proceso, debería ver algo como lo siguiente:

f6ef2b5f13479f3a.png

Esta máquina virtual está cargada con todas las herramientas de desarrollo que necesitarás. Ofrece un directorio principal persistente de 5 GB y se ejecuta en Google Cloud, lo que permite mejorar considerablemente el rendimiento de la red y la autenticación. Puedes realizar todo tu trabajo en este lab usando simplemente un navegador.

3. Configuración del lab

En este lab, usarás un proyecto y crearás dos VPC con una subred en cada una. Reservarás direcciones IP externas y, luego, crearás y configurarás una puerta de enlace de Cloud NAT (con un Cloud Router), dos instancias de productor y dos instancias de consumidor. Después de validar el comportamiento predeterminado de Cloud NAT, habilitarás la asignación de puertos dinámica y validarás su comportamiento. Por último, también configurarás reglas de NAT y observarás la interacción entre la DPA y las reglas de NAT.

Descripción general de la arquitectura de redes:

a21caa6c333909d8.png

4. Reserva direcciones IP externas

Reservaremos todas las direcciones IP externas que se usarán en este lab. Esto te ayudará a escribir todas las reglas de NAT y de firewall pertinentes en la VPC del consumidor y del productor.

En Cloud Shell, ingresa lo siguiente:

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

Resultado:

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

Propaga las direcciones IP que se reservaron como variables de entorno.

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

No se espera ningún resultado, pero se puede confirmar que las direcciones se completaron correctamente. Generemos los valores de todas las variables de entorno.

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

Resultado:

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

5. Configuración de la VPC y las instancias del productor

Ahora crearemos los recursos para los recursos del productor. Las instancias que se ejecutan en la VPC del productor ofrecerán el servicio orientado a Internet con dos IPs públicas: "producer-address-1" y "producer-address-2" .

Primero, creemos la VPC. En Cloud Shell, ingresa lo siguiente:

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

Resultado:

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

A continuación, crearemos la subred en us-east4. En Cloud Shell, ingresa lo siguiente:

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

Resultado:

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

A continuación, crearemos reglas de firewall de VPC para permitir que las direcciones IP de NAT lleguen a las instancias del productor en el puerto 8080.

Para la primera regla, desde Cloud Shell, haz lo siguiente:

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

Resultado:

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

El siguiente paso es crear las dos instancias de productor.

Las instancias de productor ejecutarán una implementación de proxy de nginx simple.

Para aprovisionar rápidamente las instancias con todo el software necesario, crearemos las instancias con una secuencia de comandos de inicio que instale nginx con el administrador de paquetes APT de Debian.

Para poder escribir reglas de NAT, aprovisionaremos cada instancia con una dirección IP reservada diferente.

Crea la primera instancia. En Cloud Shell, ingresa lo siguiente:

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"

Resultado:

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

Luego, crea la segunda instancia. En Cloud Shell, ingresa lo siguiente:

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"

Resultado:

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. Configura la VPC del consumidor, Cloud NAT y las instancias

Ahora que creaste el servicio del productor, es momento de crear la VPC del consumidor y su puerta de enlace de Cloud NAT.

Después de crear la VPC y la subred, agregaremos una regla de firewall de entrada simple para permitir los rangos de IP de origen de IAP para TCP. Esto nos permitirá acceder a las instancias de consumidor directamente con SSH a través de gcloud.

Luego, crearemos una puerta de enlace de Cloud NAT simple en el modo de asignación manual y la dirección reservada "nat-address-1" asociada a ella. En las siguientes partes del codelab, actualizaremos la configuración de la puerta de enlace para habilitar la asignación dinámica de puertos y, luego, agregaremos reglas personalizadas.

Primero, creemos la VPC. En Cloud Shell, ingresa lo siguiente:

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

Resultado:

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

A continuación, crearemos una subred en us-east4. En Cloud Shell, ingresa lo siguiente:

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

Resultado:

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

A continuación, crearemos reglas de firewall de VPC para permitir que los rangos de direcciones de IAP lleguen a las instancias del consumidor en el puerto 22.

Para la primera regla de firewall, ejecuta lo siguiente desde Cloud Shell:

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

Resultado:

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

Antes de crear una puerta de enlace de NAT, primero debemos crear una instancia de Cloud Router (usamos un número de ASN privado, pero es irrelevante para las actividades de este lab). En Cloud Shell, ingresa lo siguiente:

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

Resultado:

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

Luego, crea la instancia de puerta de enlace NAT. En Cloud Shell, ingresa lo siguiente:

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

Resultado:

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

Ten en cuenta que, de forma predeterminada, la puerta de enlace de Cloud NAT se crea con minPortsPerVm establecido en 64.

Crea las instancias de prueba del consumidor. Aquí completamos las IPs de los productores reservadas para poder consultarlas más adelante en la instancia. En Cloud Shell, ingresa lo siguiente:

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

Resultado:

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. Verifica el comportamiento predeterminado de Cloud NAT

En este punto, las instancias del consumidor usan el comportamiento predeterminado de Cloud NAT, que usa la misma IP reservada "nat-address-1" para comunicarse con todas las direcciones externas. Cloud NAT tampoco tiene habilitado el DPA aún.

Para validar qué puertos asignó Cloud NAT a nuestras instancias de consumidor, ejecuta el siguiente comando:

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

Resultado de ejemplo

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

Como puedes ver en el resultado anterior, Cloud NAT asignó 64 puertos por instancia desde la misma IP externa nat-address-1.

Validemos cuántas conexiones podemos abrir en paralelo antes de habilitar el DPA.

Establece una conexión SSH a la primera instancia del consumidor. En Cloud Shell, ingresa lo siguiente:

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

Ahora deberías estar en la shell de la instancia.

Resultado de muestra (el resultado completo se truncó para mayor brevedad)

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

Desde la instancia del consumidor, primero recuperemos las IPs del productor y propaguémoslas como variables de entorno.

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

Luego, intenta usar curl en ambas instancias de productores para asegurarte de que podamos acceder a ellas correctamente.

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

Ahora intentemos crear muchas conexiones paralelas a una de las instancias del productor ejecutando curl a través de un bucle. Recuerda que Cloud NAT no permite la reutilización de sockets cerrados durante 2 minutos. Por lo tanto, siempre que podamos iterar todos los intentos de conexión en un plazo de 2 minutos, podremos simular conexiones paralelas de esta manera.

Ejecuta el siguiente comando en la sesión de SSH de la instancia

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

Se espera que puedas abrir 64 conexiones paralelas correctamente y que la secuencia de comandos imprima lo siguiente:

Connection # 64 successful

Loop Done, Sleeping for 150s
Connection # 64 successful

Loop Done, Sleeping for 150s

Para ver que no podemos superar las 64 conexiones paralelas, primero espera 2 minutos para que se borren todos los sockets antiguos. Luego, modifica la misma línea de código de la siguiente manera y vuelve a ejecutarla:

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

Ahora deberías ver el siguiente resultado:

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

Esto indica que, si bien las primeras 64 conexiones se realizaron correctamente, las 6 restantes fallaron debido a la falta de puertos.

Entonces, hagamos algo al respecto. Sal de la shell de SSH y habilita DPA en la siguiente sección.

8. Habilita el DPA y valida su comportamiento

Ejecuta el siguiente comando de gcloud, que habilita la DPA y establece la asignación mínima de puertos por VM en 64 y la asignación máxima de puertos en 1,024.

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

que produce lo siguiente

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

Ahora, volvamos a ejecutar get-nat-mapping-info para confirmar que ambas instancias aún tienen solo 64 puertos asignados.

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

Resultado de muestra (truncado para mayor brevedad)

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

No cambió mucho en términos de asignaciones de puertos, ya que la instancia aún no usa ningún puerto de forma activa.

Volvamos a establecer una conexión SSH a la instancia:

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

Vuelve a exportar las variables de entorno de la IP del productor.

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

Vuelve a ejecutar el bucle anterior para simular conexiones paralelas:

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

Ahora deberíamos ver el siguiente resultado:

Connection # 64 successful
Connection # 65 failed

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

Entonces, ¿qué pasó aquí? Cloud NAT aumenta la asignación de puertos a medida que aumenta el uso de puertos, pero esto lleva un tiempo para programarse en toda la capa de redes. Por lo tanto, vemos de 1 a 3 tiempos de espera de conexión antes de completar correctamente el resto de los intentos de conexión.

Especificamos un tiempo de espera agresivo para curl (5 segundos), pero las aplicaciones con tiempos de espera más largos deberían poder completar las conexiones correctamente mientras el DPA aumenta las asignaciones de puertos.

Este comportamiento de aumento se puede ver con mayor claridad cuando ejecutamos el bucle para 1,024 intentos de conexión de la siguiente manera:

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

Ahora esperamos ver el siguiente resultado

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

Dado que Cloud NAT asigna puertos en potencias de 2, lo que duplica las asignaciones en cada paso, vemos que los tiempos de espera de conexión se destacan alrededor de las potencias de 2 entre 64 y 1,024.

Como establecimos maxPortsPerVM en 1,024, no esperamos poder realizar más de 1,024 conexiones. Para probarlo, vuelve a ejecutar el bucle de curl con un recuento superior a 1,024 (después de esperar 2 minutos para restablecer los puertos inactivos).

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

Como se esperaba, el resultado muestra que las conexiones más allá de 1,024 comienzan a fallar.

<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

Si establecemos maxPortsPerVM en 1,024, le indicamos a Cloud NAT que nunca escale las asignaciones de puertos más allá de 1,024 por VM.

Si salimos de la sesión de SSH y volvemos a ejecutar get-nat-mapping-info con la suficiente rapidez, podemos ver los puertos adicionales asignados.

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

Observa el siguiente resultado:

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

Observa cómo consumer-instance-1 tiene 1,024 puertos asignados, pero consumer-instance-2 solo tiene 64. Esto no era posible antes de la DPA y destaca exactamente el poder de la DPA para Cloud NAT.

Si esperas 2 minutos antes de volver a ejecutar el comando get-nat-mapping-info, notarás que consumer-instance-1 vuelve a su valor mínimo de solo 64 puertos asignados. Ilustra no solo la capacidad de la DPA para aumentar las asignaciones de puertos, sino también para liberarlos cuando no se usan y que otras instancias detrás de la misma puerta de enlace NAT los puedan usar.

9. Prueba las reglas de Cloud NAT con DPA

Recientemente, también lanzamos la funcionalidad de reglas de NAT para Cloud NAT, que permite a los clientes escribir reglas que usan IPs de NAT específicas para ciertos destinos externos. Para obtener más información, consulta la página de documentación sobre las reglas de NAT.

En este ejercicio, observaremos la interacción entre las reglas de DPA y NAT. Primero, definamos una regla NAT para usar nat-address-2 cuando se acceda a producer-address-2.

Ejecuta el siguiente comando de gcloud, que crea la regla de NAT con

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

Deberías obtener el siguiente resultado:

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

Ahora volvamos a ejecutar get-nat-mapping-info para ver el efecto de la nueva regla de NAT.

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

que debería producir el siguiente resultado

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

Observa que ahora tenemos puertos adicionales asignados (también en 64, el mínimo especificado) específicamente para nat-address-2 en la jerarquía de ruleMappings.

Entonces, ¿qué sucede si una instancia abre muchas conexiones al destino especificado por la regla de NAT? Averigüémoslo.

Volvamos a establecer una conexión SSH a la instancia:

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

Vuelve a exportar las variables de entorno de la IP del productor.

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

Ahora, volvamos a ejecutar el bucle curl en producerip2 esta vez.

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

Deberías obtener un resultado similar al siguiente:

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

Básicamente, se replica la prueba anterior. Salgamos de la sesión de SSH de la instancia y volvamos a ver las asignaciones de NAT.

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

que debería producir el siguiente resultado

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

Como puedes observar arriba, la IP de NAT predeterminada de consumer-instance-1 ( la IP de nat-address-1) aún tiene solo 64 puertos asignados, pero la IP de la regla de NAT (la IP de nat-address-2) tiene 1,024 puertos asignados. Mientras tanto, consumer-instance-2 mantuvo sus asignaciones predeterminadas de 64 puertos para todas las IPs de NAT.

Como ejercicio, puedes probar el caso inverso. Permite que Cloud NAT desasigne todos los puertos adicionales y, luego, ejecuta el bucle de curl en producerip1 y observa los efectos en el resultado de get-nat-mapping-info.

10. Pasos para la limpieza

Para evitar cargos recurrentes, debes borrar todos los recursos asociados con este codelab.

Primero, borra todas las instancias.

En Cloud Shell, ingresa lo siguiente:

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

Resultado esperado :

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

A continuación, borra el Cloud Router. En Cloud Shell, ingresa lo siguiente:

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

Deberías obtener el siguiente resultado :

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

Liberar todas las direcciones IP externas En Cloud Shell, ingresa lo siguiente:

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

Deberías obtener el siguiente resultado :

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

Borra reglas de firewall de VPC. En Cloud Shell, ingresa lo siguiente:

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

Deberías obtener el siguiente resultado :

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

Borra subredes. En Cloud Shell, ingresa lo siguiente:

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

Deberías obtener el siguiente resultado :

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

Por último, borremos las VPC. En Cloud Shell, ingresa lo siguiente:

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

Deberías obtener el siguiente resultado :

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. ¡Felicitaciones!

Completaste el lab de DPA de Cloud NAT.

Temas abordados

  • Cómo configurar una puerta de enlace de Cloud NAT en preparación para la DPA
  • Cómo inspeccionar las asignaciones de puertos sin DPA
  • Cómo habilitar y configurar el DPA para una puerta de enlace NAT
  • Cómo observar los efectos de la DPA ejecutando conexiones de salida paralelas
  • Cómo agregar reglas NAT a una puerta de enlace NAT con la DPA habilitada
  • Cómo ver el comportamiento de la DPA con reglas ejecutando conexiones de salida a varios destinos

Próximos pasos

©Google LLC o sus afiliados. Todos los derechos reservados. Do not distribute.