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 cuentas y de identidad de GKE y a los desarrolladores que necesiten configurar una lógica de administración de tráfico personalizada con extensiones de servicio.

Antes de leer esta página, asegúrate de estar familiarizado con lo siguiente:

Descripción general

GKE usa extensiones de servicio para agregar lógica personalizada al balanceo de cargas de Cloud. Una extensión se adjunta a un Gateway y hace referencia a un Service o 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 de servicios de backend ni las políticas de seguridad. Puedes usar Extensiones del servicio para tareas como la división de tráfico avanzada, la autenticación personalizada o el registro de solicitudes.

El controlador de la puerta de enlace de GKE admite las siguientes extensiones de servicio:

  • 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" está conectado 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 puertas de enlace
  • GCPTrafficExtension: Esta extensión inserta lógica personalizada en el balanceo de cargas de Cloud. Permite que un servicio de extensión cambie los encabezados y las cargas útiles de las solicitudes y respuestas. 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 puertas de enlace

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

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

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

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 servicio de puerta de enlace 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 puerta de enlace) y no es compatible con la clase de puerta de enlace gke-l7-global-external-managed.
Especificación y cadena de extensión
  • Para un GCPTrafficExtension, cada ExtensionChain puede tener un máximo de 3 Extensions.
  • Para un GCPRoutingExtension, cada ExtensionChain se limita a 1 Extension.
  • Un GCPTrafficExtensionSpec y un GCPRoutingExtensionSpec pueden tener un máximo de 5 ExtensionChains.
Tiempo y concordancia
  • 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 Route y Traffic.
  • 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 dentro 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
  • Para un GCPRoutingExtension, si no se establece requestBodySendMode, la lista supportedEvents solo puede contener eventos RequestHeaders.
  • Para un GCPRoutingExtension, si requestBodySendMode se establece como FullDuplexStreamed, la lista supportedEvents solo puede contener eventos RequestHeaders, RequestBody y RequestTrailers.
GCPTrafficExtension
  • El campo responseBodySendMode solo es compatible con GCPTrafficExtension.
  • El campo googleAPIServiceName solo es compatible con 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 HTTP2 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 las políticas de seguridad de Google Cloud Armor (campo securityPolicy de GCPBackendPolicyConfig).
  • No se puede usar Cloud CDN.
  • Se debe establecer exactamente uno de 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 las extensiones solo con backendRef.
  • Configura responseBodySendMode para las extensiones solo con backendRef.

Configura extensiones de servicio de GKE

Puedes personalizar el enrutamiento del tráfico, modificar las cargas útiles de solicitud o respuesta, y realizar la integración con servicios externos si configuras 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 de balanceador de cargas de aplicaciones interno regional.

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

  2. Implementa un servicio de llamada al backend: Crea un servicio de Kubernetes que represente el servicio de backend para la ejecución de la 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 puertas de enlace 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 y 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 de tráfico, como la modificación de encabezados o la inspección de carga útil, en varios tipos de balanceadores de cargas.

Implementa un servicio de texto destacado de backend

Un servicio de texto destacado 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 carga útil o el enrutamiento del tráfico.

Para implementar un servicio de backend que pueda funcionar como un texto destacado 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 y clave privada de TLS.

    Para crear el secreto de TLS para tu servicio de texto destacado, reemplaza lo siguiente:

    • SECRET_NAME: Es el nombre secreto de tu servicio de texto destacado.
    • path-to-cert: Las rutas de acceso de tu certificado
    • path-to-key: Las rutas de acceso 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 del Secret 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 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 implementación 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 se haya implementado la aplicación:

      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 servicio para cada implementación 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 el flujo de tráfico.

Configura GCPRoutingExtension para las puertas de enlace regionales

Puedes redireccionar el tráfico con un GCPRoutingExtension. Para configurar un GCPRoutingExtension, actualiza 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 activen 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 ejemplo 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 de cómo debe comportarse 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
        ...
        

        En el resultado, se muestran las anotaciones, que GKE usa para almacenar los vínculos entre la puerta de enlace y los recursosGoogle Cloud subyacentes. La anotación networking.gke.io/lb-route-extensions confirma la vinculación de la puerta de enlace a GCPRoutingExtension.

      2. Para verificar el estado de la extensión, confirma que GCPRoutingExtension tenga un estado Reconciled con el motivo ReconciliationSucceeded. Este comando puede 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 que la puerta de enlace, la ruta y la aplicación estén implementadas 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 la 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 muestra la dirección IP de la puerta de enlace. En los comandos posteriores, 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 un GCPTrafficExtension para usar funciones avanzadas de administración del tráfico dentro de tu entorno Google Cloud . Puedes configurar esta extensión en balanceadores de cargas de aplicaciones externos globales, balanceadores de cargas de aplicaciones externos regionales y balanceadores de cargas de aplicaciones internos regionales. Puedes usar GCPTrafficExtension para implementar una lógica de solicitud y respuesta personalizada, un enrutamiento sofisticado, transformaciones y políticas de seguridad.

  1. Actualiza HTTPRoute. Modifica tu HTTPRoute para incluir nombres de host o rutas de acceso que activen 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 ejemplo 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 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 que la puerta de enlace, la ruta y la aplicación estén implementadas 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 la 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 muestra la dirección IP de la puerta de enlace. En los comandos posteriores, 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 de 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 puerta de enlace 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 de puerta de enlace 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 el servicio o el puerto de servicio especificados en el campo backendRef del recurso GCPTrafficExtension o GCPRoutingExtension no existen:

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 de 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 se recibe ninguna respuesta o se recibe una respuesta 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 textos destacados no funcione correctamente.

Para resolver este problema, verifica los registros del servicio de texto destacado en busca de 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 texto destacado 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 tiene un error interno del servidor:

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

Para resolver este problema, verifica los registros del servicio de textos destacados para identificar la causa del error interno del servidor.

¿Qué sigue?