Personalizar o tráfego do gateway do GKE usando extensões de serviço


Nesta página, descrevemos como o Google Kubernetes Engine (GKE) usa extensões de serviço para adicionar lógica personalizada ao Cloud Load Balancing.

Esta página é destinada a administradores de identidade e conta do GKE e desenvolvedores que precisam configurar uma lógica personalizada de gerenciamento de tráfego usando extensões de serviço.

Antes de ler esta página, confira se você conhece os seguintes conceitos:

Visão geral

O GKE usa extensões de serviço para adicionar lógica personalizada ao Cloud Load Balancing. Uma extensão é anexada a um Gateway e faz referência a um Service ou um GoogleAPIServiceName. O GoogleAPIServiceName é compatível apenas com GCPTrafficExtensions.

É possível modificar cabeçalhos e payloads HTTP para solicitações e respostas ou controlar o roteamento de tráfego sem afetar a seleção serviço de back-end ou as políticas de segurança. É possível usar as extensões de serviço para tarefas como divisão avançada de tráfego, autenticação personalizada ou registro de solicitações.

O controlador de gateway do GKE é compatível com as seguintes extensões de serviço:

  • GCPRoutingExtension: essa extensão adiciona lógica personalizada ao Cloud Load Balancing para controlar o roteamento de tráfego. Ele é compatível com o balanceador de carga de aplicativo externo regional e o balanceador de carga de aplicativo interno regional.

    O recurso `GCPRoutingExtension` é anexado a um gateway e faz referência a um serviço. A extensão
        controla o roteamento de tráfego.
    Figura: como o GCPRoutingExtension funciona com gateways
  • GCPTrafficExtension: essa extensão insere uma lógica personalizada no Cloud Load Balancing. Ele permite que um serviço de extensão mude os cabeçalhos e os payloads de solicitações e respostas. O GCPTrafficExtension não afeta a seleção de serviço de back-end nem as políticas de segurança serviço de back-end.

    O recurso `GCPTrafficExtension` é anexado a um gateway e faz referência a um serviço ou a um `GoogleAPIServiceName`. A extensão muda os cabeçalhos e payloads de solicitações e respostas.
    Figura: como o GCPTrafficExtension funciona com gateways

Trusted Cloud by S3NS Compatibilidade da extensão de serviço com GatewayClasses

A tabela a seguir descreve a compatibilidade das extensões de serviço Trusted Cloud com diferentes GatewayClasses:

GatewayClass GCPRoutingExtension GCPTrafficExtension
gke-l7-rilb Com suporte Compatível
gke-l7-regional-external-managed Compatível Compatível
gke-l7-global-external-managed Incompatível Com suporte

Antes de começar

Antes de começar, veja se você realizou as seguintes tarefas:

  • Ative a API Google Kubernetes Engine.
  • Ativar a API Google Kubernetes Engine
  • Se você quiser usar a CLI do Google Cloud para essa tarefa, instale e, em seguida, inicialize a CLI gcloud. Se você instalou a gcloud CLI anteriormente, instale a versão mais recente executando gcloud components update.

Requisitos do GKE Gateway Controller

Restrições e limitações

A tabela a seguir lista as restrições associadas à configuração das extensões de serviço de gateway no GKE:

Categoria Restrições e limitações
Balanceador de carga O GCPRoutingExtension é compatível apenas com o balanceador de carga de aplicativo externo regional e o balanceador de carga de aplicativo interno regional (classes de gateway gke-l7-regional-external-managed e gke-l7-rilb) e não é compatível com a classe de gateway gke-l7-global-external-managed.
Cadeia e especificação de extensão
  • Para um GCPTrafficExtension, cada ExtensionChain pode ter no máximo três Extensions.
  • Para um GCPRoutingExtension, cada ExtensionChain é limitado a um Extension.
  • Um GCPTrafficExtensionSpec e um GCPRoutingExtensionSpec podem ter no máximo cinco ExtensionChains cada um.
Tempo e correspondência
  • O tempo limite para cada mensagem individual no stream em uma extensão precisa ser de 10 a 1.000 milissegundos. Esse limite de um segundo se aplica às extensões de rota e tráfego.
  • Cada MatchCondition em um ExtensionChain é limitado a um máximo de 10 CELExpressions.
  • A string MatchCondition resultante enviada ao GCE tem um limite de 512 caracteres.
  • A string CELMatcher em um CELExpression tem um comprimento máximo de 512 caracteres e precisa seguir um padrão específico. Não oferecemos suporte ao campo BackendRefs de CELExpression.
Cabeçalho e metadados
  • A lista ForwardHeaders em um Extension pode conter no máximo 50 nomes de cabeçalho HTTP.
  • O mapa Metadata em um Extension pode ter no máximo 16 propriedades.
  • As chaves no mapa Metadata precisam ter entre 1 e 63 caracteres.
  • Os valores no mapa Metadata precisam ter entre 1 e 1.023 caracteres.
Evento
  • Para um GCPRoutingExtension, se requestBodySendMode não estiver definido, a lista supportedEvents poderá conter apenas eventos RequestHeaders.
  • Para um GCPRoutingExtension, se requestBodySendMode estiver definido como FullDuplexStreamed, a lista supportedEvents poderá conter apenas eventos RequestHeaders, RequestBody e RequestTrailers.
GCPTrafficExtension
  • O campo responseBodySendMode é compatível apenas com GCPTrafficExtension.
  • O campo googleAPIServiceName é compatível apenas com GCPTrafficExtension.
googleAPIServiceName e backendRef Ao referenciar um serviço que usa o backendRef em uma extensão, você precisa atender às seguintes condições:
  • Precisa usar HTTP2 como appProtocol.
  • Precisa estar no mesmo namespace que a extensão e o gateway referenciado pela extensão.
  • Não é possível usar o IAP.
  • Não é possível usar políticas de segurança do Google Cloud Armor (campo securityPolicy de GCPBackendPolicyConfig.
  • Não é possível usar o Cloud CDN.
  • É necessário definir exatamente um de backendRef ou googleAPIServiceName para um Extension.
  • Defina authority se backendRef estiver definido.
  • Defina authority se googleAPIServiceName estiver definido.
  • Configure requestBodySendMode para extensões usando apenas backendRef.
  • Configure responseBodySendMode para extensões usando apenas backendRef.

Configurar extensões de serviço do GKE

É possível personalizar o roteamento de tráfego, modificar payloads de solicitação ou resposta e integrar com serviços externos configurando as extensões de serviço do GKE. Os gateways não têm extensões de serviço por padrão.

Para configurar as extensões de serviço do GKE:

  1. Implante um gateway: para configurar uma extensão de serviço do GKE, primeiro implante um gateway, que direciona o tráfego externo para seu cluster. Pode ser um balanceador de carga de aplicativo externo global, um balanceador de carga de aplicativo externo regional ou um gateway de balanceador de carga de aplicativo interno regional.

    Para mais informações sobre a implantação de gateways, consulte Como implantar gateways.

  2. Implante um serviço de callout de back-end: crie um serviço do Kubernetes que represente o serviço de back-end para execução de lógica personalizada. O balanceador de carga invoca esse serviço.

  3. Configure as extensões de serviço: configure as extensões de serviço adequadas com base no tipo e nos requisitos do balanceador de carga.

    1. GCPRoutingExtension para gateways regionais: use essa extensão para balanceadores de carga de aplicativo externos regionais e internos regionais para implementar uma lógica de roteamento personalizada na região.

    2. GCPTrafficExtension para gateways externos globais, externos regionais e internos: use essa extensão para balanceadores de carga de aplicativo externos globais, externos regionais e internos regionais para realizar manipulação de tráfego, como modificação de cabeçalho ou inspeção de payload, em vários tipos de balanceadores de carga.

Implantar um serviço de callback de back-end

Um serviço de callout implementa lógica personalizada para extensões de serviço do gateway no GKE. O gateway invoca esses aplicativos de back-end, com base nas configurações GCPTrafficExtension ou GCPRoutingExtension, para modificar ou rotear o tráfego.

Você implanta um serviço de chamada para adicionar lógica personalizada ao gateway. Esse serviço separado processa ações personalizadas, como manipulação de cabeçalho, transformações de payload ou roteamento de tráfego.

Para implantar um serviço de back-end que possa funcionar como uma callout para seu gateway, siga estas etapas:

  1. (Opcional) Crie um secret para TLS: esse comando cria um secret do Kubernetes do tipo TLS que contém seu certificado TLS e a chave privada.

    Para criar o secret TLS do seu serviço de callout, substitua o seguinte:

    • SECRET_NAME: o nome do secret para seu serviço de callout
    • path-to-cert: os caminhos dos arquivos do seu certificado
    • path-to-key: os caminhos de arquivo para sua chave
  2. Para verificar se a chave secreta foi adicionada, execute o seguinte comando:

    kubectl get secrets SECRET_NAME
    

    Substitua SECRET_NAME pelo nome do secret do seu serviço de callout.

    A saída será semelhante a esta:

    NAME            TYPE                DATA   AGE
    SECRET_NAME     kubernetes.io/tls   2      12s
    
  3. Defina recursos de implantação e serviço.

    Você precisa definir o seguinte:

    • Implantação: para gerenciar os pods de aplicativos que contêm a lógica personalizada das extensões de serviço.
    • Serviço: para expor os pods de aplicativos gerenciados pela implantação como um serviço de rede.
    1. Crie um manifesto de amostra extension-service-app.yaml com definições de implantação e serviço:

      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. Aplique o manifesto extension-service-app.yaml:

      kubectl apply -f extension-service-app.yaml
      
  4. Verifique a configuração:

    1. Verifique se o aplicativo foi implantado:

      kubectl get pod --selector app=store
      

      Depois que o aplicativo começar a ser executado, a saída será semelhante a esta:

      NAME                                     READY   STATUS    RESTARTS   AGE
      extension-service-app-85f466bc9b-b5mf4   1/1     Running   0          7s
      
    2. Verifique se o serviço foi implantado:

      kubectl get service extension-service
      

      A saída é semelhante à seguinte, que mostra um serviço para cada implantação de loja:

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

Configurar as extensões de serviço

É possível configurar um GCPRoutingExtension ou um GCPTrafficExtension para personalizar seu fluxo de tráfego.

Configurar o GCPRoutingExtension para gateways regionais

É possível redirecionar o tráfego usando um GCPRoutingExtension. Para configurar um GCPRoutingExtension, atualize o HTTPRoute para especificar as solicitações do host service-extensions.com.

  1. Atualize o HTTPRoute. Modifique sua HTTPRoute para incluir nomes de host ou caminhos que acionarão a extensão de roteamento.

    1. Salve o seguinte manifesto de amostra como o arquivo 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
      

      Substitua GATEWAY_NAME pelo nome do seu gateway.

    2. Aplique o manifesto store-route.yaml:

      kubectl apply -f store-route.yaml
      
  2. Defina o GCPRoutingExtension.

    1. Salve a configuração GCPRoutingExtension no arquivo de amostra 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
      

      Substitua GATEWAY_NAME pelo nome do seu gateway.

    2. Aplique o manifesto de amostra ao cluster:

      kubectl apply -f gcp-routing-extension.yaml
      
  3. Verifique a configuração do GCPRoutingExtension e a vinculação dele ao gateway.

    1. Verifique a implantação GCPRoutingExtension:

      kubectl describe gcproutingextension my-gateway-extension
      

      O resultado será assim:

      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>
      

      A saída mostra os detalhes do GCPRoutingExtension, chamado my-gateway-extension, no namespace padrão. A saída mostra o campo Spec, que contém a definição de como a extensão deve se comportar.

    2. Verifique a vinculação do gateway:

      1. Confirme se o GCPRoutingExtension está vinculado ao gateway. Isso pode levar alguns minutos:

        kubectl describe gateway GATEWAY_NAME
        

        O resultado será assim:

        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
        ...
        

        A saída mostra as anotações, que o GKE usa para armazenar os links entre o gateway e os recursosTrusted Cloud subjacentes. A anotação networking.gke.io/lb-route-extensions confirma a vinculação do gateway ao GCPRoutingExtension.

      2. Confira o status da extensão confirmando se o GCPRoutingExtension tem um status Reconciled com o motivo ReconciliationSucceeded. Esse comando pode levar alguns minutos.

        kubectl describe gcproutingextension my-gateway-extension
        

        O resultado será assim:

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

        O campo Status.Conditions mostra uma condição Reconciled com Status: True e Reason: ReconciliationSucceeded.

        Verdadeiro e motivo: ReconciliationSucceeded. Essas informações confirmam que a extensão foi aplicada corretamente.

  4. Envie tráfego para o aplicativo.

    Depois que o gateway, a rota e o aplicativo forem implantados no cluster, será possível transmitir o tráfego para o aplicativo.

    1. Para acessar o aplicativo, encontre o endereço IP do seu gateway.

      No terminal, use o seguinte comando:

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

      Substitua GATEWAY_NAME pelo nome do seu gateway.

      Esse comando gera o endereço IP do gateway. Nos comandos a seguir, substitua GATEWAY_IP_ADDRESS pelo endereço IP da saída.

    2. Teste a atualização de caminho acessando a versão serviceextensions do serviço da loja em store.example.com/serviceextensions:

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

      O resultado será assim:

      {
      "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 o GCPTrafficExtension

É possível usar um GCPTrafficExtension para usar recursos avançados de gerenciamento de tráfego no ambiente Trusted Cloud . É possível configurar essa extensão em balanceadores de carga de aplicativo externos globais, balanceadores de carga de aplicativo externos regionais e balanceadores de carga de aplicativo internos regionais. É possível usar GCPTrafficExtension para implementar lógica de solicitação e resposta personalizada, roteamento sofisticado, transformações e políticas de segurança.

  1. Atualize o HTTPRoute. Modifique sua HTTPRoute para incluir nomes de host ou caminhos que acionarão a extensão de tráfego.

    1. Salve o seguinte manifesto de amostra como o arquivo 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
      

      Substitua GATEWAY_NAME pelo nome do gateway, como internal-http, external-http ou global-external-http.

    2. Aplique o manifesto store-route.yaml ao cluster:

      kubectl apply -f store-route.yaml
      
  2. Defina o GCPTrafficExtension.

    1. Salve a configuração GCPTrafficExtension no arquivo de amostra 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
      

      Substitua GATEWAY_NAME pelo nome do gateway, como internal-http, external-http ou global-external-http.

    2. Aplique o manifesto de amostra ao cluster:

      kubectl apply -f gcp-traffic-extension.yaml
      
  3. Verifique a configuração do GCPTrafficExtension e a vinculação dele ao gateway.

    1. Verifique a implantação GCPTrafficExtension:

      kubectl describe gcptrafficextension my-traffic-extension
      

      O resultado será assim:

      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>
      

      A saída mostra os detalhes do GCPTrafficExtension chamado my-traffic-extension no namespace padrão. Ele mostra o campo Spec, que contém a definição de como a extensão deve se comportar.

    2. Verifique a vinculação do gateway:

      Confirme se o GCPTrafficExtension está vinculado ao gateway. Esse comando pode levar alguns minutos para ser concluído:

      kubectl describe gateway GATEWAY_NAME
      

      O resultado será assim:

      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
      ...
      

      A saída mostra as anotações, que o GKE usa para armazenar os links entre o gateway e os recursos Trusted Cloud subjacentes. A anotação networking.gke.io/lb-traffic-extensions confirma a vinculação.

    3. Verifique o status da extensão:

      Confirme se o GCPTrafficExtension tem um status Reconciled com o motivo ReconciliationSucceeded. Isso pode levar alguns minutos.

      kubectl describe gcptrafficextension my-traffic-extension
      

      O resultado será assim:

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

      O campo Status.Conditions mostra uma condição Reconciled com Status: True e Reason: ReconciliationSucceeded. Essas informações confirmam que a extensão foi aplicada com sucesso.

  4. Envie tráfego para o aplicativo.

    Depois que o gateway, a rota e o aplicativo forem implantados no cluster, será possível transmitir o tráfego para o aplicativo.

    1. Para acessar o aplicativo, encontre o endereço IP do seu gateway.

      No terminal, use o seguinte comando:

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

      Substitua GATEWAY_NAME pelo nome do seu gateway.

      Esse comando gera o endereço IP do gateway. Nos comandos a seguir, substitua GATEWAY_IP_ADDRESS pelo endereço IP da saída.

    2. Teste a atualização de caminho acessando a versão serviceextensions do serviço da loja em store.example.com/serviceextensions:

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

      O resultado será assim:

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

Resolver problemas de extensões de tráfego em gateways

Nesta seção, você encontra dicas de solução de problemas para configurar extensões de tráfego em gateways.

Gateway não encontrado

O erro a seguir indica que o recurso "Gateway" especificado no campo targetRefs do recurso GCPTrafficExtension ou GCPRoutingExtension não 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 esse problema, verifique se o recurso de gateway especificado no campo targetRefs do recurso GCPTrafficExtension ou GCPRoutingExtension existe no namespace especificado.

Serviço ou porta de serviço não encontrado

O erro a seguir indica que o serviço ou a porta de serviço especificada no campo backendRef do recurso GCPTrafficExtension ou GCPRoutingExtension não 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 esse problema, verifique se o serviço e a porta especificados no campo backendRef do recurso GCPTrafficExtension ou GCPRoutingExtension existem no namespace especificado.

Não há endpoints de rede no NEG

O erro a seguir indica que não há endpoints de rede no NEG associados ao serviço especificado no campo backendRef do recurso GCPTrafficExtension ou 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 esse problema, verifique se o serviço especificado no campo backendRef do recurso GCPTrafficExtension ou GCPRoutingExtension tem endpoints de rede.

Nenhuma resposta ou resposta com um erro ao enviar a solicitação

Se você não receber uma resposta ou se receber uma resposta com um erro ao enviar uma solicitação, isso pode indicar que o serviço de callout não está funcionando corretamente.

Para resolver esse problema, verifique se há erros nos registros do serviço de callout.

Código de erro 404 no payload JSON

O erro a seguir indica que o serviço de callout não foi encontrado ou não está respondendo à solicitação:

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

Para resolver esse problema, verifique se o serviço de callout está em execução, se ele está escutando na porta correta e se o serviço está configurado corretamente no recurso GCPTrafficExtension ou GCPRoutingExtension.

Código de erro 500 no payload JSON

O erro a seguir indica que o serviço de callout está com um erro interno do servidor:

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

Para resolver esse problema, verifique os registros do serviço de callout para identificar a causa do erro interno do servidor.

A seguir