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 función nueva de Cloud NAT. Con el DPA habilitado, Cloud NAT aumenta o reduce dinámicamente las asignaciones de puertos para las instancias según sus necesidades. El DPA está configurado con límites mínimos y máximos de puertos para que nunca reduzca la escala verticalmente de los puertos por debajo del mínimo ni escale verticalmente más allá del máximo. Esto permite que algunas instancias detrás de las puertas de enlace NAT escalen verticalmente 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 DPA, a todas las instancias detrás de Cloud NAT se les asigna la misma cantidad de puertos independientemente del uso, como se define en el parámetro minPortsPerVm .

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

Qué aprenderás

  • Cómo configurar una puerta de enlace de Cloud NAT como preparación para 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 del DPA mediante la ejecución de conexiones de salida paralelas
  • Cómo agregar reglas de NAT a una puerta de enlace de NAT con DPA habilitado
  • Cómo ver el comportamiento del DPA con reglas mediante la ejecución de 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 Herramientas de redes en Google Cloud.
  • Un proyecto de Google Cloud con “acceso alfa” habilitado.
  • Comprender los conceptos básicos de Cloud NAT

2. Usa la consola de Google Cloud y Cloud Shell

Para interactuar con GCP, usaremos la consola de Google Cloud 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 dinámica de puertos y validarás su comportamiento. Por último, también configurarás las reglas de NAT y observarás la interacción entre las reglas de NAT y DPA.

Descripción general de la arquitectura de Herramientas de redes:

a21caa6c333909d8.png

4. Reservar direcciones IP externas

Reservemos todas las direcciones IP externas para usar en este lab. Esto te ayudará a escribir todas las reglas relevantes de NAT y firewall en la VPC del consumidor y del productor.

Desde Cloud Shell:

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 para confirmar que las direcciones se propagaron correctamente. Obtengamos el resultado de 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 instancias y VPC 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 mediante dos IP públicas “producer-address-1” y “producer-address-2” de Google Cloud.

Primero, creemos la VPC. Desde Cloud Shell:

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. Desde Cloud Shell:

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:

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 del productor ejecutarán una implementación simple del proxy de nginx.

Para aprovisionar rápidamente las instancias con todo el software requerido, 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. Desde 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"

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

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 de 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 el IAP para los rangos de IP de origen de TCP. Esto nos permitirá establecer una conexión SSH a las instancias del consumidor directamente con gcloud.

A continuación, crearemos una puerta de enlace de Cloud NAT simple en el modo de asignación manual y la dirección reservada “nat-address-1”. asociados con ella. En partes posteriores del codelab, actualizaremos la configuración de la puerta de enlace para habilitar la asignación dinámica de puertos y, más adelante, agregaremos reglas personalizadas.

Primero, creemos la VPC. Desde Cloud Shell:

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. Desde Cloud Shell:

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 una regla de firewall de VPC para permitir que las direcciones de rangos 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 NAT, primero debemos crear una instancia de Cloud Router (usamos un número ASN privado, pero es irrelevante para las actividades de este lab). Desde Cloud Shell:

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

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. Propagamos las IP de productor reservadas aquí para poder hacer referencia a ellas dentro de la instancia más adelante. Desde 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

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 DPA habilitado aún.

Ejecuta el siguiente comando para validar qué puertos asignó Cloud NAT a nuestras instancias de consumidor

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

Resultado de muestra

---
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. Desde Cloud Shell:

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

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

Resultado de muestra (resultado completo truncado para abreviación)

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

Desde la instancia del consumidor, primero recuperamos ambas IP de productor y las propagamos 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 ejecutar el comando curl en ambas instancias de productor para asegurarte de que podemos llegar 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 de 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 realizar un bucle a lo largo de todos los intentos de conexión en 2 minutos, podemos simular conexiones paralelas de esta manera.

Ejecuta el siguiente comando en la sesión 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

Esperarías poder abrir correctamente 64 conexiones paralelas, y la secuencia de comandos debería mostrar lo siguiente:

Connection # 64 successful

Loop Done, Sleeping for 150s
Connection # 64 successful

Loop Done, Sleeping for 150s

Para ver que no podemos ir más allá de las 64 conexiones paralelas, primero espere 2 minutos para permitir que todos los sockets antiguos se borren. Luego, ajusta la línea para lo siguiente y vuelve a ejecutarlo.

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 esperarías 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 disponibilidad de puertos.

Hagamos algo al respecto. Sal de la shell SSH y habilitemos el DPA en la siguiente sección.

8. Habilita el DPA y valida su comportamiento

Ejecuta el siguiente comando de gcloud, que habilita el DPA, establece la asignación de puertos mínima por VM en 64 y la asignación máxima de puertos en 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

Esto da como resultado 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 abreviar)

---
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 está usando 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 IP de 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"`

Y 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

¿Qué pasó aquí? Cloud NAT acelera la asignación de puertos cuando aumenta el uso de puertos, pero eso tarda un tiempo en programarse en toda la capa de red. 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 con éxito mientras el DPA aumenta las asignaciones de puertos.

Este comportamiento de aumento se puede ver con mayor claridad cuando ejecutamos el bucle para intentos de conexión de 1,024 (de este modo)

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

Debido a que Cloud NAT asigna puertos en potencias de 2, lo que, básicamente, duplica las asignaciones en cada paso, vemos los tiempos de espera de conexión destacados alrededor de las potencias de 2 entre 64 y 1,024.

Como configuramos maxPortsPerVM en 1,024, no esperamos poder usar más de 1,024 conexiones. Para probarlo, volvemos a ejecutar el bucle 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 era de esperar, el resultado muestra que las conexiones superiores a 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

Cuando establecimos maxPortsPerVM en 1,024, 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 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 puertos asignados. Esto no era fácil de hacer antes de la DPA, y destaca con exactitud la potencia de 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 volvió a su valor mínimo de solo 64 puertos asignados. Esto ilustra la capacidad de la DPA de aumentar las asignaciones de puertos y también liberarlas cuando no estén en uso para que otras instancias detrás de la misma puerta de enlace NAT puedan usarlas.

9. Prueba las reglas de Cloud NAT con DPA

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

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

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

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

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

El resultado debería ser el siguiente:

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

Entonces, ¿qué sucede si una instancia abre muchas conexiones al destino especificado por la regla 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 IP de 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 con 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 esperar 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, replica la prueba anterior. Sal de la sesión SSH de la instancia y volvamos a observar las asignaciones NAT.

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

El resultado debería ser el siguiente:

---
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 para nat-address-1) aún tiene solo 64 puertos asignados, pero la IP de la regla NAT (IP para nat-address-2) tiene 1,024 puertos asignados. Mientras tanto, consumer-instance-2 mantuvo sus asignaciones predeterminadas de 64 puertos para todas las IP de NAT.

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

10. Pasos de limpieza

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

Primero, borra todas las instancias.

Desde Cloud Shell:

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. Desde Cloud Shell:

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

Deberías esperar el siguiente resultado :

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

Libera todas las direcciones IP externas. Desde Cloud Shell:

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

Deberías esperar 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 las reglas de firewall de VPC. Desde Cloud Shell:

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

Deberías esperar 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 las subredes. Desde Cloud Shell:

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

Deberías esperar 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. Desde Cloud Shell:

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

Deberías esperar 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 como preparación para 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 del DPA mediante la ejecución de conexiones de salida paralelas
  • Cómo agregar reglas de NAT a una puerta de enlace de NAT con DPA habilitado
  • Cómo ver el comportamiento del DPA con reglas mediante la ejecución de conexiones de salida a varios destinos

Próximos pasos

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