Usa un balanceador de cargas TCP/UDP interno

En esta página, se explica cómo crear un balanceador de cargas de TCP/UDP interno en Google Kubernetes Engine (GKE).

Descripción general

El balanceo de cargas TCP/UDP interno permite que los servicios de tu clúster sean accesibles para las aplicaciones fuera de tu clúster que usan la misma red de VPC y se encuentran en la misma región de Google Cloud. Por ejemplo, supongamos que tienes un clúster en la región us-west1 y necesitas hacer que las instancias de VM de Compute Engine que se ejecutan en esa región en la misma red de VPC tengan acceso a uno de sus servicios.

Sin el balanceo de cargas TCP/UDP interno, tendrías que configurar un balanceador de cargas externo y reglas de firewall para que la aplicación sea accesible fuera del clúster.

Anotación

Puedes crear un balanceador de cargas TCP/UDP interno si creas un recurso Servicio con una especificación type: LoadBalancer y una anotación. La anotación depende de la versión de tu clúster de GKE.

Para las versiones de GKE 1.17 y posteriores, usa la anotación networking.gke.io/load-balancer-type: "Internal".

Para versiones anteriores, usa la anotación cloud.google.com/load-balancer-type: "Internal".

Arquitectura

El balanceo de cargas de TCP/UDP interno crea una dirección IP interna para el Service que recibe tráfico de los clientes en la misma red de VPC y región de procesamiento. Si habilitas el acceso global, los clientes de cualquier región de la misma red de VPC pueden acceder al servicio. Además, los clientes en una red de VPC conectada a la red de LoadBalancer que usan el Intercambio de tráfico entre redes de VPC también pueden acceder al Service.

El controlador de Ingress de GKE implementa y administra los recursos del balanceo de cargas. Para obtener más información sobre el controlador de Ingress de GKE, consulta el Resumen del comportamiento del controlador de Ingress de GKE.

Precios

Se te cobrará por el modelo de precios de Compute Engine. Para obtener más información, consulta Precios de balanceos de cargas y de reglas de reenvío y la página de Compute Engine en la calculadora de precios de Google Cloud.

Antes de comenzar

Antes de comenzar, asegúrate de haber realizado las siguientes tareas:

Establece la configuración de gcloud predeterminada mediante uno de los siguientes métodos:

  • Usa gcloud init si deseas ver una explicación sobre cómo configurar parámetros predeterminados.
  • Usa gcloud config para establecer el ID, la zona y la región del proyecto de manera individual.

Usa gcloud init

Si recibes el error One of [--zone, --region] must be supplied: Please specify location, completa esta sección.

  1. Ejecuta gcloud init y sigue las instrucciones:

    gcloud init

    Si usas SSH en un servidor remoto, usa la marca --console-only para evitar que el comando abra un navegador:

    gcloud init --console-only
  2. Sigue las instrucciones a fin de autorizar a gcloud para que use tu cuenta de Google Cloud.
  3. Crea una configuración nueva o selecciona una existente.
  4. Elige un proyecto de Google Cloud.
  5. Elige una zona predeterminada de Compute Engine para clústeres zonales o una región para clústeres regionales o de Autopilot.

Usa gcloud config

  • Establece tu ID del proyecto predeterminado:
    gcloud config set project PROJECT_ID
  • Si trabajas con clústeres zonales, establece tu zona de procesamiento predeterminada:
    gcloud config set compute/zone COMPUTE_ZONE
  • Si trabajas con clústeres de Autopilot o regionales, configura tu región de procesamiento predeterminada:
    gcloud config set compute/region COMPUTE_REGION
  • Actualiza gcloud a la versión más reciente:
    gcloud components update

Crea una implementación

En el siguiente manifiesto, se describe una implementación que ejecuta 3 réplicas de una aplicación de Hello World.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-app
spec:
  selector:
    matchLabels:
      app: hello
  replicas: 3
  template:
    metadata:
      labels:
        app: hello
    spec:
      containers:
      - name: hello
        image: "us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0"

El código fuente y Dockerfile para esta aplicación de muestra están disponibles en GitHub. Como no se especifica ninguna variable de entorno PORT, los contenedores escuchan en el puerto 8080 predeterminado.

Para crear la implementación, crea el archivo my-deployment.yaml desde el manifiesto y, luego, ejecuta el comando siguiente en tu shell o ventana de la terminal:

kubectl apply -f my-deployment.yaml

Crea un balanceador de cargas TCP interno

En las siguientes secciones, se explica cómo crear un balanceador de cargas TCP interno mediante el uso de un servicio.

Escribe el archivo de configuración del servicio

A continuación, se muestra un ejemplo de un servicio que crea un balanceador de cargas TCP interno:

apiVersion: v1
kind: Service
metadata:
  name: ilb-service
  annotations:
    networking.gke.io/load-balancer-type: "Internal"
  labels:
    app: hello
spec:
  type: LoadBalancer
  selector:
    app: hello
  ports:
  - port: 80
    targetPort: 8080
    protocol: TCP

Requisitos mínimos de servicio

El manifiesto debe contener las siguientes características:

  • Un name para el servicio, en este caso ilb-service.
  • Una anotación que especifica un balanceador de cargas de TCP/UDP interno. La anotación depende de la versión de tu clúster de GKE. Para las versiones de GKE 1.17 y posteriores, usa la anotación networking.gke.io/load-balancer-type: "Internal". Para versiones anteriores, usa la anotación cloud.google.com/load-balancer-type: "Internal".
  • El tipo type: LoadBalancer.
  • Un campo spec: selector para especificar los pods a los que se orientará el servicio, por ejemplo, app: hello.
  • El port, el puerto sobre el que se expone el servicio, y targetPort, el puerto en el que escuchan los contenedores.

Implementa el servicio

Para crear un balanceador de cargas TCP interno, crea el archivo my-service.yaml desde el manifiesto y, luego, ejecuta el comando siguiente en tu shell o ventana de la terminal:

kubectl apply -f my-service.yaml

Inspecciona el servicio

Después de la implementación, inspecciona el servicio para verificar que se haya configurado correctamente.

Obtén información detallada sobre el servicio:

kubectl get service ilb-service --output yaml

En el resultado, puedes ver la dirección IP del balanceador de cargas interno en status.loadBalancer.ingress. Ten en cuenta que esto es diferente del valor de clusterIP. En este ejemplo, la dirección IP del balanceador de cargas es 10.128.15.193:

apiVersion: v1
kind: Service
metadata:
  ...
  labels:
    app: hello
  name: ilb-service
  ...
spec:
  clusterIP: 10.0.9.121
  externalTrafficPolicy: Cluster
  ports:
  - nodePort: 30835
    port: 80
    protocol: TCP
    targetPort: 8080
  selector:
    app: hello
  sessionAffinity: None
  type: LoadBalancer
status:
  loadBalancer:
    ingress:
    - ip: 10.128.15.193

Cualquier pod que tenga la etiqueta app: hello es miembro de este servicio. Estos son los pods que pueden ser los destinatarios finales de las solicitudes enviadas a tu balanceador de cargas interno.

Los clientes llaman al servicio mediante la dirección IP loadBalancer y el puerto TCP especificado en el campo port del manifiesto del servicio. La solicitud se reenvía a uno de los pods miembros en el puerto TCP especificado en el campo targetPort. En el ejemplo anterior, un cliente llama al Servicio en 10.128.15.193 en el puerto TCP 80. La solicitud se reenvía a uno de los pods miembros en el puerto TCP 8080. Ten en cuenta que el pod miembro debe tener un contenedor que escuche en el puerto 8080.

El valor nodePort de 30835 es extraño. No es relevante para tu balanceador de cargas interno.

Visualiza la regla de reenvío del balanceador de cargas

Un balanceador de cargas interno se implementa como una regla de reenvío. La regla de reenvío tiene un servicio de backend, que tiene un grupo de instancias.

La dirección del balanceador de cargas interno, 10.128.15.193 en el ejemplo anterior, es la misma que la dirección de la regla de reenvío. Para ver la regla de reenvío que implementa tu balanceador de cargas interno, obtén una lista de todas las reglas de reenvío en tu proyecto:

gcloud compute forwarding-rules list --filter="loadBalancingScheme=INTERNAL"

En el resultado, busca la regla de reenvío que tiene la misma dirección que tu balanceador de cargas interno, 10.128.15.193 en este ejemplo.

NAME                          ... IP_ADDRESS  ... TARGET
...
aae3e263abe0911e9b32a42010a80008  10.128.15.193   us-central1/backendServices/aae3e263abe0911e9b32a42010a80008

El resultado muestra el servicio de backend asociado, ae3e263abe0911e9b32a42010a80008 en este ejemplo.

Describe el servicio de backend:

gcloud compute backend-services describe aae3e263abe0911e9b32a42010a80008 --region us-central1

El resultado muestra el grupo de instancias asociado, k8s-ig--2328fa39f4dc1b75 en este ejemplo:

backends:
- balancingMode: CONNECTION
  group: .../us-central1-a/instanceGroups/k8s-ig--2328fa39f4dc1b75
...
kind: compute#backendService
loadBalancingScheme: INTERNAL
name: aae3e263abe0911e9b32a42010a80008
...

Cómo funciona la abstracción del servicio

Cuando una regla de reenvío maneja un paquete, este se reenvía a uno de los nodos del clúster. Estas son las direcciones y el puerto cuando el paquete lleva al nodo del clúster:

Dirección IP de destino Regla de reenvío, 10.128.15.193 en este ejemplo
Puerto TCP de destino Campo port del servicio, puerto 80 en este ejemplo

Ten en cuenta que la regla de reenvío (es decir, tu balanceador de cargas interno) no cambia la dirección IP o el puerto de destino. En cambio, las reglas de iptables en el nodo del clúster enrutan el paquete a un pod apropiado. Las reglas de iptables cambian la dirección IP de destino a una dirección IP del Pod y el puerto de destino al valor targetPort del servicio, puerto 8080 en este ejemplo.

Verifica el balanceador de cargas TCP interno

SSH en una instancia de VM, y ejecuta el siguiente comando:

curl LOAD_BALANCER_IP

Reemplaza LOAD_BALANCER_IP por tu dirección IP LoadBalancer Ingress.

La respuesta muestra la salida de hello-app:

Hello, world!
Version: 2.0.0
Hostname: hello-app-77b45987f7-pw54n

Ejecutar el comando por fuera de la misma red de VPC o por fuera de la misma región genera un error de tiempo de espera agotado. Si configuras el acceso global, los clientes de cualquier región de la misma red de VPC pueden acceder al balanceador de cargas.

Realiza una limpieza

Puedes borrar la implementación y el servicio con kubectl delete o Cloud Console.

kubectl

Borra la implementación

Para borrar la implementación, ejecuta el siguiente comando:

kubectl delete deployment hello-app

Borra el servicio

Para borrar el servicio, ejecuta el siguiente comando:

kubectl delete service ilb-service

Console

Borra la implementación

Para borrar la implementación, sigue estos pasos:

  1. Dirígete a la página Cargas de trabajo en Cloud Console.

    Ir a Cargas de trabajo

  2. Selecciona la implementación que deseas borrar y, luego, haz clic en Borrar.

  3. Cuando se le solicite que confirme la acción, seleccione la casilla de verificación Borrar el escalador automático horizontal del Pod asociado con la implementación seleccionada y, luego, haga clic en Borrar.

Borra el servicio

Para borrar el servicio, sigue estos pasos:

  1. Ve a la página Ingress y Service en Cloud Console.

    Ir a Ingress y Service

  2. Selecciona el servicio que quieres borrar y, luego, haz clic en Borrar.

  3. Cuando se te solicite confirmar, haz clic en Borrar.

Usa la subdivisión del balanceador de cargas TCP/UDP interno

La subdivisión de balanceador de cargas interno para GKE mejora la escalabilidad del balanceador de cargas TCP/UDP interno mediante la partición de backends en grupos superpuestos más pequeños. Con la subdivisión, puedes configurar balanceadores de cargas TCP/UDP internos en clústeres con más de 250 nodos.

Puedes habilitar la subdivisión cuando creas un clúster y editas un clúster existente.

Arquitectura

La subdivisión cambia la forma en la que se implementa los balanceadores de cargas TCP/UDP interno. Sin la subdivisión, el controlador de GKE coloca todos los nodos de un clúster en uno o más grupos de instancias zonales no administrados, que comparten todos los balanceadores de cargas internos del clúster de GKE. Por ejemplo, todos los balanceadores de cargas TCP/UDP internos en un clúster de GKE de 40 nodos comparten los mismos 40 nodos que los backends.

Con la subdivisión del balanceador de cargas TCP/UDP interno, el controlador de GKE coloca los nodos en GCE_VM_IP zonal network endpoint groups (NEGs). A diferencia de los grupos de instancias, los nodos pueden ser miembros de más de un NEG zonal, y un balanceador de cargas TCP/UDP interno puede hacer referencia a cada uno de los NEG zonales. El controlador de GKE crea un NEG para cada servicio con un subconjunto de los nodos de GKE como miembros. Por ejemplo, un clúster de GKE de 40 nodos puede tener un balanceador de cargas TCP/UDP interno con 25 nodos en un NEG zonal de backend y otro balanceador de cargas TCP/UDP interno con 25 nodos en un NEG zonal de backend diferente.

En el siguiente diagrama, se muestran dos servicios diferentes en un clúster que tiene habilitada la subdivisión del balanceador de cargas TCP/UDP interno. Cada servicio tiene dos Pods programados en tres nodos. Google Cloud crea un NEG GCE_VM_IP para cada servicio. El controlador de GKE selecciona un subconjunto de nodos del clúster para ser miembros del NEG y usa la dirección IP de cada nodo seleccionado como extremos.

Direcciones IP virtuales de nodos que se usan como extremos para los servicios cuando se dividen en subconjuntos.
Diagrama: Ejemplo de subdivisión en un clúster con servicios.

Selección de subconjunto de nodos de backend

Cuando habilitas la subdivisión de tu clúster, el controlador de GKE determina de forma automática cómo dividir los nodos. Puedes usar el valor Local o Cluster para externalTrafficPolicy, pero la selección del subconjunto de nodos de backend es diferente para cada valor.

  • externalTrafficPolicy: Cluster: las solicitudes de clientes se envían a la IP del nodo y se balancean sus cargas a un Pod de backend. El Pod de backend puede estar en el mismo nodo o en uno diferente. El controlador de GKE selecciona un subconjunto aleatorio de 25 nodos. Esta distribución evita puntos únicos de fallo. Si los Pods de backend están alojados en más de 25 nodos, de todos modos reciben tráfico, pero ese tráfico ingresa al clúster a través de un máximo de 25 nodos que son parte del subconjunto. Si el clúster tiene menos de 25 nodos, todos son parte del subconjunto.

  • externalTrafficPolicy: Local: las solicitudes del cliente se envían a la IP del nodo y se balancean sus cargas solo a los Pods de backend que se ejecutan en el mismo nodo. Como resultado, el subconjunto de nodos de backend solo contiene nodos que alojan uno de los Pods de objetos del servicio. El tamaño del subconjunto es la cantidad de nodos que alojan a los Pods de este servicio hasta un máximo de 250 nodos. No programes estos servicios en más de 250 nodos, ya que los nodos adicionales no reciben tráfico del balanceador de cargas.

Requisitos y limitaciones

La subdivisión para GKE tiene los requisitos y las limitaciones que se mencionan a continuación:

  • Puedes habilitar la subdivisión en clústeres nuevos y existentes en la versión de GKE 1.18.19-gke.1400 y versiones posteriores.
  • El clúster debe tener el complemento HttpLoadBalancing habilitado. Este complemento está habilitado de forma predeterminada. Un clúster que inhabilitó este complemento no puede usar la subdivisión. Para aprender a ejecutar un controlador de Ingress personalizado con el complemento HttpLoadBalancing habilitado, consulta Usa un controlador de Ingress personalizado con el complemento HttpLoadBalancing habilitado.
  • Versión 345.0.0 y posterior del SDK de Cloud.
  • La subdivisión no se puede usar con clústeres de Autopilot.
  • Se aplican cuotas para los grupos de extremos de red. Google Cloud crea 1 NEG por balanceador de cargas TCP/UDP interno por zona.
  • Se aplican cuotas para las reglas de reenvío, los servicios de backend y otros recursos de red.
  • La subdivisión no se puede inhabilitar una vez habilitada en un clúster.
  • La subdivisión no se puede usar con la anotación para compartir servicios de backend, alpha.cloud.google.com/load-balancer-backend-share.

Habilita la subdivisión del balanceador de cargas interno en un clúster nuevo

Puedes crear un clúster con la subdivisión del balanceador de cargas interno habilitada mediante la herramienta de línea de comandos de gcloud o Cloud Console:

Console

  1. Ve a la página Google Kubernetes Engine en Cloud Console.

    Ir a Google Kubernetes Engine

  2. Haz clic en Crear.

  3. Configura tu clúster como desees.

  4. En el panel de navegación, en Clúster, haz clic en Redes.

  5. Selecciona la casilla de verificación Habilitar subconjunto para balanceadores de cargas internos L4.

  6. Haz clic en Crear.

gcloud

gcloud container clusters create CLUSTER_NAME \
    --cluster-version=VERSION \
    --enable-l4-ilb-subsetting \
    --region=COMPUTE_REGION

Reemplaza lo siguiente:

  • CLUSTER_NAME es el nombre del clúster nuevo.
  • VERSION: la versión de GKE, que debe ser 1.18.19-gke.1400 o posterior. También puedes usar la opción --release-channel para seleccionar un canal de versiones. El canal de versiones debe tener una versión predeterminada 1.18.19-gke.1400 o posterior.
  • COMPUTE_REGION: es la región de procesamiento para el clúster.

Habilita la subdivisión del balanceador de cargas interno en un clúster existente

Puedes habilitar la subdivisión del balanceador de cargas interno para un clúster existente con la herramienta de gcloud o Google Cloud Console. No puedes inhabilitar la subdivisión del balanceador de cargas interno después de habilitarla en un clúster.

Console

  1. En Cloud Console, ve a la página Google Kubernetes Engine.

    Ir a Google Kubernetes Engine

  2. En la lista de clústeres, haz clic en el nombre del clúster que deseas modificar.

  3. En Herramientas de redes, junto al campo Subdivisión de balanceadores de cargas internos L4, haz clic en Habilitar la subdivisión de balanceadores de cargas internos L4.

  4. Selecciona la casilla de verificación Habilitar subconjunto para balanceadores de cargas internos L4.

  5. Haz clic en Save Changes.

gcloud

gcloud container clusters update CLUSTER_NAME \
    --enable-l4-ilb-subsetting

Reemplaza lo siguiente:

  • CLUSTER_NAME: el nombre del clúster

Verifica la subdivisión del balanceador de cargas interno

A fin de verificar que la subdivisión del balanceador de cargas interno funcione correctamente para el clúster, realiza los siguientes pasos:

  1. Implementar una carga de trabajo.

    En el siguiente manifiesto, se describe una implementación que ejecuta una imagen de contenedor de aplicación web de muestra. Guarda el manifiesto como ilb-deployment.yaml:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: ilb-deployment
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: ilb-deployment
      template:
        metadata:
          labels:
            app: ilb-deployment
        spec:
          containers:
          - name: hello-app
            image: us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0
    
  2. Aplica el manifiesto al clúster:

    kubectl apply -f ilb-deployment.yaml
    
  3. Crea un servicio.

    En el siguiente manifiesto, se describe un servicio que crea un balanceador de cargas interno en el puerto TCP 8080. Guarda el manifiesto como ilb-svc.yaml:

    apiVersion: v1
    kind: Service
    metadata:
      name: ilb-svc
      annotations:
        networking.gke.io/load-balancer-type: "Internal"
    spec:
      type: LoadBalancer
      externalTrafficPolicy: Cluster
      selector:
        app: ilb-deployment
      ports:
      - name: tcp-port
        protocol: TCP
        port: 8080
        targetPort: 8080
    
  4. Aplica el manifiesto al clúster:

    kubectl apply -f ilb-svc.yaml
    
  5. Inspecciona el servicio:

    kubectl get svc ilb-svc -o=jsonpath="{.metadata.annotations.cloud\.google\.com/neg-status}"
    

    El resultado es similar a este:

    {"network_endpoint_groups":{"0":"k8s2-knlc4c77-default-ilb-svc-ua5ugas0"},"zones":["us-central1-c"]}
    

    La respuesta indica que GKE creó un grupo de extremos de red llamado k8s2-knlc4c77-default-ilb-svc-ua5ugas0. Esta anotación está presente en los servicios del tipo LoadBalancer que utilizan la subdivisión de GKE y no está presente en los servicios que no usan la subdivisión.

Soluciona problemas

A fin de determinar la lista de nodos en el subconjunto de un servicio, usa el siguiente comando:

gcloud compute network-endpoint-groups list-network-endpoints NEG_NAME \
    --zone=COMPUTE_ZONE

Reemplaza lo siguiente:

  • NEG_NAME: el nombre del grupo de extremos de red que crea el controlador de GKE.
  • COMPUTE_ZONE: La zona de procesamiento de extremos de red en la que se operará.

A fin de determinar la lista de nodos en buen estado para un balanceador de cargas TCP/UDP interno, usa el siguiente comando:

gcloud compute backend-services get-health SERVICE_NAME \
    --region=COMPUTE_REGION

Reemplaza lo siguiente:

  • SERVICE_NAME: el nombre del servicio de backend. Este valor es el mismo que el nombre del grupo de extremos de red creado por el controlador de GKE.
  • COMPUTE_REGION: es la región de procesamiento del servicio de backend en la que se operará.

Problemas conocidos

Tiempo de espera de conexión cada 10 minutos

Los servicios LoadBalancer internos creados con subdivisión pueden observar interrupciones del tráfico cada 10 minutos, aproximadamente. Este error se corrigió en las siguientes versiones:

  • 1.18.19-gke.1700 y posteriores
  • 1.19.10-gke.1000 y posteriores
  • 1.20.6-gke.1000 y posteriores

Crea un balanceador de cargas de TCP/UDP interno con Private Service Connect

Como productor de servicios, puedes usar adjuntos de servicio a fin de que tus servicios estén disponibles para los consumidores de servicios en otras redes de VPC mediante Private Service Connect. Puedes crear, administrar y borrar adjuntos de servicio mediante un recurso personalizado ServiceAttachment.

Requisitos y limitaciones

  • Se aplican las limitaciones para Private Service Connect.
  • Puedes crear un adjunto de servicio en las versiones 1.21.4-gke.300 y posteriores de GKE.
  • No puedes usar la misma subred para múltiples parámetros de configuración de adjuntos de servicio.
  • Debes crear un servicio GKE que use un balanceador de cargas TCP/UDP interno.

Crea un ServiceAttachment

  1. Crea una subred.

    Debes crear una subred nueva para cada ServiceAttachment.

    gcloud beta compute networks subnets create SUBNET_NAME \
        --project PROJECT_ID \
        --network NETWORK_NAME \
        --region REGION \
        --range SUBNET_RANGE \
        --purpose PRIVATE_SERVICE_CONNECT
    

    Reemplaza lo siguiente:

    • SUBNET_NAME: es el nombre de la subred nueva.
    • PROJECT_ID es el ID de tu proyecto de Google Cloud.
    • NETWORK_NAME: es el nombre de la red de VPC para la subred.
    • REGION: Es la región de la subred nueva. Debes usar la misma región que el servicio que creas.
    • SUBNET_RANGE: El rango de direcciones IP que se usará para la subred.
  2. Implementar una carga de trabajo.

    En el siguiente manifiesto, se describe una implementación que ejecuta una imagen de contenedor de aplicación web de muestra. Guarda el manifiesto como my-deployment.yaml:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: psc-ilb
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: psc-ilb
      template:
        metadata:
          labels:
            app: psc-ilb
        spec:
          containers:
          - name: whereami
            image: gcr.io/google-samples/whereami:v1.2.1
            ports:
              - name: http
                containerPort: 8080
            readinessProbe:
              httpGet:
                path: /healthz
                port: 8080
                scheme: HTTP
              initialDelaySeconds: 5
              timeoutSeconds: 1
    
  3. Aplica el manifiesto al clúster:

    kubectl apply -f my-deployment.yaml
    
  4. Cómo crear un servicio En el siguiente manifiesto, se describe un servicio que crea un balanceador de cargas interno de TCP/UDP en el puerto TCP 8080. Guarda el manifiesto como my-service.yaml:

     apiVersion: v1
     kind: Service
     metadata:
       name: SERVICE_NAME
       annotations:
         networking.gke.io/load-balancer-type: "Internal"
     spec:
       type: LoadBalancer
       selector:
         app: psc-ilb
       ports:
       - port: 80
         targetPort: 8080
         protocol: TCP
    

    Reemplaza lo siguiente:

    • SERVICE_NAME: Nombre del servicio nuevo.
  5. Aplica el manifiesto al clúster:

    kubectl apply -f my-service.yaml
    
  6. Crea ServiceAttachment.

    En el siguiente manifiesto, se describe un ServiceAttachment que expone el servicio que creaste a los consumidores de servicios. Guarda el manifiesto como my-psc.yaml:

    apiVersion: networking.gke.io/v1beta1
    kind: ServiceAttachment
    metadata:
     name: SERVICE_ATTACHMENT_NAME
     namespace: default
    spec:
     connectionPreference: ACCEPT_AUTOMATIC
     natSubnets:
     - SUBNET_NAME
     proxyProtocol: false
     resourceRef:
       kind: Service
       name: SERVICE_NAME
    

    Reemplaza lo siguiente:

    • SERVICE_ATTACHMENT_NAME: Nombre del adjunto de servicio nuevo.

    ServiceAttachment tiene los siguientes campos:

    • connectionPreference: es la preferencia de conexión que determina cómo los clientes se conectan al servicio. Puedes usar la aprobación automática del proyecto con ACCEPT_AUTOMATIC o la aprobación explícita del proyecto con ACCEPT_MANUAL. Para obtener más información, consulta Publica servicios mediante Private Service Connect.
    • natSubnets: una lista de nombres de recursos de subred para usar en el adjunto de servicio.
    • proxyProtocol: cuando se configura como verdadero, la IP de origen del consumidor y la ID de conexión de Private Service Connect están disponibles en las solicitudes. Este campo es opcional y su valor predeterminado es falso si no se proporciona.
    • consumerAllowList: es la lista de proyectos de consumidor que pueden conectarse a ServiceAttachment. Este campo solo se puede usar cuando connectionPreference es ACCEPT_MANUAL. Para obtener más información sobre este campo, consulta Publica servicios mediante Private Service Connect.
      • project: El número o ID del proyecto de consumidor.
      • connectionLimit: es el límite de conexión para el proyecto de consumidor. Este campo es opcional.
      • forceSendFields: son los nombres de campo que se enviarán a fin de incluir en las solicitudes a la API. Este campo es opcional.
      • nullFields: son los nombres de campo que se incluirán en las solicitudes a la API con un valor nulo. Este campo es opcional.
    • consumerRejectList: es la lista de ID o números de proyectos de consumidor que no pueden conectarse a ServiceAttachment. Este campo solo se puede usar cuando connectionPreference es ACCEPT_MANUAL. Para obtener más información sobre este campo, consulta Publica servicios mediante Private Service Connect.
    • resourceRef: Una referencia al recurso de Kubernetes.
      • kind: es el tipo de recurso de Kubernetes. Debes usar Service.
      • name: es el nombre del recurso de Kubernetes que debe estar en el mismo espacio de nombres que el balanceador de cargas de TCP/UDP interno.
  7. Aplica el manifiesto al clúster:

    kubectl apply -f my-psc.yaml
    
  8. Verifica que el controlador de Private Service Connect haya creado el adjunto de servicio:

    gcloud beta compute service-attachments list
    

    El resultado muestra un adjunto de servicio con un nombre generado automáticamente:

    NAME        REGION       PRODUCER_FORWARDING_RULE          CONNECTION_PREFERENCE
    k8s1-sa-... us-central1  a3fea439c870148bdba5e59c9ea9451a  ACCEPT_AUTOMATIC
    

Visualiza un ServiceAttachment

Puedes ver los detalles de un ServiceAttachment con el siguiente comando:

kubectl describe serviceattachment SERVICE_ATTACHMENT_NAME /
    --project PROJECT_ID

El resultado es similar a este:

 kubectl describe serviceattachment foo-sa
Name:        <sa-name>
Namespace:    default
Labels:       <none>
Annotations:  <none>
API Version:  networking.gke.io/v1beta1
Kind:         ServiceAttachment
Metadata:
  ...
Status:
  Forwarding Rule URL:      https://www.googleapis.com/compute/beta/projects/<project>/regions/<region>/forwardingRules/<fr-name>
  Last Modified Timestamp:  2021-07-08T01:32:39Z
  Service Attachment URL:   https://www.googleapis.com/compute/beta/projects/<projects>/regions/<region>/serviceAttachments/<gce-service-attachment-name>
Events:                     <none>

Consume un ServiceAttachment

Para consumir tu servicio desde otro proyecto, realiza los siguientes pasos:

  1. Obtén la URL del ServiceAttachment:

    kubectl get serviceattachment SERVICE_ATTACHMENT_NAME -o=jsonpath="{.status.serviceAttachmentURL}"
    

    El resultado es similar a este:

      serviceAttachmentURL: https://www.googleapis.com/compute/alpha/projects/<project>/region/<region>/serviceAttachments/k8s1-...my-sa
    
  2. Crea un extremo de Private Service Connect con la URL de ServiceAttachment.

  3. Verifica que puedas conectarte al servicio que implementaste en el proyecto de productor mediante un comando curl desde una VM en el proyecto de consumidor:

    curl PSC_IP_ADDRESS
    

    Reemplaza PSC_IP_ADDRESS por la dirección IP de la regla de reenvío en el proyecto del consumidor.

    El resultado es similar a este:

    {
      "cluster_name":"cluster",
      "host_header":"10.128.15.200",
      "node_name":"gke-psc-default-pool-be9b6e0e-dvxg.c.gke_project.internal",
      "pod_name":"foo-7bf648dcfd-l5jf8",
      "pod_name_emoji":"👚",
      "project_id":"gke_project",
      "timestamp":"2021-06-29T21:32:03",
      "zone":"us-central1-c"
    }
    

Actualiza un ServiceAttachment

Puedes actualizar un ServiceAttachment mediante los siguientes pasos:

  1. Edita el manifiesto ServiceAttachment en my-psc.yaml:

    apiVersion: networking.gke.io/v1beta1
    kind: ServiceAttachment
    metadata:
      name: my-sa
      namespace: default
    spec:
      connectionPreference: ACCEPT_AUTOMATIC
      natSubnets:
      - my-nat-subnet
      proxyProtocol: false
      resourceRef:
        kind: Service
        name: ilb-service
    
  2. Aplica el manifiesto al clúster:

    kubectl apply -f my-psc.yaml
    

Realice una limpieza

No puedes borrar un balanceador de cargas TCP/UDP interno que esté conectado a un adjunto de servicio. Debes borrar el adjunto de servicio y el servicio de GKE por separado.

  1. Borra el adjunto de servicio:

    kubectl delete serviceattachment SERVICE_ATTACHMENT_NAME --wait=false
    

    Con este comando, se marca el adjunto de servicio para su eliminación, pero el recurso continúa existiendo. También puedes esperar a que finalice la eliminación si omites la marca --wait.

  2. Borrar Service:

    kubectl delete svc SERVICE_NAME
    
  3. Borra la subred:

    gcloud compute networks subnets delete SUBNET_NAME
    

Soluciona problemas

Puedes ver los mensajes de error mediante el siguiente comando:

kubectl get events -n NAMESPACE

Reemplaza NAMESPACE por el espacio de nombres del balanceador de cargas TCP/UDP interno.

Un mensaje de error similar al siguiente ocurre si intentas borrar un balanceador de cargas TCP/UDP interno que un adjunto de servicio utiliza. Debes borrar ServiceAttachment para poder borrar el balanceador de cargas TCP/UDP interno.

Error syncing load balancer: failed to ensure load balancer: googleapi:
Error 400: The forwarding_rule resource '<fwd-rule-URL>' is already being used
by '<svc-attachment-URL>', resourceInUseByAnotherResource.

Parámetros de servicio

Para obtener más información sobre los parámetros de los balanceadores de cargas que puedes configurar, consulta Configura el balanceo de cargas TCP/UDP. Además, los Service de LoadBalancer internos admiten los siguientes parámetros adicionales:

Función Descripción general Campo de servicio Compatibilidad con la versión de GKE
Subred del balanceador de cargas Especifica desde qué subred el balanceador de cargas debe aprovisionar una IP de forma automática. metadata:annotations: networking.gke.io/internal-load-balancer-subnet Beta en GKE 1.17+ y 1.16.8-gke.10+
GA en GKE 1.17.9-gke.600+
Acceso global Permite que los clientes en todas las regiones de Google Cloud puedan acceder a la dirección IP virtual del balanceador de cargas TCP/UDP interno. metadata:annotations: networking.gke.io/internal-load-balancer-allow-global-access Beta en GKE 1.16+
GA en GKE 1.17.9-gke.600+

Subred del balanceador de cargas

De forma predeterminada, GKE implementará un balanceador de cargas de TCP/UDP interno mediante el rango de subred de nodo. Un usuario puede especificar la subred servicio por servicio mediante la anotación networking.gke.io/internal-load-balancer-subnet. Esto es útil para firewalls independientes de las IP del balanceador de cargas de las IP de nodo o para compartir la misma subred de servicio en varios clústeres de GKE. Este parámetro solo es relevante para los servicios del balanceador de carga de TCP/UDP interno.

La subred debe existir antes de que el recurso de servicio haga referencia a ella, ya que GKE no administra el ciclo de vida de la subred. La subred también debe estar en la misma VPC y región que el clúster de GKE. En este paso, se crea por fuera de la banda de GKE:

gcloud compute networks subnets create gke-vip-subnet \
    --network=default \
    --range=10.23.0.0/24 \
    --region=us-central1

La siguiente definición de servicio usa internal-load-balancer-subnet para hacer referencia a la subred por nombre. De forma predeterminada, se elegirá de forma automática una IP disponible de la subred. También puedes especificar loadBalancerIP, pero debe ser parte de la subred a la que se hace referencia.

Existen varias formas de compartir esta subred del balanceador de cargas interno para lograr diferentes casos prácticos:

  • Varias subredes para grupos de servicios en el mismo clúster
  • Una única subred para todos los servicios de un clúster
  • Una única subred compartida entre varios clústeres y varios servicios
apiVersion: v1
kind: Service
metadata:
  name: ilb-service
  annotations:
    networking.gke.io/load-balancer-type: "Internal"
    networking.gke.io/internal-load-balancer-subnet: "gke-vip-subnet"
  labels:
    app: hello
spec:
  type: LoadBalancer
  loadBalancerIP: 10.23.0.15
  selector:
    app: hello
  ports:
  - port: 80
    targetPort: 8080
    protocol: TCP

Acceso global

El acceso global es un parámetro opcional para los servicios de LoadBalancer interno que permite que los clientes de cualquier región de tu red de VPC accedan al balanceador de cargas de TCP/UDP interno. Sin acceso global, el tráfico que se origina en los clientes de tu red de VPC debe estar en la misma región que el balanceador de cargas. El acceso global permite que los clientes de cualquier región accedan al balanceador de cargas. Las instancias de backend deben estar ubicadas en la misma región que el balanceador de cargas.

El acceso global se habilita por servicio mediante la siguiente anotación: networking.gke.io/internal-load-balancer-allow-global-access: "true".

El acceso global no es compatible con las redes heredadas. Se aplican costos normales de tráfico interregional cuando se usa el acceso global en todas las regiones. Consulta Precios de red a fin de obtener información sobre los precios de red para la salida entre regiones. El acceso global está disponible en versión Beta en los clústeres de GKE 1.16+ y GA en 1.17.9-gke.600+.

Para los clientes locales, el acceso global permite a los clientes acceder al balanceador de cargas mediante Cloud VPN o Cloud Interconnect (VLAN) en cualquier región. Para obtener más información, consulta Uso de Cloud VPN y Cloud Interconnect.

IP compartida

El balanceador de cargas de TCP/UDP interno permite el uso compartido de una dirección IP virtual entre varias reglas de reenvío. Esto es útil para expandir la cantidad de puertos simultáneos en la misma IP o aceptar tráfico de UDP y TCP en la misma IP. Permite un máximo de 50 puertos expuestos por dirección IP. Las IP compartidas se admiten de forma nativa en los clústeres de GKE con servicios de LoadBalancer internos. Cuando se implementa, el campo loadBalancerIP del servicio se usa para indicar qué IP se debe compartir entre los servicios.

Limitaciones

Una IP compartida para varios balanceadores de cargas tiene las siguientes limitaciones y capacidades:

  • Cada servicio (o regla de reenvío) puede tener un máximo de cinco puertos.
  • Un máximo de diez servicios (reglas de reenvío) pueden compartir una dirección IP. Esto da como resultado un máximo de 50 puertos por IP compartida.
  • Las tuplas de protocolo o de puerto no se pueden superponer entre los servicios que comparten la misma IP.
  • Se admite una combinación de servicios de solo TCP y de solo UDP en la misma IP compartida. Sin embargo, no puedes exponer ambos puertos de TCP y UDP en el mismo servicio.

Habilita la IP compartida

Si deseas habilitar que los servicios de LoadBalancer internos compartan una IP común, sigue estos pasos:

  1. Crea una IP interna estática con --purpose SHARED_LOADBALANCER_VIP. Se debe crear una dirección IP con esta finalidad para habilitar su capacidad de ser compartida. Si creas la dirección IP interna estática en una VPC compartida, debes crear la dirección IP en el mismo proyecto de servicio que la instancia que usará la dirección IP, aunque el valor de la dirección IP vendrá del rango de IP disponibles en una subred compartida seleccionada de la red de VPC compartida. Consulta Reserva una IP interna estática en la página Aprovisiona la VPC compartida para obtener más información.

  2. Implementa hasta diez servicios de LoadBalancer internos mediante esta IP estática en el campo loadBalancerIP. El controlador del servicio de GKE concilia los balanceadores de cargas de TCP/UDP internos y se implementan mediante la misma IP de frontend.

En el siguiente ejemplo, se muestra cómo hacer esto con el fin de admitir varios puertos de TCP y UDP en la misma IP del balanceador de cargas interno.

  1. Crea una IP estática en la misma región en la que se encuentra el clúster de GKE. La subred debe ser la misma que usa el balanceador de cargas. De forma predeterminada, es la misma subred que usan las IP del nodo del clúster de GKE.

    Si tu clúster y la red de VPC están en el mismo proyecto, haz lo siguiente:

    gcloud compute addresses create IP_ADDR_NAME \
        --project=PROJECT_ID \
        --subnet=SUBNET \
        --addresses=IP_ADDRESS \
        --region=COMPUTE_REGION \
        --purpose=SHARED_LOADBALANCER_VIP
    

    Si tu clúster está en un proyecto de servicio de VPC compartida, pero usa una red de VPC compartida en un proyecto host, haz lo siguiente:

    gcloud compute addresses create IP_ADDR_NAME \
        --project=SERVICE_PROJECT_ID \
        --subnet=projects/HOST_PROJECT_ID/regions/REGION/subnetworks/SUBNET \
        --addresses=IP_ADDRESS \
        --region=COMPUTE_REGION \
        --purpose=SHARED_LOADBALANCER_VIP
    

    Reemplaza lo siguiente:

    • IP_ADDR_NAME: un nombre para el objeto de dirección IP
    • SERVICE_PROJECT_ID: el ID del proyecto de servicio
    • PROJECT_ID: el ID de tu proyecto (proyecto único)
    • HOST_PROJECT_ID: el ID del proyecto host de la VPC compartida
    • COMPUTE_REGION: es la región de procesamiento que contiene la subred compartida.
    • IP_ADDRESS: una dirección IP interna sin usar del rango de direcciones IP principal de la subred seleccionada Si omites especificar una dirección IP, Google Cloud selecciona una dirección IP interna sin usar del rango de direcciones IP principal de la subred seleccionada. Para determinar una dirección seleccionada de forma automática, deberás ejecutar gcloud compute addresses describe.
    • SUBNET: el nombre de la subred compartida
  2. Guarda la siguiente configuración del servicio de TCP en un archivo llamado tcp-service.yaml y, luego, impleméntala en el clúster. Reemplaza IP_ADDRESS por la dirección IP que elegiste en el paso anterior.

    apiVersion: v1
    kind: Service
    metadata:
      name: tcp-service
      namespace: default
      annotations:
        networking.gke.io/load-balancer-type: "Internal"
    spec:
      type: LoadBalancer
      loadBalancerIP: IP_ADDRESS
      selector:
        app: myapp
      ports:
      - name: 8001-to-8001
        protocol: TCP
        port: 8001
        targetPort: 8001
      - name: 8002-to-8002
        protocol: TCP
        port: 8002
        targetPort: 8002
      - name: 8003-to-8003
        protocol: TCP
        port: 8003
        targetPort: 8003
      - name: 8004-to-8004
        protocol: TCP
        port: 8004
        targetPort: 8004
      - name: 8005-to-8005
        protocol: TCP
        port: 8005
        targetPort: 8005
    
  3. Aplica esta definición de servicio en el clúster:

    kubectl apply -f tcp-service.yaml
    
  4. Guarda la siguiente configuración del servicio de UDP en un archivo llamado udp-service.yaml y, luego, impleméntala. También usa el IP_ADDRESS que especificaste en el paso anterior.

    apiVersion: v1
    kind: Service
    metadata:
      name: udp-service
      namespace: default
      annotations:
        networking.gke.io/load-balancer-type: "Internal"
    spec:
      type: LoadBalancer
      loadBalancerIP: IP_ADDRESS
      selector:
        app: my-udp-app
      ports:
      - name: 9001-to-9001
        protocol: UDP
        port: 9001
        targetPort: 9001
      - name: 9002-to-9002
        protocol: UDP
        port: 9002
        targetPort: 9002
    
  5. Aplica este archivo en el clúster:

    kubectl apply -f udp-service.yaml
    
  6. Para validar que la VIP se comparta entre las reglas de reenvío del balanceador de cargas, enuméralas y filtra la IP estática. Esto muestra que hay una regla de reenvío de UDP y una de TCP que escuchan en siete puertos diferentes en el IP_ADDRESS compartido, que en este ejemplo es 10.128.2.98.

    gcloud compute forwarding-rules list | grep 10.128.2.98
    ab4d8205d655f4353a5cff5b224a0dde                         us-west1   10.128.2.98     UDP          us-west1/backendServices/ab4d8205d655f4353a5cff5b224a0dde
    acd6eeaa00a35419c9530caeb6540435                         us-west1   10.128.2.98     TCP          us-west1/backendServices/acd6eeaa00a35419c9530caeb6540435
    

Se reenvían todos los puertos

Las reglas de reenvío internas admiten hasta cinco puertos por regla de reenvío o un parámetro opcional --ports=ALL que reenvíe todos los puertos en la regla de reenvío.

Requisitos

Todos los puertos de GKE tienen los requisitos y las limitaciones que se describen a continuación:

  • Solo se admite cuando --enable-l4-ilb-subsetting está habilitado.
  • Solo se admite con los servicios del balanceador de cargas interno.
  • Admite cualquier cantidad de puertos en un máximo de 100 rangos de puertos contiguos.

El controlador de GKE habilita de forma automática todos los puertos en la regla de reenvío cuando un servicio tiene más de cinco puertos. Por ejemplo, el siguiente manifiesto de servicio tiene seis puertos configurados en dos rangos contiguos:

apiVersion: v1
kind: Service
metadata:
  name: all-ports
  annotations:
    networking.gke.io/load-balancer-type: "Internal"
spec:
  type: LoadBalancer
  selector:
    app: myapp
  ports:
  - port: 8081
    targetPort: 8081
    name: 8081-to-8081
    protocol: TCP
  - port: 8082
    targetPort: 8082
    name: 8082-to-8082
    protocol: TCP
  - port: 8083
    targetPort: 8083
    name: 8083-to-8083
    protocol: TCP
  - port: 9001
    targetPort: 9001
    name: 9001-to-9001
    protocol: TCP
  - port: 9002
    targetPort: 9002
    name: 9002-to-9002
    protocol: TCP
  - port: 9003
    targetPort: 9003
    name: 9003-to-9003
    protocol: TCP

El controlador de GKE habilita todos los puertos en la regla de reenvío porque el servicio tiene más de cinco puertos. Sin embargo, el controlador de GKE solo crea puertos de firewall para los puertos especificados en el servicio. Los firewalls de VPC bloquean todas las demás reglas.

Restricciones para balanceadores de cargas TCP/UDP internos

  • Para los clústeres que ejecutan Kubernetes versión 1.7.4 o superior, pueden usar balanceadores de cargas internos con subredes modo personalizado además de las subredes en modo automático
  • Los clústeres que ejecutan Kubernetes versión 1.7.X y posteriores admiten el uso de una dirección IP reservada para el balanceador de cargas de TCP/UDP interno si creas la dirección IP reservada con la marca--purpose establecida enSHARED_LOADBALANCER_VIP. Para obtener instrucciones paso a paso, consulta Habilita IP compartida. GKE solo conserva la dirección IP de un balanceador de cargas de TCP/UDP interno si el Service hace referencia a una dirección IP interna con ese propósito. De lo contrario, GKE podría cambiar la dirección IP del balanceador de cargas (spec.loadBalancerIP) si el servicio se actualiza (por ejemplo, si se cambian los puertos).
  • Incluso si la dirección IP del balanceador de cargas cambia (consulta el punto anterior), el spec.clusterIP permanece constante.

Restricciones para balanceadores de cargas UDP internos

  • Los balanceadores de cargas UDP internos no son compatibles con sessionAffinity: ClientIP.

Límites

Un servicio de Kubernetes con type: LoadBalancer y la anotación networking.gke.io/load-balancer-type: Internal crean un balanceador de cargas interno que se orienta al servicio de Kubernetes. La cantidad de esos servicios está limitada por la cantidad de reglas de reenvío internas que puedes crear en una red de VPC. Para obtener más información, consulta los Límites por red.

La cantidad máxima de nodos en un clúster de GKE con un balanceador de cargas TCP/UDP interno depende del valor de externalTrafficPolicy:

  • externalTrafficPolicy: Cluster: El backend del balanceador de cargas TCP/UDP interno usa un máximo de 250 nodos seleccionados al azar. Si el clúster tiene más de 250 nodos, todo el tráfico del balanceador de cargas ingresa al clúster a través de los 250 nodos y se reenvía a un Pod coincidente seleccionado de forma aleatoria. No se recomienda usar este modo con más de 250 nodos.

  • externalTrafficPolicy: Local: El backend del balanceador de cargas TCP/UDP interno usa un máximo de 250 nodos seleccionados de forma aleatoria. Si ninguno de los 250 nodos seleccionados ejecuta los Pods de backend para el servicio del balanceador de cargas TCP/UDP interno, las conexiones a la IP LoadBalancer fallan. No se admite el uso de este modo con más de 250 nodos.

Para quitar esta limitación, habilita la subdivisión de balanceador de cargas interno.

Para obtener más información sobre los límites de VPC, consulta Cuotas y límites.

¿Qué sigue?