Implantar um gateway de passagem de TLS

Neste documento, mostramos como implantar um recurso de gateway do Kubernetes configurado para passagem de TLS para ativar o roteamento baseado em indicação de nome de servidor (SNI, na sigla em inglês) no Google Kubernetes Engine (GKE). Essa abordagem preserva a criptografia de ponta a ponta e o TLS mútuo (mTLS) entre clientes e pods de back-end, é compatível com protocolos não HTTP baseados em TLS e conserva endereços IP.

Este documento é destinado a arquitetos de nuvem, especialistas Rede e desenvolvedores que projetam, implantam e gerenciam redes criptografadas para cargas de trabalho conteinerizadas. Para saber mais sobre papéis comuns e tarefas de exemplo, consulte Tarefas e papéis de usuário comuns do GKE.

Visão geral

Além dos balanceadores de carga de aplicativo HTTP e HTTPS da camada 7, o controlador de gateway do GKE oferece suporte a balanceadores de carga de rede de proxy da camada 4 (balanceadores de carga de proxy TCP) configurados com passagem de TLS.

Com a passagem de TLS, o balanceador de carga não encerra nem descriptografa a sessão TLS. Em vez disso, quando um cliente inicia um handshake de TLS, o balanceador de carga inspeciona a mensagem ClientHello não criptografada para ler o nome do host da indicação de nome do servidor (SNI, na sigla em inglês). Com base nesse nome de host SNI, o balanceador de carga roteia o fluxo TCP criptografado bruto para o serviço de back-end apropriado do Kubernetes, em que os pods do aplicativo encerram o TLS diretamente.

Ao usar a passagem de TLS com a API Gateway, é possível:

  • Mantenha a criptografia de ponta a ponta e ofereça suporte à conformidade de confiança zero: mantenha o tráfego totalmente criptografado do cliente para o pod de back-end sem dar ao balanceador de carga acesso a chaves privadas ou dados de texto simples.
  • Usar a autenticação TLS mútua (mTLS): autentique os clientes diretamente na camada do aplicativo de back-end.
  • Conservar endereços IPv4: multiplexar vários serviços TLS independentes em domínios ou subdomínios distintos usando um único endereço IP e porta de gateway (como 443).
  • Suporte a protocolos não HTTP baseados em TLS: roteie o tráfego criptografado para cargas de trabalho com estado, bancos de dados, serviços gRPC personalizados ou protocolos proprietários em execução no TLS.

GatewayClasses compatíveis

As seguintes GatewayClasses do GKE são compatíveis com listeners de passagem de TLS e recursos TLSRoute:

  • gke-l7-regional-external-managed
  • gke-l7-regional-external-managed-mc
  • gke-l7-rilb
  • gke-l7-rilb-mc
  • gke-l7-cross-regional-internal-managed-mc

Para uma comparação completa dos recursos de GatewayClass, consulte Recursos de GatewayClass.

Antes de começar

Antes de começar, verifique se você realizou as tarefas a seguir:

  • Ative a API Google Kubernetes Engine.
  • Ativar a API Google Kubernetes Engine
  • Para usar a Google Cloud CLI nesta tarefa, instale e inicialize a CLI gcloud. Se você instalou a CLI gcloud anteriormente, instale a versão mais recente executando o comando gcloud components update. Talvez as versões anteriores da CLI gcloud não sejam compatíveis com a execução dos comandos neste documento.
  • Verifique se você tem um cluster do Autopilot ou Standard executando o GKE versão 1.35 ou mais recente com a API Gateway ativada. Para criar um cluster do Autopilot, consulte Criar um cluster do Autopilot. Para ativar a API Gateway em um cluster, consulte Ativar a API Gateway no cluster.
  • Verifique se você tem a ferramenta de linha de comando OpenSSL instalada. Use essa ferramenta para gerar certificados TLS autoassinados para os aplicativos de amostra.

Requisitos do GKE Gateway Controller

  • A API Gateway é compatível apenas com clusters nativos da VPC.
  • Se você estiver usando as GatewayClasses regionais ou entre regiões, ative uma sub-rede somente proxy.
  • O cluster precisa ter o complemento HttpLoadBalancing ativado.
  • Se você estiver usando o Istio, será necessário fazer upgrade do Istio para uma das seguintes versões:
    • 1.15.2 ou mais recente
    • 1.14.5 ou mais recente
    • 1.13.9 ou mais recente
  • Se você estiver usando a VPC compartilhada, será necessário atribuir o papel Compute Network User à conta de serviço do GKE referente ao projeto de serviço no projeto host.

Restrições e limitações

Ao implantar gateways de passagem de TLS e recursos TLSRoute, observe as seguintes limitações:

  • Ao definir a configuração protocol: TLS em um listener, é preciso definir explicitamente o campo tls.mode como o valor Passthrough. O GKE não é compatível com o modo Terminate padrão para listeners TLS.
  • Em um listener TLS, não defina o campo certificateRefs. A validação do certificado do cliente no nível do gateway (o campo spec.tls.frontendValidation) não se aplica aos listeners TLS. Para usar mTLS, valide os certificados do cliente no back-end.
  • Um listener TLS só pode compartilhar uma porta com outros listeners TLS. Não é possível configurar listeners HTTP ou HTTPS na mesma porta que um listener TLS.
  • No campo TLSRoute.spec.hostnames, é preciso especificar uma lista de 1 a 1.024 nomes de host SNI (nome de host exato ou prefixo curinga, como *.example.com). Cada entrada não pode exceder 253 caracteres e não pode ser um endereço IP.
  • No campo TLSRoute.spec.rules, é possível configurar no máximo uma regra.
  • Cada regra é compatível com exatamente uma entrada backendRef. Os back-ends de proxy da camada 4 não são compatíveis com a divisão de tráfego ponderada em vários back-ends.
  • As GatewayClasses de cluster único são compatíveis apenas com back-ends de serviço, e as GatewayClasses de vários clusters são compatíveis apenas com back-ends ServiceImport.
  • No campo TLSRoute.spec.rules.backendRefs, defina o campo port como uma porta declarada pelo recurso de destino Service ou ServiceImport, não como a porta do contêiner.
  • O serviço de back-end do Kubernetes (incluindo serviços exportados como um ServiceImport) referenciado por um recurso TLSRoute precisa usar o valor TCP para o protocolo de porta.
  • Não é possível anexar um recurso BackendTLSPolicy, o Identity-Aware Proxy ou uma política de segurança do Google Cloud Armor a um back-end TLSRoute porque o controlador rejeita configurações desse tipo.
  • Ao anexar um recurso GCPBackendPolicy a um Service ou ServiceImport referenciado por um recurso TLSRoute, defina o campo spec.protocol como o valor TCP. Se o campo spec.protocol for omitido, o padrão será o valor HTTP, que se aplica apenas a back-ends HTTPRoute. Um serviço ou ServiceImport pode ter uma política HTTP e uma política TCP anexadas ao mesmo tempo. Se várias políticas com o mesmo valor spec.protocol segmentarem o mesmo serviço ou ServiceImport, a política mais antiga terá precedência e as mais recentes não serão anexadas.
  • Um recurso GCPBackendPolicy com o campo spec.protocol definido como TCP aceita apenas os seguintes campos no campo spec.default (ao segmentar um recurso ServiceImport, é possível definir os três últimos campos por cluster, zona ou região no campo spec.default.scopes):

    • timeoutSec
    • connectionDraining
    • logging.enabled e logging.sampleRate
    • sessionAffinity.type (os valores válidos são CLIENT_IP ou NONE)
    • capacityScalerPercent
    • balancingMode: CONNECTION
    • maxConnectionsPerEndpoint

    Não é possível criar uma política TCP que inclua outros campos ou uma política HTTP que inclua campos somente TCP (balancingMode: CONNECTION e maxConnectionsPerEndpoint). O servidor de API Kubernetes rejeita a política na criação. Para mais informações, consulte Configurar recursos de gateway usando políticas.

  • Se um recurso HTTPRoute e um recurso TLSRoute fizerem referência ao mesmo Service ou ServiceImport, anexar um recurso HealthCheckPolicy a esse destino vai substituir as verificações de integridade padrão separadas e aplicar a mesma configuração de verificação de integridade aos back-ends das duas rotas. Para configurar verificações de integridade de maneira independente (como verificações de integridade HTTP para back-ends HTTPRoute e verificações de integridade SSL ou TCP para back-ends TLSRoute), crie um serviço separado para cada rota e anexe um recurso HealthCheckPolicy a cada serviço. Os dois serviços podem selecionar os mesmos pods.

  • Os recursos da camada 7 (como regravações de URL, roteamento baseado em caminho e transformações de cabeçalho HTTP) não se aplicam aos balanceadores de carga de proxy TCP da camada 4.

Configurar uma sub-rede somente proxy

Um gateway regional requer uma sub-rede somente proxy (purpose=REGIONAL_MANAGED_PROXY) em cada região em que é implantado. Uma sub-rede somente proxy atende a todos os balanceadores de carga regionais baseados no Envoy nessa região. Se a região ainda não tiver uma, consulte Configurar uma sub-rede somente proxy.

Reservar um endereço IP estático

Antes de implantar o gateway, reserve um endereço IP estático regional para que o endereço do gateway não mude e você possa resolver os nomes de host de amostra para ele. Para instruções sobre como criar um endereço IP estático, consulte Criar um gateway HTTP(S) externo regional.

Implantar um gateway com listeners de passagem de TLS

O gateway nesta seção configura dois listeners TLS que compartilham a porta 443. Cada listener corresponde a um nome de host SNI diferente e encaminha conexões no modo de passagem para recursos TLSRoute anexados.

  1. Salve o seguinte manifesto como store-gateway.yaml:

    kind: Gateway
    apiVersion: gateway.networking.k8s.io/v1
    metadata:
      name: store-tls
    spec:
      gatewayClassName: gke-l7-regional-external-managed
      listeners:
      # Accept TLS connections for store.example.com without decrypting them.
      - name: store
        protocol: TLS
        port: 443
        hostname: "store.example.com"
        tls:
          mode: Passthrough
        allowedRoutes:
          kinds:
          - kind: TLSRoute
      # A second listener on the same port, selected by a different SNI name.
      - name: store-german
        protocol: TLS
        port: 443
        hostname: "store-de.example.com"
        tls:
          mode: Passthrough
        allowedRoutes:
          kinds:
          - kind: TLSRoute
      addresses:
      - type: NamedAddress
        value: IP_ADDRESS_NAME
    

    Substitua IP_ADDRESS_NAME pelo nome do endereço IP estático que você reservou.

    O bloco tls não tem o campo certificateRefs. No modo Passthrough, o certificado TLS reside nos pods de back-end, e não no balanceador de carga.

  2. Aplique o manifesto do gateway:

    kubectl apply -f store-gateway.yaml
    
  3. Verifique se o gateway está programado:

    kubectl get gateway store-tls
    

    O provisionamento do balanceador de carga leva alguns minutos. O resultado será assim:

    NAME        CLASS                              ADDRESS         PROGRAMMED   AGE
    store-tls   gke-l7-regional-external-managed   35.118.32.224   True         53s
    

Usar um gateway interno

Para manter o tráfego dentro da rede VPC, mude o valor do campo gatewayClassName para gke-l7-rilb e remova o campo addresses do manifesto do gateway. Em seguida, o GKE cria um balanceador de carga de rede de proxy interno regional e atribui um endereço IP interno da sub-rede do cluster. As etapas restantes nesta página não foram alteradas. Envie as solicitações de teste de uma instância do Compute Engine na mesma rede VPC, porque o endereço IP interno não pode ser acessado pela Internet.

Implantar aplicativos de amostra de TLS

Nesta seção, você vai implantar duas implantações do NGINX (store-v1 e store-german) que encerram o TLS na porta 8443. Cada implantação exibe um certificado TLS diferente e informa o nome do host SNI que recebeu, o que permite verificar se o roteamento ocorreu com base no SNI.

  1. Gere um certificado TLS autoassinado e uma chave privada para cada nome de host:

    openssl req -x509 -newkey rsa:2048 -nodes -sha256 -days 365 \
        -keyout store.key -out store.crt \
        -subj '/CN=store.example.com' \
        -addext 'subjectAltName=DNS:store.example.com'
    openssl req -x509 -newkey rsa:2048 -nodes -sha256 -days 365 \
        -keyout store-de.key -out store-de.crt \
        -subj '/CN=store-de.example.com' \
        -addext 'subjectAltName=DNS:store-de.example.com'
    

    Use certificados da sua autoridade certificadora na produção. Os certificados autoassinados mantêm este exemplo independente.

  2. Armazene cada certificado e chave em um secret do Kubernetes executando os seguintes comandos:

    kubectl create secret tls store-cert \
        --cert=store.crt --key=store.key
    kubectl create secret tls store-de-cert \
        --cert=store-de.crt --key=store-de.key
    
  3. Salve o seguinte manifesto como store-tls-app.yaml:

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: store-nginx
    data:
      default.conf: |
        server {
          listen 8443 ssl;
          ssl_certificate     /etc/nginx/ssl/tls.crt;
          ssl_certificate_key /etc/nginx/ssl/tls.key;
          default_type text/plain;
          # Report which Pod answered and which SNI name it received.
          return 200 "backend: $hostname\nsni: $ssl_server_name\n";
        }
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: store-v1
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: store-v1
      template:
        metadata:
          labels:
            app: store-v1
        spec:
          containers:
          - name: nginx
            image: nginx:1.27
            ports:
            - containerPort: 8443
            volumeMounts:
            - name: config
              mountPath: /etc/nginx/conf.d
            - name: cert
              mountPath: /etc/nginx/ssl
              readOnly: true
          volumes:
          - name: config
            configMap:
              name: store-nginx
          - name: cert
            secret:
              secretName: store-cert
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: store-v1
    spec:
      selector:
        app: store-v1
      ports:
      - port: 443
        targetPort: 8443
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: store-german
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: store-german
      template:
        metadata:
          labels:
            app: store-german
        spec:
          containers:
          - name: nginx
            image: nginx:1.27
            ports:
            - containerPort: 8443
            volumeMounts:
            - name: config
              mountPath: /etc/nginx/conf.d
            - name: cert
              mountPath: /etc/nginx/ssl
              readOnly: true
          volumes:
          - name: config
            configMap:
              name: store-nginx
          - name: cert
            secret:
              secretName: store-de-cert
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: store-german
    spec:
      selector:
        app: store-german
      ports:
      - port: 443
        targetPort: 8443
    

    Os serviços não precisam de um campo appProtocol. O GKE encaminha o tráfego de TLSRoute para o back-end como TCP, então o campo não tem efeito.

  4. Aplique o manifesto ao cluster:

    kubectl apply -f store-tls-app.yaml
    
  5. Verifique se os pods estão em execução:

    kubectl get pods -l 'app in (store-v1,store-german)'
    

    O resultado será o seguinte:

    NAME                            READY   STATUS    RESTARTS   AGE
    store-german-7d9f8c5b47-2xqkd   1/1     Running   0          41s
    store-german-7d9f8c5b47-h6tzn   1/1     Running   0          41s
    store-v1-6c4b9d8f65-kp8vr       1/1     Running   0          41s
    store-v1-6c4b9d8f65-wm2ls       1/1     Running   0          41s
    

Implantar recursos TLSRoute para roteamento baseado em SNI

Um recurso TLSRoute é anexado a um listener de gateway e roteia conexões que correspondem aos nomes de host para um único serviço de back-end.

  1. Salve o seguinte manifesto como store-tls-routes.yaml:

    kind: TLSRoute
    apiVersion: gateway.networking.k8s.io/v1
    metadata:
      name: store
    spec:
      parentRefs:
      - kind: Gateway
        name: store-tls
        sectionName: store
      hostnames:
      - "store.example.com"
      rules:
      - backendRefs:
        - name: store-v1
          port: 443
    ---
    kind: TLSRoute
    apiVersion: gateway.networking.k8s.io/v1
    metadata:
      name: store-german
    spec:
      parentRefs:
      - kind: Gateway
        name: store-tls
        sectionName: store-german
      hostnames:
      - "store-de.example.com"
      rules:
      - backendRefs:
        - name: store-german
          port: 443
    

    O campo sectionName seleciona o listener de destino no gateway. O campo port especifica a porta do Serviço (443), não a porta do contêiner.

  2. Aplique o manifesto TLSRoute:

    kubectl apply -f store-tls-routes.yaml
    
  3. Verifique se o controlador do gateway aceitou a rota:

    kubectl get tlsroute store -o yaml
    

    O campo status é semelhante ao seguinte:

    status:
      parents:
      - controllerName: networking.gke.io/gateway
        parentRef:
          name: store-tls
          sectionName: store
        conditions:
        - type: ResolvedRefs
          status: "True"
          reason: ResolvedRefs
        - type: Accepted
          status: "True"
          reason: Accepted
        - type: Reconciled
          status: "True"
          reason: ReconciliationSucceeded
    

    A condição Reconciled é uma condição de status específica do GKE que informa se o controlador de gateway criou os recursos Google Cloud subjacentes.

  4. Verifique se o listener do gateway aceitou a rota:

    kubectl get gateway store-tls -o yaml
    

    Cada entrada no campo status.listeners é semelhante ao seguinte:

    - name: store
      supportedKinds:
      - group: gateway.networking.k8s.io
        kind: TLSRoute
      attachedRoutes: 1
      conditions:
      - type: ResolvedRefs
        status: "True"
        reason: ResolvedRefs
      - type: Accepted
        status: "True"
        reason: Accepted
      - type: Programmed
        status: "True"
        reason: Programmed
    

Verificar o roteamento de tráfego

O GKE verifica a integridade de um back-end de passagem de TLS concluindo um handshake de TLS com ele. Os pods podem levar alguns minutos para passar na verificação de integridade inicial.

  1. Recupere o endereço IP do gateway:

    kubectl get gateway store-tls -o jsonpath='{.status.addresses[0].value}'
    
  2. Envie uma solicitação para cada nome de host, substituindo GATEWAY_IP pelo endereço IP da etapa anterior:

    curl --resolve store.example.com:443:GATEWAY_IP \
        --cacert store.crt https://store.example.com
    curl --resolve store-de.example.com:443:GATEWAY_IP \
        --cacert store-de.crt https://store-de.example.com
    

    Cada resposta nomeia o pod que respondeu e repete o nome do host SNI que o alcançou:

    backend: store-v1-6c4b9d8f65-kp8vr
    sni: store.example.com
    backend: store-german-7d9f8c5b47-2xqkd
    sni: store-de.example.com
    

    Como cada solicitação usou um arquivo de autoridade certificadora diferente e ambas foram bem-sucedidas, cada back-end disponibilizou o próprio certificado. O balanceador de carga encaminhou a conexão criptografada sem encerrá-la.

  3. Confirme se o roteamento acontece durante o handshake de TLS, antes que o cliente envie qualquer solicitação HTTP:

    openssl s_client -connect GATEWAY_IP:443 \
        -servername store-de.example.com </dev/null 2>/dev/null \
        | openssl x509 -noout -subject
    

    A saída mostra o certificado do back-end store-german:

    subject=CN=store-de.example.com
    

    Alterar apenas o valor da flag -servername altera o certificado retornado, confirmando que o balanceador de carga selecionou o back-end com base apenas no SNI.

  4. Envie uma solicitação com um nome de host SNI que não corresponda a nenhum listener:

    curl --resolve other.example.com:443:GATEWAY_IP \
        https://other.example.com
    

    A conexão é fechada porque nenhum listener na porta 443 corresponde ao nome do host SNI other.example.com.

Configurar a capacidade de conexão de back-end

Para os Serviços do GKE referenciados por recursos TLSRoute, o controlador de gateway do GKE configura um serviço de back-end TCP usando o modo de balanceamento CONNECTION e define o valor padrão do campo maxConnectionsPerEndpoint como 100,000,000 (1e8).

Como o controlador do gateway não pode determinar automaticamente o limite de conexão simultânea de um contêiner, use um recurso GCPBackendPolicy para substituir o valor padrão do campo maxConnectionsPerEndpoint (de 1 para 1,000,000,000). Para determinar o limite de conexão ideal para os pods de back-end, avalie o seguinte:

  • Limites de software: verifique a configuração do servidor ou do aplicativo, como a diretiva MaxRequestWorkers do Apache, as configurações worker_processes * worker_connections do NGINX, o atributo maxConnections do Tomcat ou os limites do pool de conexões do banco de dados.
  • Teste de carga: aumente gradualmente as conexões simultâneas em um pod isolado enquanto monitora os limites de CPU, memória, latência e soquete ou descritor de arquivo.

Aplicar uma GCPBackendPolicy personalizada

Para substituir o valor padrão do campo maxConnectionsPerEndpoint em um serviço de back-end TLSRoute, anexe um recurso GCPBackendPolicy com o campo spec.protocol definido como TCP e o campo balancingMode definido como CONNECTION:

  1. Salve o seguinte manifesto como backend-policy.yaml:

    apiVersion: networking.gke.io/v1
    kind: GCPBackendPolicy
    metadata:
      name: store-v1-backend-policy
    spec:
      protocol: TCP
      default:
        balancingMode: CONNECTION
        maxConnectionsPerEndpoint: 1000
      targetRef:
        group: ""
        kind: Service
        name: store-v1
    
  2. Aplique a política:

    kubectl apply -f backend-policy.yaml
    

Para mais informações sobre como configurar políticas de back-end, consulte Configurar recursos de gateway usando políticas.

Configurar verificações de integridade para passagem de TLS

Por padrão, para serviços de back-end associados a recursos TLSRoute de passagem de TLS, o controlador de gateway do GKE provisiona automaticamente uma verificação de integridade do tipo SSL.

Processar a ausência de extensões SNI de sondagens

Ao configurar verificações de integridade para back-ends de passagem de TLS, é preciso considerar como as sondagens de verificação de integridade do Google Cloud interagem com os endpoints de TLS.

Se os aplicativos de back-end exigirem um nome de host SNI válido para concluir um handshake de TLS, as verificações de integridade SSL padrão vão falhar. Para resolver isso, use uma das seguintes abordagens:

  • Configurar certificados de fallback: configure o servidor de back-end ou o pod para disponibilizar um certificado TLS de fallback padrão quando uma conexão TLS chegar sem uma extensão SNI.
  • Use verificações de integridade TCP com HealthCheckPolicy: anexe um recurso HealthCheckPolicy (com o campo config.type definido como TCP) ao Serviço para verificar a conectividade da porta TCP bruta e evitar o handshake de TLS.

Aplicar uma HealthCheckPolicy personalizada

Para configurar parâmetros personalizados de verificação de integridade ou mudar para a verificação de integridade TCP, use um recurso HealthCheckPolicy:

  1. Salve o seguinte manifesto como health-check-policy.yaml:

    apiVersion: networking.gke.io/v1
    kind: HealthCheckPolicy
    metadata:
      name: store-health-check
    spec:
      default:
        checkIntervalSec: 10
        timeoutSec: 5
        healthyThreshold: 2
        unhealthyThreshold: 3
        config:
          type: TCP
          tcpHealthCheck:
            port: 8443
      targetRef:
        group: ""
        kind: Service
        name: store-service
    
  2. Aplique a política:

    kubectl apply -f health-check-policy.yaml
    

Para mais informações sobre como configurar verificações de integridade, consulte Configurar recursos de gateway usando políticas.

Configurações avançadas

Nesta seção, descrevemos padrões de roteamento avançados, configurações de vários locatários e implantações de vários clusters compatíveis com gateways de passagem de TLS e recursos TLSRoute.

Correspondência de nome do host com caracteres curinga

Os recursos TLSRoute são compatíveis com a correspondência de prefixo de caracteres curinga para nomes de host e seguem regras de precedência determinísticas quando várias rotas correspondem ao mesmo tráfego de entrada.

Salve o manifesto a seguir para definir uma TLSRoute com caracteres curinga:

apiVersion: gateway.networking.k8s.io/v1
kind: TLSRoute
metadata:
  name: wildcard-tls-route
spec:
  parentRefs:
  - name: store-tls
    sectionName: store
  hostnames:
  - "*.example.com"
  rules:
  - backendRefs:
    - name: store-v1
      port: 443

Regras de precedência e resolução de conflitos

Quando vários recursos TLSRoute se anexam ao mesmo listener de gateway e reivindicam nomes de host sobrepostos ou idênticos, o controlador de gateway do GKE resolve conflitos usando a mesma especificidade de nome de host e regras de carimbo de data/hora de criação que outras rotas de gateway:

  • As correspondências exatas de nome do host (como store.example.com) têm precedência sobre as correspondências de caracteres curinga (como *.example.com), e as correspondências de caracteres curinga mais longas têm precedência sobre as correspondências de caracteres curinga mais amplas (como *.com).
  • Se dois ou mais recursos TLSRoute declararem exatamente o mesmo nome de host, a rota com o carimbo de data/hora de criação mais antigo (metadata.creationTimestamp) terá prioridade. Se os carimbos de data/hora de criação forem iguais, o identificador <namespace>/<name> lexicograficamente menor vai desempatar. O controlador de gateway não aceita rotas conflitantes, que informam uma condição Accepted: False com o motivo Conflicted.

Para mais informações sobre a precedência da rota, consulte Mesclagem, precedência e validação de rotas.

Roteamento entre namespaces com ReferenceGrant

Em ambientes multilocatários, uma equipe de plataforma centralizada pode gerenciar o gateway em um namespace de infraestrutura (como gateway-infra), enquanto as equipes de aplicativos gerenciam os recursos TLSRoute e Service em namespaces de desenvolvedor (como store-ns).

  1. No listener do gateway, permita rotas de todos os namespaces (ou namespaces selecionados):

    apiVersion: gateway.networking.k8s.io/v1
    kind: Gateway
    metadata:
      name: shared-tls-gateway
      namespace: gateway-infra
    spec:
      gatewayClassName: gke-l7-regional-external-managed
      listeners:
      - name: tls-passthrough
        protocol: TLS
        port: 443
        tls:
          mode: Passthrough
        allowedRoutes:
          namespaces:
            from: All
          kinds:
          - kind: TLSRoute
    
  2. No namespace do aplicativo (store-ns), crie um recurso ReferenceGrant que permita que o gateway no namespace gateway-infra faça referência ao recurso TLSRoute ou Service:

    apiVersion: gateway.networking.k8s.io/v1beta1
    kind: ReferenceGrant
    metadata:
      name: allow-gateway-infra
      namespace: store-ns
    spec:
      from:
      - group: gateway.networking.k8s.io
        kind: Gateway
        namespace: gateway-infra
      to:
      - group: ""
        kind: Service
    
  3. No namespace do aplicativo (store-ns), crie o recurso TLSRoute referenciando o gateway compartilhado:

    apiVersion: gateway.networking.k8s.io/v1
    kind: TLSRoute
    metadata:
      name: store-tls-route
      namespace: store-ns
    spec:
      parentRefs:
      - name: shared-tls-gateway
        namespace: gateway-infra
        sectionName: tls-passthrough
      hostnames:
      - "store.example.com"
      rules:
      - backendRefs:
        - name: store-service
          port: 443
    

Gateway de passagem de TLS de vários clusters

É possível implantar gateways de vários clusters com passagem de TLS em vários clusters do GKE em uma frota:

  1. Use uma GatewayClass de vários clusters compatível (gke-l7-regional-external-managed-mc, gke-l7-rilb-mc ou gke-l7-cross-regional-internal-managed-mc).
  2. Exporte o serviço de back-end para toda a frota usando um recurso ServiceExport.
  3. No recurso TLSRoute, faça referência ao back-end de vários clusters usando um recurso ServiceImport:

    apiVersion: gateway.networking.k8s.io/v1
    kind: TLSRoute
    metadata:
      name: mc-store-tls-route
    spec:
      parentRefs:
      - name: mc-tls-gateway
        sectionName: tls-passthrough
      hostnames:
      - "store.example.com"
      rules:
      - backendRefs:
        - group: net.gke.io
          kind: ServiceImport
          name: store-service
          port: 443
    

Vários endereços IP em gateways de vários clusters

Ao implantar gateways de vários clusters entre regiões (como ao usar o GatewayClass gke-l7-cross-regional-internal-managed-mc), é possível definir vários endereços IP no campo spec.addresses para expor um VIP interno em diferentes regiões.

Quando você configura vários endereços IP em um único gateway, o controlador do gateway do GKE traduz cada endereço IP em uma regra de encaminhamento separada. Ao mesmo tempo, o controlador faz referência a um proxy de destino compartilhado e reutiliza a mesma configuração de roteamento subjacente. O controlador não multiplica os recursos TLSRoute subjacentes pelo número de endereços IP, o que ajuda a evitar a duplicação de rotas e o esgotamento de cotas.

O exemplo a seguir mostra um gateway de vários clusters configurado com endereços IP temporários em duas regiões:

kind: Gateway
apiVersion: gateway.networking.k8s.io/v1
metadata:
  name: internal-cross-region-tls-gateway
spec:
  gatewayClassName: gke-l7-cross-regional-internal-managed-mc
  addresses:
  - type: networking.gke.io/ephemeral-ipv4-address/us-west1
    value: "us-west1"
  - type: networking.gke.io/ephemeral-ipv4-address/us-east1
    value: "us-east1"
  listeners:
  - name: tls-passthrough
    protocol: TLS
    port: 443
    tls:
      mode: Passthrough
    allowedRoutes:
      kinds:
      - kind: TLSRoute

Para mais informações sobre como implantar gateways internos de vários clusters, consulte Implantar um gateway interno de vários clusters.

Agrupamento de conexões HTTP

De acordo com a RFC 7540 (Seção 9.1.1), os navegadores da Web e os clientes HTTP/2 podem reutilizar uma conexão TLS estabelecida para várias solicitações se as duas condições a seguir forem atendidas:

  • Os nomes de host de destino são resolvidos para o mesmo endereço IP.
  • O certificado TLS apresentado pelo servidor é autoritativo para os dois nomes de host. Por exemplo, um certificado pode abranger vários nomes de host quando você usa certificados curinga, como *.example.com, ou nomes alternativos de assunto (SANs, na sigla em inglês) de vários domínios.

Como um balanceador de carga de proxy TCP da camada 4 não inspeciona os cabeçalhos de solicitação HTTP após o handshake de TLS inicial, ele encaminha as solicitações unidas pela conexão atual para o pod de back-end correspondente inicialmente.

Para evitar problemas de coalescência de conexão:

  • Use certificados TLS distintos e que não se sobreponham: não compartilhe certificados curinga ou identidades SAN comuns em diferentes serviços de back-end multiplexados por trás do mesmo endereço IP do gateway.
  • Retornar solicitação HTTP 421 com direcionamento incorreto: configure os servidores HTTPS de back-end para verificar o cabeçalho HTTP :authority (ou Host). Se o host solicitado não corresponder ao domínio esperado do servidor, retorne um código de status HTTP 421 Misdirected Request, solicitando que o cliente abra uma nova conexão.
  • Ativar o frame ORIGIN do HTTP/2: adote o suporte ao frame ORIGIN do RFC 8336 nos servidores de origem e declare explicitamente quais nomes de host são válidos para reutilização de conexão.

Limpar

Para evitar cobranças na conta do Google Cloud pelos recursos usados nesta página, exclua os recursos:

  1. Exclua os recursos TLSRoute:

    kubectl delete tlsroute store store-german
    
  2. Exclua o recurso de gateway:

    kubectl delete gateway store-tls
    
  3. Exclua os recursos de amostra de implantação, serviço e secret:

    kubectl delete -f store-tls-app.yaml
    kubectl delete secret store-cert store-de-cert
    

A seguir