Personalizar el tráfico de GKE Gateway mediante extensiones de servicio

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

Esta página está dirigida a administradores de identidades y cuentas de GKE, así como a desarrolladores que necesiten configurar lógica de gestión del tráfico personalizada mediante extensiones de servicio.

Antes de leer esta página, asegúrese de que conoce los siguientes conceptos:

Información general

GKE usa extensiones de servicio para añadir lógica personalizada a Cloud Load Balancing. Puedes usar 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 servicio:

  • GCPRoutingExtension: esta extensión añade lógica personalizada a Cloud Load Balancing para controlar el enrutamiento del tráfico.
  • GCPTrafficExtension: esta extensión inserta lógica personalizada en Cloud Load Balancing para modificar el tráfico. Esta lógica se aplica al tráfico después de seleccionar el servicio. El balanceador de carga puede añadir o cambiar los encabezados y las cargas útiles de las solicitudes y respuestas HTTP. GCPTrafficExtension no afecta a la selección de servicios ni a las políticas de seguridad de los servicios.

Una extensión se adjunta a una pasarela y hace referencia a un Service, un GCPWasmPlugin o un googleAPIServiceName.

  • Hacer referencia a un servicio: en este modelo, despliega tu lógica personalizada como una aplicación backend independiente, expuesta como un servicio de Kubernetes. El balanceador de carga hace una llamada a este servicio para procesar el tráfico. Este enfoque es versátil y te permite implementar una lógica de enrutamiento personalizada o manipular el tráfico, como modificar encabezados o inspeccionar cargas útiles. Puedes hacer referencia a un servicio con GCPRoutingExtension o GCPTrafficExtension.

  • Hacer referencia a un recurso GCPWasmPlugin: en casos prácticos de alto rendimiento, puedes insertar lógica personalizada escrita por el usuario directamente en la ruta de datos del balanceador de cargaGoogle Cloud mediante un módulo WebAssembly (Wasm). Define un recurso GCPWasmPlugin que apunte a la imagen de tu módulo Wasm en Artifact Registry. Este método solo se usa con un GCPTrafficExtension y un balanceador de carga de aplicación externo global.

  • Hacer referencia a un servicio de API de Google: también puedes hacer referencia a un servicio de API de Google directamente mediante el campo googleAPIServiceName en un GCPTrafficExtension.

En el siguiente diagrama, el recurso GCPRoutingExtension está asociado a un Gateway y hace referencia a varios Services. La extensión controla el enrutamiento del tráfico a los Servicios.

El recurso `GCPRoutingExtension` se adjunta a una pasarela y hace referencia a un servicio. La extensión
        controla el enrutamiento del tráfico.
Ilustración: Cómo funciona GCPRoutingExtension con las pasarelas

En el siguiente diagrama, el recurso GCPTrafficExtension está asociado a una puerta de enlace y hace referencia a un servicio, un GoogleAPIServiceName o un GCPWasmPlugin. La extensión cambia los encabezados y las cargas útiles de las solicitudes y las respuestas.

El recurso `GCPTrafficExtension` se adjunta a una pasarela y hace referencia a un servicio, a un `GoogleAPIServiceName` o a un `GCPWasmPlugin`. La extensión cambia los encabezados y las cargas útiles de las solicitudes y las respuestas.
Ilustración: Cómo funciona GCPTrafficExtension con las pasarelas

Antes de empezar

Antes de empezar, asegúrate de que has realizado las siguientes tareas:

  • Habilita la API de Google Kubernetes Engine.
  • Habilitar la API de Google Kubernetes Engine
  • Si quieres usar Google Cloud CLI para esta tarea, instálala y, a continuación, inicialízala. Si ya has instalado la CLI de gcloud, obtén la versión más reciente ejecutando el comando gcloud components update. Es posible que las versiones anteriores de la interfaz de línea de comandos de gcloud no admitan la ejecución de los comandos de este documento.

Requisitos de GKE Gateway Controller

  • Tu clúster debe usar la versión 1.33 de GKE o una posterior.
  • Para usar GCPWasmPlugin, tu clúster debe usar la versión 1.33.3 de GKE o una posterior.
  • Tu clúster debe tener habilitada la API Gateway.
  • Debes tener un recurso Gateway configurado. Este recurso puede ser un balanceador de carga de aplicaciones externo global, un balanceador de carga de aplicaciones externo regional o un balanceador de carga de aplicaciones interno regional. Si usas un recurso GCPWasmPlugin, solo debes desplegar una pasarela de balanceador de carga de aplicación externo global.
  • Debes tener un recurso HTTPRoute configurado.

Restricciones y limitaciones

En la siguiente tabla se indican las restricciones asociadas a la configuración de las extensiones de servicio de pasarela en GKE:

Categoría Restricciones y limitaciones
Balanceador de carga El GCPRoutingExtension se admite en los siguientes balanceadores de carga:
  • Balanceador de carga de aplicación externo regional (gke-l7-regional-external-managed GatewayClass)
  • Balanceador de carga de aplicación interno regional(gke-l7-rilbclase Gateway)
El GCPTrafficExtension se admite en los siguientes balanceadores de carga:
  • Balanceador de carga de aplicación externo regional (gke-l7-regional-external-managed GatewayClass)
  • Balanceador de carga de aplicación interno regional (clase Gateway gke-l7-rilb)
  • Balanceador de carga de aplicación externo global (clase Gateway gke-l7-global-external-managed)
Cadena y especificación de la extensión
  • En un GCPTrafficExtension, cada ExtensionChain puede tener un máximo de 3 Extensions.
  • En el caso de GCPRoutingExtension, cada ExtensionChain está limitado a 1 Extension.
  • Un GCPTrafficExtensionSpec y un GCPRoutingExtensionSpec pueden tener un máximo de 5 ExtensionChains cada uno.
Tiempos y coincidencias
  • El tiempo de espera de cada mensaje del flujo de una extensión debe estar entre 10 y 10.000 milisegundos. Este límite de un segundo se aplica a las extensiones de ruta y de tráfico.
  • Cada MatchCondition de un ExtensionChain puede tener 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 de un CELExpression tiene una longitud máxima de 512 caracteres y debe seguir un patrón específico. No admitimos el campo BackendRefs de CELExpression.
Encabezado y metadatos
  • La lista ForwardHeaders de un Extension puede contener un máximo de 50 nombres de encabezado HTTP.
  • El mapa Metadata de un Extension puede tener un máximo de 16 propiedades.
  • Las claves del mapa Metadata deben tener entre 1 y 63 caracteres.
  • Los valores del mapa Metadata deben tener entre 1 y 1023 caracteres.
Evento
  • En el caso de GCPRoutingExtension, si no se define requestBodySendMode, la lista supportedEvents solo puede contener eventos RequestHeaders.
  • En el caso de GCPRoutingExtension, si requestBodySendMode tiene el valor FullDuplexStreamed, la lista supportedEvents solo puede contener eventos RequestHeaders, RequestBody y RequestTrailers.
GCPTrafficExtension
  • El campo responseBodySendMode solo se admite en GCPTrafficExtension.
  • El campo googleAPIServiceName solo se admite en GCPTrafficExtension.
  • El campo GCPWasmPlugin solo se admite en GCPTrafficExtension.
GCPWasmPlugin
  • Las extensiones con GCPWasmPlugin no admiten los siguientes campos:
    • authority
    • timeout
    • metadata
    • requestBodySendMode
    • responseBodySendMode
  • Las extensiones con compatibilidad con GCPWasmPlugin solo admiten eventos RequestHeaders, RequestBody, ResponseHeaders y ResponseBody.
googleAPIServiceName y backendRef Cuando hagas referencia a un Servicio que use la backendRef en una extensión, debes cumplir las siguientes condiciones:
  • Debe usar HTTP2 como appProtocol.
  • Debe estar en el mismo espacio de nombres que la extensión y la pasarela 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.
  • Debe definir exactamente uno de los valores backendRef o googleAPIServiceName para un Extension.
  • Debe definir authority si backendRef está definido y kind es Service.
  • No se debe definir authority si se ha definido googleAPIServiceName.
  • Configura requestBodySendMode para las extensiones usando solo backendRef y Service.
  • Configura responseBodySendMode para las extensiones usando solo backendRef y Service.

Hacer referencia a un servicio

En las extensiones de servicio, puedes hacer referencia a un servicio que aloja la lógica personalizada que quieres que ejecute el balanceador de carga. Las pasarelas no tienen extensiones de servicio de forma predeterminada.

Para configurar las extensiones de servicio de GKE, sigue estos pasos:

  1. Despliega un servicio 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 carga invoca este servicio.

  2. Configura las extensiones de servicio: usa la extensión adecuada en función del tipo de balanceador de carga.

    1. GCPRoutingExtension para las pasarelas regionales: usa esta extensión para los balanceadores de carga de aplicación externos regionales y los balanceadores de carga de aplicación internos regionales para implementar lógica de enrutamiento personalizada en la región.

    2. GCPTrafficExtension para las pasarelas externas globales, externas regionales e internas: usa esta extensión para los balanceadores de carga de aplicación externos globales, los balanceadores de carga de aplicación externos regionales y los balanceadores de carga de aplicación internos regionales para manipular el tráfico, como modificar encabezados o inspeccionar cargas útiles, en varios tipos de balanceadores de carga.

Implementar un servicio de llamada de backend

Un servicio de texto destacado implementa lógica personalizada para las extensiones de servicio de Gateway en GKE. La pasarela invoca estas aplicaciones backend en función de las configuraciones GCPTrafficExtension o GCPRoutingExtension para modificar o enrutar el tráfico.

Implementa un servicio de llamadas para añadir lógica personalizada a tu pasarela. Este servicio independiente gestiona el procesamiento personalizado, como la manipulación de encabezados, las transformaciones de cargas útiles o el enrutamiento del tráfico.

Para implementar un servicio que pueda funcionar como texto destacado de tu Gateway, 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 de tu servicio de llamadas, sustituye lo siguiente:

    • SECRET_NAME: el nombre secreto de tu servicio de llamada
    • path-to-cert: las rutas de archivo de tu certificado
    • path-to-key: las rutas de archivo de tu clave
  2. Para verificar que se ha añadido el secreto, ejecuta el siguiente comando:

    kubectl get secrets SECRET_NAME
    

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

    La salida debería ser similar a la siguiente:

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

    Debes definir lo siguiente:

    • Despliegue: para gestionar los pods de aplicaciones que contienen la lógica personalizada de tus extensiones de servicio.
    • Servicio: para exponer los pods de la aplicación que gestiona el Deployment como servicio de red.
    1. Crea un archivo de manifiesto de ejemplo extension-service-app.yaml que tenga las siguientes definiciones: 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 tu configuración:

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

      kubectl get pod --selector app=store
      

      Una vez que la aplicación empieza a ejecutarse, el resultado es similar al siguiente:

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

      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
      

Configurar Service Extensions

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

Configura el GCPRoutingExtension para las pasarelas regionales

Puedes redirigir el tráfico mediante 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 que activen la extensión de enrutamiento.

    1. Guarda el siguiente archivo de manifiesto de ejemplo como 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
      

      Sustituye GATEWAY_NAME por el nombre de tu pasarela.

    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 de ejemplo: gcp-routing-extension.yaml

      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
      

      Sustituye GATEWAY_NAME por el nombre de tu pasarela.

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

      kubectl apply -f gcp-routing-extension.yaml
      
  3. Verifica la configuración del GCPRoutingExtension y su vinculación con la pasarela.

    1. Comprueba el despliegue de GCPRoutingExtension:

      kubectl describe gcproutingextension my-gateway-extension
      

      El resultado debería ser similar al siguiente:

      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>
      

      En la salida se muestran los detalles de GCPRoutingExtension, que se llama my-gateway-extension, en el 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 el enlace de la pasarela:

      1. Comprueba que el GCPRoutingExtension esté vinculado a la pasarela. Este proceso puede tardar unos minutos:

        kubectl describe gateway GATEWAY_NAME
        

        El resultado debería ser similar al siguiente:

        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 usa GKE para almacenar los enlaces entre la Gateway y los recursosGoogle Cloud subyacentes. La anotación networking.gke.io/lb-route-extensions confirma la vinculación de la pasarela con GCPRoutingExtension.

      2. Comprueba el estado de la extensión confirmando que GCPRoutingExtension tiene el estado Programmed con el motivo ProgrammingSucceeded. Este comando puede tardar unos minutos.

        kubectl describe gcproutingextension my-gateway-extension
        

        El resultado debería ser similar al siguiente:

        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:                ProgrammingSucceeded
              Status:                True
              Type:                  Programmed
            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 Programmed con Status: True y Reason: ProgrammingSucceeded. Esta información confirma que la extensión se ha aplicado correctamente.

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

    Una vez que se hayan desplegado la pasarela, la ruta y la aplicación en tu clúster, podrás enviar tráfico a tu aplicación.

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

      En el terminal, usa el siguiente comando:

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

      Sustituye GATEWAY_NAME por el nombre de tu pasarela.

      Este comando muestra la dirección IP de la pasarela. En los comandos posteriores, sustituye GATEWAY_IP_ADDRESS por la dirección IP de la salida.

    2. Prueba la actualización de la ruta. Para ello, ve a la versión serviceextensions del servicio de tienda en store.example.com/serviceextensions:

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

      El resultado debería ser similar al siguiente:

      {
      "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"
      }
      

Configurar el GCPTrafficExtension

Puedes usar un GCPTrafficExtension para usar funciones avanzadas de gestión del tráfico en tu Google Cloud entorno. Puedes configurar esta extensión en balanceadores de carga de aplicación externos globales, balanceadores de carga de aplicación externos regionales y balanceadores de carga de aplicación internos regionales. Puedes usar GCPTrafficExtension para implementar lógica personalizada de solicitudes y respuestas HTTP, enrutamiento sofisticado, transformaciones y políticas de seguridad.

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

    1. Guarda el siguiente archivo de manifiesto de ejemplo como 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
      

      Sustituye GATEWAY_NAME por el nombre de tu pasarela, 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 de ejemplo: gcp-traffic-extension.yaml

      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
      

      Sustituye GATEWAY_NAME por el nombre de tu pasarela, 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 del GCPTrafficExtension y su vinculación con la pasarela.

    1. Comprueba el despliegue de GCPTrafficExtension:

      kubectl describe gcptrafficextension my-traffic-extension
      

      El resultado debería ser similar al siguiente:

      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>
      

      En la salida se muestran los detalles del GCPTrafficExtension llamado my-traffic-extension en el espacio de nombres predeterminado. Se muestra el campo Spec, que contiene la definición de cómo debe comportarse la extensión.

    2. Verifica el enlace de la pasarela:

      Comprueba que el GCPTrafficExtension esté vinculado a la pasarela. Este comando puede tardar unos minutos en completarse:

      kubectl describe gateway GATEWAY_NAME
      

      El resultado debería ser similar al siguiente:

      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 usa GKE para almacenar los enlaces entre la Gateway y los recursos subyacentes de Google Cloud . La anotación networking.gke.io/lb-traffic-extensions confirma el enlace.

    3. Comprueba el estado de la extensión:

      Confirma que el elemento GCPTrafficExtension tiene el estado Programmed con el motivo ProgrammingSucceeded. El comando puede tardar unos minutos en completarse.

      Para comprobar el estado de la extensión GCPTrafficExtension, ejecuta el siguiente comando:

      kubectl describe gcptrafficextension my-traffic-extension
      

      El resultado del recurso GCPTrafficExtension es similar al siguiente:

      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:                ProgrammingSucceeded
            Status:                True
            Type:                  Programmed
          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 Programmed con Status: True y Reason: ProgrammingSucceeded. Esta información confirma que la extensión se ha aplicado correctamente.

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

    Una vez que se hayan desplegado la pasarela, la ruta y la aplicación en tu clúster, podrás enviar tráfico a tu aplicación.

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

      En el terminal, usa el siguiente comando:

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

      Sustituye GATEWAY_NAME por el nombre de tu Gateway.

      Este comando muestra la dirección IP de la pasarela. En los comandos posteriores, sustituye GATEWAY_IP_ADDRESS por la dirección IP de la salida.

    2. Prueba la actualización de la ruta. Para ello, ve a la versión serviceextensions del servicio de tienda en store.example.com/serviceextensions:

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

      El resultado debería ser similar al siguiente:

      {
      *   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
      }
      

Hacer referencia a un recurso GCPWasmPlugin

Puedes insertar lógica personalizada directamente en la ruta de datos del balanceador de carga mediante un GCPWasmPlugin con un GCPTrafficExtension. Este método te permite implementar funciones de gestión del tráfico personalizadas empaquetadas como un módulo Wasm.

Para configurar las extensiones de servicio de GKE, sigue estos pasos:

  1. Implementar un GCPWasmPlugin: crea e implementa una definición de recurso personalizado (CRD) de GCPWasmPlugin que contenga el código personalizado de tu módulo Wasm. Solo puedes usar GCPWasmPlugin con GCPTrafficExtension para gke-l7-global-external-managed GatewayClass.

  2. Configura las extensiones de servicio: usa el GCPTrafficExtension para el balanceador de carga de aplicaciones externo global.

Desplegar un GCPWasmPlugin

El GCPWasmPlugin le permite insertar lógica personalizada escrita por el usuario directamente en la ruta de datos del balanceador de carga Google Cloud . El recurso GCPWasmPlugin apunta a la imagen del módulo Wasm en Artifact Registry, que luego ejecuta el balanceador de carga.

Antes de continuar con los pasos siguientes, asegúrate de haber subido tu módulo Wasm a un repositorio de Artifact Registry. Para obtener más información, consulta Preparar el código del complemento.

Para implementar un recurso de GCPWasmPlugin, sigue estos pasos:

  1. Guarda el siguiente archivo de manifiesto como wasm-plugin.yaml:

    kind: GCPWasmPlugin
    apiVersion: networking.gke.io/v1
    metadata:
      name: gcp-wasm-plugin
    spec:
      versions:
      - name: wasm-plugin-version
        description: "Test wasm plugin version"
        image: "us-docker.pkg.dev/service-extensions-samples/plugins/local-reply:main"
        weight: 1000000
      logConfig:
        enabled: true
        # Configures the sampling rate of activity logs.
        # The value of the field must be in range [0, 1e6].
        sampleRate: 1000000
        # Specifies the lowest level of logs that are exported to Cloud Logging.
        minLogLevel: INFO
    

    Ten en cuenta lo siguiente:

    • spec.versions.name: el nombre de la versión debe ser único en el recurso GCPWasmPlugin. Puede incluir hasta 10 versiones, pero solo una de ellas debe tener un peso distinto de cero.
    • spec.versions.image: hace referencia a la imagen que contiene el código del complemento y que está almacenada en Artifact Registry.
    • spec.versions.weight: especifica el peso de la versión del complemento. El peso debe ser un número entre 0 y 1.000.000, ambos incluidos.
    • spec.logConfig: especifica si se debe habilitar Cloud Logging para este complemento. Si no se especifica ningún valor, Cloud Logging se inhabilita de forma predeterminada.
    • spec.logConfig.sampleRate: configura la frecuencia de muestreo de los registros de actividad. El valor debe ser un número entre 0 y 1.000.000, ambos incluidos. Si no se especifica cuando Cloud Logging está habilitado, el valor predeterminado es 1,000,000 (se registran el 100% de las solicitudes).
    • spec.logConfig.minLogLevel: especifica el nivel más bajo de registros que se exportan a Cloud Logging. Si no se especifica ningún valor cuando Cloud Logging está habilitado, el campo se define como INFO de forma predeterminada.
  2. Aplica el manifiesto wasm-plugin.yaml:

    kubectl apply -f wasm-plugin.yaml
    
  3. Verifica que el complemento se haya implementado:

    kubectl describe gcpwasmplugins.networking.gke.io gcp-wasm-plugin
    

    El resultado debería ser similar al siguiente:

    Name:         gcp-wasm-plugin
    Namespace:    default
    Labels:       <none>
    Annotations:  <none>
    API Version:  networking.gke.io/v1
    Kind:         GCPWasmPlugin
    Metadata:
      Creation Timestamp:  2025-08-08T19:54:18Z
      Generation:          1
      Resource Version:    44578
      UID:                 549a12c7-91d1-43ad-a406-d6157a799b79
    Spec:
      Log Config:
        Enabled: true
        Min Log Level: INFO
        Sample Rate: 1000000
      Versions:
        Description:  Test wasm plugin version
        Image:        us-docker.pkg.dev/service-extensions-samples/plugins/local-reply:main
        Name:         wasm-plugin-version
        Weight:       1000000
      Events:     <none>
    

Configurar Service Extensions

Para añadir lógica personalizada a tu balanceador de carga de aplicación externo global, puedes configurar un GCPTrafficExtension para que use un GCPWasmPlugin. Puedes usar un GCPTrafficExtension para disfrutar de funciones avanzadas de gestión del tráfico en tu entorno de Google Cloud . Puedes configurar esta extensión en balanceadores de carga de aplicación externos globales.

Para configurar un GCPTrafficExtension de forma que use un GCPWasmPlugin, sigue estos pasos:

  1. Define el GCPTrafficExtension.

    1. Guarda la configuración de GCPTrafficExtension como gcp-traffic-extension-with-plugin.yaml:

      kind: GCPTrafficExtension
      apiVersion: networking.gke.io/v1
      metadata:
        name: gcp-traffic-extension-with-plugin
        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
            supportedEvents:
            - RequestHeaders
            - ResponseHeaders
            backendRef:
              group: "networking.gke.io"
              kind: GCPWasmPlugin
              name: gcp-wasm-plugin
      

      Sustituye GATEWAY_NAME por el nombre de tu pasarela, como global-external-http.

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

      kubectl apply -f gcp-traffic-extension-with-plugin.yaml
      
  2. Verifica la configuración del GCPTrafficExtension y su vinculación con la pasarela.

    1. Comprueba el despliegue de GCPTrafficExtension:

      kubectl describe gcptrafficextensions.networking.gke.io gcp-traffic-extension-with-plugin
      

      El resultado debería ser similar al siguiente:

      Name:         gcp-traffic-extension-with-plugin
      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:
            Backend Ref:
              Group: networking.gke.io
              Kind: GCPWasmPlugin
              Name: gcp-wasm-plugin
            Name:       ext1
            Supported Events:
              RequestHeaders
              ResponseHeaders
          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>
      

      En la salida se muestran los detalles del GCPTrafficExtension llamado gcp-traffic-extension-with-plugin en el espacio de nombres predeterminado. Se muestra el campo Spec, que contiene la definición de cómo debe comportarse la extensión.

    2. Verifica el enlace de la pasarela:

      Comprueba que el GCPTrafficExtension esté vinculado a la pasarela. Este comando puede tardar unos minutos en completarse:

      kubectl describe gateway GATEWAY_NAME
      

      El resultado debería ser similar al siguiente:

      Name:         GATEWAY_NAME
      Namespace:    default
      Labels:       <none>
      Annotations:  networking.gke.io/addresses: /projects/922988411345/global/addresses/test-k18j-default-external-http-2jfqxrkgd0fm
                    networking.gke.io/backend-services:
                      /projects/922988411345/global/backendServices/test-k18j-default-gw-serve404-80-8zjp3d8cqfsu, /projects/922988411345/global/backendServices...
                      networking.gke.io/certmap: store-example-com-map
                      networking.gke.io/firewalls: /projects/922988411345/global/firewalls/test-k18j-l7-default-global
                      networking.gke.io/forwarding-rules: /projects/922988411345/global/forwardingRules/test-k18j-default-external-http-wt1tl0cwi6zr
                      networking.gke.io/health-checks:
                        /projects/922988411345/global/healthChecks/test-k18j-default-gw-serve404-80-8zjp3d8cqfsu, /projects/922988411345/global/healthChecks/test-...
                      networking.gke.io/last-reconcile-time: 2025-08-08T20:27:35Z
                      networking.gke.io/lb-route-extensions:
                      networking.gke.io/lb-traffic-extensions:
                        projects/922988411345/locations/global/lbTrafficExtensions/test-k18j-default-external-http-0tdum40yts35
                      networking.gke.io/ssl-certificates:
                      networking.gke.io/target-http-proxies:
                      networking.gke.io/target-https-proxies: /projects/922988411345/global/targetHttpsProxies/test-k18j-default-external-http-jy9mc97xb5yh
                      networking.gke.io/url-maps: /projects/922988411345/global/urlMaps/test-k18j-default-external-http-jy9mc97xb5yh
                      networking.gke.io/wasm-plugin-versions:
                        projects/922988411345/locations/global/wasmPlugins/test-k18j-default-gcp-wasm-plugin-itle20jj9nyk/versions/test-k18j-wasm-plugin-version-i...
                      networking.gke.io/wasm-plugins: projects/922988411345/locations/global/wasmPlugins/test-k18j-default-gcp-wasm-plugin-itle20jj9nyk
      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
      Spec:
        Gateway Class Name:  gke-l7-global-external-managed
        Listeners:
          Allowed Routes:
            Namespaces:
              From:  Same
          Name:      https
          Port:      443
          Protocol:  HTTPS
      ...
      

      El resultado muestra las anotaciones que usa GKE para almacenar los enlaces entre la pasarela y los recursos Google Cloudsubyacentes. Las anotaciones networking.gke.io/lb-traffic-extensions, networking.gke.io/wasm-plugin-versions y networking.gke.io/wasm-plugins confirman la vinculación.

    3. Comprueba el estado de la extensión:

      Confirma que el elemento GCPTrafficExtension tiene el estado Programmed con el motivo ProgrammingSucceeded. El comando puede tardar unos minutos en completarse.

      kubectl describe gcptrafficextensions.networking.gke.io gcp-traffic-extension-with-plugin
      

      El resultado debería ser similar al siguiente:

      Name:         gcp-traffic-extension-with-plugin
      Namespace:    default
      Labels:       <none>
      Annotations:  <none>
      API Version:  networking.gke.io/v1
      Kind:         GCPTrafficExtension
      Metadata:
        Creation Timestamp:  2025-08-08T20:08:09Z
        Generation:          1
        Resource Version:    56528
        UID:                 1389f790-9663-45ca-ac4e-a2c082f43359
      Spec:
        Extension Chains:
          Extensions:
            Backend Ref:
              Group:  networking.gke.io
              Kind:   GCPWasmPlugin
              Name:   gcp-wasm-plugin
            Name:     ext1
            Supported Events:
              RequestHeaders
              ResponseHeaders
          Match Condition:
            Cel Expressions:
              Cel Matcher:  request.path.contains("serviceextensions")
          Name:             chain1
        Target Refs:
          Group:  gateway.networking.k8s.io
          Kind:   Gateway
          Name:   external-http
      Status:
        Ancestors:
          Ancestor Ref:
            Group:      gateway.networking.k8s.io
            Kind:       Gateway
            Name:       external-http
            Namespace:  default
          Conditions:
            Last Transition Time:  2025-08-08T20:16:13Z
            Message:
            Observed Generation:   1
            Reason:                Accepted
            Status:                True
            Type:                  Accepted
            Last Transition Time:  2025-08-08T20:16:13Z
            Message:
            Observed Generation:   1
            Reason:                ResolvedRefs
            Status:                True
            Type:                  ResolvedRefs
            Last Transition Time:  2025-08-08T20:16:13Z
            Message:
            Observed Generation:   1
            Reason:                ProgrammingSucceeded
            Status:                True
            Type:                  Programmed
          Controller Name:         networking.gke.io/gateway
      Events:
        Type    Reason  Age                  From                   Message
        ----    ------  ----                 ----                   -------
        Normal  ADD     19m                  sc-gateway-controller  default/gcp-traffic-extension-with-plugin
        Normal  SYNC    3m25s (x4 over 11m)  sc-gateway-controller  Attachment of GCPTrafficExtension "default/gcp-traffic-extension-with-plugin" to AncestorRef {Group:       "gateway.networking.k8s.io",
      Kind:        "Gateway",
      Namespace:   "default",
      Name:        "external-http",
      SectionName: nil,
      Port:        nil} was a success
        Normal  SYNC  3m25s (x4 over 11m)  sc-gateway-controller  All the object references were able to be resolved for GCPTrafficExtension "default/gcp-traffic-extension-with-plugin" bound to AncestorRef {Group:       "gateway.networking.k8s.io",
      Kind:        "Gateway",
      Namespace:   "default",
      Name:        "external-http",
      SectionName: nil,
      Port:        nil}
        Normal  SYNC  3m25s (x4 over 11m)  sc-gateway-controller  Programming of GCPTrafficExtension "default/gcp-traffic-extension-with-plugin" to AncestorRef {Group:       "gateway.networking.k8s.io",
      Kind:        "Gateway",
      Namespace:   "default",
      Name:        "external-http",
      SectionName: nil,
      Port:        nil} was a success
      
    4. Comprueba el estado del complemento.

      Confirma que el recurso GCPWasmPlugin tiene el estado Programmed con el ProgrammingSucceeded motivo. El comando puede tardar unos minutos en completarse.

      kubectl describe gcpwasmplugins.networking.gke.io gcp-wasm-plugin
      

      El resultado debería ser similar al siguiente:

      Name:         gcp-wasm-plugin
      Namespace:    default
      Labels:       <none>
      Annotations:  <none>
      API Version:  networking.gke.io/v1
      Kind:         GCPWasmPlugin
      Metadata:
        Creation Timestamp:  2025-08-08T19:54:18Z
        Generation:          1
        Resource Version:    44578
        UID:                 549a12c7-91d1-43ad-a406-d6157a799b79
      Spec:
        Log Config:
          Enabled: true
          Min Log Level: INFO
          Sample Rate: 1000000
        Versions:
          Description:  Test wasm plugin version
          Image:        us-docker.pkg.dev/service-extensions-samples/plugins/local-reply:main
          Name:         wasm-plugin-version
          Weight:       1000000
      Status:
        Ancestors:
          Ancestor Ref:
            Group:      gateway.networking.k8s.io
            Kind:       Gateway
            Name:       external-http
            Namespace:  default
          Conditions:
            Last Transition Time:  2025-08-08T19:59:06Z
            Message:
            Observed Generation:   1
            Reason:                Accepted
            Status:                True
            Type:                  Accepted
            Last Transition Time:  2025-08-08T19:59:06Z
            Message:
            Observed Generation:   1
            Reason:                ResolvedRefs
            Status:                True
            Type:                  ResolvedRefs
            Last Transition Time:  2025-08-08T19:59:06Z
            Message:
            Observed Generation:   1
            Reason:                ProgrammingSucceeded
            Status:                True
            Type:                  Programmed
          Controller Name:         networking.gke.io/gateway
      Events:
        Type    Reason  Age                 From                   Message
        ----    ------  ----                ----                   -------
        Normal  ADD     31m                 sc-gateway-controller  default/gcp-wasm-plugin
        Normal  SYNC    2m1s (x7 over 26m)  sc-gateway-controller  Attachment of WasmPlugin "default/gcp-wasm-plugin" to AncestorRef {Group:       "gateway.networking.k8s.io",
      Kind:        "Gateway",
      Namespace:   "default",
      Name:        "external-http",
      SectionName: nil,
      Port:        nil} was a success
        Normal  SYNC  2m1s (x7 over 26m)  sc-gateway-controller  All the object references were able to be resolved for WasmPlugin "default/gcp-wasm-plugin" bound to AncestorRef {Group:       "gateway.networking.k8s.io",
      Kind:        "Gateway",
      Namespace:   "default",
      Name:        "external-http",
      SectionName: nil,
      Port:        nil}
        Normal  SYNC  2m1s (x7 over 26m)  sc-gateway-controller  Programming of WasmPlugin "default/gcp-wasm-plugin" to AncestorRef {Group:       "gateway.networking.k8s.io",
      Kind:        "Gateway",
      Namespace:   "default",
      Name:        "external-http",
      SectionName: nil,
      Port:        nil} was a success
      
  3. Envía tráfico a tu aplicación.

    Una vez que se hayan desplegado la pasarela, la ruta y la aplicación en tu clúster, podrás enviar tráfico a tu aplicación.

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

      En el terminal, usa el siguiente comando:

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

      Sustituye GATEWAY_NAME por el nombre de tu Gateway.

      Este comando muestra la dirección IP de la pasarela. En los comandos posteriores, sustituye GATEWAY_IP_ADDRESS por la dirección IP de la salida.

    2. Prueba la actualización de la ruta. Para ello, ve a la versión serviceextensions del servicio de tienda en store.example.com/serviceextensions:

      curl https://store.example.com/serviceextensions --resolve store.example.com:443:GATEWAY_IP_ADDRESS --cacert cacert.pem -v
      

      La salida devuelve Hello World.

Gestionar el recurso GCPWasmPlugin

Puedes actualizar el GCPWasmPlugin CRD y monitorizar el complemento.

Actualizar el GCPWasmPlugin

Para actualizar un recurso GCPWasmPlugin, sigue estos pasos:

  1. Haz el cambio en el manifiesto de tu GCPWasmPlugin y sigue los pasos que se describen en Implementar un GCPWasmPlugin.

    Por ejemplo, para tener dos versiones del complemento, una que sirva tráfico y otra que no, actualice el archivo wasm-plugin.yaml de la siguiente manera:

    kind: GCPWasmPlugin
    apiVersion: networking.gke.io/v1
    metadata:
      name: gcp-wasm-plugin
    spec:
      versions:
      - name: wasm-plugin-version-v1
        description: "Serving Wasm Plugin version"
        image: "us-docker.pkg.dev/service-extensions-samples/plugins/local-reply:main"
        weight: 1000000
      - name: wasm-plugin-version-v2
        description: "Non serving Wasm Plugin version"
        image: "us-docker.pkg.dev/service-extensions-samples/plugins/local-reply:main"
        weight: 0
      logConfig:
        enabled: true
        sampleRate: 1000000
        minLogLevel: INFO
    

    En este ejemplo, se aplica lo siguiente:

    • wasm-plugin-version-v1 tiene un weight de 1000000, lo que significa que sirve todo el tráfico.
    • wasm-plugin-version-v2 tiene un weight de 0, lo que significa que no sirve tráfico.
  2. Para asegurarte de que la pasarela se ha actualizado, ejecuta el siguiente comando. Este comando puede tardar unos minutos en completarse:

    kubectl describe gateway GATEWAY_NAME
    

    Sustituye GATEWAY_NAME por el nombre de tu pasarela.

Monitor GCPWasmPlugin

Para ver las métricas de GCPWasmPlugin en la consola de Google Cloud , consulta Monitorización desde la perspectiva de los complementos.

Cuando llegues al paso de la guía en el que debes seleccionar un valor de la lista Filtro de versión del complemento, busca el formato prefix−WASM_PLUGIN_VERSION_NAME_FROM_FILE−suffix, donde WASM_PLUGIN_VERSION_NAME_FROM_FILE es el nombre de la versión específica que has definido en el archivo de configuración GCPWasmPlugin.

Solucionar problemas de extensiones de tráfico en pasarelas

En esta sección se ofrecen consejos para solucionar problemas al configurar extensiones de tráfico en gateways.

Pasarela no encontrada

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

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úrese de que el recurso Gateway especificado en el campo targetRefs del recurso GCPTrafficExtension o GCPRoutingExtension exista en el espacio de nombres especificado.

No se ha encontrado el servicio o el puerto de servicio

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

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úrese de que el servicio y el puerto de servicio especificados en el campo backendRef del recurso GCPTrafficExtension o GCPRoutingExtension existen en el espacio de nombres especificado.

No hay endpoints de red en el NEG

El siguiente error indica que no hay endpoints de red en el NEG asociados al 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 solucionar este problema, asegúrese de que el servicio especificado en el campo backendRef del recurso GCPTrafficExtension o GCPRoutingExtension tenga endpoints de red.

No se recibe ninguna respuesta o se recibe una respuesta con un error al enviar la solicitud

Si no recibes una respuesta o recibes una respuesta con un error al enviar una solicitud, puede que el servicio de llamada no esté funcionando correctamente.

Para solucionar este problema, comprueba si hay errores en los registros del servicio de llamada.

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

El siguiente error indica que no se ha encontrado el servicio de llamada o que no responde a la solicitud:

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

Para solucionar este problema, asegúrate de que el servicio de llamada esté en ejecución, de que esté escuchando en el puerto correcto y de que 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 llamada está experimentando un error de servidor interno:

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

Para solucionar este problema, consulta los registros del servicio de llamada para identificar la causa del error interno del servidor.

GCPWasmPlugin no existe

El siguiente error indica que el recurso GCPWasmPlugin no existe en tu proyecto:

Status:
  Ancestors:
    Ancestor Ref:
      Group:      gateway.networking.k8s.io
      Kind:       Gateway
      Name:       external-http
      Namespace:  default
    Conditions:
      Last Transition Time:  2025-03-06T16:27:57Z
      Message:
      Reason:                Accepted
      Status:                True
      Type:                  Accepted
      Last Transition Time:  2025-03-06T16:27:57Z
      Message:               error cause: invalid-wasm-plugin: GCPWasmPlugin default/my-wasm-plugin in GCPTrafficExtension default/my-gateway-plugin-extension does not exist
      Reason:                GCPWasmPluginNotFound
      Status:                False
      Type:                  ResolvedRefs
    Controller Name:         networking.gke.io/gateway

Para solucionar este problema, crea un elemento correspondienteGCPWasmPlugin en el Google Cloud proyecto o asigna una extensión a un elementoGCPWasmPlugin.

Siguientes pasos