Personaliza el tráfico de GKE Gateway con extensiones de servicio


En esta página, se describe cómo Google Kubernetes Engine (GKE) usa extensiones de servicio para agregar lógica personalizada a Cloud Load Balancing.

Esta página está dirigida a los administradores de identidades y cuentas de GKE y a los desarrolladores que necesitan configurar lógica personalizada de administración del tráfico con extensiones de servicio.

Antes de leer esta página, asegúrate de estar familiarizado con los siguientes temas:

Descripción general

GKE usa extensiones de servicio para agregar lógica personalizada a Cloud Load Balancing. Una extensión se adjunta a un Gateway y hace referencia a un Service o a un GoogleAPIServiceName. GoogleAPIServiceName solo es compatible con GCPTrafficExtensions.

Puedes modificar los encabezados y las cargas útiles HTTP para las solicitudes y respuestas, o controlar el enrutamiento del tráfico, sin afectar la selección del servicio de backend ni las políticas de seguridad. Puedes usar las extensiones de servicio para tareas como la división avanzada del tráfico, la autenticación personalizada o el registro de solicitudes.

El controlador de GKE Gateway admite las siguientes extensiones de Service:

  • GCPRoutingExtension: Esta extensión agrega lógica personalizada a Cloud Load Balancing para controlar el enrutamiento del tráfico. Es compatible con el balanceador de cargas de aplicaciones externo regional y el balanceador de cargas de aplicaciones interno regional.

    El recurso `GCPRoutingExtension` se conecta a una puerta de enlace y hace referencia a un servicio. La extensión controla el enrutamiento del tráfico.
    Figura: Cómo funciona GCPRoutingExtension con las Gateways
  • GCPTrafficExtension: Esta extensión inserta lógica personalizada en Cloud Load Balancing. Permite que un servicio de extensión cambie los encabezados y las cargas útiles de las solicitudes y respuestas. El GCPTrafficExtension no afecta la selección del servicio de backend ni las políticas de seguridad del servicio de backend.

    El recurso `GCPTrafficExtension` se adjunta a una puerta de enlace y hace referencia a un servicio o a un `GoogleAPIServiceName`. La extensión cambia los encabezados y las cargas útiles de las solicitudes y respuestas.
    Figura: Cómo funciona GCPTrafficExtension con las Gateways

Google Cloud Compatibilidad de la extensión del servicio con GatewayClasses

En la siguiente tabla, se describe la compatibilidad de las extensiones de servicio de Google Cloud con diferentes GatewayClasses:

GatewayClass GCPRoutingExtension GCPTrafficExtension
gke-l7-rilb Admitido Compatible
gke-l7-regional-external-managed Compatible Compatible
gke-l7-global-external-managed No compatible Admitido

Antes de comenzar

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

  • Habilita la API de Google Kubernetes Engine.
  • Habilitar la API de Google Kubernetes Engine
  • Si deseas usar Google Cloud CLI para esta tarea, instala y, luego, inicializa gcloud CLI. Si ya instalaste gcloud CLI, ejecuta gcloud components update para obtener la versión más reciente.

Requisitos del controlador de la puerta de enlace de GKE

Restricciones y limitaciones

En la siguiente tabla, se enumeran las restricciones asociadas con la configuración de las extensiones de Gateway Service en GKE:

Categoría Restricciones y limitaciones
Balanceador de cargas GCPRoutingExtension solo es compatible con el balanceador de cargas de aplicaciones externo regional y el balanceador de cargas de aplicaciones interno regional (gke-l7-regional-external-managed y gke-l7-rilb clases de Gateway) y no es compatible con la clase de Gateway gke-l7-global-external-managed.
Cadena y especificación de la extensión
  • En el caso de un GCPTrafficExtension, cada ExtensionChain puede tener un máximo de 3 Extensions.
  • En el caso de un GCPRoutingExtension, cada ExtensionChain se limita a 1 Extension.
  • Un GCPTrafficExtensionSpec y un GCPRoutingExtensionSpec pueden tener un máximo de 5 ExtensionChains cada uno.
Sincronización y correlación
  • El tiempo de espera de cada mensaje individual en la transmisión dentro de una extensión debe ser de entre 10 y 1,000 milisegundos. Este límite de un segundo se aplica a las extensiones de Rutas y Tráfico.
  • Cada MatchCondition dentro de un ExtensionChain está limitado a un máximo de 10 CELExpressions.
  • La cadena MatchCondition resultante que se envía a GCE tiene un límite de 512 caracteres.
  • La cadena CELMatcher dentro de un CELExpression tiene una longitud máxima de 512 caracteres y debe cumplir con un patrón específico. No admitimos el campo BackendRefs de CELExpression.
Encabezado y metadatos
  • La lista ForwardHeaders en un Extension puede contener un máximo de 50 nombres de encabezados HTTP.
  • El mapa Metadata en un Extension puede tener un máximo de 16 propiedades.
  • Las claves del mapa Metadata deben tener entre 1 y 63 caracteres.
  • Los valores dentro del mapa Metadata deben tener entre 1 y 1,023 caracteres.
Evento
  • En el caso de un GCPRoutingExtension, si no se establece requestBodySendMode, la lista supportedEvents solo puede contener eventos RequestHeaders.
  • En el caso de un GCPRoutingExtension, si requestBodySendMode se establece en FullDuplexStreamed, la lista supportedEvents solo puede contener eventos RequestHeaders, RequestBody y RequestTrailers.
GCPTrafficExtension
  • El campo responseBodySendMode solo se admite para GCPTrafficExtension.
  • El campo googleAPIServiceName solo se admite para GCPTrafficExtension.
googleAPIServiceName y backendRef Cuando haces referencia a un Servicio que usa backendRef en una Extensión, debes cumplir con las siguientes condiciones:
  • Debe usar HTTP/2 como su appProtocol.
  • Debe estar en el mismo espacio de nombres que la extensión y la puerta de enlace a la que hace referencia la extensión.
  • No se puede usar IAP.
  • No se pueden usar políticas de seguridad de Google Cloud Armor (campo securityPolicy de GCPBackendPolicyConfig).
  • No se puede usar Cloud CDN.
  • Se debe establecer exactamente uno de los campos backendRef o googleAPIServiceName para un Extension.
  • Se debe establecer authority si se establece backendRef.
  • Se debe establecer authority si se establece googleAPIServiceName.
  • Configura requestBodySendMode para extensiones solo con backendRef.
  • Configura responseBodySendMode para extensiones solo con backendRef.

Configura las extensiones de servicio de GKE

Puedes personalizar el enrutamiento del tráfico, modificar las cargas útiles de solicitudes o respuestas, y realizar integraciones con servicios externos configurando las extensiones de servicio de GKE. Las puertas de enlace no tienen extensiones de servicio de forma predeterminada.

Para configurar las extensiones de servicio de GKE, haz lo siguiente:

  1. Implementa una puerta de enlace: Para configurar una extensión de servicio de GKE, primero debes implementar una puerta de enlace, que dirige el tráfico externo a tu clúster. Puede ser un balanceador de cargas de aplicaciones externo global, un balanceador de cargas de aplicaciones externo regional o una puerta de enlace del balanceador de cargas de aplicaciones interno regional.

    Para obtener más información sobre la implementación de Gateways, consulta Implementa Gateways.

  2. Implementa un servicio de devolución de llamada de backend: Crea un servicio de Kubernetes que represente el servicio de backend para la ejecución de lógica personalizada. El balanceador de cargas invoca este servicio.

  3. Configura las extensiones de servicio: Configura las extensiones de servicio adecuadas según el tipo y los requisitos de tu balanceador de cargas.

    1. GCPRoutingExtension para Gateways regionales: Usa esta extensión para el balanceador de cargas de aplicaciones externo regional y el balanceador de cargas de aplicaciones interno regional para implementar una lógica de enrutamiento personalizada dentro de la región.

    2. GCPTrafficExtension para puertas de enlace externas globales, externas regionales e internas: Usa esta extensión para el balanceador de cargas de aplicaciones externo global, el balanceador de cargas de aplicaciones externo regional y el balanceador de cargas de aplicaciones interno regional para realizar la manipulación del tráfico, como la modificación de encabezados o la inspección de cargas útiles, en varios tipos de balanceadores de cargas.

Implementa un servicio de devolución de llamada de backend

Un servicio de devolución de llamada implementa lógica personalizada para las extensiones de servicio de la puerta de enlace en GKE. La puerta de enlace invoca estas aplicaciones de backend, según las configuraciones de GCPTrafficExtension o GCPRoutingExtension, para modificar o enrutar el tráfico.

Implementas un servicio de texto destacado para agregar lógica personalizada a tu puerta de enlace. Este servicio independiente controla el procesamiento personalizado, como la manipulación de encabezados, las transformaciones de cargas útiles o el enrutamiento del tráfico.

Para implementar un servicio de backend que pueda funcionar como una llamada externa para tu puerta de enlace, sigue estos pasos:

  1. (Opcional) Crea un secreto para TLS: Este comando crea un secreto de Kubernetes de tipo TLS que contiene tu certificado TLS y tu clave privada.

    Para crear el secreto de TLS para tu servicio de devolución de llamada, reemplaza lo siguiente:

    • SECRET_NAME: El nombre secreto de tu servicio de texto destacado
    • path-to-cert: las rutas de acceso a tu certificado
    • path-to-key: Rutas de acceso a los archivos de tu clave
  2. Para verificar que se haya agregado el secreto, ejecuta el siguiente comando:

    kubectl get secrets SECRET_NAME
    

    Reemplaza SECRET_NAME por el nombre secreto de tu servicio de llamada.

    El resultado debería ser similar al siguiente ejemplo:

    NAME            TYPE                DATA   AGE
    SECRET_NAME     kubernetes.io/tls   2      12s
    
  3. Define los recursos de Deployment y Service.

    Debes definir lo siguiente:

    • Implementación: Para administrar los pods de la aplicación que contienen la lógica personalizada de tus extensiones de servicio.
    • Service: Para exponer los pods de la aplicación que administra la Deployment como un servicio de red.
    1. Crea un manifiesto de muestra extension-service-app.yaml que tenga definiciones de Deployment y Service:

      apiVersion: apps/v1
      kind: Deployment
      metadata:
      name: extension-service-app
      spec:
      selector:
          matchLabels:
            app: store
        replicas: 1
        template:
          metadata:
            labels:
              app: store
          spec:
            containers:
            - name: serviceextensions
              image: us-docker.pkg.dev/service-extensions-samples/callouts/python-example-basic:main
              ports:
              - containerPort: 8080
              - containerPort: 443
              volumeMounts:
              - name: certs
                mountPath: "/etc/certs/"
                readOnly: true
              env:
              - name: POD_NAME
                valueFrom:
                  fieldRef:
                    fieldPath: metadata.name
              - name: NAMESPACE
                valueFrom:
                  fieldRef:
                    fieldPath: metadata.namespace
              - name: TLS_SERVER_CERT
                value: "/etc/certs/path-to-cert"
              - name: TLS_SERVER_PRIVKEY
                value: "/etc/certs/path-to-key"
                resources:
                requests:
                  cpu: 10m
            volumes:
            - name: certs
              secret:
                secretName: SECRET_NAME
                optional: false
      ---
      apiVersion: v1
      kind: Service
      metadata:
        name: extension-service
      spec:
        ports:
        - port: 443
          targetPort: 443
          appProtocol: HTTP2
        selector:
          app: store
      
    2. Aplica el manifiesto extension-service-app.yaml:

      kubectl apply -f extension-service-app.yaml
      
  4. Verifica la configuración:

    1. Verifica que la aplicación se haya implementado:

      kubectl get pod --selector app=store
      

      Después de que la aplicación comienza a ejecutarse, el resultado es similar al siguiente:

      NAME                                     READY   STATUS    RESTARTS   AGE
      extension-service-app-85f466bc9b-b5mf4   1/1     Running   0          7s
      
    2. Verifica que se haya implementado el servicio:

      kubectl get service extension-service
      

      El resultado es similar al siguiente, que muestra un objeto Service para cada Deployment de la tienda:

      NAME                TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
      extension-service   ClusterIP   34.118.225.9   <none>        443/TCP   2m40s
      

Configura las extensiones de servicio

Puedes configurar un GCPRoutingExtension o un GCPTrafficExtension para personalizar tu flujo de tráfico.

Configura GCPRoutingExtension para las puertas de enlace regionales

Puedes cambiar la ruta del tráfico con un GCPRoutingExtension. Para configurar un GCPRoutingExtension, actualiza la HTTPRoute para especificar las solicitudes del host service-extensions.com.

  1. Actualiza HTTPRoute. Modifica tu HTTPRoute para incluir nombres de host o rutas de acceso que activarán la extensión de enrutamiento.

    1. Guarda el siguiente manifiesto de muestra como el archivo store-route.yaml:

      kind: HTTPRoute
      apiVersion: gateway.networking.k8s.io/v1
      metadata:
        name: store
      spec:
        parentRefs:
        - kind: Gateway
          name:GATEWAY_NAME
        hostnames:
        - "store.example.com"
        - "service-extensions.example.com"
        rules:
        - backendRefs:
          - name: store-v1
            port: 8080
        - matches:
          - headers:
            - name: env
              value: canary
          backendRefs:
          - name: store-v2
            port: 8080
        - matches:
          - path:
              value: /de
          backendRefs:
          - name: store-german
            port: 8080
      

      Reemplaza GATEWAY_NAME por el nombre de tu puerta de enlace.

    2. Aplica el manifiesto store-route.yaml:

      kubectl apply -f store-route.yaml
      
  2. Define el GCPRoutingExtension.

    1. Guarda la configuración de GCPRoutingExtension en el archivo gcp-routing-extension.yaml de muestra:

      kind: GCPRoutingExtension
      apiVersion: networking.gke.io/v1
      metadata:
        name: my-gateway-extension
        namespace: default
      spec:
        targetRefs:
        - group: "gateway.networking.k8s.io"
          kind: Gateway
          name: GATEWAY_NAME
        extensionChains:
        - name: chain1
          matchCondition:
            celExpressions:
            - celMatcher: request.path.contains("serviceextensions")
          extensions:
          - name: ext1
            authority: "myext.com"
            timeout: 1s
              backendRef:
                group: ""
              kind: Service
              name: extension-service
              port: 443
      

      Reemplaza GATEWAY_NAME por el nombre de tu puerta de enlace.

    2. Aplica el manifiesto de muestra a tu clúster:

      kubectl apply -f gcp-routing-extension.yaml
      
  3. Verifica la configuración de GCPRoutingExtension y su vinculación a la puerta de enlace.

    1. Verifica la implementación de GCPRoutingExtension:

      kubectl describe gcproutingextension my-gateway-extension
      

      El resultado es similar a este:

      Name:         my-gateway-extension
      Namespace:    default
      Labels:       <none>
      Annotations:  <none>
      API Version:  networking.gke.io/v1
      Kind:         GCPRoutingExtension
      Metadata:
        Creation Timestamp:  2025-03-02T17:12:30Z
        Generation:        1
        Resource Version:  31283253
        UID:               ec8efaa0-d8e7-4e1b-9fd4-0ae0ef3c74d0
      Spec:
        Extension Chains:
          Extensions:
            Authority:    myext.com
            Backend Ref:
              Group:
              Kind: Service
              Name: extension-service
              Port: 443
            Name:       ext1
            Timeout:    1s
          Match Condition:
            Cel Expressions:
              Cel Matcher: request.path.contains("serviceextensions")
          Name:  chain1
        Target Refs:
          Group: gateway.networking.k8s.io
          Kind: Gateway
          Name: GATEWAY_NAME
      Events:  <none>
      

      El resultado muestra los detalles de GCPRoutingExtension, que se llama my-gateway-extension, dentro del espacio de nombres predeterminado. El resultado muestra el campo Spec, que contiene la definición del comportamiento de la extensión.

    2. Verifica la vinculación de la puerta de enlace:

      1. Confirma que GCPRoutingExtension esté vinculado a la puerta de enlace. Esto puede tardar algunos minutos:

        kubectl describe gateway GATEWAY_NAME
        

        El resultado es similar a este:

        Name:         GATEWAY_NAME
        Namespace:    default
        Labels:       none
        Annotations:  networking.gke.io/addresses: /projects/1234567890/regions/us-central1/addresses/test-hgbk-default-internal-http-5ypwen3x2gcr
                      networking.gke.io/backend-services:
                        /projects/1234567890/regions/us-central1/backendServices/test-hgbk-default-extension-service-443-rduk21fwhoj0, /projects/1234567890/re...
                      networking.gke.io/firewalls: /projects/1234567890/global/firewalls/test-hgbk-l7-default-us-central1
                      networking.gke.io/forwarding-rules: /projects/1234567890/regions/us-central1/forwardingRules/test-hgbk-default-internal-http-qn7dk9i9zm73
                      networking.gke.io/health-checks:
                        /projects/1234567890/regions/us-central1/healthChecks/test-hgbk-default-extension-service-443-rduk21fwhoj0, /projects/1234567890/regio...
                      networking.gke.io/last-reconcile-time: 2025-03-02T17:15:02Z
                      networking.gke.io/lb-route-extensions:
                        /projects/1234567890/locations/us-central1/lbRouteExtensions/test-hgbk-default-internal-http-lwh0op4qorb0
                      networking.gke.io/lb-traffic-extensions:
                      networking.gke.io/ssl-certificates:
                      networking.gke.io/target-http-proxies:
                        /projects/1234567890/regions/us-central1/targetHttpProxies/test-hgbk-default-internal-http-2jzr7e3xclhj
                      networking.gke.io/target-https-proxies:
                      networking.gke.io/url-maps: /projects/1234567890/regions/us-central1/urlMaps/test-hgbk-default-internal-http-2jzr7e3xclhj
        API Version:  gateway.networking.k8s.io/v1
        Kind:         Gateway
        Metadata:
          Creation Timestamp:  2025-03-02T16:37:50Z
          Finalizers:
          gateway.finalizer.networking.gke.io
          Generation:        1
          Resource Version:  31284863
          UID:               fd512611-bad2-438e-abfd-5619474fbf31
        ...
        

        El resultado muestra las anotaciones que GKE usa para almacenar los vínculos entre la puerta de enlace y los recursos deGoogle Cloud subyacentes. La anotación networking.gke.io/lb-route-extensions confirma la vinculación de la puerta de enlace a GCPRoutingExtension.

      2. Verifica el estado de la extensión. Para ello, confirma que GCPRoutingExtension tenga el estado Reconciled con el motivo ReconciliationSucceeded. Este comando podría tardar unos minutos.

        kubectl describe gcproutingextension my-gateway-extension
        

        El resultado es similar a este:

        Name:         my-gateway-extension
        Namespace:    default
        Labels:       <none>
        Annotations:  <none>
        API Version:  networking.gke.io/v1
        Kind:         GCPRoutingExtension
        Metadata:
          Creation Timestamp:  2025-03-02T17:12:30Z
          Generation:          1
          Resource Version:    31284378
          UID:                 ec8efaa0-d8e7-4e1b-9fd4-0ae0ef3c74d0
        Spec:
          Extension Chains:
            Extensions:
              Authority:  myext.com
              Backend Ref:
                Group:
                Kind:   Service
                Name:   extension-service
                Port:   443
              Name:     ext1
              Timeout:  1s
            Match Condition:
              Cel Expressions:
                Cel Matcher:  request.path.contains("serviceextensions")
            Name:             chain1
          Target Refs:
            Group:  gateway.networking.k8s.io
            Kind:   Gateway
            Name:   GATEWAY_NAME
        Status:
          Ancestors:
            Ancestor Ref:
              Group:      gateway.networking.k8s.io
              Kind:       Gateway
              Name:       GATEWAY_NAME
              Namespace:  default
            Conditions:
              Last Transition Time:  2025-03-02T17:14:15Z
              Message:
              Reason:                Accepted
              Status:                True
              Type:                  Accepted
              Last Transition Time:  2025-03-02T17:14:15Z
              Message:
              Reason:                ReconciliationSucceeded
              Status:                True
              Type:                  Reconciled
            Controller Name:         networking.gke.io/gateway
        Events:
          Type    Reason  Age                From                   Message
          ----    ------  ----               ----                   -------
          Normal  ADD     2m31s              sc-gateway-controller  default/my-gateway-extension
        Normal  SYNC    51s (x2 over 98s)  sc-gateway-controller  Attachment of GCPRoutingExtension "default/my-gateway-extension" to AncestorRef {Group:       "gateway.networking.k8s.io",
        Kind:        "Gateway",
        Namespace:   "default",
        Name:        "GATEWAY_NAME",
        SectionName: nil,
        Port:        nil} was a success
          Normal  SYNC    23s           sc-gateway-controller  Reconciliation of GCPRoutingExtension "default/my-gateway-extension" to AncestorRef {Group:       "gateway.networking.k8s.io",
        Kind:        "Gateway",
        Namespace:   "default",
        Name:        "GATEWAY_NAME",
        SectionName: nil,
        Port:        nil} was a success
        

        El campo Status.Conditions muestra una condición Reconciled con Status: True y Reason: ReconciliationSucceeded.

        Verdadero y motivo: ReconciliationSucceeded. Esta información confirma que la extensión se aplicó correctamente.

  4. Envía tráfico a tu aplicación.

    Después de implementar la puerta de enlace, la ruta y la aplicación en el clúster, puedes pasar el tráfico a la aplicación.

    1. Para acceder a tu aplicación, debes encontrar la dirección IP de tu puerta de enlace.

      En tu terminal, usa el siguiente comando:

      kubectl get gateways.gateway.networking.k8s.io GATEWAY_NAME -o=jsonpath="{.status.addresses[0].value}"
      

      Reemplaza GATEWAY_NAME por el nombre de tu puerta de enlace.

      Este comando genera la dirección IP de la puerta de enlace. En los comandos de seguimiento, reemplaza GATEWAY_IP_ADDRESS por la dirección IP del resultado.

    2. Para probar la actualización de la ruta de acceso, ve a la versión serviceextensions del servicio de almacenamiento en store.example.com/serviceextensions:

      curl http://store.example.com/serviceextensions --resolve store.example.com:80:GATEWAY_IP_ADDRESS -v
      

      El resultado es similar a este:

      {
      "cluster_name": "gke1",
      "host_header": "service-extensions.com",
      "metadata": "store-v1",
      "pod_name": "store-v1-5d9554f847-cvxpd",
      "pod_name_emoji": "💇🏼‍♀️",
      "project_id": "gateway-demo",
      "timestamp": "2025-03-15T12:00:00",
      "zone": "us-central1-c"
      }
      

Configura el GCPTrafficExtension

Puedes usar una GCPTrafficExtension para aprovechar las capacidades avanzadas de administración del tráfico dentro de tu entorno de Google Cloud . Puedes configurar esta extensión en los balanceadores de cargas de aplicaciones externos globales, los balanceadores de cargas de aplicaciones externos regionales y los balanceadores de cargas de aplicaciones internos regionales. Puedes usar GCPTrafficExtension para implementar lógica personalizada de solicitud y respuesta, enrutamiento sofisticado, transformaciones y políticas de seguridad.

  1. Actualiza HTTPRoute. Modifica tu HTTPRoute para incluir nombres de host o rutas de acceso que activarán la extensión de tráfico.

    1. Guarda el siguiente manifiesto de muestra como el archivo store-route.yaml:

      kind: HTTPRoute
      apiVersion: gateway.networking.k8s.io/v1
      metadata:
        name: store
      spec:
        parentRefs:
        - kind: Gateway
          name: GATEWAY_NAME
        hostnames:
        - "store.example.com"
        - "service-extensions.example.com"
        rules:
        - backendRefs:
          - name: store-v1
            port: 8080
        - matches:
          - headers:
            - name: env
              value: canary
          backendRefs:
          - name: store-v2
            port: 8080
        - matches:
          - path:
              value: /de
          backendRefs:
          - name: store-german
            port: 8080
      

      Reemplaza GATEWAY_NAME por el nombre de tu puerta de enlace, como internal-http, external-http o global-external-http.

    2. Aplica el manifiesto store-route.yaml a tu clúster:

      kubectl apply -f store-route.yaml
      
  2. Define el GCPTrafficExtension.

    1. Guarda la configuración de GCPTrafficExtension en el archivo gcp-traffic-extension.yaml de muestra:

      kind: GCPTrafficExtension
      apiVersion: networking.gke.io/v1
      metadata:
        name: my-traffic-extension
        namespace: default
      spec:
        targetRefs:
        - group: "gateway.networking.k8s.io"
          kind: Gateway
          name: GATEWAY_NAME
        extensionChains:
        - name: chain1
          matchCondition:
            celExpressions:
            - celMatcher: request.path.contains("serviceextensions")
          extensions:
          - name: ext1
            authority: "myext.com"
            timeout: 1s
            backendRef:
              group: ""
              kind: Service
              name: extension-service
              port: 443
      

      Reemplaza GATEWAY_NAME por el nombre de tu puerta de enlace, como internal-http, external-http o global-external-http.

    2. Aplica el manifiesto de muestra a tu clúster:

      kubectl apply -f gcp-traffic-extension.yaml
      
  3. Verifica la configuración de GCPTrafficExtension y su vinculación a la puerta de enlace.

    1. Verifica la implementación de GCPTrafficExtension:

      kubectl describe gcptrafficextension my-traffic-extension
      

      El resultado es similar a este:

      Name:         my-traffic-extension
      Namespace:    default
      Labels:       <none>
      Annotations:  <none>
      API Version:  networking.gke.io/v1
      Kind:         GCPTrafficExtension
      Metadata:
        Creation Timestamp:  2025-03-02T17:12:30Z
        Generation:        1
        Resource Version:  31283253
        UID:               ec8efaa0-d8e7-4e1b-9fd4-0ae0ef3c74d0
      Spec:
        Extension Chains:
          Extensions:
            Authority:    myext.com
            Backend Ref:
              Group:
              Kind: Service
              Name: extension-service
              Port: 443
            Name:       ext1
            Timeout:    1s
          Match Condition:
            Cel Expressions:
              Cel Matcher: request.path.contains("serviceextensions")
          Name:  chain1
        Target Refs:
          Group: gateway.networking.k8s.io
          Kind: Gateway
          Name: GATEWAY_NAME
      Events:  <none>
      

      El resultado muestra los detalles del GCPTrafficExtension llamado my-traffic-extension dentro del espacio de nombres predeterminado. Muestra el campo Spec, que contiene la definición de cómo debe comportarse la extensión.

    2. Verifica la vinculación de la puerta de enlace:

      Confirma que GCPTrafficExtension esté vinculado a la puerta de enlace. Este comando puede tardar unos minutos en completarse:

      kubectl describe gateway GATEWAY_NAME
      

      El resultado es similar a este:

      Name:         GATEWAY_NAME
      Namespace:    default
      Labels:       <none>
      Annotations:  networking.gke.io/addresses: /projects/1234567890/regions/us-central1/addresses/test-hgbk-default-internal-http-5ypwen3x2gcr
                    networking.gke.io/backend-services:
                      /projects/1234567890/regions/us-central1/backendServices/test-hgbk-default-extension-service-443-rduk21fwhoj0, /projects/1234567890/re...
                    networking.gke.io/firewalls: /projects/1234567890/global/firewalls/test-hgbk-l7-default-us-central1
                    networking.gke.io/forwarding-rules: /projects/1234567890/regions/us-central1/forwardingRules/test-hgbk-default-internal-http-qn7dk9i9zm73
                    networking.gke.io/health-checks:
                      /projects/1234567890/regions/us-central1/healthChecks/test-hgbk-default-extension-service-443-rduk21fwhoj0, /projects/1234567890/regio...
                    networking.gke.io/last-reconcile-time: 2025-03-02T17:15:02Z
                    networking.gke.io/lb-traffic-extensions:
                      /projects/1234567890/locations/us-central1/lbTrafficExtensions/test-hgbk-default-internal-http-lwh0op4qorb0
                    networking.gke.io/ssl-certificates:
                    networking.gke.io/target-http-proxies:
                      /projects/1234567890/regions/us-central1/targetHttpProxies/test-hgbk-default-internal-http-2jzr7e3xclhj
                    networking.gke.io/target-https-proxies:
                    networking.gke.io/url-maps: /projects/1234567890/regions/us-central1/urlMaps/test-hgbk-default-internal-http-2jzr7e3xclhj
      API Version:  gateway.networking.k8s.io/v1
      Kind:         Gateway
      Metadata:
        Creation Timestamp:  2025-03-02T16:37:50Z
        Finalizers:
          gateway.finalizer.networking.gke.io
        Generation:        1
        Resource Version:  31284863
        UID:               fd512611-bad2-438e-abfd-5619474fbf31
      ...
      

      El resultado muestra las anotaciones que GKE usa para almacenar los vínculos entre la puerta de enlace y los recursos Google Cloud subyacentes. La anotación networking.gke.io/lb-traffic-extensions confirma la vinculación.

    3. Verifica el estado de la extensión:

      Confirma que el GCPTrafficExtension tenga el estado Reconciled con el motivo ReconciliationSucceeded. Este comando puede tardar unos minutos en completarse.

      kubectl describe gcptrafficextension my-traffic-extension
      

      El resultado es similar a este:

      Name:         my-traffic-extension
      Namespace:    default
      Labels:       <none>
      Annotations:  <none>
      API Version:  networking.gke.io/v1
      Kind:         GCPTrafficExtension
      Metadata:
        Creation Timestamp:  2025-03-02T17:12:30Z
        Generation:          1
        Resource Version:    31284378
        UID:                 ec8efaa0-d8e7-4e1b-9fd4-0ae0ef3c74d0
      Spec:
        Extension Chains:
          Extensions:
            Authority:  myext.com
            Backend Ref:
              Group:
              Kind:   Service
              Name:   extension-service
              Port:   443
            Name:     ext1
            Timeout:  1s
          Match Condition:
            Cel Expressions:
              Cel Matcher:  request.path.contains("serviceextensions")
          Name:             chain1
        Target Refs:
          Group:  gateway.networking.k8s.io
          Kind:   Gateway
          Name:   GATEWAY_NAME
      Status:
        Ancestors:
          Ancestor Ref:
            Group:      gateway.networking.k8s.io
            Kind:       Gateway
            Name:       GATEWAY_NAME
            Namespace:  default
          Conditions:
            Last Transition Time:  2025-03-02T17:14:15Z
            Message:
            Reason:                Accepted
            Status:                True
            Type:                  Accepted
            Last Transition Time:  2025-03-02T17:14:15Z
            Message:
            Reason:                ReconciliationSucceeded
            Status:                True
            Type:                  Reconciled
          Controller Name:         networking.gke.io/gateway
      Events:
        Type    Reason  Age                From                   Message
        ----    ------  ----               ----                   -------
        Normal  ADD     2m31s              sc-gateway-controller  default/my-traffic-extension
        Normal  SYNC    51s (x2 over 98s)  sc-gateway-controller  Attachment of GCPTrafficExtension "default/my-gateway-extension" to AncestorRef {Group:       "gateway.networking.k8s.io",
        Kind:        "Gateway",
        Namespace:   "default",
        Name:        "GATEWAY_NAME",
        SectionName: nil,
        Port:        nil} was a success
        Normal  SYNC    23s           sc-gateway-controller  Reconciliation of GCPTrafficExtension "default/my-traffic-extension" to AncestorRef {Group:       "gateway.networking.k8s.io",
        Kind:        "Gateway",
        Namespace:   "default",
        Name:        "GATEWAY_NAME",
        SectionName: nil,
        Port:        nil} was a success
      

      El campo Status.Conditions muestra una condición Reconciled con Status: True y Reason: ReconciliationSucceeded. Esta información confirma que la extensión se aplicó correctamente.

  4. Envía tráfico a tu aplicación.

    Después de implementar la puerta de enlace, la ruta y la aplicación en el clúster, puedes pasar el tráfico a la aplicación.

    1. Para acceder a tu aplicación, debes encontrar la dirección IP de tu puerta de enlace.

      En tu terminal, usa el siguiente comando:

      kubectl get gateways.gateway.networking.k8s.io GATEWAY_NAME -o=jsonpath="{.status.addresses[0].value}"
      

      Reemplaza GATEWAY_NAME por el nombre de tu puerta de enlace.

      Este comando genera la dirección IP de la puerta de enlace. En los comandos de seguimiento, reemplaza GATEWAY_IP_ADDRESS por la dirección IP del resultado.

    2. Para probar la actualización de la ruta de acceso, ve a la versión serviceextensions del servicio de almacenamiento en store.example.com/serviceextensions:

      curl http://store.example.com/serviceextensions --resolve store.example.com:80:GATEWAY_IP_ADDRESS -v
      

      El resultado es similar a este:

      {
      *   Request completely sent off
      < HTTP/1.1 200 OK
      < server: Werkzeug/2.3.7 Python/3.11.3
      < date: Sun, 02 Mar 2025 16:58:10 GMT
      < content-type: application/json
      < access-control-allow-origin: *
      < hello: service-extensions
      < via: 1.1 google
      < transfer-encoding: chunked
      }
      

Soluciona problemas relacionados con las extensiones de tráfico en las puertas de enlace

En esta sección, se proporcionan sugerencias para solucionar problemas relacionados con la configuración de extensiones de tráfico en las puertas de enlace.

No se encontró la puerta de enlace

El siguiente error indica que no existe el recurso de Gateway especificado en el campo targetRefs del recurso GCPTrafficExtension o GCPRoutingExtension:

error: failed to create resource: GCPTrafficExtension.networking.gke.io "my-traffic-extension" is invalid: spec.gatewayRef: gateway "my-gateway" not found in namespace "default"

Para resolver este problema, asegúrate de que el recurso Gateway especificado en el campo targetRefs del recurso GCPTrafficExtension o GCPRoutingExtension exista en el espacio de nombres especificado.

No se encontró el servicio o el puerto de servicio

El siguiente error indica que no existe el servicio o el puerto de servicio especificado en el campo backendRef del recurso GCPTrafficExtension o GCPRoutingExtension:

error: failed to create resource: GCPTrafficExtension.networking.gke.io "my-traffic-extension" is invalid: spec.service: service "callout-service" not found in namespace "default"

Para resolver este problema, asegúrate de que el servicio y el puerto del servicio especificados en el campo backendRef del recurso GCPTrafficExtension o GCPRoutingExtension existan en el espacio de nombres especificado.

No hay extremos de red en el NEG.

El siguiente error indica que no hay extremos de red en el NEG asociados con el servicio especificado en el campo backendRef del recurso GCPTrafficExtension o GCPRoutingExtension:

error: failed to create resource: GCPTrafficExtension.networking.gke.io "my-traffic-extension" is invalid: spec.service: no network endpoints found for service "callout-service"

Para resolver este problema, asegúrate de que el servicio especificado en el campo backendRef del recurso GCPTrafficExtension o GCPRoutingExtension tenga extremos de red.

No hay respuesta o se responde con un error cuando se envía la solicitud

Si no recibes una respuesta o si recibes una respuesta con un error cuando envías una solicitud, es posible que el servicio de llamada no esté funcionando correctamente.

Para resolver este problema, revisa los registros del servicio de texto destacado para detectar errores.

Código de error 404 en la carga útil de JSON

El siguiente error indica que no se encontró el servicio de texto destacado o que no responde a la solicitud:

{
  "error": {
    "code": 404,
    "message": "Requested entity was not found.",
    "status": "NOT_FOUND"
  }
}

Para resolver este problema, asegúrate de que el servicio de llamadas esté en ejecución, de que esté escuchando en el puerto correcto y de que el servicio esté configurado correctamente en el recurso GCPTrafficExtension o GCPRoutingExtension.

Código de error 500 en la carga útil de JSON

El siguiente error indica que el servicio de texto destacado está experimentando un error interno del servidor:

{
  "error": {
    "code": 500,
    "message": "Internal server error.",
    "status": "INTERNAL"
  }
}

Para resolver este problema, revisa los registros del servicio de texto destacado para identificar la causa del error interno del servidor.

¿Qué sigue?