Configurer des adresses IP publiques utilisées en mode privé pour GKE

Ce tutoriel explique comment appliquer des adresses IP publiques utilisées en mode privé (Privately Used Public IPs ou PUPI) à des blocs d'adresses de pod Google Kubernetes Engine (GKE). Les organisations clientes du service dont l'adresse IPv4 est limitée peuvent gérer les adresses à l'aide d'adresses PUPI dans les clouds privés virtuels (VPC) du producteur de services, grâce à une option de gestion des adresses.

Ce document est destiné aux architectes réseau et aux administrateurs système GKE dont les entreprises proposent des services gérés sur une infrastructure GKE hébergée sur Google Cloud.

Présentation

Certaines entreprises souhaitent fournir des services gérés à leurs clients via des clusters Kubernetes ou via GKE sur Google Cloud. Toutefois, Kubernetes peut nécessiter de nombreuses adresses IP pour ses différents composants. Pour certaines organisations, répondre à cette exigence est difficile, voire impossible, car elles ne peuvent pas attribuer des blocs CIDR (Classless Inter-domain Routing) 10.0.0.0/8, 172.16.0.0/12 et 192.168.0.0/16 (RFC 1918) d'une taille appropriée.

Une manière de réduire l'épuisement des adresses consiste à utiliser des adresses PUPI pour le bloc CIDR de pod GKE. Les adresses PUPI sont des adresses IP publiques qui n'appartiennent pas à Google, mais qu'un client peut utiliser en mode privé sur Google Cloud. Le client n'est pas nécessairement le propriétaire de ces adresses.

Le schéma suivant illustre une entreprise (soit un producteur) qui propose un service géré à un client (soit un consommateur).

Adresses PUPI du bloc CIDR du pod GKE.

Cette configuration implique les éléments suivants :

  • Bloc CIDR principal : bloc CIDR non-PUPI utilisé pour les nœuds et l'équilibreur de charge interne, qui ne doit pas se chevaucher entre plusieurs VPC.
  • Bloc CIDR secondaire du producteur : bloc CIDR PUPI utilisé pour les pods (par exemple, 45.45.0.0/16).
  • Bloc CIDR secondaire du consommateur : tout autre bloc CIDR PUPI côté client (par exemple, 5.5/16).

Le service géré de l'entreprise se trouve dans le VPC de producteur (vpc-producer) et repose sur un déploiement GKE. Le cluster GKE de l'entreprise utilise le bloc CIDR PUPI 45.0.0.0/8 pour les adresses de pod. Les applications du client sont situées dans le VPC de consommateur (vpc-consumer). Le client dispose également d'une installation GKE. Le cluster GKE du VPC de consommateur utilise le bloc CIDR PUPI 5.0.0.0/8 pour les adresses de pod. Les deux VPC sont appairés et utilisent l'espace d'adressage RFC 1918 pour les adresses de nœud, de service et d'équilibrage de charge.

Par défaut, le VPC de consommateur (vpc-consumer) exporte l'ensemble des adresses RFC 1918 vers le VPC de producteur (vpc-producer). Contrairement aux adresses privées RFC 1918 et aux adresses privées étendues (CGN, classe E), les adresses PUPI ne sont pas automatiquement annoncées par défaut aux pairs VPC. Si les pods vpc-consumer doivent communiquer avec vpc-producer, le client ou consommateur doit autoriser la connexion d'appairage du VPC à exporter les adresses PUPI. De même, le producteur doit configurer son VPC de façon à importer les routes PUPI via la connexion d'appairage du VPC.

L'espace d'adressage vpc-consumer exporté vers vpc-producer ne doit pas chevaucher une adresse RFC 1918 ou PUPI utilisée dans vpc-producer. Le producteur doit indiquer au consommateur les blocs CIDR PUPI qui sont utilisés par le service géré. Il doit également s'assurer que le consommateur n'utilise pas ces blocs. Le producteur et le consommateur doivent également s'accorder sur les espaces d'adressage à choisir, puis les attribuer à l'équilibrage de charge interne et aux adresses de nœud dans vpc-producer (ces espaces d'adressage ne doivent pas se chevaucher).

Dans la plupart des cas, les ressources de vpc-consumer communiquent avec les services de vpc-producer via les adresses de l'équilibreur de charge interne du cluster producteur. Si les pods du producteur doivent initier la communication directement avec les ressources dans vpc-consumer et que les adresses PUPI ne se chevauchent pas, le producteur doit configurer le VPC de producteur de façon à exporter les routes PUPI sur la connexion d'appairage du VPC. De même, le client ou consommateur doit configurer la connexion d'appairage du VPC de sorte que les routes soient importées dans vpc-consumer. Si le VPC de consommateur utilise déjà l'adresse PUPI, le producteur doit plutôt configurer la fonctionnalité de masquage d'adresses IP afin de masquer les adresses IP du pod derrière les adresses IP du nœud de producteur.

Le tableau suivant indique les paramètres d'importation et d'exportation par défaut de chaque VPC. Vous pouvez modifier les paramètres d'appairage du VPC par défaut à l'aide de la commande gcloud compute networks peerings update du SDK Cloud.

Option PUPI Importation Exportation
Côté producteur (options contrôlées via la mise en réseau de services)

Pour activer : --import-subnet-routes-with-public-ip (via l'appairage)

Comportement par défaut : désactivé

Pour désactiver : --no-export-subnet-routes-with-public-ip (via l'appairage)

Comportement par défaut : activé

Côté consommateur (propriété du client, modification possible autrement que via la mise en réseau de services) Désactivé (par défaut) Activé (par défaut)

L'application de ces paramètres aura les conséquences suivantes :

  • Le VPC de producteur verra toutes les routes clientes.
  • Le VPC de consommateur ne verra pas les routes des adresses PUPI configurées sur le sous-réseau de pod du VPC de producteur.
  • Le trafic en provenance des pods du producteur vers le réseau vpc-consumer devra être traduit derrière les adresses du nœud du cluster du producteur.

Qualifications

  • La plage d'adresses que vous sélectionnez pour l'adressage PUPI ne peut pas être accessible via Internet ou être une adresse détenue par Google.
  • Les adresses IP de nœuds et la plage principale ne doivent pas se chevaucher entre les deux VPC.
  • Si la communication directe d'un pod à un autre est requise (entre le VPC de consommateur et le service géré), les adresses IP des pods du producteur doivent être traduites derrière leurs adresses IP de nœud correspondantes.

Objectifs

  • Configurer deux réseaux VPC.
  • Configurer un sous-réseau dans chaque réseau VPC.
  • Configurer une plage d'adresses PUPI sur une plage d'adresses secondaire dans chaque sous-réseau.
  • Établir une relation d'appairage de VPC entre les deux réseaux VPC avec des paramètres d'importation et d'exportation appropriés.
  • Inspecter les routes contenues dans chaque VPC.

Coûts

Ce tutoriel utilise les composants facturables suivants de Google Cloud :

Obtenez une estimation des coûts en fonction de votre utilisation prévue à l'aide du simulateur de coût. Les nouveaux utilisateurs de Google Cloud peuvent bénéficier d'un essai gratuit.

Avant de commencer

  1. Dans Cloud Console, activez Cloud Shell.

    Activer Cloud Shell

    La majeure partie de ce tutoriel se fait à partir du terminal Cloud Shell, à l'aide de l'outil Terraform de HashiCorp et du SDK Cloud.

  2. Clonez le dépôt GitHub et accédez au répertoire de travail local :

    git clone https://github.com/GoogleCloudPlatform/terraform-vpc-pupi $HOME/pupi
    

    Le dépôt contient tous les fichiers dont vous avez besoin pour suivre ce tutoriel. Pour obtenir une description complète de chaque fichier, consultez le fichier README.md dans le dépôt.

  3. Exécutez tous les scripts shell :

    sudo chmod 755 $HOME/pupi/*.sh
    

Préparer l'environnement

Dans cette section, vous allez installer et configurer Terraform, puis définir des variables d'environnement.

Configurer Terraform

  1. Installez Terraform en suivant les étapes de la documentation HashiCorp.
  2. Dans Cloud Shell, initialisez Terraform :

    cd $HOME/pupi
    terraform init
    

    Le résultat ressemble à ce qui suit :

    ...
    Initializing provider plugins...
    The following providers do not have any version constraints in
    configuration, so the latest version was installed.
    ...
    Terraform has been successfully initialized!
    ...
    

    Lors de l'initialisation de Terraform, les messages de progression sont consignés. À la fin du résultat, un message indique que Terraform a bien été initialisé.

Définir des variables d'environnement

  1. Dans Cloud Shell, définissez la variable TF_VAR_org_id :

    export TF_VAR_org_id=$(gcloud organizations list | \
        awk '/YOUR_ORGANIZATION_NAME/ {print $2}')
    

    Remplacez l'élément suivant :

    • YOUR_ORGANIZATION_NAME:  nom de l'organisation Google Cloud que vous souhaitez utiliser pour ce tutoriel
  2. Vérifiez que vous avez correctement défini la variable d'environnement :

    echo $TF_VAR_org_id
    

    Le résultat affiche l'ID numérique de votre organisation et se présente comme suit :

    ...
    123123123123
    ...
    
  3. Définissez les variables d'environnement restantes :

    source $HOME/pupi/set_variables.sh
    

    Ce script shell définit les paramètres de base tels que la région, l'ID de l'organisation et l'ID du projet Google Cloud en tant que variables dans l'environnement shell. Terraform utilise ces variables pour configurer vos ressources Google Cloud. Vous pouvez ajuster ou modifier les paramètres du script shell en fonction de votre environnement. Pour obtenir la liste complète des variables, consultez le script shell set_variables.

  4. Vérifiez que vous avez correctement défini les variables d'environnement :

    env | grep TF_
    

    Le résultat ressemble à ce qui suit :

    ...
    TF_VAR_billing_account=QQQQQQ-XAAAAA-E8769
    TF_VAR_org_id=406999999999
    TF_VAR_region1=us-west1
    TF_VAR_region2=us-west2
    TF_VAR_consumer_ilb_ip=10.129.0.200
    TF_VAR_user_account=user@example
    TF_VAR_pid=pupi-pid--999999999
    TF_VAR_zone2=us-west2-b
    TF_VAR_zone1=us-west1-b
    ...
    
  5. Créez un fichier de variables d'environnement :

    $HOME/pupi/saveVars.sh
    

    Cette commande redirige les variables d'environnement que vous avez créées dans un fichier nommé TF_ENV_VARS. Chaque variable est précédée de la commande export. Si votre session Cloud Shell s'arrête, vous pouvez utiliser ce fichier pour réinitialiser les variables. Ces variables sont utilisées par les scripts Terraform, les scripts Cloud Shell et l'outil de ligne de commande gcloud.

    Si vous devez réinitialiser les variables ultérieurement, exécutez la commande suivante :

    source $HOME/pupi/TF_ENV_VARS
    

Déployer l'infrastructure de soutien

  1. Déployez l'infrastructure Terraform dans Cloud Shell :

    terraform apply
    

    Lorsque vous y êtes invité, saisissez yes pour appliquer l'une des configurations. Le déploiement des ressources par Terraform peut prendre plusieurs minutes.

    La commande terraform apply demande à Terraform de déployer tous les composants de la solution. Pour comprendre comment l'infrastructure est définie de manière déclarative, consultez les fichiers manifestes Terraform, c'est-à-dire les fichiers avec une extension .tf.

  2. Établissez la relation d'appairage de VPC. Comme la fonctionnalité est en version alpha et n'est pas compatible avec Terraform, vous devez utiliser des commandes gcloud pour configurer l'appairage.

    gcloud alpha compute networks peerings create consumer \
        --project="$TF_VAR_pid" \
        --network=consumer \
        --peer-network=producer
    
    gcloud alpha compute networks peerings create producer \
        --project="$TF_VAR_pid" \
        --network=producer \
        --peer-network=consumer \
        --no-export-subnet-routes-with-public-ip \
        --import-subnet-routes-with-public-ip
    

    Par défaut, le VPC de consommateur exporte les adresses PUPI. Lorsque vous créez le VPC de producteur, utilisez les arguments suivants pour le configurer de sorte qu'il importe les adresses PUPI sans les exporter :

    --no-export-subnet-routes-with-public-ip
    --import-subnet-routes-with-public-ip
    

Inspecter l'infrastructure de soutien

Vous allez maintenant vérifier que Terraform a bien créé les ressources. Si c'est le cas, elles répondront à votre commande.

Valider les projets

  1. Dans Cloud Shell, répertoriez le projet :

    gcloud projects list | grep pupi-pid
    

    Le résultat ressemble à ce qui suit :

    ...
    pupi-pid--1234567899            pupi-test             777999333555
    ...
    

    Dans ce résultat, pupi-test correspond au nom du projet et pupi-pid- au préfixe de l'ID de votre projet.

  2. Indiquez l'état de l'API :

    gcloud services list --project=$TF_VAR_pid \
        | grep -E "compute|container"
    

    Le résultat ressemble à ce qui suit :

    ...
    compute.googleapis.com            Compute Engine API
    container.googleapis.com          Kubernetes Engine API
    containerregistry.googleapis.com  Container Registry API
    ...
    

    Ce résultat indique que les API Compute Engine, GKE et Container Registry sont activées.

Valider les réseaux et les sous-réseaux

  1. Dans Cloud Shell, vérifiez le réseau et le sous-réseau du producteur :

    gcloud compute networks describe producer \
        --project=$TF_VAR_pid
    
    gcloud compute networks subnets describe producer-nodes \
        --project=$TF_VAR_pid \
        --region=$TF_VAR_region1
    

    Le résultat ressemble à ce qui suit :

    ...
    kind: compute#network
    name: producer
    ...
    ipCidrRange: 10.128.0.0/24
    kind: compute#isubnetwork
    name: producer-nodes
    ...
    secondaryIpRanges:
    - ipCidrRange: 45.45.45.0/24
      rangeName: producer-pods
    - ipCidrRange: 172.16.45.0/24
      rangeName: producer-cluster
    ...
    

    Le résultat indique que :

    • le réseau a été créé avec le bloc CIDR 10.128.0.0/24 ;
    • les deux sous-réseaux ont été créés avec les blocs CIDR 45.45.45.0/24 et 172.16.45.0/24.
  2. Vérifiez le réseau et le sous-réseau consommateur :

    gcloud compute networks describe consumer \
        --project=$TF_VAR_pid
    
    gcloud compute networks subnets describe consumer-nodes \
        --project=$TF_VAR_pid \
        --region=$TF_VAR_region2
    

    Le résultat ressemble à ce qui suit :

    ...
    kind: compute#network
    name: consumer
    ...
    ipCidrRange: 10.129.0.0/24
    kind: compute#isubnetwork
    name: consumer-nodes
    ...
    secondaryIpRanges:
    - ipCidrRange: 5.5.5.0/24
      rangeName: producer-pods
    - ipCidrRange: 172.16.5.0/24
      rangeName: consumer-cluster
    ...
    

    Le résultat indique que :

    • le réseau a été créé à l'aide du bloc CIDR 10.129.0.0/24 ;
    • les deux sous-réseaux ont été créés à l'aide des blocs CIDR 5.5.5.0/24 et 172.16.5.0/24.

Valider le cluster GKE et ses ressources

  1. Dans Cloud Shell, obtenez les identifiants du cluster :

    gcloud container clusters get-credentials consumer-cluster \
        --project=$TF_VAR_pid \
        --zone=$TF_VAR_zone2
    

    Le résultat ressemble à ce qui suit :

    ...
    Fetching cluster endpoint and auth data.
    kubeconfig entry generated for consumer-cluster.
    ...
    
  2. Validez le cluster :

    gcloud container clusters list \
        --project=$TF_VAR_pid \
        --zone=$TF_VAR_zone2
    

    Le résultat ressemble à ce qui suit :

    NAME              LOCATION    MASTER_VERSION  MASTER_IP      MACHINE_TYPE   NODE_VERSION    NUM_NODES  STATUS
    consumer-cluster  us-west2-b  1.14.10-gke.17  35.236.104.74  n1-standard-1  1.14.10-gke.17  3          RUNNING
    

    Ce résultat montre un cluster nommé consumer-cluster.

  3. Validez l'application Hello World :

    kubectl get deployment my-app
    

    Le résultat ressemble à ce qui suit :

    ...
    NAME     DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
    my-app   3         3         3            3           118m
    ...
    

    Ce résultat montre un déploiement nommé my-app.

  4. Validez le service de l'équilibreur de charge interne :

    kubectl get service hello-server
    

    Le résultat ressemble à ce qui suit :

    NAME           TYPE           CLUSTER-IP    EXTERNAL-IP    PORT(S)          AGE
    hello-server   LoadBalancer   172.16.5.99   10.129.0.200   8080:31673/TCP   4d23h
    

    Ce résultat montre un service nommé hello-server.

Valider la solution

  1. Dans Cloud Shell, vérifiez que l'appairage de VPC a bien été créé :

    gcloud alpha compute networks peerings list
    

    Le résultat ressemble à ce qui suit :

    NAME      NETWORK   PEER_PROJECT          PEER_NETWORK  IMPORT_CUSTOM_ROUTES  EXPORT_CUSTOM_ROUTES  STATE   STATE_DETAILS
    consumer  consumer  pupi-pid--1324732197  producer      False                 False                 ACTIVE  [2020-02-26T11:33:16.886-08:00]: Connected.
    producer  producer  pupi-pid--1324732197  consumer      False                 False                 ACTIVE  [2020-02-26T11:33:16.886-08:00]: Connected.
    

    Ce résultat montre les appairages nommés consumer et producer.

  2. Confirmez que le VPC de consommateur exporte les routes PUPI :

    gcloud alpha compute networks peerings list-routes consumer \
        --direction=OUTGOING \
        --network=consumer \
        --region="$TF_VAR_region2"
    

    Le résultat ressemble à ce qui suit :

    DEST_RANGE     TYPE                  NEXT_HOP_REGION  PRIORITY  STATUS
    10.129.0.0/24  SUBNET_PEERING_ROUTE  us-west2         1000      accepted by peer
    172.16.5.0/24  SUBNET_PEERING_ROUTE  us-west2         1000      accepted by peer
    5.5.5.0/24     SUBNET_PEERING_ROUTE  us-west2         1000      accepted by peer
    

    Ce résultat montre les trois blocs CIDR consommateurs.

  3. Vérifiez les routes PUPI importées par le VPC de producteur :

    gcloud alpha compute networks peerings list-routes producer \
        --direction=INCOMING \
        --network=producer \
        --region="$TF_VAR_region1"
    

    Le résultat ressemble à ce qui suit :

    DEST_RANGE     TYPE                  NEXT_HOP_REGION  PRIORITY  STATUS
    10.129.0.0/24  SUBNET_PEERING_ROUTE  us-west2         1000      accepted
    172.16.5.0/24  SUBNET_PEERING_ROUTE  us-west2         1000      accepted
    5.5.5.0/24     SUBNET_PEERING_ROUTE  us-west2         1000      accepted
    

    Ce résultat montre les trois blocs CIDR consommateurs.

  4. Vérifiez que les pods GKE disposent d'une adresse PUPI :

    kubectl get pod -o wide
    

    Le résultat ressemble à ce qui suit :

    NAME                      READY   STATUS    RESTARTS   AGE     IP         NODE                                              NOMINATED NODE   READINESS GATES
    my-app-594b56d7bc-642d8   1/1     Running   0          4d23h   5.5.5.21   gke-consumer-cluster-default-pool-cd302b68-tccf   <none>           <none>
    my-app-594b56d7bc-chnw8   1/1     Running   0          4d23h   5.5.5.38   gke-consumer-cluster-default-pool-cd302b68-h8v9   <none>           <none>
    my-app-594b56d7bc-fjvbz   1/1     Running   0          4d23h   5.5.5.20   gke-consumer-cluster-default-pool-cd302b68-tccf   <none>           <none>
    

    Les adresses IP des pods sont comprises dans la plage 5.5.5/24.

Nettoyer

Pour éviter que les ressources utilisées dans ce tutoriel soient facturées sur votre compte Google Cloud, procédez comme suit :

Détruire l'infrastructure

  1. Dans Cloud Shell, détruisez tous les composants du tutoriel :

    terraform destroy
    

    Lorsque vous y êtes invité, saisissez yes pour détruire la configuration.

    Vous constaterez peut-être l'affichage de l'erreur Terraform suivante :

    ...
    ∗ google_compute_network.ivpc (destroy): 1 error(s) occurred:
    ∗ google_compute_network.ivpc: Error waiting for Deleting Network: The network resource 'projects/pupi-pid--1324732197/global/networks/consumer-cluster' is already being used by 'projects/pupi-pid--1324732197/global/firewalls/k8s-05693142c93de80e-node-hc'
    ...
    

    Cette erreur se produit lorsque la commande tente de détruire le réseau VPC avant de détruire les règles de pare-feu GKE. Si vous obtenez cette erreur, procédez comme suit :

    1. Supprimez les règles de pare-feu autres que celles par défaut du VPC :

      $HOME/pupi/k8-fwr.sh
      

      Le résultat affiche les règles de pare-feu à supprimer. Vérifiez les règles et, lorsque vous y êtes invité, saisissez yes.

    2. Exécutez à nouveau la commande suivante :

      cd $HOME/pupi
      terraform destroy
      

    Lorsque vous y êtes invité, saisissez yes pour détruire la configuration.

  2. Supprimez le dépôt Git :

    rm -rf $HOME/pupi
    

Étape suivante