Como implantar gateways


Nesta página, descrevemos como implantar recursos de gateway do Kubernetes no Google Kubernetes Engine (GKE). Explicamos como implantar um gateway particular e um gateway voltado para a Internet para expor aplicativos. Também demonstramos alguns dos conceitos do modelo de recursos da API Gateway.

No momento, a implantação de gateway para balanceamento de carga de vários clusters está disponível em Visualização. Para ver como os gateways são implantados no balanceamento de carga de vários clusters, consulte Como implantar gateways de vários clusters.

Antes de começar

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

  • Ativar a API Google Kubernetes Engine.
  • Ativar a API Google Kubernetes Engine
  • Se você quiser usar a Google Cloud CLI para essa tarefa, instale e, em seguida, inicialize a CLI gcloud.

Requisitos do GKE Gateway Controller

  • Para o Standard, o GKE versão 1.24 ou posterior.
  • Para o Autopilot, o GKE versão 1.26 ou posterior.
  • Google Cloud CLI versão 407.0.0 ou mais recente.
  • A API Gateway é compatível apenas com clusters nativos da VPC.
  • Se você estiver usando o GatewayClasses interno, 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
  • Não é possível usar as APIs v1alpha do gateway com o Istio. Para mais informações, consulte Gateways do Kubernetes e gateways do Istio.
  • A API Gateway não é compatível com a anotação networking.gke.io/app-protocols. Em vez disso, use o campo appProtocol .

Limitações e problemas conhecidoss

  • O GatewayClasses do GKE é compatível com diferentes recursos, dependendo do balanceador de carga que eles usam. Para saber mais sobre os diferentes recursos compatíveis com cada GatewayClass, consulte Recursos da GatewayClass.
  • O gateway do GKE se comporta de maneira diferente da entrada, porque não infere parâmetros de verificação de integridade. Se o Serviço não retornar 200 para solicitações a GET / ou se você tiver outras verificações de prontidão de pod ajustadas, será necessário configurar uma HealthCheckPolicy para seu serviço.
  • É possível visualizar os recursos do balanceador de carga que o GKE cria para gateways no Console do Google Cloud, mas esses recursos não fazem referência ao gateway ou ao cluster do GKE ao qual estão anexados.
  • Não é possível ver os recursos Gateway, HTTPRoute e Policy no Console do Google Cloud. É possível descobrir e gerenciar recursos do Gateway usando a API Kubernetes.
  • Não é possível gerar automaticamente um certificado SSL gerenciado pelo Google com gateways, mas é possível criar e referenciar manualmente um certificado SSL gerenciado pelo Google. Para mais informações, consulte Proteger um gateway.
  • Implante um gateway em um cluster do GKE no mesmo projeto de host ou serviço. Não é possível fazer implantações entre projetos.
  • Os recursos de gerenciamento de tráfego para gateways de cluster único geralmente estão disponíveis (GA) com o GatewayClass interno e o GatewayClass externo no GA. Os recursos de gerenciamento de tráfego não são compatíveis com a GatewayClass.
  • O HTTPRoute é o único tipo de rota suportado. TCPRoutes, UDPRoutes e TLSRoutes não são compatíveis. Para ver uma lista de campos compatíveis com o controlador do gateway do GKE, consulte Recursos do GatewayClass.

Os seguintes recursos de balanceamento de carga não são compatíveis com os gateways do GKE:

  • Cloud CDN
  • Identity-Aware Proxy
  • Cabeçalhos personalizados de solicitação e resposta

Ative a API Gateway no cluster

Antes de usar os recursos de gateway no GKE, seu cluster precisa ter a API Gateway ativada. É possível ativar a API Gateway em clusters novos ou atuais do GKE Autopilot e Standard.

Criar um novo cluster com a API Gateway ativada

O GKE oferece suporte à API Gateway em clusters do Autopilot a partir da versão 1.26 do GKE. Se você criar novos clusters do Autopilot no GKE 1.26 e em versões posteriores, a API Gateway ficará ativada por padrão. Para os clusters atuais no GKE versão 1.25 e anterior, a API Gateway ficará desativada por padrão.

Piloto automático

Crie um novo cluster do GKE Autopilot com a API Gateway ativada:

  gcloud container clusters create-auto CLUSTER_NAME --region=COMPUTE_REGION \
      --release-channel=RELEASE_CHANNEL \
      --cluster-version=VERSION

Substitua:

  • CLUSTER_NAME: o nome do cluster.
  • COMPUTE_REGION: a região do Compute Engine para o novo cluster. Para clusters zonais, use --zone=COMPUTE_ZONE.
  • RELEASE_CHANNEL: o nome do canal de lançamento.
  • VERSION: a versão do GKE, que precisa ser 1.26 ou posterior. Também é possível usar a sinalização --release-channel para selecionar um canal de lançamento. O canal de lançamento precisa ter a versão padrão 1.26 ou posterior.

Standard

Com o GKE Standard, a API Gateway é controlada pela sinalização --gateway-api. É possível usar o padrão de valor ao ativar e desativar ao desativar.

Crie um novo cluster nativo do VPC do GKE com a API Gateway ativada:

  gcloud container clusters create CLUSTER_NAME \
    --gateway-api=standard \
    --cluster-version=VERSION \
    --region=COMPUTE_REGION

Substitua:

  • RELEASE_CHANNEL: o nome do canal de lançamento.
  • CLUSTER_NAME: o nome do cluster.
  • VERSION: a versão do GKE, que precisa ser 1.18 ou posterior. Também é possível usar a sinalização --release-channel para selecionar um canal de lançamento. O canal de lançamento precisa ter a versão padrão 1.24 ou posterior.
  • COMPUTE_REGION: a região do Compute Engine para o novo cluster. Para clusters zonais, use --zone=COMPUTE_ZONE.

A sinalização --gateway-api=standard instrui o GKE a instalar os CRDs v1beta1 com o cluster.

Ativar a API Gateway em um cluster atual

Piloto automático

Para ativar a API Gateway em um cluster atual do GKE Autopilot, use o seguinte:

  gcloud container clusters upgrade CLUSTER_NAME --region=COMPUTE_REGION\
    --master \
    --release-channel=RELEASE_CHANNEL \
    --cluster-version=VERSION

Substitua:

  • RELEASE_CHANNEL: o nome do canal de lançamento.

  • VERSION: a versão do GKE, que precisa ser 1.26 ou posterior. Também é possível usar a sinalização --release-channel para selecionar um canal de lançamento. O canal de lançamento precisa ter a versão padrão 1.26 ou posterior.

  • CLUSTER_NAME: o nome do cluster existente.

  • COMPUTE_REGION: a região do Compute Engine do cluster. Para clusters zonais, use --zone=COMPUTE_ZONE.

Standard

Para ativar a API Gateway em um cluster existente do GKE nativo da VPC, use o seguinte:

   gcloud container clusters update CLUSTER_NAME \
    --gateway-api=standard \
    --region=COMPUTE_REGION

Substitua:

  • CLUSTER_NAME: o nome do cluster.
  • COMPUTE_REGION: a região do Compute Engine para o novo cluster. Para clusters zonais, use --zone=COMPUTE_ZONE.

A sinalização --gateway-api=standard instrui o GKE a instalar os CRDs v1beta1 com o cluster.

Verifique o cluster

Depois de criar ou fazer upgrade do cluster, o controlador de gateway do GKE instala automaticamente o GatewayClasses. Pode levar alguns minutos para que o controlador reconheça os CRDs e instale o GatewayClasses.

Confirme se os GatewayClasses estão instalados no cluster:

kubectl get gatewayclass

O resultado será assim:

NAME                             CONTROLLER                  ACCEPTED   AGE
gke-l7-global-external-managed   networking.gke.io/gateway   True       16h
gke-l7-gxlb                      networking.gke.io/gateway   True       16h
gke-l7-rilb                      networking.gke.io/gateway   True       16h

Para entender os recursos de cada GatewayClass do GKE, consulte Recursos do GatewayClass.

Implantar um gateway interno

Um gateway interno expõe aplicativos que só podem ser acessados pela VPC ou pelas redes conectadas a ela.

Configurar uma sub-rede somente proxy

É preciso configurar uma sub-rede somente proxy antes de criar um gateway que use um balanceador de carga HTTP(S) interno. Cada região de uma VPC em que você usa balanceadores de carga HTTP(S) internos precisa ter uma sub-rede somente proxy. Essa sub-rede fornece endereços IP internos para os proxies do balanceador de carga.

  1. Crie uma sub-rede somente proxy:

    gcloud compute networks subnets create SUBNET_NAME \
        --purpose=REGIONAL_MANAGED_PROXY \
        --role=ACTIVE \
        --region=REGION \
        --network=VPC_NETWORK_NAME \
        --range=CIDR_RANGE
    

    Substitua:

    • SUBNET_NAME: o nome da sub-rede somente proxy.
    • REGION: a região da sub-rede somente proxy.
    • VPC_NETWORK_NAME: o nome da rede VPC que contém a sub-rede.
    • CIDR_RANGE: o intervalo de endereços IP principal da sub-rede. Use uma máscara de sub-rede de até /26 de comprimento para que ao menos 64 endereços IP estejam disponíveis para os proxies na região. A máscara de sub-rede recomendada é /23.
  2. Verifique sua sub-rede somente proxy:

    gcloud compute networks subnets describe SUBNET_NAME \
        --region=REGION
    

    O resultado será assim:

    ...
    gatewayAddress: 10.1.1.1
    ipCidrRange: 10.1.1.0/24
    kind: compute#subnetwork
    name: proxy-subnet
    network: https://www.googleapis.com/compute/v1/projects/PROJECT_NAME/global/networks/default
    privateIpGoogleAccess: false
    privateIpv6GoogleAccess: DISABLE_GOOGLE_ACCESS
    purpose: REGIONAL_MANAGED_PROXY
    region: https://www.googleapis.com/compute/v1/projects/PROJECT_NAME/regions/REGION
    role: ACTIVE
    selfLink: https://www.googleapis.com/compute/v1/projects/PROJECT_NAME/regions/REGION/subnetworks/proxy-subnet
    state: READY
    

Criar um gateway

Um recurso de gateway representa um plano de dados que roteia o tráfego no Kubernetes. Um Gateway pode representar vários tipos diferentes de balanceamento de carga e roteamento, dependendo do GatewayClass que o deriva. Para saber mais sobre o recurso Gateway, consulte a descrição do recurso de gateway ou a especificação da API.

Nesse caso, o administrador do cluster do GKE quer criar um gateway que possa ser usado por equipes diferentes para expor aplicativos internamente. O administrador implanta o gateway e as equipes de aplicativo implantam as rotas de maneira independente e as anexam a esse gateway.

  1. Salve o seguinte manifesto de gateway em um arquivo chamado gateway.yaml:

    kind: Gateway
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: internal-http
    spec:
      gatewayClassName: gke-l7-rilb
      listeners:
      - name: http
        protocol: HTTP
        port: 80
    

    Esse manifesto inclui os seguintes campos:

    • gatewayClassName: gke-l7-rilb especifica o GatewayClass que deriva este gateway. gke-l7-rilb corresponde ao balanceador de carga HTTP(S) interno regional.
    • port: 80 especifica que o gateway expõe apenas a porta 80 para detectar o tráfego HTTP.
  2. Para implantar o gateway no cluster:

    kubectl apply -f gateway.yaml
    
  3. Verifique se o gateway foi implantado corretamente. Pode levar alguns minutos para implantar todos os recursos.

    kubectl describe gateways gateway.networking.k8s.io internal-http
    

    O resultado será assim:

    Name:         internal-http
    Namespace:    default
    Spec:
      Gateway Class Name:  gke-l7-rilb
      Listeners:
        Allowed Routes:
          Kinds:
            Group:  gateway.networking.k8s.io
            Kind:   HTTPRoute
          Namespaces:
            From:  Same
        Name:      http
        Port:      80
        Protocol:  HTTP
    Status:
      Addresses:
        Type:   IPAddress
        Value:  192.168.1.14
      Conditions:
        Last Transition Time:  1970-01-01T00:00:00Z
        Message:               Waiting for controller
        Reason:                NotReconciled
        Status:                False
        Type:                  Scheduled
    Events:
      Type    Reason  Age                From                       Message
      ----    ------  ----               ----                       -------
      Normal  ADD     92s                networking.gke.io/gateway  test/internal-http
      Normal  UPDATE  45s (x3 over 91s)  networking.gke.io/gateway  test/internal-http
      Normal  SYNC    45s                networking.gke.io/gateway  SYNC on test/internal-http was a success
    

    Neste ponto, um gateway implantado no cluster já provisionou um balanceador de carga e um endereço IP. No entanto, o gateway não tem rotas. Portanto, ele ainda não sabe como enviar tráfego para os back-ends. Sem as rotas, todo o tráfego vai para um back-end padrão, que retorna um HTTP 404. Em seguida, implante um aplicativo e rotas que informam ao gateway como acessar os back-ends do aplicativo.

Implante os aplicativos de demonstração

As equipes de aplicativos podem implantar os próprios aplicativos e rotas independentemente da implantação dos gateways. Em alguns casos, a equipe de aplicativos pode querer ser proprietária do gateway e implantá-lo por conta própria como um recurso dedicado aos aplicativos deles. Consulte Vinculação de rotas para ver diferentes modelos de propriedade de gateways e rotas. No entanto, neste exemplo, a equipe da loja implanta o aplicativo e um HTTPRoute associado para expor o aplicativo dela pelo gateway internal-http criado na seção anterior.

O recurso HTTPRoute tem muitos campos configuráveis para correspondência de tráfego. Para uma explicação dos campos do HTTPRoute, consulte a especificação da API.

  1. Para implantar o aplicativo da loja (store-v1, store-v2 e store-german) no cluster:

    kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/main/gateway/gke-gateway-controller/app/store.yaml
    

    Isso cria três implantações e três serviços, chamados store-v1, store-v2 e store-german.

  2. Para validar a implantação do aplicativo:

    kubectl get pod
    

    A saída será semelhante à seguinte depois que o aplicativo estiver em execução:

    NAME                        READY   STATUS    RESTARTS   AGE
    store-german-66dcb75977-5gr2n   1/1     Running   0          38s
    store-v1-65b47557df-jkjbm       1/1     Running   0          14m
    store-v2-6856f59f7f-sq889       1/1     Running   0          14m
    
  3. Para confirmar que os serviços também foram implantados:

    kubectl get service
    

    A saída mostra um serviço para cada implantação de loja:

    NAME           TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)    AGE
    store-german   ClusterIP   10.48.3.183   <none>        8080/TCP   4s
    store-v1       ClusterIP   10.48.2.224   <none>        8080/TCP   5s
    store-v2       ClusterIP   10.48.4.48    <none>        8080/TCP   5s
    

Implante o HTTPRoute

Os recursos de rota definem regras específicas do protocolo que mapeiam o tráfego de um gateway para os back-ends do Kubernetes. O recurso HTTPRoute faz a correspondência e filtragem de tráfego HTTP e HTTPS e é compatível com todas os GatewayClasses gke-l7.

Nesta seção, você verá como implantar um HTTPRoute, que programa o gateway com as regras de roteamento necessárias para alcançar o aplicativo da loja.

  1. Salve o seguinte manifesto HTTPRoute em um arquivo chamado store-route.yaml:

    kind: HTTPRoute
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: store
    spec:
      parentRefs:
      - kind: Gateway
        name: internal-http
      hostnames:
      - "store.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
    
  2. Implante o HTTPRoute no cluster:

    kubectl apply -f store-route.yaml
    

    O HTTPRoute store está vinculado ao gateway internal-http usando a propriedade parentRefs: Essas regras de roteamento são configuradas no balanceador de carga subjacente, como neste diagrama:

    As regras de roteamento configuradas pelo HTTPRoute da loja

    Essas regras de roteamento processarão o tráfego HTTP da seguinte maneira:

    • O tráfego para store.example.com/de vai para o Serviço store-german.
    • O tráfego para store.example.com com o cabeçalho HTTP "env: canary" vai para o Serviço store-v2.
    • O tráfego restante para store.example.com vai para o serviço store-v1.
  3. Verifique se o HTTPRoute foi implantado:

    kubectl describe httproute store
    

    O resultado será assim:

    Name:         store
    Namespace:    default
    Labels:       <none>
    Annotations:  <none>
    API Version:  gateway.networking.k8s.io/v1beta1
    Kind:         HTTPRoute
    <...>
    Spec:
      Hostnames:
        store.example.com
      Parent Refs:
        Group:  gateway.networking.k8s.io
        Kind:   Gateway
        Name:   internal-http
      Rules:
        Backend Refs:
          Group:
          Kind:    Service
          Name:    store-v1
          Port:    8080
          Weight:  1
        Matches:
          Path:
            Type:   PathPrefix
            Value:  /
        Backend Refs:
          Group:
          Kind:    Service
          Name:    store-v2
          Port:    8080
          Weight:  1
        Matches:
          Headers:
            Name:   env
            Type:   Exact
            Value:  canary
          Path:
            Type:   PathPrefix
            Value:  /
        Backend Refs:
          Group:
          Kind:    Service
          Name:    store-german
          Port:    8080
          Weight:  1
        Matches:
          Path:
            Type:   PathPrefix
            Value:  /de
    Status:
      Parents:
        Conditions:
          Last Transition Time:  2022-11-01T04:18:52Z
          Message:
          Reason:                Accepted
          Status:                True
          Type:                  Accepted
          Last Transition Time:  2022-11-01T04:18:52Z
          Message:
          Reason:                ReconciliationSucceeded
          Status:                True
          Type:                  Reconciled
        Controller Name:         networking.gke.io/gateway
        Parent Ref:
          Group:  gateway.networking.k8s.io
          Kind:   Gateway
          Name:   internal-http
    Events:
      Type    Reason  Age                From                   Message
      ----    ------  ----               ----                   -------
      Normal  ADD     24m                sc-gateway-controller  default/store
      Normal  SYNC    16m (x4 over 23m)  sc-gateway-controller  Bind of HTTPRoute "default/store" to ParentRef {Group:       gateway.networking.k8s.io",
      <...>
    
  4. Verifique se o HTTPRoute está vinculado ao Gateway:

    kubectl describe gateway
    

    O resultado será assim:

    Name:         internal-http
    Namespace:    default
    Labels:       <none>
    <...>
    Status:
      Addresses:
        Type:   IPAddress
        Value:  10.128.15.203
      Conditions:
        Last Transition Time:  2022-11-01T03:47:01Z
        Message:
        Reason:                Scheduled
        Status:                True
        Type:                  Scheduled
        Last Transition Time:  2022-11-01T03:47:01Z
        Message:
        Reason:                Ready
        Status:                True
        Type:                  Ready
      Listeners:
        Attached Routes:  1
        Conditions:
          Last Transition Time:  2022-11-01T03:47:01Z
          Message:
          Reason:                Ready
          Status:                True
          Type:                  Ready
        Name:                    http
        Supported Kinds:
          Group:  gateway.networking.k8s.io
          Kind:   HTTPRoute
          <...>
    

Enviar tráfego para o aplicativo

Agora que o gateway, a rota e o aplicativo estão implantados no cluster, é possível transmitir o tráfego para o aplicativo.

  1. Recuperar o endereço IP do gateway para enviar tráfego ao aplicativo:

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

    A saída é um endereço IP.

  2. Envie tráfego para esse endereço IP pelo shell em uma instância de máquina virtual (VM) conectada ao cluster. É possível criar uma VM para essa finalidade. Isso é necessário porque o gateway tem um endereço IP interno. Ele só é acessível na rede VPC. Como internal-http é um balanceador de carga regional, o shell do cliente precisa estar na mesma região que o cluster do GKE.

    Como você não é proprietário do nome do host example.com, defina o cabeçalho do host manualmente para que o roteamento do tráfego possa ser observado. Primeiro, solicite store.example.com:

    curl -H "host: store.example.com" VIP
    

    Substitua VIP pelo endereço IP da etapa anterior.

    A saída do app de demonstração mostra informações sobre o local em que o app está em execução:

    {
      "cluster_name": "gke1",
      "host_header": "store.example.com",
      "metadata": "store-v1",
      "node_name": "gke-gke1-pool-2-bd121936-5pfc.c.gateway-demo-243723.internal",
      "pod_name": "store-v1-84b47c7f58-pmgmk",
      "pod_name_emoji": "💇🏼‍♀️",
      "project_id": "gateway-demo-243723",
      "timestamp": "2022-10-25T13:31:17",
      "zone": "us-central1-a"
    }
    
  3. Teste a correspondência de caminho acessando a versão em alemão do serviço da loja em store.example.com/de:

    curl -H "host: store.example.com" VIP/de
    

    A resposta confirma que a solicitação foi exibida por um pod store-german:

    {
      "cluster_name": "gke1",
      "host_header": "store.example.com",
      "metadata": "Gutentag!", 
      "node_name": "gke-gke1-pool-2-bd121936-n3xn.c.gateway-demo-243723.internal",
      "pod_name": "store-german-5cb6474c55-lq5pl", 
      "pod_name_emoji": "🧞‍♀",
      "project_id": "gateway-demo-243723",
      "timestamp": "2022-10-25T13:35:37",
      "zone": "us-central1-a"
    }
    
  4. Por fim, use o cabeçalho HTTP env: canary para enviar o tráfego à versão canário do serviço de armazenamento:

    curl -H "host: store.example.com" -H "env: canary " VIP
    

    A resposta confirma que a solicitação foi exibida por um pod store-v2:

    {
      "cluster_name": "gke1",
      "host_header": "store.example.com",
      "metadata": "store-v2", 
      "node_name": "gke-gke1-pool-2-bd121936-5pfc.c.gateway-demo-243723.internal",
      "pod_name": "store-v2-5788476cbd-s9thb", 
      "pod_name_emoji": "🦰",
      "project_id": "gateway-demo-243723",
      "timestamp": "2022-10-25T13:38:26",
      "zone": "us-central1-a"
    }
    

Implantar um gateway externo

Um gateway externo expõe aplicativos que podem ser acessados pela Internet ou por redes fora da sua VPC. A implantação é semelhante a uma implantação do gateway interno, mas você precisa proteger seus aplicativos porque o gateway é acessível à Internet pública.

Como administrador da plataforma, talvez você precise expor seu aplicativo usando um Gateway externo. O exemplo a seguir mostra como expor um aplicativo de loja com vários certificados anexados ao gateway e agrupados em um mapa de certificados usando o Gerenciador de certificados e um HTTPRoute.

Criar um CertificateMap

O Google recomenda usar o Gerenciador de certificados para gerenciar os certificados quando você precisar de 15 ou mais certificados por gateway ou quando precisar usar certificados curinga.

Também é possível proteger o gateway externo usando secrets do Kubernetes ou certificados SSL gerenciados pelo Google. Para mais informações, consulte Segurança do gateway.

Nesta seção, você cria certificados usando o Gerenciador de certificados para proteger os aplicativos em execução no cluster.

  1. Ative a API Certificate Manager:

    gcloud services enable certificatemanager.googleapis.com
    
  2. Criar um CertificateMap

    gcloud beta certificate-manager maps create store-example-com-map
    
  3. Carregue suas chaves e seu certificado gerenciado pelo Google em um Certificado:

    gcloud beta certificate-manager certificates create store-example-com-cert \
        --certificate-file="CERTIFICATE_FILE" \
        --private-key-file="PRIVATE_KEY_FILE"
    

    Substitua:

    • CERTIFICATE_FILE: o nome do novo arquivo escolhido. O arquivo precisa ter a extensão .pem. Por exemplo, cert.pem.
    • PRIVATE_KEY_FILE: o nome do arquivo da chave privada.

    Para mais informações, consulte Como criar uma chave privada e um certificado.

  4. Crie um CertificateMapEntry que atribua o certificado ao mapa de certificados:

    gcloud beta certificate-manager maps entries create store-example-com-map-entry \
        --map=store-example-com-map \
        --hostname=store.example.com \
        --certificates=store-example-com-cert
    

Para saber como proteger um gateway usando outras fontes de certificados, como secrets do Kubernetes ou certificados SSL, consulte Proteger um gateway.

Criar um gateway

Um recurso de gateway representa um plano de dados que roteia o tráfego no Kubernetes. Um Gateway pode representar muitos tipos diferentes de balanceamento de carga e roteamento, dependendo da GatewayClass usada.

Para saber mais sobre o recurso Gateway, consulte a descrição do recurso de gateway ou a especificação da API.

Nesta seção, você vai criar um gateway. As equipes de aplicativos podem usar o gateway para expor seus aplicativos à Internet implantando as rotas de maneira independente e anexando-as com segurança ao gateway.

  1. Salve o seguinte manifesto em um arquivo chamado gateway.yaml:

    kind: Gateway
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: external-http
      annotations:
        networking.gke.io/certmap: store-example-com-map
    spec:
      gatewayClassName: gke-l7-global-external-managed
      listeners:
      - name: https
        protocol: HTTPS
        port: 443
    
    

    Este manifesto descreve um Gateway com os seguintes campos:

    • gatewayClassName: gke-l7-global-external-managed: especifica o GatewayClass para esse gateway. Esta classe de gateway usa um balanceador de carga HTTP(S) externo global.
    • protocol: HTTPS e port: 443: especifica que o gateway expõe a porta 443 para o tráfego HTTPS. Esses campos ativam o TLS.
    • networking.gke.io/certmap: store-example-com-map: especifica o nome do mapa de certificados no Gerenciador de certificados.

    Não há uma seção TLS porque o TLS está configurado com o Gerenciador de certificados usando a anotação networking.gke.io/certmap.

  2. Aplique o manifesto ao cluster:

    kubectl apply -f gateway.yaml
    

    Pode levar alguns minutos para o GKE implantar os recursos.

  3. Verifique se o gateway foi implantado:

    kubectl describe gateway
    

    O resultado será assim:

    Name:         external-http
    Namespace:    default
    Labels:       <none>
    ...
    Spec:
      Gateway Class Name:  gke-l7-global-external-managed
      Listeners:
        Allowed Routes:
          Namespaces:
            From:  Same
        Name:      https
        Port:      443
        Protocol:  HTTPS
        Tls:
          Certificate Refs:
            Group:
            Kind:   Secret
            Name:   store-example-com
          Mode:     Terminate
     ...
    

    Esta saída mostra que o gateway implantado no cluster tem um balanceador de carga e um endereço IP público. O gateway não tem rotas, o que significa que não pode enviar tráfego para back-ends. Sem as rotas, todo o tráfego vai para um back-end padrão, que retorna um HTTP 404. Na próxima seção, você implantará rotas, que instrui o gateway a enviar tráfego para back-ends.

Implante os aplicativos de demonstração

As equipes de aplicativos podem implantar os próprios aplicativos e rotas independentemente da implantação dos gateways. Em alguns casos, a equipe de aplicativos pode querer ser proprietária do gateway e implantá-lo por conta própria como um recurso dedicado aos aplicativos deles. Consulte Vinculação de rotas para ver diferentes modelos de propriedade de gateways e rotas. No entanto, neste exemplo, a equipe da loja implanta o aplicativo e um HTTPRoute associado para expor o aplicativo dela pelo gateway external-http criado na seção anterior.

Para mais informações sobre os campos de HTTPRoute, consulte a especificação da API.

  1. Implante o aplicativo de amostra no cluster:

    kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/main/gateway/gke-gateway-controller/app/store.yaml
    

    Esse aplicativo cria três implantações e três serviços, chamados store-v1, store-v2 e store-german.

  2. Para validar a implantação do aplicativo:

    kubectl get pod
    

    O resultado será assim:

    NAME                            READY   STATUS    RESTARTS   AGE
    store-german-66dcb75977-5gr2n   1/1     Running   0          38s
    store-v1-65b47557df-jkjbm       1/1     Running   0          14m
    store-v2-6856f59f7f-sq889       1/1     Running   0          14m
    
  3. Verifique se os serviços foram implantados:

    kubectl get service
    

    O resultado será assim:

    NAME           TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)    AGE
    store-german   ClusterIP   10.48.3.183   <none>        8080/TCP   4s
    store-v1       ClusterIP   10.48.2.224   <none>        8080/TCP   5s
    store-v2       ClusterIP   10.48.4.48    <none>        8080/TCP   5s
    

Criar um HTTPRoute

Os recursos de rota definem regras específicas do protocolo que mapeiam o tráfego de um gateway para os back-ends do Kubernetes. O recurso HTTPRoute faz a correspondência e filtragem de tráfego HTTP e HTTPS e é compatível com todas os GatewayClasses gke-l7-*.

Nesta seção, você implantará um HTTPRoute, que configura o Gateway com regras de roteamento necessárias para acessar o aplicativo de amostra.

  1. Salve o seguinte manifesto em um arquivo chamado store-route-external.yaml:

    kind: HTTPRoute
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: store-external
    spec:
      parentRefs:
      - kind: Gateway
        name: external-http
      hostnames:
      - "store.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
    

    Esse manifesto descreve um HTTPRoute que faz referência ao Gateway external-http.

  2. Aplique o manifesto ao cluster:

    kubectl apply -f store-route-external.yaml
    

    O HTTPRoute store está vinculado ao gateway external-http usando a propriedade parentRefs: Veja no diagrama a seguir as regras de roteamento configuradas no balanceador de carga subjacente:

    As regras de roteamento configuradas pelo HTTPRoute da loja

    As regras de roteamento processam tráfego HTTP da seguinte maneira:

    • Tráfego para store.example.com/de, trajeto para o serviço store-german.
    • O tráfego para store.example.com com o cabeçalho HTTP "env: canary" encaminha para o serviço store-v2.
    • O tráfego restante para os trajetos store.example.com é enviado para o serviço store-v1.
  3. Verifique se o HTTPRoute foi implantado:

    kubectl describe httproute store-external
    

    O resultado será assim:

    Name:         store-external
    Namespace:    default
    Labels:       <none>
    Annotations:  <none>
    API Version:  gateway.networking.k8s.io/v1beta1
    Kind:         HTTPRoute
    <...>
    Spec:
      Hostnames:
        store.example.com
      Parent Refs:
        Group:  gateway.networking.k8s.io
        Kind:   Gateway
        Name:   external-http
      Rules:
        Backend Refs:
          Group:
          Kind:    Service
          Name:    store-v1
          Port:    8080
          Weight:  1
        Matches:
          Path:
            Type:   PathPrefix
            Value:  /
        Backend Refs:
          Group:
          Kind:    Service
          Name:    store-v2
          Port:    8080
          Weight:  1
        Matches:
          Headers:
            Name:   env
            Type:   Exact
            Value:  canary
          Path:
            Type:   PathPrefix
            Value:  /
        Backend Refs:
          Group:
          Kind:    Service
          Name:    store-german
          Port:    8080
          Weight:  1
        Matches:
          Path:
            Type:   PathPrefix
            Value:  /de
    Status:
      Parents:
        Conditions:
          Last Transition Time:  2022-11-01T05:42:31Z
          Message:
          Reason:                Accepted
          Status:                True
          Type:                  Accepted
          Last Transition Time:  2022-11-01T05:43:18Z
          Message:
          Reason:                ReconciliationSucceeded
          Status:                True
          Type:                  Reconciled
        Controller Name:         networking.gke.io/gateway
        Parent Ref:
          Group:  gateway.networking.k8s.io
          Kind:   Gateway
          Name:   external-http
    Events:
      Type     Reason  Age    From                   Message
      ----     ------  ----   ----                   -------
      Normal   ADD     2m48s  sc-gateway-controller  default/store-external
      Normal  SYNC  61s (x3 over 2m27s)  sc-gateway-controller  Bind of HTTPRoute "default/store-external" to ParentRef Group:       "gateway.networking.k8s.io",
      ...
    
  4. Verifique se o HTTPRoute está vinculado ao Gateway:

    kubectl describe gateway external-http
    

    O resultado será assim:

    Name:         external-http
    Namespace:    default
    Labels:       <none>
    <...>
    Status:
      Addresses:
        Type:   IPAddress
        Value:  34.149.207.45
      Conditions:
        Last Transition Time:  2022-11-01T05:37:21Z
        Message:
        Reason:                Scheduled
        Status:                True
        Type:                  Scheduled
        Last Transition Time:  2022-11-01T05:43:18Z
        Message:
        Reason:                Ready
        Status:                True
        Type:                  Ready
      Listeners:
        Attached Routes:  1
        Conditions:
          Last Transition Time:  2022-11-01T05:43:18Z
          Message:
          Reason:                Ready
          Status:                True
          Type:                  Ready
        Name:                    https
        Supported Kinds:
          Group:  gateway.networking.k8s.io
          Kind:   HTTPRoute
          <...>
    

Enviar tráfego para o aplicativo

Agora que o gateway, a rota e o aplicativo estão implantados no cluster, é possível transmitir o tráfego para o aplicativo.

  1. Consiga o endereço IP do gateway:

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

    A saída é um endereço IP.

  2. Crie uma VM:

    gcloud cloud-shell ssh
    
  3. Enviar tráfego para o endereço IP do gateway a partir da VM. Defina o cabeçalho do host manualmente, porque você não é o proprietário do nome do host example.com.

    curl -H "host: store.example.com" https://GATEWAY_IP_ADDRESS --resolve store.example.com:443:GATEWAY_IP_ADDRESS --cacert cacert.pem -v
    

    Substitua GATEWAY_IP_ADDRESS pelo endereço IP do gateway da etapa anterior.

    A saída mostra informações do app de demonstração sobre o local em que ele está em execução:

    {
      "cluster_name": "gke1",
      "host_header": "store.example.com",
      "metadata": "store-v1",
      "node_name": "gke-gke1-pool-2-bd121936-5pfc.c.gateway-demo-243723.internal",
      "pod_name": "store-v1-84b47c7f58-pmgmk",
      "pod_name_emoji": "💇🏼‍♀️",
      "project_id": "gateway-demo-243723",
      "timestamp": "2022-09-25T13:31:17",
      "zone": "us-central1-a"
    }
    
  4. Teste a correspondência de caminho acessando a versão em alemão do serviço store da loja em store.example.com/de:

    curl -H "host: store.example.com" https://GATEWAY_IP_ADDRESS/de --resolve store.example.com:443:GATEWAY_IP_ADDRESS --cacert cacert.pem -v
    

    A resposta confirma que a solicitação foi exibida por um pod store-german:

    {
      "cluster_name": "gke1",
      "host_header": "store.example.com",
      "metadata": "Gutentag!",
      "node_name": "gke-gke1-pool-2-bd121936-n3xn.c.gateway-demo-243723.internal",
      "pod_name": "store-german-5cb6474c55-lq5pl",
      "pod_name_emoji": "🧞‍♀",
      "project_id": "gateway-demo-243723",
      "timestamp": "2022-09-25T13:35:37",
      "zone": "us-central1-a"
    }
    
  5. Envie o tráfego para a versão canário do serviço store usando o cabeçalho HTTP env: canary:

    curl -H "host: store.example.com" -H "env: canary " https://GATEWAY_IP_ADDRESS/de --resolve store.example.com:443:GATEWAY_IP_ADDRESS --cacert cacert.pem -v
    

    A resposta confirma que a solicitação foi exibida por um pod store-v2:

    {
      "cluster_name": "gke1",
      "host_header": "store.example.com",
      "metadata": "store-v2",
      "node_name": "gke-gke1-pool-2-bd121936-5pfc.c.gateway-demo-243723.internal",
      "pod_name": "store-v2-5788476cbd-s9thb",
      "pod_name_emoji": "👩🏿",
      "project_id": "gateway-demo-243723",
      "timestamp": "2022-09-25T13:38:26",
      "zone": "us-central1-a"
    }
    

Usar gateways compartilhados

As APIs Gateway usam recursos separados, gateways e recursos de rota para implantar balanceadores de carga e regras de roteamento. Isso é diferente do Ingress, que combina tudo em um recurso. Ao dividir a responsabilidade entre recursos, o gateway permite que o balanceador de carga e as regras de roteamento dele sejam implantados separadamente e implantados por diferentes usuários ou equipes. Isso permite que gateways se tornem gateways compartilhados que se anexam a muitas rotas diferentes, que podem ser gerenciadas por equipes independentes e de propriedade total delas, mesmo em namespaces diferentes.

Implantar rotas em um gateway compartilhado

Este exemplo se baseia no gateway internal-http implantado em Implantar um gateway interno.

Neste exemplo, a equipe do site implanta o aplicativo dela, os serviços e um HTTPRoute correspondente ao tráfego do gateway a esses serviços.

  1. Implantar o aplicativo de exemplo:

    kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/main/gateway/gke-gateway-controller/app/site.yaml
    
  2. Salve o seguinte manifesto em um arquivo chamado site-route-internal.yaml:

    kind: HTTPRoute
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: site-internal
    spec:
      parentRefs:
      - kind: Gateway
        name: internal-http
      hostnames:
      - "site.example.com"
      rules:
      - backendRefs:
        - name: site-v1
          port: 8080
    

    Esse manifesto descreve um HTTPRoute que corresponde a todo o tráfego de site.example.com e o encaminha ao serviço site-v1.

  3. Aplique o manifesto ao cluster:

    kubectl apply -f site-route-internal.yaml
    
  4. Verifique se o HTTPRoute está vinculado ao Gateway:

    kubectl describe httproute.gateway.networking.k8s.io site-internal
    

    O resultado será assim:

    Status:
      Parents:
        Conditions:
          Last Transition Time:  2023-01-09T15:05:43Z
          Message:
          Reason:                Accepted
          Status:                True
          Type:                  Accepted
          Last Transition Time:  2023-01-09T15:05:43Z
          Message:
          Reason:                ReconciliationSucceeded
          Status:                True
          Type:                  Reconciled
        Controller Name:         networking.gke.io/gateway
        Parent Ref:
          Group:  gateway.networking.k8s.io
          Kind:   Gateway
          Name:   internal-http
          ...
    

    Se a condição permitida do gateway for True, o HTTPRoute foi vinculado. Para saber mais sobre o campo "Status", consulte Status da rota.

  5. Verifique se o tráfego para o gateway é roteado corretamente:

    curl -H "host: site.example.com" GATEWAY_IP_ADDRESS
    curl -H "host: store.example.com" GATEWAY_IP_ADDRESS
    

    Substitua GATEWAY_IP_ADDRESS pelo endereço IP do gateway.

    Use uma máquina virtual (VM) na mesma VPC que o gateway.

    O resultado será assim:

    {
      "cluster_name": "CLUSTER_NAME",
      "host_header": "site.example.com",
      "metadata": "site-v1",
      "pod_name": "site-v1-5d64fc4d7d-fz6f6",
      "pod_name_emoji": "👩🏼‍🍳",
      "project_id": "PROJECT_ID",
      "timestamp": "2022-11-02T19:07:01",
      "zone": "us-central1-a"
    }
    ...
    {
      "cluster_name": "CLUSTER_NAME",
      "host_header": "store.example.com",
      "metadata": "store-v1",
      "pod_name": "store-v1-6d8d58d78-vz8pn",
      "pod_name_emoji": "🧝🏻‍♂️",
      "project_id": "PROJECT_ID",
      "timestamp": "2022-11-02T19:07:01",
      "zone": "us-central1-a"
    }
    

Configurar o back-end padrão do gateway

Todas as gke-l7-* GatewayClasses retornam HTTP 404 para tráfego sem correspondência. É possível configurar o back-end padrão usando uma rota padrão explícita que envia tráfego incomparável a um serviço fornecido pelo usuário.

O HTTPRoute a seguir é um exemplo de como personalizar o back-end padrão. Se você aplicar um HTTPRoute semelhante ao seguinte, ele terá precedência sobre o back-end padrão implícito:

kind: HTTPRoute
apiVersion: gateway.networking.k8s.io/v1beta1
metadata:
  name: custom-default-backend
spec:
  parentRefs:
  - kind: Gateway
    name: my-internal-gateway
  rules:
  - backendRefs:
    - name: my-custom-default-backend-service
      port: 8080

Esse HTTPRoute corresponde a todo o tráfego de um gateway específico. Só é possível ter uma regra para cada gateway. Caso contrário, as regras entrarão em conflito e a ordem de precedência será aplicada.

É possível usar um back-end padrão para evitar que alguém crie um back-end de rota padrão que direcione todo o tráfego do gateway. Um HTTPRoute explícito sempre tem precedência sobre novos HTTPRoutes com regras de roteamento conflitantes.

Configurar um endereço IP estático para um gateway

Cada gateway tem um endereço IP que usa para detectar o tráfego. Se você não especificar um endereço IP no Gateway, o controlador do Gateway fornecerá automaticamente um endereço IP. Também é possível criar um endereço IP estático para que ele exista, independentemente do ciclo de vida do gateway.

Depois que um gateway é implantado, o endereço IP dele é exibido no campo de status:

kind: Gateway
...
status:
  addresses:
    - value: 10.15.32.3

Dependendo da GatewayClass, o endereço IP é alocado das seguintes sub-redes:

GatewayClasses Pool de endereços IP padrão
  • gke-l7-rilb
  • gke-l7-rilb-rc
  • Endereços IP particulares regionais do intervalo de endereços IP do nó principal
  • gke-l7-gxlb
  • gke-l7-gxlb-mc
  • gke-l7-global-external-managed
  • gke-l7-global-external-managed-mc
  • Endereços IP públicos globais dos intervalos de IP públicos do Google

    O campo addresses.NamedAddress permite especificar um endereço IP independentemente do gateway. É possível criar um recurso de endereço IP estático antes da implantação do gateway, e o recurso é referenciado pelo NamedAddress. Reutilize o endereço IP estático mesmo que o gateway seja excluído.

    Usar um endereço IP nomeado

    Configure um endereço IP especificando um NamedAddress. É preciso provisionar um endereço IP estático antes de criar um gateway.

    1. Crie um recurso de endereço IP estático para um gateway global ou regional:

      gcloud compute addresses create IP_ADDRESS_NAME \
          --purpose=SHARED_LOADBALANCER_VIP \
          --region=REGION \
          --subnet=SUBNET \
          --project=PROJECT_ID
      

      Substitua:

      • IP_ADDRESS_NAME: o nome do novo endereço IP estático.
      • REGION: para gateways regionais, a região do Compute Engine em que o cluster está em execução. Essa sinalização não é necessária para gateways globais externos.
      • SUBNET: a sub-rede do endereço IP. Essa sinalização não é necessária para gateways globais externos.
      • PROJECT_ID: o projeto em que o cluster do GKE está em execução.
    2. Salve o seguinte manifesto em um arquivo chamado named-ip-gateway.yaml:

      kind: Gateway
      apiVersion: gateway.networking.k8s.io/v1beta1
      metadata:
        name: internal-http
      spec:
        gatewayClassName: gke-l7-rilb
        listeners:
        - name: http
          protocol: HTTP
          port: 80
        addresses:
        - type: NamedAddress
          value: IP_ADDRESS_NAME
      

      Esse manifesto descreve um gateway que faz referência ao endereço IP nomeado.

    3. Aplique o manifesto ao cluster:

      kubectl apply -f named-ip-gateway.yaml
      
    4. Verifique o endereço IP do gateway:

      kubectl describe gateway internal-http
      

      O resultado será assim:

      Name:         internal-http
      Namespace:    default
      Labels:       <none>
      ...
      Spec:
        Addresses:
          Type:              NamedAddress
          Value:             IP_ADDRESS_NAME
        Gateway Class Name:  gke-l7-rilb
        Listeners:
          Allowed Routes:
            Namespaces:
              From:  Same
          Name:      http
          Port:      80
          Protocol:  HTTP
      Status:
        Addresses:
          Type:   IPAddress
          Value:  10.15.32.103
      

    Configurar redirecionamentos de HTTP para HTTPS

    O Cloud Load Balancing oferece redirecionamento de HTTP para HTTPS. Um balanceador de carga HTTP(S) externo redireciona as solicitações HTTP não criptografadas para um balanceador de carga HTTPS que usa o mesmo endereço IP. Quando você cria um gateway com redirecionamentos de HTTP para HTTPS ativados, os dois balanceadores de carga são criados automaticamente. As solicitações para o endereço IP externo do Gateway na porta 80 são redirecionadas automaticamente para o mesmo endereço IP externo na porta 443.

    Por padrão, os redirecionamentos de HTTP para HTTPS não são definidos no gateway.

    Para redirecionar o tráfego HTTP para HTTPS, configure um gateway para processar o tráfego HTTP e HTTPS. Se você desativar o HTTP ou o HTTPS, o Gateway não redirecionará o tráfego.

    Os exemplos a seguir mostram como usar o redirecionamento de HTTP para HTTPS para garantir que o tráfego dos clientes que vai para os aplicativos da Web seja sempre redirecionado para uma página segura.

    Redirecionar o tráfego HTTP a partir do namespace do gateway

    No exemplo a seguir, o gateway é configurado para permitir Same (cookies SameSite) no listener HTTP, enquanto o listener HTTPS é aberto para todos os namespaces. Essa configuração pressupõe que o HTTPRoute da equipe de desenvolvimento não seja permitido no namespace gateway-infra.

    Essa configuração garante que nenhuma HTTPRoute extra seja vinculada ao listener HTTP do gateway. Isso exige que os HTTPRoutes da equipe do aplicativo não sejam permitidos no namespace gateway-infra.

    1. Crie o namespace gateway-infra do gateway. Salve o manifesto como gateway-namespace.yaml:

      apiVersion: v1
      Kind: Namespace
      metadata:
      name: gateway-infra
      
    2. Aplique o manifesto:

      kubectl apply -f gateway-namespace.yaml
      
    3. Crie um gateway usando o manifesto a seguir e salve-o como external-gateway.yaml:

      kind: Gateway
      apiVersion: gateway.networking.k8s.io/v1beta1
      metadata:
      name: external-http
      namespace: gateway-infra
      spec:
        gatewayClassName: gke-l7-global-external-managed
        listeners:
        - name: http
          protocol: HTTP
          port: 80
          allowedRoutes:
            kinds:
            - kind: HTTPRoute
            namespaces:
              from: Same
        - name: https
          protocol: HTTPS
          port: 443
          allowedRoutes:
            kinds:
            - kind: HTTPRoute
            namespaces:
              from: All
          tls:
            mode: Terminate
            options:
              networking.gke.io/pre-shared-certs: store-example-com
      
      • O campo namespaces na seção allowedRoutes restringe apenas o listener HTTP ao namespace gateway-infra do gateway.

      • O listener de HTTPS não inclui uma restrição nos namespaces permitidos. Portanto, todos os namespaces usam esse listener com um HTTPRoute.

    4. Aplique o manifesto:

      kubectl apply -f external-gateway.yaml
      
    5. Para forçar o redirecionamento HTTPS, crie um HTTPRoute padrão usando o manifesto a seguir e salve o manifesto como redirect-httproute.yaml:

      kind: HTTPRoute
      apiVersion: gateway.networking.k8s.io/v1beta1
      metadata:
        name: redirect
        namespace: gateway-infra
      spec:
        parentRefs:
        - namespace: gateway-infra
          name: external-http
          sectionName: http
        rules:
        - filters:
          - type: RequestRedirect
            requestRedirect:
              scheme: https
      
      • O campo sectionName instrui o gateway a corresponder apenas ao listener http. O filtro RequestRedirect força o redirecionamento para o listener https.

      Essa configuração redireciona todo o tráfego recebido na porta 80 do gateway para o listener na porta 443, aplicando uma comunicação segura entre o cliente e o balanceador de carga.

    6. Aplique o manifesto:

      kubectl apply -f redirect-httproute.yaml
      
    7. Crie um serviço para um aplicativo que usa o manifesto a seguir. Salve o manifesto como service-deployment.yaml.

      apiVersion: v1
      kind: Service
      metadata:
        name: store-v1
      spec:
        selector:
          app: store
          version: v1
        ports:
        - port: 8080
          targetPort: 8080
      
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: store-v1
      spec:
        replicas: 2
        selector:
          matchLabels:
            app: store
            version: v1
        template:
          metadata:
            labels:
              app: store
              version: v1
          spec:
            containers:
            - name: whereami
              image: us-docker.pkg.dev/google-samples/containers/gke/whereami:v1.2.19
              ports:
              - containerPort: 8080
              env:
              - name: METADATA
                value: "store-v1"
      
    8. Aplique o manifesto:

      kubectl apply -f service-deployment.yaml
      
    9. Crie um HTTPRoute para um aplicativo que só permita HTTPS. Salve o manifesto como httproute.yaml:

      kind: HTTPRoute
      apiVersion: gateway.networking.k8s.io/v1beta1
      metadata:
        name: store-external
        labels:
          gateway: external-http
      spec:
        parentRefs:
        - name: external-http
          namespace: gateway-infra
          sectionName: https
        hostnames:
        - "store.example.com"
        rules:
        - backendRefs:
          - name: store-v1
            port: 8080
      
    10. Aplique o manifesto:

      kubectl apply -f httproute.yaml
      

    Redirecionar o tráfego HTTP de um namespace de infraestrutura

    Em alguns casos, não há uma distinção clara entre as equipes de administrador de infraestrutura ou de plataforma e a prevenção do uso indevido do Gateway.

    O exemplo a seguir restringe ainda mais o uso do listener HTTP para impedir o uso não intencional de protocolos não seguros por parte das equipes do aplicativo. Este exemplo configura o gateway para permitir que um HTTPRoute use o listener HTTP apenas se a rota estiver em um determinado namespace (http-redirect) enquanto abre o listener HTTPS para todos os namespaces. É possível restringir o namespace http-redirect usando o RBAC do Kubernetes para que as equipes de aplicativo não possam criar um HTTPRoute nesse namespace por engano.

    1. Crie o namespace de um gateway. Salve o manifesto como gateway-namespace.yaml.

      apiVersion: v1
      kind: Namespace
      metadata:
        name: gateway-infra
      
    2. Aplique o manifesto:

      kubectl apply -f gateway-namespace.yaml
      
    3. Crie o namespace de um gateway e salve o manifesto como redirect-namespace.yaml:

      apiVersion: v1
      kind: Namespace
      metadata:
        name: http-redirect
        labels:
          otherInfra: httpToHttps
      
      • Identificadores específicos estão definidos para esse namespace.
    4. Aplique o manifesto:

      kubectl apply -f redirect-namespace.yaml
      
    5. Para restringir o uso do listener http, crie um gateway usando o manifesto a seguir. Salve o manifesto como external-gateway.yaml:

      kind: Gateway
      apiVersion: gateway.networking.k8s.io/v1beta1
      metadata:
        name: external-http
        namespace: gateway-infra
      spec:
        gatewayClassName: gke-l7-global-external-managed
        listeners:
        - name: http
          protocol: HTTP
          port: 80
          allowedRoutes:
            kinds:
            - kind: HTTPRoute
            namespaces:
              from: selector
              selector:
                matchLabels:
                  otherInfra: httpToHttps
        - name: https
          protocol: HTTPS
          port: 443
          allowedRoutes:
            kinds:
            - kind: HTTPRoute
            namespaces:
              from: All
          tls:
            mode: Terminate
            options:
              networking.gke.io/pre-shared-certs: store-example-com
        ```
      
      • O campo namespace especifica que o gateway é criado no namespace gateway-infra.

      • O campo namespaces na seção allowedRoutes restringe o listener HTTP ao namespace correspondente ao rótulo otherInfra: httpToHttps.

    6. Aplique o manifesto:

      kubectl apply -f external-gateway.yaml
      
    7. Para forçar o redirecionamento HTTPS, crie um HTTPRoute padrão usando o seguinte manifesto. Salve o manifesto como http-redirect.yaml:

      kind: HTTPRoute
      apiVersion: gateway.networking.k8s.io/v1beta1
      metadata:
        name: redirect
        namespace: http-redirect
      spec:
        parentRefs:
        - namespace: gateway-infra
          name: external-http
          sectionName: http
        rules:
        - filters:
          - type: RequestRedirect
            requestRedirect:
              scheme: https
      
      • O campo sectionName instrui o gateway a corresponder apenas ao listener http. O filtro RequestRedirect força o redirecionamento para o listener https.
    8. Aplique o manifesto:

      kubectl apply -f http-redirect.yaml
      
    9. Crie um serviço para um aplicativo que usa o manifesto a seguir. Salve o manifesto como service-deployment.yaml.

      apiVersion: v1
      kind: Service
      metadata:
        name: store-v1
      spec:
        selector:
          app: store
          version: v1
        ports:
        - port: 8080
          targetPort: 8080
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: store-v1
      spec:
        replicas: 2
        selector:
          matchLabels:
            app: store
            version: v1
        template:
          metadata:
            labels:
              app: store
              version: v1
          spec:
            containers:
            - name: whereami
              image: us-docker.pkg.dev/google-samples/containers/gke/whereami:v1.2.19
              ports:
              - containerPort: 8080
              env:
              - name: METADATA
                value: "store-v1"
      
    10. Aplique o manifesto:

      kubectl apply -f service-deployment.yaml
      
    11. Crie um HTTPRoute para um aplicativo que só permita HTTPS usando o manifesto a seguir. Salve o manifesto como http-route.yaml:

      kind: HTTPRoute
      apiVersion: gateway.networking.k8s.io/v1beta1
      metadata:
        name: store-external
        labels:
          gateway: external-http
      spec:
        parentRefs:
        - name: external-http
          namespace: gateway-infra
          sectionName: https
        hostnames:
        - "store.example.com"
        rules:
        - backendRefs:
          - name: store-v1
            port: 8080
      
    12. Aplique o manifesto:

      kubectl apply -f http-route.yaml
      

    Status da rota

    Os recursos de HTTPRoute emitem condições e eventos para ajudar os usuários a entender se um HTTPRoute foi vinculado a um ou mais Gateways ou se ele foi rejeitado.

    Condições do HTTPRoute

    As condições do HTTPRoute indicam o status da Rota e dos Gateways aos quais ela está vinculada. Como uma rota pode ser vinculada a vários gateways, mostraremos uma lista de gateways e as condições individuais entre a rota e cada gateway.

    • Accepted=True indica que o HTTPRoute está vinculado a um Gateway.
    • Accepted=False indica que a vinculação do HTTPRoute foi rejeitada com esse gateway.

    Se não houver gateways listados no título Gateway bindings, os rótulos HTTPRoute e seletores de rótulos de gateway podem não corresponder. Isso pode ocorrer se a rota não está sendo selecionada por nenhum gateway.

    Eventos do HTTPRoute

    Os eventos HTTPRoute fornecem detalhes sobre o status da HTTPRoute. Os eventos são agrupados pelos seguintes motivos:

    • Eventos ADD são acionados por um recurso que está sendo adicionado.
    • Os eventos UPDATE são acionados por um recurso que está sendo atualizado.
    • Os eventos SYNC são acionados pela reconciliação periódica.

    Combinação, precedência e validação de rotas

    Precedência da rota

    A API Gateway define regras de precedência rígidas que definem como o tráfego é correspondido por rotas que tenham regras de roteamento sobrepostas. A precedência entre dois HTTPRoutes sobrepostos é a seguinte:

    1. Mesclagem de nomes do host: a correspondência de nome do host mais longa ou mais específica.
    2. Mesclagem de caminho: a correspondência de caminho mais longa ou mais específica.
    3. Mesclagem de cabeçalhos: o maior número de cabeçalhos HTTP correspondentes.
    4. Conflito: se as três regras anteriores não estabelecerem precedência, a precedência irá para o recurso HTTPRoute com o carimbo de data/hora mais antigo.

    Mesclagem de rotas

    Para GatewayClasses gke-l7, todos os HTTPRoutes de um determinado gateway são mesclados no mesmo recurso de mapa de URL. A maneira como os HTTPRoutes são mesclados depende do tipo de sobreposição entre HTTPRoutes. O HTTPRoute do exemplo anterior pode ser dividido em três HTTPRoutes separados para ilustrar a mesclagem e a precedência de rotas:

    1. Mesclagem de rotas: todas as três HTTPRoutes são anexadas com o mesmo gateway de internal-http para que sejam mescladas.
    2. Mesclagem de nome do host: todas as três rotas correspondem a store.example.com. Portanto, as regras de nome de host delas são mescladas.
    3. Mesclagem de caminhos: store-german-route tem um caminho /de mais específico. Portanto, ele não é mesclado. As rotas store-v1-route e store-v2-route também correspondem ao mesmo caminho /*, então são mesclados ao caminho.
    4. Mesclagem de cabeçalho: store-v2-route tem um conjunto mais específico de correspondências de cabeçalho HTTP do que store-v1-route e, portanto, não são combinados.
    5. Conflito: como as rotas podem ser mescladas no nome do host, no caminho e nos cabeçalhos, não há conflitos, e todas as regras de roteamento serão aplicadas ao tráfego.

    O único HTTPRoute usado no exemplo anterior é equivalente a estas três rotas separadas:

    kind: HTTPRoute
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: store-v1-route
    spec:
      parentRefs:
      - kind: Gateway
        name: internal-http
      hostnames:
      - "store.example.com"
      rules:
      - backendRefs:
        - kind: Service
          name: store-v1
          port: 8080
    ---
    kind: HTTPRoute
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: store-v2-route
    spec:
      parentRefs:
      - kind: Gateway
        name: internal-http
      hostnames:
      - "store.example.com"
      rules:
      - matches:
        - headers:
          - type: Exact
            name: env
            value: canary
        backendRefs:
        - kind: Service
          name: store-v2
          port: 8080
    ---
    kind: HTTPRoute
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: store-german-route
    spec:
      parentRefs:
      - kind: Gateway
        name: internal-http
      hostnames:
      - "store.example.com"
      rules:
      - matches:
        - path:
            type: PathPrefix
            value: /de
        backendRefs:
        - kind: Service
          name: store-german
          port: 8080
    

    Gateways do Kubernetes e gateways do Istio

    Observe que a API Gateway do Kubernetes e a API do Istio têm um recurso chamado Gateway. Eles executam funções semelhantes, mas não são a mesma funcionalidade. Se você estiver usando o Istio e a API Gateway no mesmo cluster do Kubernetes, esses nomes se sobreporão ao usar o kubectl na linha de comando. kubectl get gateway pode retornar os recursos do gateway do Kubernetes, e não os recursos do gateway do Istio, ou vice-versa.

    $ kubectl api-resources
    NAME       SHORTNAMES   APIGROUP                       NAMESPACED   KIND
    gateways   gw           networking.istio.io/v1beta1    true         Gateway
    gateways   gtw          networking.k8s.io/v1beta1      true         Gateway
    

    Se estiver usando o Istio e fizer upgrade para o GKE 1.20 e posterior, é recomendável começar a usar o nome curto do recurso do gateway ou especificar o grupo da API. A abreviação de um gateway do Kubernetes é gtw e a abreviação de um gateway do Istio é gw. Os comandos a seguir retornam os recursos do gateway do Kubernetes e do Istio, respectivamente.

    # Kubernetes Gateway
    $ kubectl get gtw
    NAME                        CLASS
    multi-cluster-gateway       gke-l7-gxlb-mc
    
    $ kubectl get gateway.networking.x-k8s.io
    NAME                        CLASS
    multi-cluster-gateway       gke-l7-gxlb-mc
    
    # Istio Gateway
    $ kubectl get gw
    NAME               AGE
    bookinfo-gateway   64m
    
    $ kubectl get gateway.networking.istio.io
    NAME               AGE
    bookinfo-gateway   64m
    

    Solução de problemas

    Sub-rede apenas proxy ausente para o gateway interno

    O seguinte problema pode ocorrer ao criar um gateway interno:

    generic::invalid_argument: error ensuring load balancer: Insert: Invalid value for field 'resource.target': 'regions/[REGION_NAME]/targetHttpProxies/gkegw-x5vt-default-internal-http-[ID]'. A reserved and active subnetwork is required in the same region and VPC as the forwarding rule.
    

    Para resolver esse problema, configure uma sub-rede apenas proxy.

    A seguir