Utiliser l'allocation de ports dynamique Cloud NAT

Utiliser l'allocation de ports dynamique Cloud NAT

À propos de cet atelier de programmation

subjectDernière mise à jour : août 25, 2023
account_circleRédigé par Ghaleb Al-Habian

1. Présentation

L'allocation dynamique de ports (DPA) est une nouvelle fonctionnalité de Cloud NAT. Lorsque le DPA est activé, Cloud NAT effectue un scaling dynamique des allocations de ports pour les instances en fonction de leurs besoins. Le DPA est configuré avec des limites minimales et maximales de ports de sorte qu'il ne diminue jamais le nombre de ports en dessous de la valeur minimale, ni à la hausse au-delà de la valeur maximale. Cela permet à certaines instances situées derrière des passerelles NAT d'augmenter de manière dynamique le nombre de connexions sans avoir à allouer plus de ports à toutes les instances protégées par Cloud NAT.

Sans DPA, toutes les instances derrière Cloud NAT se voient attribuer le même nombre de ports, quelle que soit leur utilisation, comme défini par le paramètre minPortsPerVm .

Pour en savoir plus, consultez la section de la documentation sur le DPA NAT .

Points abordés

  • Configurer une passerelle Cloud NAT en vue du DPA.
  • Inspecter les attributions de ports sans DPA
  • Activer et configurer le DPA pour une passerelle NAT
  • Comment observer les effets du DPA en exécutant des connexions de sortie parallèles
  • Ajouter des règles NAT à une passerelle NAT avec DPA activé
  • Comment visualiser le comportement de l'APD avec des règles en exécutant des connexions de sortie vers plusieurs destinations.

Prérequis

  • Connaissance de base de Google Compute Engine
  • Connaissance de base de la mise en réseau et des protocoles TCP/IP
  • Connaissances de base de la ligne de commande Unix/Linux
  • Il est utile d'avoir suivi une visite guidée de la mise en réseau dans Google Cloud, par exemple lors de l'atelier Networking in Google Cloud.
  • Un projet Google Cloud avec "accès alpha" est activé.
  • Comprendre les principes de base de Cloud NAT

2. Utiliser la console Google Cloud et Cloud Shell

Pour interagir avec GCP, nous allons utiliser à la fois la console Google Cloud et Cloud Shell tout au long de cet atelier.

Console Google Cloud

La console Cloud est accessible à l'adresse https://console.cloud.google.com.

75eef5f6fd6d7e41.png

Configuration de l'environnement au rythme de chacun

  1. Connectez-vous à la console Google Cloud, puis créez un projet ou réutilisez un projet existant. (Si vous ne possédez pas encore de compte Gmail ou Google Workspace, vous devez en créer un.)

96a9c957bc475304.png

b9a10ebdf5b5a448.png

a1e3c01a38fa61c2.png

  • Le nom du projet est le nom à afficher pour les participants au projet. Il s'agit d'une chaîne de caractères qui n'est pas utilisée par les API Google, et que vous pouvez modifier à tout moment.
  • L'ID du projet doit être unique sur l'ensemble des projets Google Cloud et doit être immuable (vous ne pouvez pas le modifier une fois que vous l'avez défini). Cloud Console génère automatiquement une chaîne unique dont la composition importe peu, en général. Dans la plupart des ateliers de programmation, vous devrez référencer l'ID du projet (généralement identifié comme PROJECT_ID), donc s'il ne vous convient pas, générez-en un autre au hasard ou définissez le vôtre, puis vérifiez s'il est disponible. Il est ensuite "gelé" une fois le projet créé.
  • La troisième valeur est le numéro de projet, utilisé par certaines API. Pour en savoir plus sur ces trois valeurs, consultez la documentation.
  1. Vous devez ensuite activer la facturation dans Cloud Console afin d'utiliser les ressources/API Cloud. L'exécution de cet atelier de programmation est très peu coûteuse, voire sans frais. Pour arrêter les ressources afin d'éviter qu'elles ne vous soient facturées après ce tutoriel, suivez les instructions de nettoyage indiquées à la fin de l'atelier. Les nouveaux utilisateurs de Google Cloud peuvent participer au programme d'essai gratuit pour bénéficier d'un crédit de 300 $.

Démarrer Cloud Shell

Bien que Google Cloud puisse être utilisé à distance depuis votre ordinateur portable, nous allons nous servir de Google Cloud Shell pour cet atelier de programmation, un environnement de ligne de commande exécuté dans le cloud.

Depuis la console GCP, cliquez sur l'icône Cloud Shell de la barre d'outils située dans l'angle supérieur droit :

bce75f34b2c53987.png

Le provisionnement et la connexion à l'environnement prennent quelques instants seulement. Une fois l'opération terminée, le résultat devrait ressembler à ceci :

f6ef2b5f13479f3a.png

Cette machine virtuelle contient tous les outils de développement nécessaires. Elle comprend un répertoire d'accueil persistant de 5 Go et s'exécute sur Google Cloud, ce qui améliore nettement les performances du réseau et l'authentification. Vous pouvez réaliser toutes les activités de cet atelier dans un simple navigateur.

3. Mettre en place l'atelier

Dans cet atelier, vous allez utiliser un projet et créer deux VPC comportant chacun un sous-réseau. Vous allez réserver des adresses IP externes, puis créer et configurer une passerelle Cloud NAT (avec un routeur Cloud Router), deux instances de producteur et deux instances client. Après avoir validé le comportement Cloud NAT par défaut, vous activerez l'allocation de ports dynamique et validerez son comportement. Enfin, vous configurerez des règles NAT et observerez les interactions entre l'APD et les règles NAT.

Présentation de l'architecture réseau:

a21caa6c333909d8.png

4. Réserver des adresses IP externes

Nous allons réserver toutes les adresses IP externes pour cet atelier. Cela vous aidera à écrire toutes les règles NAT et de pare-feu pertinentes dans les VPC du client et du producteur.

Depuis Cloud Shell:

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

Sortie :

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

Renseignez les adresses IP réservées en tant que variables d'environnement.

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

Aucun résultat attendu, mais pour confirmer que les adresses ont été correctement renseignées. Nous allons générer les valeurs de toutes les variables d'environnement.

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

Sortie :

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

5. Configuration du VPC du producteur et des instances.

Nous allons maintenant créer les ressources pour les ressources du producteur. Les instances exécutées dans le VPC du producteur proposent le service Internet à l'aide de deux adresses IP publiques : "producer-address-1". et "producteur-address-2" pour en savoir plus.

Commençons par créer le VPC. Depuis Cloud Shell:

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

Sortie :

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

Créons maintenant le sous-réseau dans la région us-east4. Depuis Cloud Shell:

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

Sortie :

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

Nous allons maintenant créer des règles de pare-feu VPC pour permettre aux adresses IP NAT d'atteindre les instances du producteur sur le port 8080.

Pour la première règle, dans Cloud Shell:

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

Sortie :

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

L'étape suivante consiste à créer les deux instances de producteur.

Les instances du producteur vont exécuter un déploiement de proxy nginx simple.

Pour provisionner rapidement les instances avec tous les logiciels nécessaires, nous allons créer les instances avec un script de démarrage qui installe nginx à l'aide du gestionnaire de packages Debian APT.

Pour pouvoir écrire des règles NAT, nous allons provisionner chaque instance avec une adresse IP réservée différente.

Créez la première instance. Depuis 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"

Sortie :

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

Créez ensuite la deuxième instance. Depuis 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"

Sortie :

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. Configurer le VPC client, Cloud NAT et les instances

Maintenant que vous avez créé le service producteur, vous pouvez créer le VPC consommateur et sa passerelle Cloud NAT.

Après avoir créé le VPC et le sous-réseau, nous ajouterons une simple règle de pare-feu d'entrée pour autoriser IAP pour les plages d'adresses IP sources TCP. Cela nous permettra de nous connecter en SSH aux instances client directement à l'aide de gcloud.

Nous créerons ensuite une passerelle Cloud NAT simple en mode d'allocation manuelle et l'adresse réservée "nat-address-1". qui lui est associée. Dans les parties suivantes de l'atelier de programmation, nous mettrons à jour la configuration de la passerelle pour activer l'allocation de ports dynamique. Nous ajouterons ensuite des règles personnalisées.

Commençons par créer le VPC. Depuis Cloud Shell:

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

Sortie :

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

Créons maintenant un sous-réseau dans la région us-east4. Depuis Cloud Shell:

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

Sortie :

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

Nous allons maintenant créer des règles de pare-feu VPC afin d'autoriser les plages d'adresses IAP à atteindre les instances de clients sur le port 22.

Pour la première règle de pare-feu, exécutez la commande suivante à partir de Cloud Shell:

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

Sortie :

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

Avant de créer une passerelle NAT, nous devons d'abord créer une instance Cloud Router (nous utilisons un numéro ASN privé qui n'est pas pertinent pour les activités de cet atelier). Depuis Cloud Shell:

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

Sortie :

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

Créez ensuite l'instance de passerelle NAT. Depuis 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

Sortie :

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

Notez que, par défaut, la passerelle Cloud NAT est créée avec minPortsPerVm défini sur 64

Créer les instances de test client Nous insérons ici les adresses IP de producteurs réservées afin de pouvoir y faire référence ultérieurement dans l'instance. Depuis 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

Sortie :

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. Vérifier le comportement Cloud NAT par défaut

À ce stade, les instances consommateur utilisent le comportement Cloud NAT par défaut, qui utilise la même adresse IP réservée "nat-address-1". pour communiquer avec toutes les adresses externes. L'APD n'est pas encore activé pour Cloud NAT.

Vérifions les ports sur lesquels Cloud NAT a alloué nos instances clientes en exécutant la commande suivante :

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

Exemple de résultat

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

Comme vous pouvez le voir dans le résultat ci-dessus, Cloud NAT a alloué 64 ports par instance à partir de la même adresse IP externe nat-address-1.

Vérifions le nombre de connexions qu'il est possible d'ouvrir en parallèle avant d'activer le DPA.

Connectez-vous en SSH à la première instance de client. Depuis Cloud Shell:

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

Vous devriez à présent vous trouver dans le shell de l'instance.

Exemple de résultat (la sortie complète est tronquée pour des raisons de concision)

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

À partir de l'instance consommateur, récupérons les deux adresses IP de producteur et ajoutons-les en tant que variables d'environnement.

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

Essayez ensuite d'utiliser la commande curl avec les deux instances du producteur pour vous assurer de pouvoir les joindre.

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

Essayons maintenant de créer de nombreuses connexions parallèles à l'une des instances de producteur en exécutant curl via une boucle. Rappelez-vous que Cloud NAT n'autorise pas la réutilisation de sockets fermés pendant deux minutes. Par conséquent, tant que nous pouvons boucler toutes les tentatives de connexion en moins de deux minutes, nous pouvons simuler des connexions parallèles de cette façon.

Exécutez la commande suivante dans la session SSH de l'instance

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

Vous vous attendez à ce qu'il puisse ouvrir 64 connexions parallèles et le script devrait afficher ce qui suit :

Connection # 64 successful

Loop Done, Sleeping for 150s
Connection # 64 successful

Loop Done, Sleeping for 150s

Pour vérifier que nous ne pouvons pas dépasser les 64 connexions parallèles, attendez d'abord deux minutes pour permettre à tous les anciens sockets de s'effacer. Ensuite, modifiez la même ligne de texte comme suit et réexécutez-la.

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

Vous devez obtenir le résultat suivant :

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

Cela indique que si les 64 premières connexions ont réussi, les 6 autres connexions ont échoué en raison de l'indisponibilité des ports.

Ensuite, nous allons quitter le shell SSH et activer l'APD dans la section suivante.

8. Activer l&#39;APD et valider son comportement

Exécutez la commande gcloud suivante, qui active le DPA, définit l'allocation de ports minimale par VM sur 64 et l'allocation de ports maximale sur 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

Ce qui renvoie le résultat suivant :

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

Exécutons à nouveau get-nat-mapping-info pour vérifier que les deux instances ne disposent toujours que de 64 ports alloués

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

Exemple de sortie (tronqué pour des raisons de concision)

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

Rien n'a changé en termes d'allocation de ports, car l'instance n'utilise pas encore activement de ports.

Reconnectez-vous en SSH à l'instance:

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

Exportez à nouveau les variables d'environnement IP du producteur.

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

Réexécutez la boucle précédente pour simuler des connexions parallèles:

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

Le résultat suivant doit s'afficher :

Connection # 64 successful
Connection # 65 failed

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

Que s'est-il passé ? Cloud NAT augmente l'allocation des ports en fonction de l'augmentation de l'utilisation des ports, mais leur programmation prend un certain temps dans la couche réseau. Par conséquent, nous voyons entre un et trois délais avant expiration de la connexion avant de terminer les autres tentatives de connexion.

Nous avons spécifié un délai avant expiration agressif pour curl (5 secondes), mais les applications avec des délais d'inactivité plus longs devraient pouvoir terminer les connexions avec succès pendant que le DPA augmente les allocations de ports.

Ce comportement d'augmentation est plus clair lorsque nous exécutons la boucle pour 1 024 tentatives de connexion comme ceci

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

Nous nous attendons à présent à la sortie suivante :

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

Comme Cloud NAT alloue des ports en puissances de 2, ce qui double les allocations à chaque étape, nous voyons les délais avant expiration de la connexion mis en évidence autour des puissances 2 entre 64 et 1 024.

Comme nous avons défini maxPortsPerVM sur 1 024, nous ne nous attendons pas à pouvoir dépasser 1 024 connexions. Nous pouvons tester cela en exécutant à nouveau la boucle curl avec un nombre supérieur à 1 024 (après avoir attendu deux minutes pour réinitialiser les ports obsolètes).

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

Comme prévu, la sortie indique que les connexions après 1024 ne démarrent pas

<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

En définissant maxPortsPerVM sur 1 024, nous avons demandé à Cloud NAT de ne jamais effectuer un scaling des allocations de ports au-delà de 1 024 par VM.

Si nous quittons la session SSH et réexécutons get-nat-mapping-info assez rapidement, nous pouvons voir les ports supplémentaires alloués.

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

Observez le résultat suivant :

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

Notez que 1 024 ports sont alloués pour consumer-instance-1, mais que 64 ports sont alloués pour consumer-instance-2. Cela n'était pas facile à réaliser avant l'adoption du DPA, et cela met en évidence la puissance de l'APD pour Cloud NAT.

Si vous attendez deux minutes avant d'exécuter à nouveau la commande get-nat-mapping-info, vous remarquerez que consumer-instance-1 a retrouvé sa valeur minimale de 64 ports alloués. Illustration de la capacité du DPA à augmenter les allocations de ports, mais aussi à les libérer lorsqu'elles ne sont pas utilisées pour une utilisation potentielle par d'autres instances derrière la même passerelle NAT.

9. Tester les règles Cloud NAT avec l&#39;APD

Nous avons récemment lancé une fonctionnalité de règles NAT pour Cloud NAT, qui permet aux clients d'écrire des règles qui utilisent des adresses IP NAT spécifiques pour certaines destinations externes. Pour en savoir plus, consultez la page de documentation sur les règles NAT.

Dans cet exercice, nous observons l'interaction entre l'APD et les règles NAT. Commençons par définir une règle NAT à utiliser pour nat-address-2 lors de l'accès à producer-address-2.

Exécutez la commande gcloud suivante, qui crée la règle NAT à l'aide de

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

Vous devriez obtenir le résultat suivant :

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

Exécutons à nouveau get-nat-mapping-info pour observer l'effet de la nouvelle règle NAT.

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

Ce qui doit générer le résultat suivant :

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

Notez que des ports supplémentaires sont maintenant alloués (64, le nombre minimal spécifié) spécifiquement pour nat-address-2 sous la hiérarchie ruleMappings.

Que se passe-t-il si une instance ouvre de nombreuses connexions vers la destination spécifiée par la règle NAT ? Vérifions-le dès maintenant.

Reconnectez-vous en SSH à l'instance:

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

Exportez à nouveau les variables d'environnement IP du producteur.

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

Maintenant, réexécutons la boucle curl sur producerip2 cette fois-ci.

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

Vous devriez obtenir un résultat semblable à celui-ci :

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

En gros, en reproduisant le test précédent. Quittons la session SSH de l'instance et examinons à nouveau les mappages nat.

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

Vous devriez obtenir le résultat suivant :

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

Comme vous pouvez le constater ci-dessus, l'adresse IP NAT par défaut de consumer-instance-1 ( l'adresse IP de nat-address-1) n'a toujours que 64 ports alloués, tandis que 1 024 ports sont alloués à l'adresse IP de la règle NAT (adresse IP pour nat-address-2). Dans le même temps, consumer-instance-2 a conservé ses allocations par défaut de 64 ports pour toutes les adresses IP NAT.

À titre d'exercice, vous pouvez tester le cas inverse. Laissez Cloud NAT désallouer tous les ports supplémentaires, puis exécutez la boucle curl sur producerip1 et observez les effets sur le résultat de get-nat-mapping-info.

10. Étapes de nettoyage

Pour éviter des frais récurrents, vous devez supprimer toutes les ressources associées à cet atelier de programmation.

Commencez par supprimer toutes les instances.

Depuis Cloud Shell:

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

Résultat attendu :

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

Supprimez ensuite le routeur Cloud Router. Depuis Cloud Shell:

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

Vous devez obtenir le résultat suivant :

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

Libérez toutes les adresses IP externes. Depuis Cloud Shell:

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

Vous devez obtenir le résultat suivant :

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

Supprimer des règles de pare-feu VPC Depuis Cloud Shell:

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

Vous devez obtenir le résultat suivant :

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

supprimer des sous-réseaux ; Depuis Cloud Shell:

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

Vous devez obtenir le résultat suivant :

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

Enfin, supprimons les VPC. Depuis Cloud Shell:

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

Vous devez obtenir le résultat suivant :

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. Félicitations !

Vous avez terminé l'atelier DPA Cloud NAT.

Points abordés

  • Configurer une passerelle Cloud NAT en vue du DPA.
  • Inspecter les attributions de ports sans DPA
  • Activer et configurer le DPA pour une passerelle NAT
  • Comment observer les effets du DPA en exécutant des connexions de sortie parallèles
  • Ajouter des règles NAT à une passerelle NAT avec DPA activé
  • Comment visualiser le comportement de l'APD avec des règles en exécutant des connexions de sortie vers plusieurs destinations.

Étapes suivantes

©Google, Inc. or its affiliates. Tous droits réservés. Ne pas diffuser.