Este documento orienta você em um exemplo prático para implantar um gateway externo de vários clusters e rotear o tráfego da Internet para um aplicativo executado em dois clusters diferentes do GKE.
Os gateways de vários clusters oferecem uma maneira eficiente de gerenciar o tráfego de serviços implantados em vários clusters do GKE. Ao usar a infraestrutura global de balanceamento de carga do Google, você pode criar um único ponto de entrada para seus aplicativos, o que simplifica o gerenciamento e melhora a confiabilidade.Neste tutorial, você usa um aplicativo store de amostra para simular um cenário real em que um serviço de compras on-line é de propriedade e operado por equipes separadas e implantado em uma frota de clusters compartilhados do GKE.
Antes de começar
Os gateways de vários clusters precisam de preparação do ambiente para serem implantados. Antes de continuar, siga as etapas em Preparar o ambiente para gateways de vários clusters:
Implante cluster do GKE.
Registre os clusters em uma frota, se ainda não tiver feito isso.
Ative os controladores do gateway de vários clusters e do serviço de vários clusters.
Por fim, analise as limitações e problemas conhecidos do GKE Gateway controller antes de usá-lo no seu ambiente.
Gateway externo multicluster e multirregional
Neste tutorial, você vai criar um gateway externo de vários clusters que veicula tráfego externo em um aplicativo executado em dois clusters do GKE.
Nas etapas a seguir, você:
- Implante o aplicativo
storede amostra nos clustersgke-west-1egke-east-1. - Configure serviços em cada cluster a ser exportado para sua frota (serviços de vários clusters).
- Implante um gateway de vários clusters externos e uma HTTPRoute no cluster de configuração (
gke-west-1).
Depois que os recursos de aplicativo e de gateway forem implantados, será possível controlar o tráfego nos dois clusters do GKE usando o roteamento baseado em caminho:
- As solicitações para
/westsão roteadas para podsstoreno clustergke-west-1. - As solicitações para
/eastsão roteadas para podsstoreno clustergke-east-1. - As solicitações para qualquer outro caminho são roteadas para qualquer cluster, de acordo com a integridade, a capacidade e a proximidade do cliente solicitante.
Como implantar o aplicativo de demonstração
Crie a implantação e o namespace
storeem todos os três clusters que foram implantados em Preparar o ambiente para gateways de vários clusters:kubectl apply --context gke-west-1 -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/main/gateway/gke-gateway-controller/multi-cluster-gateway/store.yaml kubectl apply --context gke-west-2 -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/main/gateway/gke-gateway-controller/multi-cluster-gateway/store.yaml kubectl apply --context gke-east-1 -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/main/gateway/gke-gateway-controller/multi-cluster-gateway/store.yamlEle implanta os seguintes recursos em cada cluster:
namespace/store created deployment.apps/store createdTodos os exemplos nesta página usam o aplicativo implantado nesta etapa. Verifique se o app está implantado nos três clusters antes de tentar qualquer uma das etapas restantes. Neste exemplo, usamos apenas os clusters
gke-west-1egke-east-1, e ogke-west-2é usado em outro exemplo.
Serviços de vários clusters
Os serviços são como os pods são expostos aos clientes. Como o controlador de gateway do GKE usa balanceamento de carga nativo de contêiner, ele não usa o balanceamento de carga ClusterIP ou Kubernetes para alcançar pods. O tráfego é enviado diretamente do balanceador de carga para os endereços IP do pod. No entanto, os serviços ainda desempenham um papel crítico como um identificador lógico para o agrupamento de pods.
Serviços de vários clusters (MCS, na sigla em inglês) é um padrão de API para serviços que abrange clusters e o controlador do GKE dele fornece descoberta de serviços em clusters do GKE. O controlador de gateway de vários clusters usa recursos da API MCS para agrupar pods em um serviço endereçável ou que abrange vários clientes.
A API de serviços de vários clusters define os seguintes recursos personalizados:
- ServiceExports mapeia para um serviço do Kubernetes, exportando os endpoints desse serviço para todos os clusters registrados na frota. Quando um Serviço tem um ServiceExport correspondente, ele pode ser endereçado por um gateway de vários clusters.
- Os ServiceImports são gerados automaticamente pelo controlador do Serviço de vários clusters. O ServiceExport e o ServiceImport vêm em pares. Se houver uma ServiceExport na frota, uma ServiceImport correspondente será criada para permitir que o Service mapeado para a ServiceExport seja acessado entre os clusters.
A exportação de Serviços funciona da seguinte forma. Há um serviço de armazenamento em
gke-west-1, que seleciona um grupo de pods nesse cluster. Uma ServiceExport é
criada no cluster, o que permite que os pods em gke-west-1 fiquem acessíveis para os outros clusters na frota. A ServiceExport é mapeada e expõe
Serviços com o mesmo nome e namespace que o recurso ServiceExport.
apiVersion: v1
kind: Service
metadata:
name: store
namespace: store
spec:
selector:
app: store
ports:
- port: 8080
targetPort: 8080
---
kind: ServiceExport
apiVersion: net.gke.io/v1
metadata:
name: store
namespace: store
O diagrama a seguir mostra o que acontece depois que um ServiceExport é implantado. Se houver um
par de ServiceExport e Service, o controlador de serviço de vários clusters implantará
um ServiceImport correspondente em cada cluster do GKE
na frota. O ServiceImport é a representação local do serviço store
em cada cluster. Isso permite que o pod client em gke-east-1 use ClusterIP ou
serviços headless para alcançar os pods store em gke-west-1. Quando usados dessa maneira,
os serviços de vários clusters fornecem balanceamento de carga de leste-oeste entre clusters sem
exigir um serviço LoadBalancer interno.
Para usar serviços de vários clusters no balanceamento de carga de cluster para cluster, consulte Como configurar serviços de vários clusters.
Os gateways de vários clusters também usam ServiceImports, mas não para balanceamento de carga de cluster para cluster. Em vez disso, os gateways usam ServiceImports como identificadores lógicos de um serviço que existe em outro cluster ou que se estende por vários clusters. O HTTPRoute a seguir refere-se a um ServiceImport em vez de um recurso Serviço. Ao referenciar um ServiceImport, isso indica que ele está encaminhando tráfego para um grupo de pods de back-end que são executados em um ou mais clusters.
kind: HTTPRoute
apiVersion: gateway.networking.k8s.io/v1
metadata:
name: store-route
namespace: store
labels:
gateway: multi-cluster-gateway
spec:
parentRefs:
- kind: Gateway
namespace: store
name: external-http
hostnames:
- "store.example.com"
rules:
- backendRefs:
- group: net.gke.io
kind: ServiceImport
name: store
port: 8080
O diagrama a seguir mostra como o HTTPRoute encaminha o tráfego store.example.com para
pods store em gke-west-1 e gke-east-1. O balanceador de carga os trata como um
pool de back-ends. Se os pods de um dos clusters se tornarem não íntegros,
inacessíveis ou sem capacidade de tráfego, a carga de tráfego será balanceada para os
pods restantes no outro cluster. Novos clusters podem ser adicionados ou removidos com
o serviço store e o ServiceExport. Isso adiciona ou remove
de maneira transparente os pods de back-end sem alterações explícitas na configuração de roteamento.
Como exportar serviços
Neste ponto, o aplicativo está em execução nos dois clusters. Em seguida, você vai expor e exportar os aplicativos implantando Services e ServiceExports em cada cluster.
Aplique o manifesto a seguir ao cluster
gke-west-1para criar os serviços e o ServiceExportsstoreestore-west-1:cat << EOF | kubectl apply --context gke-west-1 -f - apiVersion: v1 kind: Service metadata: name: store namespace: store spec: selector: app: store ports: - port: 8080 targetPort: 8080 --- kind: ServiceExport apiVersion: net.gke.io/v1 metadata: name: store namespace: store --- apiVersion: v1 kind: Service metadata: name: store-west-1 namespace: store spec: selector: app: store ports: - port: 8080 targetPort: 8080 --- kind: ServiceExport apiVersion: net.gke.io/v1 metadata: name: store-west-1 namespace: store EOFAplique o manifesto a seguir ao cluster
gke-east-1para criar os serviços e o ServiceExportsstoreestore-east-1:cat << EOF | kubectl apply --context gke-east-1 -f - apiVersion: v1 kind: Service metadata: name: store namespace: store spec: selector: app: store ports: - port: 8080 targetPort: 8080 --- kind: ServiceExport apiVersion: net.gke.io/v1 metadata: name: store namespace: store --- apiVersion: v1 kind: Service metadata: name: store-east-1 namespace: store spec: selector: app: store ports: - port: 8080 targetPort: 8080 --- kind: ServiceExport apiVersion: net.gke.io/v1 metadata: name: store-east-1 namespace: store EOFVerifique se as ServiceExports corretas foram criadas no cluster.
kubectl get serviceexports --context CLUSTER_NAME --namespace storeSubstitua CLUSTER_NAME por
gke-west-1egke-east-1. A saída será assim:# gke-west-1 NAME AGE store 2m40s store-west-1 2m40s # gke-east-1 NAME AGE store 2m25s store-east-1 2m25sA saída demonstra que o Serviço
storecontém podsstorenos dois clusters, e os Serviçosstore-west-1estore-east-1contêm apenas podsstorenos respectivos clusters. Esses serviços sobrepostos são usados para segmentar os pods em vários clusters ou em um subconjunto de pods em um único cluster.Após alguns minutos, verifique se o
ServiceImportscomplementar foi criado automaticamente pelo controlador de vários clusters dos serviços em todos os clusters da frota.kubectl get serviceimports --context CLUSTER_NAME --namespace storeSubstitua CLUSTER_NAME por
gke-west-1egke-east-1. A saída será semelhante a esta:# gke-west-1 NAME TYPE IP AGE store ClusterSetIP ["10.112.31.15"] 6m54s store-east-1 ClusterSetIP ["10.112.26.235"] 5m49s store-west-1 ClusterSetIP ["10.112.16.112"] 6m54s # gke-east-1 NAME TYPE IP AGE store ClusterSetIP ["10.72.28.226"] 5d10h store-east-1 ClusterSetIP ["10.72.19.177"] 5d10h store-west-1 ClusterSetIP ["10.72.28.68"] 4h32mIsso demonstra que os três serviços podem ser acessados pelos dois clusters na frota. No entanto, como há apenas um único cluster de configuração ativo por frota, só é possível implantar gateways e HTTPRoutes que referenciam esses ServiceImports em
gke-west-1. Quando um HTTPRoute no cluster de configuração referencia esses ServiceImports como back-ends, o gateway pode encaminhar o tráfego para esses Services, independentemente do cluster de onde eles foram exportados.
Como implantar o gateway e o HTTPRoute
Depois que os aplicativos forem implantados, é possível configurar um gateway usando
o GatewayClass gke-l7-global-external-managed-mc. Esse gateway cria um balanceador de carga de aplicativo externo configurado para distribuir o tráfego entre os clusters de destino.
Aplique o manifesto
Gatewaya seguir ao cluster de configuração,gke-west-1neste exemplo:cat << EOF | kubectl apply --context gke-west-1 -f - kind: Gateway apiVersion: gateway.networking.k8s.io/v1 metadata: name: external-http namespace: store spec: gatewayClassName: gke-l7-global-external-managed-mc listeners: - name: http protocol: HTTP port: 80 allowedRoutes: kinds: - kind: HTTPRoute EOFEssa configuração de gateway implanta recursos externos do balanceador de carga de aplicativo com a seguinte convenção de nomenclatura:
gkemcg1-NAMESPACE-GATEWAY_NAME-HASH.Os recursos padrão criados com essa configuração são:
- 1 balanceador de carga:
gkemcg1-store-external-http-HASH - 1 Endereço IP público:
gkemcg1-store-external-http-HASH - 1 Regra de encaminhamento:
gkemcg1-store-external-http-HASH - 2 Serviços de back-end:
- Serviço de back-end padrão 404:
gkemcg1-store-gw-serve404-HASH - Serviço de back-end padrão 500:
gkemcg1-store-gw-serve500-HASH
- Serviço de back-end padrão 404:
- 1 Verificação de integridade:
- Verificação de integridade 404 padrão:
gkemcg1-store-gw-serve404-HASH
- Verificação de integridade 404 padrão:
- 0 regras de roteamento (o mapa de URL está vazio)
Nesta etapa, qualquer solicitação para GATEWAY_IP:80 resulta em uma página padrão exibindo a seguinte mensagem:
fault filter abort.- 1 balanceador de carga:
Aplique o manifesto
HTTPRouteao cluster de configuração, neste exemplogke-west-1:cat << EOF | kubectl apply --context gke-west-1 -f - kind: HTTPRoute apiVersion: gateway.networking.k8s.io/v1 metadata: name: public-store-route namespace: store labels: gateway: external-http spec: hostnames: - "store.example.com" parentRefs: - name: external-http rules: - matches: - path: type: PathPrefix value: /west backendRefs: - group: net.gke.io kind: ServiceImport name: store-west-1 port: 8080 - matches: - path: type: PathPrefix value: /east backendRefs: - group: net.gke.io kind: ServiceImport name: store-east-1 port: 8080 - backendRefs: - group: net.gke.io kind: ServiceImport name: store port: 8080 EOFNesta etapa, qualquer solicitação para GATEWAY_IP:80 resulta em uma página padrão exibindo a seguinte mensagem:
fault filter abort.Depois da implantação, esse HTTPRoute configura o seguinte comportamento de roteamento:
- As solicitações para
/westsão roteadas para podsstoreno clustergke-west-1, porque os pods selecionados pelo ServiceExportstore-west-1só existem no clustergke-west-1. - As solicitações para
/eastsão roteadas para podsstoreno clustergke-east-1, porque os pods selecionados pelo ServiceExportstore-east-1só existem no clustergke-east-1. - As solicitações para qualquer outro caminho são roteadas para Pods
storeem qualquer cluster, de acordo com a integridade, a capacidade e a proximidade do cliente solicitante. - As solicitações para GATEWAY_IP:80 resultam em uma
página padrão exibindo a seguinte mensagem:
fault filter abort.
Se todos os pods em um determinado cluster não forem íntegros (ou não existirem), o tráfego para o serviço
storesó será enviado para clusters que realmente tenham podsstore. A existência de um ServiceExport e um Service em um determinado cluster não garante que o tráfego seja enviado para esse cluster. Os pods precisam existir e responder à verificação de integridade do balanceador de carga. Caso contrário, o balanceador de carga enviará apenas tráfego para podsstoreíntegros em outros clusters.Novos recursos são criados com esta configuração:
- 3 Serviços de back-end:
- O serviço de back-end
store:gkemcg1-store-store-8080-HASH - O serviço de back-end
store-east-1:gkemcg1-store-store-east-1-8080-HASH - O serviço de back-end
store-west-1:gkemcg1-store-store-west-1-8080-HASH
- O serviço de back-end
- 3 Verificações de integridade:
- A verificação de integridade
store:gkemcg1-store-store-8080-HASH - A verificação de integridade
store-east-1:gkemcg1-store-store-east-1-8080-HASH - A verificação de integridade
store-west-1:gkemcg1-store-store-west-1-8080-HASH
- A verificação de integridade
- 1 regra de roteamento no URLmap:
- A regra de roteamento
store.example.com: - 1 Host:
store.example.com - Vários
matchRulespara rotear aos novos serviços de back-end
- A regra de roteamento
- As solicitações para
O diagrama a seguir mostra os recursos que você implantou nos dois clusters.
Como gke-west-1 é o cluster de configuração do gateway, ele
é o cluster em que nosso gateway, HTTPRoutes e ServiceImports são assistidos
pelo controlador de gateway. Cada cluster tem um ServiceImport store e outro
específico dele. Ambos apontam para os mesmos pods. Isso permite
que o HTTPRoute especifique exatamente para onde o tráfego precisa ir: para os pods store
em um cluster específico ou para os pods store em todos os clusters.
Esse é um modelo de recurso lógico, e não uma representação do fluxo de tráfego. O caminho do tráfego vai diretamente do balanceador de carga para pods de back-end e não tem relação direta com o cluster da configuração.
Como validar a implantação
Agora é possível emitir solicitações para o gateway de vários clusters e distribuir o tráfego entre vários clusters do GKE.
Confirme se o gateway e o HTTPRoute foram implantados, inspecionando o status e os eventos do gateway.
kubectl describe gateways.gateway.networking.k8s.io external-http --context gke-west-1 --namespace storeA resposta será semelhante a:
Name: external-http Namespace: store Labels: <none> Annotations: networking.gke.io/addresses: /projects/PROJECT_NUMBER/global/addresses/gkemcg1-store-external-http-laup24msshu4 networking.gke.io/backend-services: /projects/PROJECT_NUMBER/global/backendServices/gkemcg1-store-gw-serve404-80-n65xmts4xvw2, /projects/PROJECT_NUMBER/global/backendServices/gke... networking.gke.io/firewalls: /projects/PROJECT_NUMBER/global/firewalls/gkemcg1-l7-default-global networking.gke.io/forwarding-rules: /projects/PROJECT_NUMBER/global/forwardingRules/gkemcg1-store-external-http-a5et3e3itxsv networking.gke.io/health-checks: /projects/PROJECT_NUMBER/global/healthChecks/gkemcg1-store-gw-serve404-80-n65xmts4xvw2, /projects/PROJECT_NUMBER/global/healthChecks/gkemcg1-s... networking.gke.io/last-reconcile-time: 2023-10-12T17:54:24Z networking.gke.io/ssl-certificates: networking.gke.io/target-http-proxies: /projects/PROJECT_NUMBER/global/targetHttpProxies/gkemcg1-store-external-http-94oqhkftu5yz networking.gke.io/target-https-proxies: networking.gke.io/url-maps: /projects/PROJECT_NUMBER/global/urlMaps/gkemcg1-store-external-http-94oqhkftu5yz API Version: gateway.networking.k8s.io/v1 Kind: Gateway Metadata: Creation Timestamp: 2023-10-12T06:59:32Z Finalizers: gateway.finalizer.networking.gke.io Generation: 1 Resource Version: 467057 UID: 1dcb188e-2917-404f-9945-5f3c2e907b4c Spec: Gateway Class Name: gke-l7-global-external-managed-mc 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: 34.36.127.249 Conditions: Last Transition Time: 2023-10-12T07:00:41Z Message: The OSS Gateway API has deprecated this condition, do not depend on it. Observed Generation: 1 Reason: Scheduled Status: True Type: Scheduled Last Transition Time: 2023-10-12T07:00:41Z Message: Observed Generation: 1 Reason: Accepted Status: True Type: Accepted Last Transition Time: 2023-10-12T07:00:41Z Message: Observed Generation: 1 Reason: Programmed Status: True Type: Programmed Last Transition Time: 2023-10-12T07:00:41Z Message: The OSS Gateway API has altered the "Ready" condition semantics and reservedit for future use. GKE Gateway will stop emitting it in a future update, use "Programmed" instead. Observed Generation: 1 Reason: Ready Status: True Type: Ready Listeners: Attached Routes: 1 Conditions: Last Transition Time: 2023-10-12T07:00:41Z Message: Observed Generation: 1 Reason: Programmed Status: True Type: Programmed Last Transition Time: 2023-10-12T07:00:41Z Message: The OSS Gateway API has altered the "Ready" condition semantics and reservedit for future use. GKE Gateway will stop emitting it in a future update, use "Programmed" instead. Observed Generation: 1 Reason: Ready Status: True Type: Ready Name: http Supported Kinds: Group: gateway.networking.k8s.io Kind: HTTPRoute Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal UPDATE 35m (x4 over 10h) mc-gateway-controller store/external-http Normal SYNC 4m22s (x216 over 10h) mc-gateway-controller SYNC on store/external-http was a successDepois que o gateway for implantado, recupere com sucesso o endereço IP externo do gateway
external-http.kubectl get gateways.gateway.networking.k8s.io external-http -o=jsonpath="{.status.addresses[0].value}" --context gke-west-1 --namespace storeSubstitua
VIPnas etapas a seguir pelo endereço IP que você recebe como saída.Envie tráfego para o caminho raiz do domínio. Isso balanceia a carga do tráfego para o ServiceImport
storeque está no clustergke-west-1egke-east-1. O balanceador de carga envia o tráfego para a região mais próxima e talvez você não veja respostas da outra região.curl -H "host: store.example.com" http://VIPA saída confirma que a solicitação foi atendida pelo pod do cluster
gke-east-1:{ "cluster_name": "gke-east-1", "zone": "us-east1-b", "host_header": "store.example.com", "node_name": "gke-gke-east-1-default-pool-7aa30992-t2lp.c.agmsb-k8s.internal", "pod_name": "store-5f5b954888-dg22z", "pod_name_emoji": "⏭", "project_id": "agmsb-k8s", "timestamp": "2021-06-01T17:32:51" }Em seguida, envie o tráfego para o caminho
/west. Isso direciona o tráfego para o ServiceImportstore-west-1, que só tem pods em execução no clustergke-west-1. Um ServiceImport específico do cluster, comostore-west-1, permite que um proprietário de aplicativo envie tráfego explicitamente para um cluster específico, em vez de permitir que o balanceador de carga tome a decisão.curl -H "host: store.example.com" http://VIP/westA saída confirma que a solicitação foi atendida pelo pod do cluster
gke-west-1:{ "cluster_name": "gke-west-1", "zone": "us-west1-a", "host_header": "store.example.com", "node_name": "gke-gke-west-1-default-pool-65059399-2f41.c.agmsb-k8s.internal", "pod_name": "store-5f5b954888-d25m5", "pod_name_emoji": "🍾", "project_id": "agmsb-k8s", "timestamp": "2021-06-01T17:39:15", }Por fim, envie o tráfego para o caminho
/east.curl -H "host: store.example.com" http://VIP/eastA saída confirma que a solicitação foi atendida pelo pod do cluster
gke-east-1:{ "cluster_name": "gke-east-1", "zone": "us-east1-b", "host_header": "store.example.com", "node_name": "gke-gke-east-1-default-pool-7aa30992-7j7z.c.agmsb-k8s.internal", "pod_name": "store-5f5b954888-hz6mw", "pod_name_emoji": "🧜🏾", "project_id": "agmsb-k8s", "timestamp": "2021-06-01T17:40:48" }
Limpar
Depois de concluir os exercícios neste documento, siga estas etapas para remover os recursos e evitar cobranças indesejadas na conta:
Cancele o registro dos clusters da frota se eles não precisarem ser registrados para outra finalidade.
Desative o recurso
multiclusterservicediscovery:gcloud container fleet multi-cluster-services disableDesativar a Entrada de vários clusters:
gcloud container fleet ingress disableDesative as APIs:
gcloud services disable \ multiclusterservicediscovery.googleapis.com \ multiclusteringress.googleapis.com \ trafficdirector.googleapis.com \ --project=PROJECT_ID
Solução de problemas
Nenhum upstream íntegro
Sintoma:
O seguinte problema pode ocorrer quando você cria um gateway mas não pode acessar os serviços de back-end (código de resposta 503):
no healthy upstream
Motivo:
Esta mensagem de erro indica que a sondagem da verificação de integridade não consegue encontrar a integridade dos serviços de back-end. É possível que os serviços de back-end estejam íntegros, mas talvez seja necessário personalizar as verificações de integridade.
Alternativa:
Para resolver esse problema, personalize a verificação de integridade com base nas condições
(por exemplo, /health) usando um HealthCheckPolicy.
A seguir
- Saiba mais sobre o controlador de gateway.