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 identidades de GKE, y a los desarrolladores que necesitan configurar lógica personalizada de administración del tráfico con extensiones de servicio.

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

Descripción general

GKE usa extensiones de servicio para agregar lógica personalizada a Cloud Load Balancing. Puedes usar las extensiones del 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 agrega 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 que se selecciona el servicio. El balanceador de cargas puede agregar o cambiar los encabezados y las cargas útiles de las solicitudes y respuestas HTTP. GCPTrafficExtension no afecta la selección de servicios ni las políticas de seguridad de los servicios.

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

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

  • Hacer referencia a un recurso GCPWasmPlugin: Para casos de uso de alto rendimiento, puedes insertar lógica personalizada escrita por el usuario directamente en la ruta de datos del balanceador de cargasGoogle Cloud con un módulo de WebAssembly (Wasm). Defines un recurso GCPWasmPlugin que apunta a la imagen de tu módulo de Wasm en Artifact Registry. Este método solo se usa con un GCPTrafficExtension y un balanceador de cargas de aplicaciones externo global.

  • Hacer referencia a un servicio de la API de Google: También puedes hacer referencia a un servicio de la API de Google directamente con el campo googleAPIServiceName dentro de un GCPTrafficExtension.

En el siguiente diagrama, el recurso GCPRoutingExtension está asociado a una puerta de enlace y hace referencia a varios servicios. La extensión controla el enrutamiento del tráfico hacia los Servicios.

El recurso `GCPRoutingExtension` se conecta a una puerta de enlace y hace referencia a un servicio. La extensión controla el enrutamiento del tráfico.
Figura: Cómo funciona GCPRoutingExtension con las Gateways

En el siguiente diagrama, el recurso GCPTrafficExtension se adjunta 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 respuestas.

El recurso `GCPTrafficExtension` se adjunta a una puerta de enlace 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 respuestas.
Figura: Cómo funciona GCPTrafficExtension con las Gateways

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 el comando gcloud components update para obtener la versión más reciente. Es posible que las versiones anteriores de gcloud CLI no admitan la ejecución de los comandos que se describen en este documento.

Requisitos del controlador de la puerta de enlace de GKE

  • 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 de Gateway.
  • Debes tener un recurso de Gateway configurado. Este recurso puede ser un balanceador de cargas de aplicaciones externo global, un balanceador de cargas de aplicaciones externo regional o una puerta de enlace del balanceador de cargas de aplicaciones interno regional. Si usas un recurso GCPWasmPlugin, solo debes implementar una puerta de enlace de balanceador de cargas de aplicaciones externo global.
  • Debes tener un recurso de HTTPRoute configurado.

Restricciones y limitaciones

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

Categoría Restricciones y limitaciones
Balanceador de cargas El GCPRoutingExtension es compatible con los siguientes balanceadores de cargas:
  • Balanceador de cargas de aplicaciones externo regional (clase Gateway gke-l7-regional-external-managed)
  • Balanceador de cargas de aplicaciones interno regional(clase Gatewaygke-l7-rilb)
El GCPTrafficExtension es compatible con los siguientes balanceadores de cargas:
  • Balanceador de cargas de aplicaciones externo regional (clase Gateway gke-l7-regional-external-managed)
  • Balanceador de cargas de aplicaciones interno regional (clase de puerta de enlace gke-l7-rilb)
  • Balanceador de cargas de aplicaciones externo global (clase de puerta de enlace gke-l7-global-external-managed)
Cadena y especificación de la extensión
  • En el caso de un GCPTrafficExtension, cada ExtensionChain puede tener un máximo de 3 Extensions.
  • En el caso de un GCPRoutingExtension, cada ExtensionChain se limita a 1 Extension.
  • Un GCPTrafficExtensionSpec y un GCPRoutingExtensionSpec pueden tener un máximo de 5 ExtensionChains cada uno.
Sincronización y correlación
  • El tiempo de espera para cada mensaje individual en la transmisión dentro de una extensión debe estar entre 10 y 10,000 milisegundos. Este límite de un segundo se aplica a las extensiones de 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 del mapa Metadata deben tener entre 1 y 63 caracteres.
  • Los valores dentro del mapa Metadata deben tener entre 1 y 1,023 caracteres.
Evento
  • En el caso de un GCPRoutingExtension, si no se establece requestBodySendMode, la lista supportedEvents solo puede contener eventos RequestHeaders.
  • En el caso de un GCPRoutingExtension, si requestBodySendMode se establece en FullDuplexStreamed, la lista supportedEvents solo puede contener eventos RequestHeaders, RequestBody y RequestTrailers.
GCPTrafficExtension
  • El campo responseBodySendMode solo se admite para GCPTrafficExtension.
  • El campo googleAPIServiceName solo se admite para GCPTrafficExtension.
  • El campo GCPWasmPlugin solo se admite para 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 haces referencia a un Servicio que usa backendRef en una Extensión, debes cumplir con las siguientes condiciones:
  • Debe usar HTTP/2 como su appProtocol.
  • Debe estar en el mismo espacio de nombres que la extensión y la puerta de enlace a la que hace referencia la extensión.
  • No se puede usar IAP.
  • No se pueden usar políticas de seguridad de Google Cloud Armor (campo securityPolicy de GCPBackendPolicyConfig).
  • No se puede usar Cloud CDN.
  • Se debe establecer exactamente uno de los campos backendRef o googleAPIServiceName para un Extension.
  • Se debe establecer authority si se establece backendRef y kind es Service.
  • No se debe configurar authority si se configura googleAPIServiceName.
  • Configura requestBodySendMode para extensiones usando solo backendRef y Service.
  • Configura responseBodySendMode para extensiones usando solo backendRef y Service.

Referencia a un servicio

En las extensiones de servicio, puedes hacer referencia a un servicio que aloja la lógica personalizada que deseas que ejecute el balanceador de cargas. Las puertas de enlace no tienen extensiones de servicio de forma predeterminada.

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

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

  2. Configura extensiones de servicio: Usa la extensión adecuada según el tipo de balanceador de cargas.

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

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

Implementa un servicio de devolución de llamada de backend

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

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

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

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

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

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

    kubectl get secrets SECRET_NAME
    

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

    El resultado debería ser similar al siguiente ejemplo:

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

    Debes definir lo siguiente:

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

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

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

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

      kubectl get pod --selector app=store
      

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

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

      kubectl get service extension-service
      

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

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

Configura extensiones de servicio

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

Configura GCPRoutingExtension para las puertas de enlace regionales

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

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

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

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

      Reemplaza GATEWAY_NAME por el nombre de tu puerta de enlace.

    2. Aplica el manifiesto store-route.yaml:

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

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

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

      Reemplaza GATEWAY_NAME por el nombre de tu puerta de enlace.

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

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

    1. Verifica la implementación de GCPRoutingExtension:

      kubectl describe gcproutingextension my-gateway-extension
      

      El resultado es similar a este:

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

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

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

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

        kubectl describe gateway GATEWAY_NAME
        

        El resultado es similar a este:

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

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

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

        kubectl describe gcproutingextension my-gateway-extension
        

        El resultado es similar a este:

        Name:         my-gateway-extension
        Namespace:    default
        Labels:       <none>
        Annotations:  <none>
        API Version:  networking.gke.io/v1
        Kind:         GCPRoutingExtension
        Metadata:
          Creation Timestamp:  2025-03-02T17:12:30Z
          Generation:          1
          Resource Version:    31284378
          UID:                 ec8efaa0-d8e7-4e1b-9fd4-0ae0ef3c74d0
        Spec:
          Extension Chains:
            Extensions:
              Authority:  myext.com
              Backend Ref:
                Group:
                Kind:   Service
                Name:   extension-service
                Port:   443
              Name:     ext1
              Timeout:  1s
            Match Condition:
              Cel Expressions:
                Cel Matcher:  request.path.contains("serviceextensions")
            Name:             chain1
          Target Refs:
            Group:  gateway.networking.k8s.io
            Kind:   Gateway
            Name:   GATEWAY_NAME
        Status:
          Ancestors:
            Ancestor Ref:
              Group:      gateway.networking.k8s.io
              Kind:       Gateway
              Name:       GATEWAY_NAME
              Namespace:  default
            Conditions:
              Last Transition Time:  2025-03-02T17:14:15Z
              Message:
              Reason:                Accepted
              Status:                True
              Type:                  Accepted
              Last Transition Time:  2025-03-02T17:14:15Z
              Message:
              Reason:                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 aplicó correctamente.

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

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

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

      En tu terminal, usa el siguiente comando:

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

      Reemplaza GATEWAY_NAME por el nombre de tu puerta de enlace.

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

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

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

      El resultado es similar a este:

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

Configura el GCPTrafficExtension

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

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

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

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

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

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

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

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

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

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

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

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

    1. Verifica la implementación de GCPTrafficExtension:

      kubectl describe gcptrafficextension my-traffic-extension
      

      El resultado es similar a este:

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

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

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

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

      kubectl describe gateway GATEWAY_NAME
      

      El resultado es similar a este:

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

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

    3. Verifica el estado de la extensión:

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

      Para verificar el estado de la extensión de 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 aplicó correctamente.

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

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

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

      En tu terminal, usa el siguiente comando:

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

      Reemplaza GATEWAY_NAME por el nombre de tu puerta de enlace.

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

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

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

      El resultado es similar a este:

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

Haz referencia a un recurso GCPWasmPlugin

Puedes insertar lógica personalizada directamente en la ruta de acceso de datos del balanceador de cargas con un GCPWasmPlugin y un GCPTrafficExtension. Este método te permite implementar capacidades personalizadas de administración del tráfico empaquetadas como un módulo de Wasm.

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

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

  2. Configura extensiones de servicio: Usa GCPTrafficExtension para el balanceador de cargas de aplicaciones externo global.

Implementa un GCPWasmPlugin

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

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

Para implementar un recurso GCPWasmPlugin, completa los siguientes pasos:

  1. Guarda el siguiente 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 dentro del recurso GCPWasmPlugin. Puedes enumerar hasta 10 versiones, y 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 se almacena 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, inclusive.
    • spec.logConfig: Especifica si se debe habilitar Cloud Logging para este complemento. Si no se especifica el valor, Cloud Logging se inhabilita de forma predeterminada.
    • spec.logConfig.sampleRate: Configura la tasa de muestreo de los registros de actividad. La tasa debe ser un número entre 0 y 1,000,000, inclusive. Si no se especifica cuando Cloud Logging está habilitado, el valor predeterminado es 1,000,000 (se registra 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 el valor cuando se habilita Cloud Logging, el campo se establece en INFO de forma predeterminada.
  2. Aplica el manifiesto wasm-plugin.yaml:

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

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

    El resultado es similar a este:

    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>
    

Configura extensiones de servicio

Para agregar lógica personalizada a tu balanceador de cargas de aplicaciones externo global, puedes configurar un GCPTrafficExtension para que use un GCPWasmPlugin. Puedes usar una GCPTrafficExtension para aprovechar las capacidades avanzadas de administración del tráfico dentro de tu entorno de Google Cloud . Puedes configurar esta extensión en todos los balanceadores de cargas de aplicaciones externos globales.

Para configurar un GCPTrafficExtension para que use un GCPWasmPlugin, completa los siguientes 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
      

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

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

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

    1. Verifica la implementación de GCPTrafficExtension:

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

      El resultado es similar a este:

      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>
      

      El resultado muestra los detalles del GCPTrafficExtension llamado gcp-traffic-extension-with-plugin 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é vinculada 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/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 GKE usa para almacenar los vínculos entre la puerta de enlace 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. Verifica el estado de la extensión:

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

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

      El resultado es similar a este:

      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. Verifica el estado del complemento.

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

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

      El resultado es similar a este:

      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.

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

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

      En tu terminal, usa el siguiente comando:

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

      Reemplaza GATEWAY_NAME por el nombre de tu puerta de enlace.

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

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

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

      El resultado devuelve Hello World.

Administra el recurso GCPWasmPlugin

Puedes actualizar el CRD GCPWasmPlugin y supervisar el complemento.

Actualiza el GCPWasmPlugin

Para actualizar un recurso GCPWasmPlugin, sigue estos pasos:

  1. Realiza el cambio en el manifiesto de GCPWasmPlugin y sigue los pasos que se describen en Implementa un GCPWasmPlugin.

    Por ejemplo, para tener dos versiones del complemento, en las que una versión publica tráfico y la otra no, actualiza tu 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 entrega todo el tráfico.
    • wasm-plugin-version-v2 tiene un weight de 0, lo que significa que no publica ningún tráfico.
  2. Para asegurarte de que la puerta de enlace se actualizó, ejecuta el siguiente comando. Este comando puede tardar unos minutos en completarse:

    kubectl describe gateway GATEWAY_NAME
    

    Reemplaza GATEWAY_NAME por el nombre de tu puerta de enlace.

Supervisa GCPWasmPlugin

Para ver las métricas de GCPWasmPlugin en la consola de Google Cloud , consulta Supervisió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, en el que WASM_PLUGIN_VERSION_NAME_FROM_FILE es el nombre específico de la versión que definiste en tu archivo de configuración GCPWasmPlugin.

Soluciona problemas relacionados con las extensiones de tráfico en Gateways

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

No se encontró la puerta de enlace

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

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

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

No se encontró el servicio o el puerto de servicio

El siguiente error indica que 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 del servicio especificados en el campo backendRef del recurso GCPTrafficExtension o GCPRoutingExtension existan en el espacio de nombres especificado.

No hay extremos de red en el NEG.

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

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

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

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

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

Para resolver este problema, revisa los registros del servicio de texto destacado 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 llamadas esté en ejecución, de que esté escuchando en el puerto correcto y de que el servicio esté configurado correctamente en el recurso GCPTrafficExtension o GCPRoutingExtension.

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

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

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

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

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 resolver este problema, crea un GCPWasmPlugin correspondiente en el proyecto Google Cloud o dirige una extensión a un GCPWasmPlugin existente.

¿Qué sigue?