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

1. Visão geral

A alocação dinâmica de portas (DPA) é um novo recurso do Cloud NAT. Com a DPA ativada, o Cloud NAT escalona dinamicamente as alocações de porta para as instâncias de acordo com a necessidade. A DPA é configurada com limites mínimos e máximos de portas para que nunca reduza as portas abaixo do mínimo nem escalone além do máximo. Isso permite que algumas instâncias por trás de gateways NAT escalonem dinamicamente a contagem de conexões sem precisar alocar mais portas para todas as instâncias que estão atrás do Cloud NAT.

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

Para mais informações, consulte a seção "Documentação sobre a DPA do 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 o DPA.
  • Como ativar e configurar o 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 a DPA ativada.
  • Como conferir o comportamento da DPA com as 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
  • É útil fazer um tour sobre redes no Google Cloud, como o laboratório Rede no Google Cloud.
  • Um projeto do Google Cloud com "Acesso Alfa" ativado.
  • Noções básicas sobre os 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 neste 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 depois criar e configurar um gateway do Cloud NAT (com um Cloud Router), duas instâncias de produtor e duas instâncias do 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. Por fim, você também vai configurar regras NAT e observar a interação entre as regras de DPA e de NAT.

Visão geral da arquitetura de rede:

a21caa6c333909d8.png

4. Reservar endereços IP externos

Vamos reservar todos os endereços IP externos para serem usados neste laboratório. Isso vai ajudar você a gravar todas as regras relevantes de NAT e firewall na VPC 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 que foram 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 resposta é 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. VPC do produtor e configuração das instâncias.

Agora criaremos os recursos para os recursos do produtor. As instâncias em execução na VPC do produtor oferecerão 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

A seguir, 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 de VPC para permitir que os endereços IP do NAT alcancem as instâncias do produtor na porta 8080.

Para a primeira regra do 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 do produtor.

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

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

Para escrever regras NAT, provisionaremos 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 do produtor, é hora de criar a VPC do consumidor 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 nos permitirá estabelecer conexões SSH com as instâncias de consumidores diretamente usando a gcloud.

Depois vamos criar um gateway simples do Cloud NAT no modo de alocação manual e o endereço reservado "nat-address-1" associados 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, mais tarde, 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

A seguir, 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 de 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 ASN privado, mas ele é 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 do produtor reservados aqui para poder se referir a 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 do consumidor usam o comportamento padrão do Cloud NAT, que utiliza o mesmo IP reservado "nat-address-1" para comunicação com endereços externos. O Cloud NAT também não tem a DPA ativada.

Vamos validar quais portas o Cloud NAT alocou 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 é possível observar 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 via SSH à primeira instância do consumidor. No Cloud Shell:

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

Agora você deve estar no shell da instância.

Exemplo de resposta (resultado completo truncado para concisão)

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

Na instância do consumidor, primeiro buscaremos os dois IPs do produtor e os preencheremos 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, use o curl para as duas instâncias do produtor e garanta que elas podem ser alcançadas com sucesso.

<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. Lembre-se de que o Cloud NAT não permite a reutilização de soquetes fechados por dois minutos. Portanto, desde que seja possível fazer a repetição de todas as tentativas de conexão em dois minutos, será 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

O esperado é que você consiga abrir 64 conexões paralelas e o script mostre o seguinte:

Connection # 64 successful

Loop Done, Sleeping for 150s
Connection # 64 successful

Loop Done, Sleeping for 150s

Para confirmar que não é possível ultrapassar 64 conexões paralelas, aguarde dois minutos para que todos os soquetes antigos sejam apagados. Em seguida, ajuste a mesma descrição para o seguinte e execute-a 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

A saída a seguir seria

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 conexões restantes falharam devido à indisponibilidade de portas.

Vamos fazer algo a respeito. Em seguida, saia do shell SSH e ative a DPA na próxima seção.

8. Ativar a DPA e validar o comportamento dela

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

O que gera o seguinte

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

Agora, execute novamente o get-nat-mapping-info 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 resposta (truncado para simplificar)

---
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 mudou muita coisa em termos de alocações de portas, porque a instância ainda não está usando portas ativamente.

Vamos usar o SSH de volta para a instância:

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

Exporte novamente as variáveis de ambiente do 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"`

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

A seguinte saída vai aparecer:

Connection # 64 successful
Connection # 65 failed

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

O que aconteceu aqui? O Cloud NAT intensifica a alocação de portas conforme o aumento no uso delas, mas isso leva algum tempo para ser programado em toda a camada de rede. Portanto, vemos de 1 a 3 tempos limite de conexão antes de concluirmos com êxito o restante das tentativas de conexão.

Especificamos um tempo limite agressivo para curl (5 segundos), mas os aplicativos com tempos limite mais longos devem conseguir concluir as conexões com sucesso enquanto a DPA está aumentando as alocações de portas.

Esse comportamento de ampliação pode ser visto com mais clareza quando executamos o loop para 1024 tentativas de conexão, como

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 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, basicamente dobrando as alocações em cada etapa, vemos os tempos limite de conexão destacados com a potência de 2 entre 64 e 1.024.

Como definimos maxPortsPerVM como 1.024, não esperamos a capacidade de mais de 1.024 conexões. Para testar isso, execute novamente o loop curl com uma contagem maior que 1.024, depois de esperar 2 minutos para redefinir as portas desatualizadas.

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 além 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 1.024, instruímos o Cloud NAT a nunca escalonar as alocações de porta além de 1.024 por VM.

Se sairmos da sessão SSH e executarmos o get-nat-mapping-info de novo rápido o bastante, 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 portas alocadas. Isso não era possível antes da DPA e destaca exatamente o poder da DPA para o Cloud NAT.

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

9. Testar as regras do Cloud NAT com o DPA

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

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

Execute o comando gcloud a seguir, que cria a regra 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

A saída a seguir será

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

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

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

O que deve produzir o seguinte

---
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 quando uma instância abre muitas conexões com o destino especificado pela regra NAT? Vamos descobrir.

Vamos usar o SSH de volta para a instância:

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

Exporte novamente as variáveis de ambiente do 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 novamente o loop curl 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

Espelhando basicamente o teste anterior. Vamos sair da sessão SSH da instância e analisar os mapeamentos de novo.

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

O que deve produzir o seguinte

---
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, 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, execute o loop curl em producerip1 e 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

Saída 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ê deve esperar a seguinte saída :

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ê deve esperar a seguinte saída :

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 as regras de firewall da VPC. No Cloud Shell:

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

Você deve esperar a seguinte saída :

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

Excluir sub-redes. No Cloud Shell:

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

Você deve esperar a seguinte saída :

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ê deve esperar a seguinte saída :

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 de DPA do Cloud NAT.

Conteúdo abordado

  • Como configurar um gateway do Cloud NAT em preparação para a DPA.
  • Como inspecionar alocações de portas sem o DPA.
  • Como ativar e configurar o 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 a DPA ativada.
  • Como conferir o comportamento da DPA com as 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.