Configura IP públicas de uso privado para GKE

En este instructivo, se muestra cómo aplicar direcciones IP públicas de uso privado (PUPI) a los bloques de direcciones de Pods de Google Kubernetes Engine (GKE). Las organizaciones de consumidores de servicios con restricción de dirección IPv4 pueden usar direcciones PUPI en las nubes privadas virtuales (VPC) del productor de servicios como una opción de administración de direcciones.

Este documento está dirigido a arquitectos de redes y administradores de sistemas de GKE cuyas empresas ofrecen servicios administrados en una infraestructura de GKE en Google Cloud.

Introducción

Algunas empresas quieren entregar servicios administrados a sus clientes a través de clústeres de Kubernetes o GKE en Google Cloud. Sin embargo, Kubernetes puede requerir muchas direcciones IP para sus diversos componentes. Para algunas organizaciones, cumplir con este requisito es difícil o imposible porque no pueden asignar bloques de enrutamiento entre dominios sin clases (CIDR) 10.0.0.0/8, 172.16.0.0/12 y 192.168.0.0/16 (RFC 1918) del tamaño adecuado.

Una forma de mitigar el agotamiento de direcciones es usar direcciones IP públicas de uso privado (PUPI) para el bloque CIDR del Pod de GKE. Las PUPI son direcciones IP públicas que no son propiedad de Google, que un cliente puede usar de forma privada en Google Cloud. No es necesario que el cliente sea el propietario de estas direcciones.

En el siguiente diagrama, se muestra una empresa (productor) que ofrece un servicio administrado a un cliente (consumidor).

Direcciones PUPI para el bloque CIDR del Pod de GKE.

Esta configuración implica las siguientes consideraciones:

  • Bloque CIDR principal: un bloque CIDR que no es de PUPI que se usa para ILB y nodos, y no debe superponerse en las VPC.
  • Bloque CIDR secundario del productor: un bloque CIDR de PUPI que se usa para los Pods (por ejemplo, 45.45.0.0/16).
  • Bloque CIDR secundario del consumidor: cualquier otro bloque CIDR de PUPI del lado del cliente (por ejemplo, 5.5/16).

El servicio administrado de la empresa se encuentra en la VPC del productor (vpc-producer) y se compila en una implementación de GKE. El clúster de GKE de la empresa usa el bloque CIDR 45.0.0.0/8 de PUPI para las direcciones de Pods. Las aplicaciones del cliente se ubican en la VPC del consumidor (vpc-consumer). El cliente también tiene una instalación de GKE. El clúster de GKE en la VPC del consumidor usa el bloque CIDR 5.0.0.0/8 de PUPI para direcciones de Pods. Las dos VPC intercambian tráfico entre sí. Ambas VPC usan el espacio de direcciones RFC 1918 para las direcciones de nodo, servicio y balanceo de cargas.

De forma predeterminada, la VPC del consumidor (vpc-consumer) exporta todo el RFC 1918 a la VPC del productor (vpc-producer). A diferencia de las direcciones privadas RFC 1918 y las direcciones privadas extendidas (CGN, Clase E), las PUPI no se anuncian de forma automática en el intercambio de tráfico de VPC de forma predeterminada. Si los Pods vpc-consumer deben comunicarse con vpc-producer, el consumidor debe habilitar la conexión de intercambio de tráfico de VPC para exportar direcciones PUPI. Del mismo modo, el productor debe configurar su VPC para importar rutas PUPI mediante la conexión de intercambio de tráfico de VPC.

El espacio de direcciones vpc-consumer que se exporta a vpc-producer no debe superponerse con ninguna dirección RFC 1918 ni PUPI usada en vpc-producer. El productor debe informar al consumidor qué bloques CIDR de PUPI usa el servicio administrado y asegurarse de que el consumidor no los esté usando. El productor y el consumidor también deben acordar y asignar un espacio de direcciones que no se superpongan para el balanceo de cargas interno (ILB) y las direcciones de nodo en vpc-producer.

En la mayoría de los casos, los recursos en vpc-consumer se comunican con los servicios en vpc-producer a través de direcciones de ILB en el clúster del productor. Si se requiere que los Pods del productor inicien la comunicación directamente con los recursos en vpc-consumer, y las direcciones PUPI no se superponen, entonces el productor debe configurar la VPC del productor para exportar las rutas PUPI a través de la conexión de intercambio de tráfico de VPC. Del mismo modo, el consumidor debe configurar la conexión de intercambio de tráfico de VPC para importar rutas a vpc-consumer. Si la VPC de consumidor ya usa la dirección PUPI, entonces el productor debe configurar la función de enmascaramiento de IP y ocultar las direcciones IP del Pod detrás de las direcciones IP del nodo de productor.

En la siguiente tabla, se muestra la configuración predeterminada de importación y exportación para cada VPC. Puedes modificar la configuración predeterminada del intercambio de tráfico de VPC mediante el comando gcloud compute networks peerings update del SDK de Cloud.

Marca PUPI Importar Exportar
Del lado del productor (marcas controladas mediante las herramientas de redes de servicios)

Para activar: --import-subnet-routes-with-public-ip (mediante el intercambio de tráfico)

Comportamiento predeterminado: desactivado

Para desactivar: --no-export-subnet-routes-with-public-ip (mediante el intercambio de tráfico)

Comportamiento predeterminado: activado

Del lado del consumidor (propiedad del cliente, no es obligatorio modificarlo mediante las redes de servicio) Desactivado (predeterminado) Activado (predeterminado)

Esta configuración da como resultado lo siguiente:

  • La VPC del productor ve todas las rutas de clientes.
  • La VPC del consumidor no ve las rutas de PUPI configuradas en la subred del Pod en la VPC del productor.
  • El tráfico que se origina de los Pods del productor a la red vpc-consumer debe traducirse detrás de las direcciones de nodo en el clúster del productor.

Requisitos

  • El rango de direcciones que seleccionas para una PUPI no puede ser accesible a través de Internet ni puede ser una dirección que sea propiedad de Google.
  • Las IP de nodo y el rango principal no deben superponerse entre las dos VPC.
  • Si se requiere una comunicación directa de Pod a Pod entre la VPC del cliente y el servicio administrado, las direcciones IP del Pod del productor deben traducirse detrás de sus IP de nodo correspondientes.

Objetivos

  • Configurar dos redes de VPC
  • Configurar una subred dentro de cada red de VPC
  • Configurar un rango de direcciones PUPI en un rango de direcciones secundario en cada subred
  • Establecer una relación de intercambio de tráfico de VPC entre las dos redes de VPC con la configuración adecuada de importación y exportación
  • Inspeccionar las rutas dentro de cada VPC

Costos

En este instructivo, se usan los siguientes componentes facturables de Google Cloud:

Para generar una estimación de costos en función del uso previsto, usa la calculadora de precios. Es posible que los usuarios nuevos de Google Cloud sean aptos para obtener una prueba gratuita.

Antes de comenzar

  1. En Cloud Console, activa Cloud Shell.

    Activar Cloud Shell

    Completarás la mayor parte de este instructivo desde la terminal de Cloud Shell mediante Terraform de HashiCorp y el SDK de Cloud.

  2. Clona el repositorio de GitHub y cambia al directorio de trabajo local:

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

    El repositorio contiene todos los archivos que necesitas para completar este instructivo. Para obtener una descripción completa de cada archivo, consulta el archivo README.md en el repositorio.

  3. Haz que todas las secuencias de comandos de shell sean ejecutables:

    sudo chmod 755 $HOME/pupi/*.sh
    

Prepara tu entorno

En esta sección, instalarás y configurarás Terraform y, luego, configurarás las variables de entorno.

Configura Terraform

  1. Para instalar Terraform, sigue los pasos de la documentación de HashiCorp.
  2. En Cloud Shell, inicializa Terraform:

    cd $HOME/pupi
    terraform init
    

    La salida es similar a lo siguiente:

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

    A medida que Terraform se inicializa, registra mensajes de progreso. Al final de la salida del mensaje, verás un mensaje que indica que Terraform se inicializó de forma correcta.

Configura las variables de entorno

  1. En Cloud Shell, configura la variable TF_VAR_org_id:

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

    Reemplaza lo siguiente:

    • YOUR_ORGANIZATION_NAME: El nombre de la organización de Google Cloud que deseas usar para este instructivo.
  2. Verifica si configuraste la variable de entorno de forma correcta:

    echo $TF_VAR_org_id
    

    El resultado muestra el ID numérico de la organización y es similar al siguiente:

    ...
    123123123123
    ...
    
  3. Configura las variables de entorno restantes:

    source $HOME/pupi/set_variables.sh
    

    Mediante esta secuencia de comandos de shell, se establecen parámetros básicos, como la región de Google Cloud, el ID de la organización y el ID del proyecto como variables en el entorno de shell. Terraform usa estas variables para configurar sus recursos de Google Cloud. Puedes ajustar o cambiar los parámetros de la secuencia de comandos de shell para que se ajusten a tu entorno. Para obtener una lista completa de las variables, revisa la secuencia de comandos de shell set_variables.

  4. Verifica si configuraste las variables de entorno de forma correcta:

    env | grep TF_
    

    La salida es similar a lo siguiente:

    ...
    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. Crea un archivo de variable de entorno:

    $HOME/pupi/saveVars.sh
    

    Mediante este comando, se redireccionan las variables de entorno que creaste a un archivo llamado TF_ENV_VARS. Cada variable está precedida por el comando export. Si tu sesión de Cloud Shell finaliza, puedes usar este archivo para restablecer las variables. Las secuencias de comandos de Terraform, las de Cloud Shell y la herramienta de línea de comandos de gcloud usan estas variables.

    Si necesitas reiniciar las variables más adelante, ejecuta el siguiente comando:

    source $HOME/pupi/TF_ENV_VARS
    

Implementa una infraestructura de respaldo

  1. En Cloud Shell, implementa la infraestructura de respaldo de Terraform:

    terraform apply
    

    Cuando se te solicite, ingresa yes para aplicar cualquiera de las opciones de configuración. Puede llevarle varios minutos a Terraform implementar los recursos.

    El comando terraform apply indica a Terraform que implemente todos los componentes de la solución. Para comprender cómo se define la infraestructura de forma declarativa, consulta los manifiestos de Terraform (archivos con una extensión .tf).

  2. Establece la relación de intercambio de tráfico de VPC. Debido a que la función está en Alfa y no es compatible con Terraform, debes usar comandos de gcloud para configurar el intercambio de tráfico.

    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
    

    De forma predeterminada, la VPC del consumidor exporta las direcciones PUPI. Cuando creas la VPC del productor, usas los siguientes argumentos para configurar la VPC a fin de importar direcciones PUPI, pero no exportarlas:

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

Inspecciona la infraestructura de respaldo

Ahora, verifica que Terraform creó de forma correcta los recursos; para ello, verifica si los recursos responden después de que envías un comando.

Verifica los proyectos

  1. En Cloud Shell, enumera el proyecto con el siguiente comando:

    gcloud projects list | grep pupi-pid
    

    La salida es similar a lo siguiente:

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

    En esta salida, pupi-test es el nombre del proyecto y pupi-pid- es el prefijo del ID del proyecto.

  2. Enumera el estado de la API:

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

    La salida es similar a lo siguiente:

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

    En esta salida, se muestra que las API de Compute Engine, GKE y Container Registry están habilitadas.

Verifica las redes y las subredes

  1. En Cloud Shell, verifica la red y la subred del productor:

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

    La salida es similar a lo siguiente:

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

    En esta salida, se muestra lo siguiente:

    • La red se creó con el bloque CIDR 10.128.0.0/24.
    • Las dos subredes se crearon con los bloques CIDR 45.45.45.0/24172.16.45.0/24.
  2. Verifica la red y la subred de consumidor:

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

    La salida es similar a lo siguiente:

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

    En esta salida, se muestra lo siguiente:

    • La red se creó con el bloque CIDR 10.129.0.0/24.
    • Las dos subredes se crearon mediante los bloques CIDR 5.5.5.0/24172.16.5.0/24.

Verifica el clúster de GKE y sus recursos

  1. En Cloud Shell, obtén las credenciales del clúster con el siguiente comando:

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

    La salida es similar a lo siguiente:

    ...
    Fetching cluster endpoint and auth data.
    kubeconfig entry generated for consumer-cluster.
    ...
    
  2. Verifica el clúster con el siguiente comando:

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

    La salida es similar a lo siguiente:

    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
    

    En esta salida, se muestra un clúster llamado consumer-cluster.

  3. Verifica la app de Hello World:

    kubectl get deployment my-app
    

    La salida es similar a lo siguiente:

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

    En esta salida, se muestra una implementación llamada my-app.

  4. Verifica el servicio del balanceador de cargas interno:

    kubectl get service hello-server
    

    La salida es similar a lo siguiente:

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

    En esta salida, se muestra un servicio llamado hello-server.

Verifica la solución

  1. En Cloud Shell, verifica que creaste el intercambio de tráfico de VPC de forma correcta:

    gcloud alpha compute networks peerings list
    

    La salida es similar a lo siguiente:

    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.
    

    En esta salida, se muestran los intercambios de tráfico llamados consumer y producer.

  2. Valida que la VPC del consumidor exporte rutas PUPI:

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

    La salida es similar a lo siguiente:

    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
    

    En esta salida, se muestran los tres bloques CIDR del consumidor.

  3. Valida las rutas PUPI que importó la VPC del productor:

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

    La salida es similar a lo siguiente:

    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
    

    En esta salida, se muestran los tres bloques CIDR del consumidor.

  4. Valida que los Pods de GKE tengan una dirección PUPI:

    kubectl get pod -o wide
    

    La salida es similar a lo siguiente:

    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>
    

    Las direcciones IP de los Pods se encuentran dentro del rango 5.5.5/24.

Realiza una limpieza

Para evitar que se generen costos en tu cuenta de Google Cloud por los recursos que se usaron en este instructivo, sigue estos pasos:

Destruye la infraestructura

  1. En Cloud Shell, destruye todos los componentes del instructivo:

    terraform destroy
    

    Cuando se te solicite, ingresa yes para destruir la configuración.

    Es posible que veas el siguiente error de Terraform:

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

    Este error ocurre cuando el comando intenta destruir la red de VPC antes de destruir las reglas de firewall de GKE. Si recibes este error, haz lo siguiente:

    1. Quita las reglas de firewall no predeterminadas de la VPC:

      $HOME/pupi/k8-fwr.sh
      

      En la salida, se muestran las reglas de firewall que se deben quitar. Revisa las reglas y, cuando se te solicite, ingresa yes.

    2. Vuelve a emitir el siguiente comando:

      cd $HOME/pupi
      terraform destroy
      

    Cuando se te solicite, ingresa yes para destruir la configuración.

  2. Quita el repositorio de Git:

    rm -rf $HOME/pupi
    

¿Qué sigue?