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.
Para ver como os gateways são implantados no balanceamento de carga de vários clusters, consulte Como implantar gateways de vários clusters. Para entender as diferenças entre GatewayClasses, consulte Recursos do GatewayClass.
Requisitos do GKE Gateway Controller
- GKE versão 1.20 ou posterior
- A API Gateway é compatível apenas com clusters nativo de VPC (IP de alias).
- Se você estiver usando os recursos GatewayClasses internos, será necessário ativar uma sub-rede somente proxy.
- Os gateways de vários clusters e de cluster único são compatíveis com todas as regiões do Google Cloud.
Visualizar limitações e problemas conhecidos
Embora o suporte do GKE à API Gateway esteja em prévia, as seguintes limitações se aplicam:
- Os clusters do Autopilot não são suportados.
- O GatewayClasses do GKE é compatível com diferentes recursos, dependendo do balanceador de carga subjacente. Consulte os recursos do GatewayClass para saber mais sobre os diferentes recursos compatíveis com os GatewayClasses disponíveis.
- Os clusters do GKE que têm recursos
Gateway
ou Istio do ASM entrarão em conflito com os recursos do gateway do Kubernetes ao usar o kubectl. Talvez okubectl get gateway
não retorne os recursos do gateway do Istio ou do ASM conforme esperado. Para evitar conflitos de recursos da linha de comando com os gateways do Istio, consulte Gateways do Kubernetes e gateways do Istio - Os recursos do balanceador de carga do Google Cloud criados por gateways não são visíveis na IU do console do Google Cloud.
- A visualização dos recursos de gateway, HTTPRoute e ServiceExport na IU do GKE não é compatível.
- O uso do GKE Gateway Controller com o Kubernetes no Compute Engine (Kubernetes autogerenciado) não é compatível.
- Não é possível encerrar o tráfego TLS usando credenciais armazenadas em secrets do Kubernetes. No entanto, é possível referenciar recursos de certificado SSL do Google Cloud para encerrar o TLS.
- Não é possível configurar políticas de SSL ou de redirecionamentos HTTPS usando o recurso FrontendConfig.
- O recurso BackendConfig não é compatível com as GatewayClasses de vários clusters (
-mc
). No entanto, ele é compatível com gateways de cluster único. - Não é possível gerar automaticamente certificados SSL gerenciados pelo
Google. No entanto, um certificado SSL gerenciado pelo Google pode ser criado
e consultado manualmente usando a opção
networking.gke.io/pre-shared-certs
do TLS. - As configurações de capacidade de tráfego do serviço
max-rate-per-endpoint
,max-rate
ecapacity-scaler
não são compatíveis.
Instale os CRDs da API Gateway
Antes de usar os recursos do Gateway no GKE, instale as definições de recursos personalizados da API Gateway (CRDs, na sigla em inglês) no cluster. Instale os CRDs v1alpha1
e v1alpha2
na seguinte ordem:
Execute o seguinte comando no cluster do GKE em que você quer implantar os recursos de gateway:
kubectl apply -k "github.com/kubernetes-sigs/gateway-api/config/crd?ref=v0.4.3"
Esse comando instala os CRDs
v1alpha2
.A saída será assim:
customresourcedefinition.apiextensions.k8s.io/gatewayclasses.gateway.networking.k8s.io configured customresourcedefinition.apiextensions.k8s.io/gateways.gateway.networking.k8s.io configured customresourcedefinition.apiextensions.k8s.io/httproutes.gateway.networking.k8s.io configured customresourcedefinition.apiextensions.k8s.io/referencepolicies.gateway.networking.k8s.io configured customresourcedefinition.apiextensions.k8s.io/tcproutes.gateway.networking.k8s.io configured customresourcedefinition.apiextensions.k8s.io/tlsroutes.gateway.networking.k8s.io configured customresourcedefinition.apiextensions.k8s.io/udproutes.gateway.networking.k8s.io configured
Execute o seguinte comando no cluster do GKE em que você quer implantar os recursos de gateway:
kubectl apply -k "github.com/kubernetes-sigs/gateway-api/config/crd?ref=v0.3.0"
Esse comando instala os CRDs
v1alpha1
.A saída será assim:
customresourcedefinition.apiextensions.k8s.io/backendpolicies.networking.x-k8s.io created customresourcedefinition.apiextensions.k8s.io/gatewayclasses.networking.x-k8s.io created customresourcedefinition.apiextensions.k8s.io/gateways.networking.x-k8s.io created customresourcedefinition.apiextensions.k8s.io/httproutes.networking.x-k8s.io created customresourcedefinition.apiextensions.k8s.io/tcproutes.networking.x-k8s.io created customresourcedefinition.apiextensions.k8s.io/tlsroutes.networking.x-k8s.io created customresourcedefinition.apiextensions.k8s.io/udproutes.networking.x-k8s.io created
GatewayClasses do GKE
Depois que um cluster do GKE detecta a existência de CRDs da API Gateway, as seguintes GatewayClasses do GKE são instaladas automaticamente pelo GKE Gateway Controller. Pode levar alguns minutos para que o controlador reconheça os CRDs e instale o GatewayClasses.
Verifique se o GatewayClasses está disponível com o seguinte comando:
kubectl get gatewayclass
Esta saída confirma que as GatewayClasses do GKE estão prontas para uso no cluster:
NAME CONTROLLER gke-l7-rilb networking.gke.io/gateway gke-l7-gxlb networking.gke.io/gateway
Para entender os recursos de cada GatewayClass do GKE, consulte Recursos do GatewayClass.
Como configurar uma sub-rede somente proxy
Se você ainda não tiver feito isso, configure uma sub-rede somente proxy para cada região em que os gateways internos estão sendo implantados. Essa sub-rede é usada para fornecer endereços IP internos aos proxies do balanceador de carga.
É necessário criar uma sub-rede somente proxy antes de gerar gateways que gerenciam balanceadores de carga HTTP(S) internos. Cada região de uma VPC em que você usa balanceadores de carga HTTP(S) internos precisa ter uma sub-rede somente proxy.
O comando
gcloud compute networks subnets create
cria 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
.
Se o evento a seguir aparecer no gateway interno, não existe uma sub-rede apenas proxy nessa região. Para resolver esse problema, implante uma sub-rede apenas de proxy.
generic::invalid_argument: error ensuring load balancer: Insert: Invalid value for field 'resource.target': 'regions/us-west1/targetHttpProxies/gkegw-x5vt-default-internal-http-2jzr7e3xclhj'. A reserved and active subnetwork is required in the same region and VPC as the forwarding rule.
Como implantar um gateway interno
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.
Salve o seguinte manifesto de gateway em um arquivo chamado
gateway.yaml
:kind: Gateway apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: internal-http spec: gatewayClassName: gke-l7-rilb listeners: - name: http protocol: HTTP port: 80
Explicação dos 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.
Para implantar o gateway no cluster:
kubectl apply -f gateway.yaml
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
A saída será assim:
Name: internal-http Namespace: default ... 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.
Como implantar 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.
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.
Para validar a implantação do aplicativo:
kubectl get pod
O resultado será semelhante ao 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
Para confirmar que os serviços também foram implantados:
kubectl get service
A saída será semelhante à seguinte, e mostrará 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
Balanceamento de carga nativo de contêiner
O GKE Gateway Controller usa o balanceamento de carga nativo do
contêiner por
padrão. Isso significa que o tráfego com carga balanceada é enviado diretamente aos endereços IP do
pod. O balanceador de carga tem visibilidade direta dos endereços IP do pod para
que o tráfego não passe pelo balanceamento de carga do serviço do Kubernetes. Isso leva a um
tráfego mais eficiente, estável e compreensível. Os GatewayClasses gke-l7-*
não são compatíveis com o balanceamento de carga baseado em grupo de instâncias.
Os gateways do GKE não exigem nenhuma anotação especial especificada pelo usuário nos serviços. Qualquer serviço referenciado por um HTTPRoute é anotado automaticamente pelo GKE Gateway Controller com referências aos NEGs do serviço, como no exemplo a seguir:
Name: store-v1
Namespace: default
Annotations: cloud.google.com/neg: {"exposed_ports":{"8080":{}}}
cloud.google.com/neg-status: {"network_endpoint_groups":{"8080":"k8s1-cb368ccb-default-foo-v1-8080-f376ae25"},"zones":["us-central1-a"]}
...
Como implantar 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.
Salve o seguinte manifesto HTTPRoute em um arquivo chamado
store-route.yaml
:kind: HTTPRoute apiVersion: gateway.networking.k8s.io/v1alpha2 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
Implante o HTTPRoute no cluster:
kubectl apply -f store-route.yaml
A HTTPRoute store
está vinculada ao gateway internal-http
e, por isso, essas regras de roteamento são configuradas no balanceador de carga subjacente, como neste diagrama:
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çostore-v2
. - O tráfego restante para store.example.com vai para o serviço
store-v1
.
Vinculação de rotas
Os gateways usam a vinculação de rotas para corresponder rotas com gateways. Quando uma rota é vinculada a um gateway, o balanceador de carga ou proxy subjacente é programado com as regras de roteamento especificadas na rota. Os recursos Route e Gateway têm controles integrados para permitir ou restringir o modo como eles selecionam uns aos outros, o que determina a vinculação.
O HTTPRoute store
está vinculado ao gateway internal-http
usando a
propriedade parentsRefs
:
kind: Gateway
apiVersion: gateway.networking.k8s.io/v1alpha2
metadata:
name: internal-http
spec:
gatewayClassName: gke-l7-gxlb
listeners:
- name: https
protocol: HTTPS
port: 443
allowedRoutes:
kinds:
- kind: HTTPRoute
---
kind: HTTPRoute
apiVersion: gateway.networking.k8s.io/v1alpha2
metadata:
name: store
spec:
parentRefs:
- name: internal-http
Um HTTPRoute é anexado a um gateway específico por meio da propriedade parentsRef
.
Se o gateway estiver configurado para permitir o anexo desse tipo específico de
namespace e rota, a anexação será feita. Por padrão, o gateway confia em todas
as rotas do mesmo namespace. As rotas anexadas aos gateways configuram as
regras de roteamento do balanceador de carga subjacente. Uma rota pode ser anexada a vários
gateways, e eles também podem ter várias rotas anexadas.
Quando muitas rotas se anexam ao mesmo gateway, o GKE Gateway Controller mescla essas rotas em uma única configuração de roteamento para o balanceador de carga subjacente. É isso que permite que equipes diferentes compartilhem a mesma infraestrutura subjacente, enquanto cada uma controla a respectiva parte da configuração de roteamento de forma independente.
O GKE Gateway Controller implementa uma lógica rigorosa de mesclagem, precedência e validação de rota, que oferece mesclagem previsível entre rotas e impede que rotas inválidas interrompam a configuração do balanceador de carga subjacente. Para ver detalhes, consulte Mesclagem, precedência e validação de rotas.
Para instruções sobre como implantar um segundo HTTPRoute que também use o gateway http interno, consulte a seção Gateways compartilhados.
Como 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.
Verifique se o HTTPRoute de armazenamento foi aplicado. Os eventos são emitidos na rota quando ela é vinculada a um gateway.
kubectl describe httproute.gateway.networking.k8s.io store
A seção de eventos da saída inclui eventos como os mostrados a seguir se a HTTPRoute estiver vinculada ao gateway:
Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ADD 11m networking.gke.io/gateway default/store Normal ADD 11m multi-cluster-ingress-controller default/store
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.
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.church-243723.internal", "pod_name": "store-v1-84b47c7f58-pmgmk", "pod_name_emoji": "💇🏼♀️", "project_id": "church-243723", "timestamp": "2021-03-25T13:31:17", "zone": "us-central1-a" }
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.church-243723.internal", "pod_name": "store-german-5cb6474c55-lq5pl", "pod_name_emoji": "🧞♀", "project_id": "church-243723", "timestamp": "2021-03-25T13:35:37", "zone": "us-central1-a" }
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.church-243723.internal", "pod_name": "store-v2-5788476cbd-s9thb", "pod_name_emoji": "👩🏿🦰", "project_id": "church-243723", "timestamp": "2021-03-25T13:38:26", "zone": "us-central1-a" }
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.
Nas etapas anteriores, a equipe da loja implantou o aplicativo
store.example.com. Em seguida, a equipe independente do site implantou
o aplicativo dela, site.example.com, atrás do mesmo gateway
internal-http
usando o mesmo endereço IP.
Como implantar rotas em um gateway compartilhado
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.
Implantar o aplicativo de exemplo:
kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/main/gateway/gke-gateway-controller/app/site.yaml
Salve o seguinte manifesto HTTPRoute em um arquivo chamado
site-route.yaml
:Esse HTTPRoute
site
corresponde a todo o tráfego parasite.example.com
e o encaminha para o Serviçosite-v1
. Assim como o HTTPRoute do site, o HTTPRoute do site especifica o gatewayinternal-http
. O GKE Gateway Controller mescla esses HTTPRoutes em um único URLmap subjacente com rotas para site.example.com e store.example.com.kind: HTTPRoute apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: site spec: hostnames: - "site.example.com" rules: - backendRefs: - name: site-v1 port: 8080
Implantar o HTTPRoute no cluster:
kubectl apply -f site-route.yaml
Com ambos os HTTPRoutes implantados, a lógica de roteamento será semelhante ao diagrama a seguir. O tráfego para
site.example.com
precisa ir aos pods site-v1. O tráfego parastore.example.com
, aos pods store-v1, store-v2 ou store-german.Verifique se o HTTPRoute foi vinculado ao gateway
internal-http
:kubectl describe httproute.gateway.networking.k8s.io site
A saída será semelhante à seguinte se o HTTPRoute for vinculado ao gateway.
Status: Gateways: Conditions: Last Transition Time: 2021-04-19T16:13:46Z Message: Route admitted Observed Generation: 1 Reason: RouteAdmitted Status: True Type: Admitted Gateway Ref: Name: internal-http Namespace: default Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ADD 60m networking.gke.io/gateway foo/foo-route
Se a condição permitida para o gateway de http interno for
True
, isso indica que HTTPRoute/site foi vinculado ao http interno.Configurações inválidas, referências a serviços inexistentes do Kubernetes, rotulagem incorreta de gateways ou conflitos com outras rotas podem fazer com que a vinculação do HTTPRoute com um gateway seja rejeitada
Para detalhes sobre como interpretar o status das rotas, consulte a seção Status da rota.
Depois de confirmar que a rota de
site
foi vinculada, envie o tráfego ao gateway para confirmar se ele está sendo roteado corretamente. Envie o tráfego de uma VM na mesma rede VPC do gateway. Envie uma solicitação HTTP para site.example.com e store.example.com para validar as respostas:curl -H "host: site.example.com" VIP curl -H "host: store.example.com" VIP
Status da rota
Os recursos do HTTPRoute emitem condições e eventos para ajudar os usuários a entender o status da configuração aplicada. Juntos, eles indicam se uma rota foi vinculada a um ou mais gateways ou se foi rejeitada.
Condições do HTTPRoute
As condições do HTTPRoute indicam o status da vinculação de rota entre os gateways a que uma rota 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.
- "Admitted=True" indica que o HTTPRoute está vinculado a um gateway.
- "Admitted=False" indica que a vinculação do HTTPRoute ao gateway foi rejeitada.
Se não houver gateways listados na seção Gateway bindings
,
significa que os rótulos de rota e os seletores de rótulo de gateway provavelmente não correspondem. Isso
significa que a rota não está sendo selecionada por nenhum gateway e, portanto, a
configuração não é aplicada a lugar algum.
Eventos do HTTPRoute
Os eventos do HTTPRoute fornecem mais detalhes sobre o status da rota. Há algumas classes ou motivos pelos quais os eventos são agrupados:
- 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.
Como implantar um gateway externo
O exemplo a seguir mostra como implantar um gateway a ser usado para balanceamento
de carga externo de Internet. Ele demonstra como configurar o TLS para a
conexão do cliente proteger o gateway. Este exemplo usa o GatewayClass gke-l7-gxlb
,
mas esses conceitos TLS se aplicam igualmente a todos os
GatewayClasses gke-l7-*
.
O aplicativo implantado anteriormente é um pré-requisito deste exemplo. Se você ainda não tiver implantando, volte e implante esse aplicativo no cluster antes de continuar.
Os GatewayClasses gke-l7-gxlb
e gke-l7-gxlb-mc
implantam um
balanceador de carga HTTP(S) externo global para o tráfego voltado para a Internet. Eles têm funcionalidades
equivalentes, exceto que o gke-l7-gxlb-mc
também é compatível com casos de uso de
vários clusters, porque ele faz o balanceamento de carga de aplicativos em vários
clusters do GKE. Para uma comparação com outros GatewayClasses, consulte
Recursos do
GatewayClass.
TLS entre o cliente e o gateway
Um balanceador de carga HTTP(S) externo atua como um proxy entre seus clientes e o aplicativo. Se você quiser aceitar solicitações HTTPS dos seus clientes, o balanceador de carga precisará ter um certificado para provar a identidade dele aos clientes. Além disso, ele precisa ter uma chave privada para concluir o handshake HTTPS. O certificado e a chave privada são chamados de credenciais TLS.
A chave e o certificado TLS são armazenados como recursos de certificado SSL do Google Cloud.
O manifesto de gateway a seguir mostra como o TLS é configurado:
kind: Gateway
apiVersion: gateway.networking.k8s.io/v1alpha2
metadata:
name: external-http
spec:
gatewayClassName: gke-l7-gxlb
listeners:
- name: https
protocol: HTTPS
port: 443
allowedRoutes:
kinds:
- kind: HTTPRoute
tls:
mode: Terminate
options:
networking.gke.io/pre-shared-certs: store-example-com
Estes elementos são obrigatórios em um gateway que use TLS:
- A porta e o protocolo do listener do gateway precisam ser definidos como 443 e HTTPS.
- O campo
listener.tls.mode
precisa ser definido comoTerminate
. - As credenciais TLS precisam ser referenciadas no bloco
listeners.tls
.
O manifesto de exemplo faz referência a um recurso de certificado SSL chamado
store-example-com
. Todo o tráfego para a porta 443 desse gateway é encerrado
por esse certificado.
Como criar e armazenar um certificado TLS
Há muitas maneiras de gerar certificados TLS. Eles podem ser gerados manualmente na linha de comando, gerados com certificados gerenciados pelo Google ou internamente pelo sistema de infraestrutura de chave pública (ICP) de uma empresa. Neste exemplo, geramos manualmente um certificado autoassinado. Os certificados autoassinados geralmente não são usados para serviços públicos. Eles serão usados aqui porque demonstram estes conceitos com mais facilidade.
Siga a Etapa 1: criar uma chave privada e um certificado do guia de certificados SSL autogerenciados. Isso gera um certificado autoassinado e um par de chaves usando a linha de comando. Use a seguinte configuração do OpenSSL para criar um certificado autoassinado para store.example.com.
[req] default_bits = 2048 req_extensions = extension_requirements distinguished_name = dn_requirements prompt = no [extension_requirements] basicConstraints = CA:FALSE keyUsage = nonRepudiation, digitalSignature, keyEncipherment subjectAltName = @sans_list [dn_requirements] 0.organizationName = example commonName = store.example.com [sans_list] DNS.1 = store.example.com
Salve os arquivos de certificado e de chave como
cert.pem
ekey.pem
, respectivamente. Não prossiga para a etapa 2 das instruções sobre como usar certificados SSL autogerenciados.Salve as credenciais do certificado como um recurso de certificado SSL global:
gcloud compute ssl-certificates create store-example-com \ --certificate=cert.pem \ --private-key=key.pem \ --global
O nome do GatewayClass indica o tipo de recurso de certificado SSL que pode ser usado com os gateways dessa classe. O escopo e o local do certificado SSL precisam corresponder ao escopo e ao local do gateway que está usando o certificado. Por exemplo, um certificado SSL global não pode ser usado por um gateway regional.
A tabela a seguir mostra os requisitos de escopo e local para os recursos de certificado SSL usados pelos gateways:
GatewayClasses Escopo do certificado SSL Local do certificado SSL - gke-l7-rilb
- gke-l7-rilb-mc
Certificado SSL regional Precisa ser a mesma região do gateway - gke-l7-gxlb
- gke-l7-gxlb-mc
Certificado SSL global Global
Como implantar o gateway
Salve o seguinte manifesto de gateway, que usa o GatewayClass
gke-l7-gxlb
, comoexternal-gateway.yaml
:kind: Gateway apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: external-http spec: gatewayClassName: gke-l7-gxlb listeners: - name: https protocol: HTTPS port: 443 allowedRoutes: kinds: - kind: HTTPRoute tls: mode: Terminate options: networking.gke.io/pre-shared-certs: store-example-com
Esse manifesto de gateway externo difere do exemplo de gateway interno anterior de várias maneiras:
- Ele usa o GatewayClass
gke-l7-gxlb
, que implanta um balanceador de carga HTTP(S) externo. - A porta e o protocolo dele estão definidos como 443 e HTTPS.
- A seção
tls
do manifesto está configurada para encerrar o TLS usando um recurso de certificado SSL.
- Ele usa o GatewayClass
Implante este gateway no cluster do GKE:
kubectl apply -f external-gateway.yaml
Salve o seguinte manifesto HTTPRoute como
store-external-route.yaml
:kind: HTTPRoute apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: store-external labels: gateway: external-http spec: parentRefs: - name: external-http hostnames: - "store.example.com" rules: - backendRefs: - name: store-v1 port: 8080
Implantar o HTTPRoute no cluster:
kubectl apply -f store-external-route.yaml
Pode levar vários minutos para que o gateway
gke-l7-gxlb
seja totalmente implantado.Verifique se o gateway funciona enviando uma solicitação pela Internet.
Salve o arquivo cert.pem gerado anteriormente na máquina que você está usando para se conectar ao gateway. O gateway usa um certificado autoassinado, que é necessário para autenticar o gateway.
Consiga o endereço IP do balanceador de carga.
kubectl get gateways.gateway.networking.k8s.io external-http -o=jsonpath="{.status.addresses[0].value}"
O comando gera o endereço IP do balanceador de carga. Esse é um endereço IP público. Portanto, qualquer cliente com acesso à Internet pode se conectar a ele.
Use
curl
para acessar o domínio do gateway. Como o DNS não está configurado para esse domínio, use a opção--resolve
para instruir ocurl
a resolver o nome de domínio para o endereço IP do gateway:curl https://store.example.com --resolve store.example.com:443:VIP --cacert cert.pem -v
Substitua
VIP
pelo endereço IP do balanceador de carga.A saída detalhada de
curl
inclui um handshake de TLS bem-sucedido seguido por uma resposta do aplicativo, como a saída a seguir. Isso prova que o TLS está sendo encerrado corretamente no gateway e que o aplicativo está respondendo ao cliente com segurança.... * TLSv1.2 (OUT), TLS handshake, Client hello (1): * TLSv1.2 (IN), TLS handshake, Server hello (2): * TLSv1.2 (IN), TLS handshake, Certificate (11): * TLSv1.2 (IN), TLS handshake, Server key exchange (12): * TLSv1.2 (IN), TLS handshake, Server finished (14): * TLSv1.2 (OUT), TLS handshake, Client key exchange (16): * TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1): * TLSv1.2 (OUT), TLS handshake, Finished (20): * TLSv1.2 (IN), TLS change cipher, Change cipher spec (1): * TLSv1.2 (IN), TLS handshake, Finished (20): * SSL connection using TLSv1.2 / ECDHE-RSA-CHACHA20-POLY1305 * ALPN, server accepted to use h2 * Server certificate: * subject: O=example; CN=store.example.com * start date: Apr 19 15:54:50 2021 GMT * expire date: Apr 19 15:54:50 2022 GMT * common name: store.example.com (matched) * issuer: O=example; CN=store.example.com * SSL certificate verify ok. ... { "cluster_name": "gw", "host_header": "store.example.com", "metadata": "store-v1", "node_name": "gke-gw-default-pool-51ccbf30-yya8.c.agmsb-k8s.internal", "pod_name": "store-v1-84b47c7f58-tj5mn", "pod_name_emoji": "😍", "project_id": "agmsb-k8s", "timestamp": "2021-04-19T16:30:08", "zone": "us-west1-a" }
BackendConfig
com gateway
Os GatewayClasses gke-l7
são compatíveis com o recurso BackendConfig, que personalizam
configurações de back-end em nível por serviço. Isso requer a
anotação de serviço cloud.google.com/backend-config
para fazer referência ao
recurso BackendConfig. No exemplo a seguir, as configurações de verificação de
integridade e diminuição de conexão do balanceador de carga são personalizadas para o serviço store-v1.
apiVersion: v1
kind: Service
metadata:
name: store-v1
annotations:
cloud.google.com/backend-config: '{"default": "store-backendconfig"}'
spec:
selector:
app: store
version: v1
ports:
- port: 8080
targetPort: 8080
---
apiVersion: cloud.google.com/v1
kind: BackendConfig
metadata:
name: store-backendconfig
spec:
healthCheck:
checkIntervalSec: 15
port: 15020
type: HTTPS
requestPath: /healthz
connectionDraining:
drainingTimeoutSec: 60
Consulte Como configurar recursos do Ingress usando parâmetros BackendConfig para mais detalhes sobre como usar o recurso BackendConfig.
Endereçamento IP do gateway
Cada gateway tem um endereço IP em que ele escuta o tráfego. Se nenhum endereço for especificado no gateway, um endereço IP será automaticamente provisionado pelo gateway. Os endereços estáticos também podem ser pré-provisionados para que o ciclo de vida do endereço IP seja independente 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 |
---|---|
|
Endereços IP privados regionais do intervalo de sub-rede do nó do cluster do GKE |
|
Endereços IP públicos globais dos intervalos de IP públicos do Google |
É possível especificar um endereço IP de duas maneiras:
addresses.IPAddress
: permite especificar um endereço IP no momento da implantação do gateway. O endereço IP é configurável, em vez de provisionado automaticamente, mas tem o mesmo ciclo de vida do gateway e é liberado se o gateway for excluído.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 peloNamedAddress
. Reutilize o endereço IP estático mesmo que o gateway seja excluído.
É possível configurar um IPAddress
especificando o endereço IP no
campo addresses
do gateway implantado.
Implante o gateway interno a seguir e especifique
10.0.0.3
como o endereço IP estático:kind: Gateway apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: internal-http spec: gatewayClassName: gke-l7-rilb listeners: - name: http protocol: HTTP port: 80 allowedRoutes: kinds: - kind: HTTPRoute addresses: - type: IPAddress value: 10.0.0.3
Um
NamedAddress
exige que você provisione um IP estático fora da implantação do gateway. Isso exige duas etapas separadas:Crie um recurso de endereço IP estático. Nesse caso, um gateway interno e regional é implantado. Portanto, é necessário um endereço IP interno regional correspondente.
gcloud compute addresses create ADDRESS_NAME \ --region REGION \ --subnet SUBNET \ --project PROJECT_ID
Ao usar gateways regionais, substitua
PROJECT_ID
eREGION
pelo projeto e pela região em que o cluster do GKE está em execução. Os gateways externos globais não exigem uma especificação de região ou sub-rede.Implante seu gateway fazendo referência ao mesmo nome de recurso do endereço que o
NamedAddress
.kind: Gateway apiVersion: gateway.networking.k8s.io/v1alpha2 metadata: name: internal-http spec: gatewayClassName: gke-l7-rilb listeners: - name: http protocol: HTTP port: 80 addresses: - type: NamedAddress value: ADDRESS_NAME
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:
- Mesclagem de nomes do host: a correspondência de nome do host mais longa ou mais específica.
- Mesclagem de caminho: a correspondência de caminho mais longa ou mais específica.
- Mesclagem de cabeçalhos: o maior número de cabeçalhos HTTP correspondentes.
- 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:
- Mesclagem de rotas: todos os três HTTPRoutes se anexam com o mesmo
gateway
internal-http
para serem mesclados. - 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. - 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. - 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.
- 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/v1alpha2
metadata:
name: store-v1-route
labels:
gateway: internal-http
spec:
hostnames:
- "store.example.com"
rules:
- backendRefs:
- kind: Service
name: store-v1
port: 8080
---
kind: HTTPRoute
apiVersion: gateway.networking.k8s.io/v1alpha2
metadata:
name: store-v2-route
labels:
gateway: internal-http
spec:
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/v1alpha2
metadata:
name: store-german-route
labels:
gateway: internal-http
spec:
hostnames:
- "store.example.com"
rules:
- matches:
- path:
type: PathPrefix
value: /de
backendRefs:
- kind: Service
name: store-german
port: 8080
Back-end padrão de gateway
Todas os GatewayClasses gke-l7
têm um back-end padrão implícito que
retorna um HTTP 404 para tráfego sem correspondência. É possível personalizar o
back-end padrão com uma rota padrão explícita que envia tráfego sem correspondência a
um serviço fornecido pelo usuário. O HTTPRoute a seguir é um exemplo de como
personalizar o back-end padrão. Se aplicado, ele terá precedência sobre o
back-end padrão implícito:
kind: HTTPRoute
apiVersion: gateway.networking.k8s.io/v1alpha2
metadata:
name: custom-default-backend
labels:
gateway: my-gateway
spec:
rules:
- backendRefs:
- name: my-custom-default-backend-service
port: 8080
Esse HTTPRoute corresponde a todo o tráfego de um gateway específico. Só pode haver um HTTPRoute por gateway. Caso contrário, eles entrarão em conflito, e a ordem de precedência será aplicada.
Um back-end padrão explícito também é uma estratégia eficaz para evitar que alguém crie acidentalmente uma rota padrão que descarta o tráfego para um gateway. Como um HTTPRoute padrão explícito é o recurso mais antigo, ele sempre terá precedência sobre novos HTTPRoutes que tiverem regras de roteamento conflitantes.
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/v1alpha2 true Gateway
Para clusters do GKE 1.20 e posteriores, o controlador de gateway do GKE instala automaticamente o recurso gateway.networking.k8s.io/v1alpha2
nos clusters. 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
A seguir
- Saiba mais sobre o controlador de gateway.