Como usar a alocação de porta dinâmica do Cloud NAT

1. Visão geral

A alocação dinâmica de portas (DPA, na sigla em inglês) é um novo recurso do Cloud NAT. Com a DPA ativada, o Cloud NAT aumenta/diminui dinamicamente as alocações de portas para instâncias, dependendo da necessidade delas. A DPA é configurada com limites mínimo e máximo de portas para que nunca reduza as portas abaixo do mínimo nem aumente além do máximo. Isso permite que algumas instâncias por trás dos gateways NAT escalonem verticalmente a contagem de conexões dinamicamente sem precisar alocar mais portas para todas as instâncias por trás do Cloud NAT.

Sem a DPA, todas as instâncias por trás do Cloud NAT recebem o mesmo número de portas, independente do uso, conforme definido pelo parâmetro minPortsPerVm .

Para mais informações, consulte a seção de documentação sobre a DPA de NAT .

O que você vai aprender

  • Como configurar um gateway do Cloud NAT em preparação para a DPA.
  • Como inspecionar alocações de portas sem DPA.
  • Como ativar e configurar a DPA para um gateway NAT.
  • Como observar os efeitos da DPA executando conexões de saída paralelas.
  • Como adicionar regras NAT a um gateway NAT com o DPA ativado.
  • Como ver o comportamento da DPA com regras executando conexões de saída para vários destinos.

O que é necessário

  • Conhecimento básico do Google Compute Engine
  • Conhecimento básico de TCP/IP e rede
  • Conhecimento básico de linha de comando do Unix/Linux
  • É recomendável ter concluído um tour de redes no Google Cloud, como o laboratório Redes no Google Cloud.
  • Um projeto na nuvem do Google Cloud com o "Acesso Alfa" ativado.
  • Entendimento dos conceitos básicos do Cloud NAT.

2. Como usar o console do Google Cloud e o Cloud Shell

Para interagir com o GCP, vamos usar o console do Google Cloud e o Cloud Shell ao longo deste laboratório.

Console do Google Cloud

O console do Cloud pode ser acessado em https://console.cloud.google.com.

75eef5f6fd6d7e41.png

Configuração de ambiente autoguiada

  1. Faça login no Console do Google Cloud e crie um novo projeto ou reutilize um existente. Crie uma conta do Gmail ou do Google Workspace, se ainda não tiver uma.

96a9c957bc475304.png

b9a10ebdf5b5a448.png

a1e3c01a38fa61c2.png

  • O Nome do projeto é o nome de exibição para os participantes do projeto. Ele é uma string de caracteres que não é usada pelas APIs do Google e pode ser atualizada a qualquer momento.
  • O ID do projeto precisa ser exclusivo em todos os projetos do Google Cloud e não pode ser alterado após a definição. O Console do Cloud gera automaticamente uma string única, geralmente não importa o que seja. Na maioria dos codelabs, você precisará fazer referência ao ID do projeto, que geralmente é identificado como PROJECT_ID. Então, se você não gostar dele, gere outro ID aleatório ou crie um próprio e veja se ele está disponível. Em seguida, ele fica "congelado" depois que o projeto é criado.
  • Há um terceiro valor, um Número de projeto, que algumas APIs usam. Saiba mais sobre esses três valores na documentação.
  1. Em seguida, você precisará ativar o faturamento no Console do Cloud para usar os recursos/APIs do Cloud. A execução deste codelab não será muito cara, se tiver algum custo. Para encerrar os recursos e não gerar cobranças além deste tutorial, siga as instruções de "limpeza" encontradas no final do codelab. Novos usuários do Google Cloud estão qualificados para o programa de US$ 300 de avaliação sem custos.

Inicie o Cloud Shell

Embora o Google Cloud e o Spanner possam ser operados remotamente do seu laptop, neste codelab usaremos o Google Cloud Shell, um ambiente de linha de comando executado no Cloud.

No Console do GCP, clique no ícone do Cloud Shell na barra de ferramentas localizada no canto superior direito:

bce75f34b2c53987.png

O provisionamento e a conexão com o ambiente levarão apenas alguns instantes para serem concluídos: Quando o processamento for concluído, você verá algo como:

f6ef2b5f13479f3a.png

Essa máquina virtual contém todas as ferramentas de desenvolvimento necessárias. Ela oferece um diretório principal persistente de 5 GB, além de ser executada no Google Cloud. Isso aprimora o desempenho e a autenticação da rede. Todo o trabalho neste laboratório pode ser feito apenas com um navegador.

3. configurar o laboratório

Neste laboratório, você vai usar um projeto e criar duas VPCs com uma sub-rede em cada uma. Você vai reservar endereços IP externos e criar e configurar um gateway do Cloud NAT (com um Cloud Router), duas instâncias de produtor e duas de consumidor. Depois de validar o comportamento padrão do Cloud NAT, você vai ativar a alocação dinâmica de portas e validar o comportamento dela. Por fim, você também vai configurar regras de NAT e observar a interação entre o DPA e essas regras.

Visão geral da arquitetura de rede:

a21caa6c333909d8.png

4. Reservar endereços IP externos

Vamos reservar todos os endereços IP externos que serão usados neste laboratório. Isso vai ajudar você a escrever todas as regras de NAT e firewall relevantes nas VPCs do consumidor e do produtor.

No Cloud Shell:

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

Saída:

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

Preencha os endereços IP reservados como variáveis de ambiente.

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

Nenhuma saída é esperada, mas para confirmar que os endereços foram preenchidos corretamente. Vamos gerar os valores de todas as variáveis de ambiente.

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

Saída:

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

5. Configuração da VPC e das instâncias do produtor.

Agora vamos criar os recursos do produtor. As instâncias em execução na VPC do produtor vão oferecer o serviço voltado à Internet usando dois IPs públicos "producer-address-1" e "producer-address-2" .

Primeiro, vamos criar a VPC. No Cloud Shell:

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

Saída:

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

Em seguida, vamos criar a sub-rede em us-east4. No Cloud Shell:

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

Saída:

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

Em seguida, vamos criar regras de firewall da VPC para permitir que os endereços IP do NAT alcancem as instâncias do produtor na porta 8080.

Para a primeira regra, no Cloud Shell:

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

Saída:

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

A próxima etapa é criar as duas instâncias de produtor.

As instâncias do produtor vão executar uma implantação simples de proxy nginx.

Para provisionar rapidamente as instâncias com todo o software necessário, vamos criar as instâncias com um script de inicialização que instala o nginx usando o gerenciador de pacotes APT do Debian.

Para escrever regras de NAT, vamos provisionar cada instância com um endereço IP reservado diferente.

Crie a primeira instância. No 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"

Saída:

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

Em seguida, crie a segunda instância. No 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"

Saída:

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. Configurar a VPC do consumidor, o Cloud NAT e as instâncias

Agora que você criou o serviço produtor, é hora de criar a VPC consumidora e o gateway do Cloud NAT.

Depois de criar a VPC e a sub-rede, vamos adicionar uma regra de firewall de entrada simples para permitir o IAP para intervalos de IP de origem TCP. Isso vai permitir que façamos SSH nas instâncias do consumidor diretamente usando o gcloud.

Em seguida, vamos criar um gateway simples do Cloud NAT no modo de alocação manual e o endereço reservado "nat-address-1" associado a ele. Nas próximas partes do codelab, vamos atualizar a configuração do gateway para ativar a alocação dinâmica de portas e, depois, adicionar regras personalizadas.

Primeiro, vamos criar a VPC. No Cloud Shell:

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

Saída:

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

Em seguida, vamos criar uma sub-rede em us-east4. No Cloud Shell:

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

Saída:

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

Em seguida, vamos criar regras de firewall da VPC para permitir que os endereços de intervalos do IAP alcancem as instâncias do consumidor na porta 22.

Para a primeira regra de firewall, execute o seguinte no Cloud Shell:

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

Saída:

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 criar um gateway NAT, precisamos criar uma instância do Cloud Router. Usamos um número de ASN particular, mas isso é irrelevante para as atividades deste laboratório. No Cloud Shell:

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

Saída:

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

Em seguida, crie a instância do gateway NAT. No 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

Saída:

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

Por padrão, o gateway do Cloud NAT é criado com minPortsPerVm definido como 64.

Crie as instâncias de teste do consumidor. Preenchemos os IPs de produtor reservados aqui para poder consultar eles na instância mais tarde. No 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

Saída:

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. Verificar o comportamento padrão do Cloud NAT

Neste ponto, as instâncias consumidoras usam o comportamento padrão do Cloud NAT, que usa o mesmo IP reservado "nat-address-1" para se comunicar com todos os endereços externos. O Cloud NAT ainda não tem a DPA ativada.

Vamos validar quais portas o Cloud NAT alocou para nossas instâncias de consumidor executando o seguinte comando:

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

Exemplo de saída

---
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 você pode ver na saída acima, o Cloud NAT alocou 64 portas por instância do mesmo IP externo nat-address-1.

Vamos validar quantas conexões podemos abrir em paralelo antes de ativar a DPA.

Conecte-se por SSH à primeira instância de consumidor. No Cloud Shell:

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

Agora você está no shell da instância.

Exemplo de saída (saída completa truncada para brevidade)

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

Na instância do consumidor, vamos buscar os IPs do produtor e preenchê-los como variáveis de ambiente.

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

Em seguida, tente fazer curl nas duas instâncias de produtor para garantir que elas possam ser acessadas.

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

Agora vamos tentar criar muitas conexões paralelas com uma das instâncias do produtor executando curl em um loop. O Cloud NAT não permite a reutilização de sockets fechados por dois minutos. Portanto, desde que possamos fazer um loop em todas as tentativas de conexão em dois minutos, é possível simular conexões paralelas dessa forma.

Execute o seguinte comando na sessão SSH da instância:

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

Você espera conseguir abrir 64 conexões paralelas, e o script vai imprimir o seguinte:

Connection # 64 successful

Loop Done, Sleeping for 150s
Connection # 64 successful

Loop Done, Sleeping for 150s

Para ver que não é possível ir além de 64 conexões paralelas, aguarde dois minutos para que todos os sockets antigos sejam limpos. Em seguida, ajuste o mesmo comando de uma linha para o seguinte e execute-o novamente:

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

Agora você vai ver a seguinte saída

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

Isso indica que, embora as primeiras 64 conexões tenham sido bem-sucedidas, as 6 restantes falharam devido à indisponibilidade de portas.

Vamos fazer algo a respeito. Saia do shell SSH e ative a DPA na seção a seguir.

8. Ativar a DPA e validar o comportamento dela

Execute o seguinte comando gcloud, que ativa a DPA e define a alocação mínima de portas por VM como 64 e a alocação máxima como 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

que produz o seguinte:

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

Agora, execute get-nat-mapping-info novamente para confirmar que as duas instâncias ainda têm apenas 64 portas alocadas.

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

Exemplo de saída (truncada para facilitar a leitura)

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

Não houve muitas mudanças em termos de alocações de portas, já que a instância ainda não está usando nenhuma porta ativamente.

Vamos acessar a instância novamente por SSH:

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

Reexporte as variáveis de ambiente de IP do produtor.

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

E execute novamente o loop anterior para simular conexões 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

Agora você vai ver a seguinte saída

Connection # 64 successful
Connection # 65 failed

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

O que aconteceu aqui? O Cloud NAT aumenta a alocação de portas com o aumento do uso, mas isso leva algum tempo para ser programado em toda a camada de rede. Por isso, vemos de uma a três vezes o tempo limite de conexão antes de concluir as demais tentativas.

Especificamos um tempo limite agressivo para curl (5 segundos), mas aplicativos com tempos limite mais longos podem concluir as conexões com sucesso enquanto a DPA aumenta as alocações de porta.

Esse comportamento de aumento pode ser visto mais claramente quando executamos o loop para 1024 tentativas de conexão, assim:

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

Agora esperamos ver a seguinte saída

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

Como o Cloud NAT aloca portas em potências de 2, essencialmente dobrando as alocações em cada etapa, vemos os tempos limite de conexão destacados em torno das potências de 2 entre 64 e 1024.

Como definimos maxPortsPerVM como 1024, não esperamos conseguir mais de 1024 conexões. Para testar isso, execute o loop curl novamente com uma contagem maior que 1024 (depois de esperar dois minutos para redefinir as portas inativas).

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 esperado, a saída mostra que as conexões acima de 1024 começam a falhar.

<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

Ao definir maxPortsPerVM como 1024, instruímos o Cloud NAT a nunca dimensionar as alocações de porta além de 1024 por VM.

Se sairmos da sessão SSH e executarmos get-nat-mapping-info novamente com rapidez suficiente, poderemos ver as portas extras alocadas.

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

e observe a seguinte saída:

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

Observe como consumer-instance-1 tem 1.024 portas alocadas, mas consumer-instance-2 tem apenas 64. Isso não era possível antes do DPA e destaca exatamente o poder do DPA para o Cloud NAT.

Se você esperar dois minutos antes de executar o comando get-nat-mapping-info novamente, vai notar que consumer-instance-1 voltou ao valor mínimo de apenas 64 portas alocadas. Ilustrando não apenas a capacidade do DPA de aumentar as alocações de porta, mas também de liberá-las quando não estão em uso para possível uso por outras instâncias por trás do mesmo gateway NAT.

9. Testar regras do Cloud NAT com DPA

Também lançamos recentemente a funcionalidade de regras de NAT para o Cloud NAT, permitindo que os clientes escrevam regras que usam IPs NAT específicos para determinados destinos externos. Para mais informações, consulte a página de documentação sobre regras de NAT.

Neste exercício, vamos observar a interação entre a DPA e as regras de NAT. Primeiro, vamos definir uma regra NAT para usar nat-address-2 ao acessar producer-address-2.

Execute o seguinte comando gcloud, que cria a regra de NAT usando

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

Você vai receber a seguinte saída

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

Agora, vamos executar get-nat-mapping-info novamente para ver o efeito da nova regra de NAT.

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

que vai gerar o seguinte 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

Agora temos portas extras alocadas (também em 64, o mínimo especificado) especificamente para nat-address-2 na hierarquia ruleMappings.

O que acontece se uma instância abrir muitas conexões com o destino especificado pela regra de NAT? Vamos descobrir.

Vamos acessar a instância novamente por SSH:

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

Reexporte as variáveis de ambiente de IP do produtor.

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

Agora, vamos executar o loop curl novamente em producerip2 desta 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

A saída será semelhante a esta:

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

Basicamente, espelhando o teste anterior. Vamos sair da sessão SSH da instância e analisar os mapeamentos de NAT novamente.

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

que vai gerar o seguinte 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 você pode observar acima, o IP NAT padrão de consumer-instance-1 ( o IP de nat-address-1) ainda tem apenas 64 portas alocadas, mas o IP da regra NAT (IP de nat-address-2) tem 1.024 portas alocadas. Enquanto isso, o consumer-instance-2 manteve as alocações padrão de 64 portas para todos os IPs NAT.

Como exercício, teste o caso inverso. Deixe o Cloud NAT desalocar todas as portas extras e execute o loop curl em producerip1. Observe os efeitos na saída de get-nat-mapping-info.

10. Etapas de limpeza

Para evitar cobranças recorrentes, exclua todos os recursos associados a este codelab.

Primeiro, exclua todas as instâncias.

No Cloud Shell:

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

Resposta esperada :

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

Em seguida, exclua o Cloud Router. No Cloud Shell:

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

Você vai receber esta resposta :

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

Libere todos os endereços IP externos. No Cloud Shell:

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

Você vai receber esta resposta :

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

Exclua regras de firewall da VPC. No Cloud Shell:

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

Você vai receber esta resposta :

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

Exclua sub-redes. No Cloud Shell:

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

Você vai receber esta resposta :

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 fim, vamos excluir as VPCs. No Cloud Shell:

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

Você vai receber esta resposta :

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. Parabéns!

Você concluiu o laboratório sobre a DPA do Cloud NAT.

O que você abordou

  • Como configurar um gateway do Cloud NAT em preparação para a DPA.
  • Como inspecionar alocações de portas sem DPA.
  • Como ativar e configurar a DPA para um gateway NAT.
  • Como observar os efeitos da DPA executando conexões de saída paralelas.
  • Como adicionar regras NAT a um gateway NAT com o DPA ativado.
  • Como ver o comportamento da DPA com regras executando conexões de saída para vários destinos.

Próximas etapas

©Google, Inc. ou afiliadas. Todos os direitos reservados. Distribuição proibida.