Conheça os componentes do GCP Load Balancing e aprenda, passo a passo, a configurar um load balancer multi-cluster global no GKE.

Um dos recursos que mais curto no GCP é o HTTP(S) Load Balancing externo. É um load balancer global que entrega um único endereço IP anycast (sem precisar de DNS load balancing, ufa!). As requisições entram na rede global do Google por um dos pontos de presença (POPs) de borda mais próximos do usuário¹ e são encaminhadas via proxy para a região mais próxima com capacidade disponível. O resultado é um load balancing altamente disponível, distribuído globalmente, escalável e totalmente gerenciado. Dá ainda para somar proteção contra DDoS e WAF com Cloud Armor, Cloud CDN ou Identity-Aware Proxy (IAP) para proteger o acesso às suas aplicações web.

Com isso, vem logo à mente o load balancing multi-cluster com GKE, tema recorrente entre nossos clientes. E embora ainda não exista suporte nativo no GKE/Kubernetes,² o GCP oferece todos os blocos necessários para você montar essa configuração por conta própria.
Na primeira parte, vamos nos familiarizar com os componentes do GCP Load Balancing. Vamos seguir a jornada de uma requisição ao entrar no sistema e entender o que cada bloco do load balancing representa. Na segunda parte, vamos configurar o load balancing entre dois clusters GKE, passo a passo.
Visão geral do GCP Load Balancing

Fig. 1: Visão geral do GCP Load Balancing
Vamos começar com uma visão geral do fluxo do Load Balancing. A conexão HTTP(S) do cliente é encerrada na localização de borda pelos Google Front Ends (GFEs),³ com base na configuração do Target Proxy HTTP(S) e da Forwarding Rule. O Target Proxy consulta as definições de URL Map e Backend Service associadas para decidir como rotear o tráfego. A partir dos GFEs, uma nova conexão é estabelecida e o tráfego flui pela Google Network até o Backend saudável mais próximo com capacidade disponível. Dentro da região, o tráfego é então distribuído entre os Backend Endpoints individuais, conforme a capacidade de cada um.
Componentes do GCP Load Balancing

Fig. 2: Componentes do GCP Load Balancing
- Forwarding Rule — cada regra está associada a um IP e uma porta específicos. Como estamos falando de HTTP(S) load balancing global, será um endereço IP global anycast (opcionalmente, um IP estático reservado). A porta associada é aquela em que o load balancer aceita tráfego de clientes externos.⁴
- Target HTTP(S) Proxy — o tráfego é encerrado conforme a configuração do Target Proxy. Cada Target Proxy é vinculado a exatamente um URL Map (relação N:1). No caso de proxy HTTPS, você também precisa anexar pelo menos um certificado SSL e configurar a SSL Policy.
- URL Map — é o componente central de gerenciamento de tráfego e permite rotear o tráfego de entrada entre diferentes Backend Services (incluindo buckets do GCS). O roteamento básico é por hostname e path, mas também dá para fazer um gerenciamento de tráfego mais avançado — redirecionamentos de URL, reescrita de URL e roteamento por headers e parâmetros de query. Cada regra direciona o tráfego para um Backend Service.
- Backend Service — é um agrupamento lógico de backends para um mesmo serviço, junto com as opções de configuração relevantes, como distribuição de tráfego entre Backends individuais, protocolos, session affinity ou recursos como Cloud CDN, Cloud Armor e IAP. Cada Backend Service também está associado a um Health Check.
- Health Check — define como cada backend endpoint é verificado quanto à disponibilidade, e é assim que se calcula o estado geral de saúde de cada Backend. Protocolo e porta são obrigatórios na criação, junto com alguns parâmetros opcionais como intervalo de verificação, thresholds de saúde e falha, ou timeout. Um detalhe importante: é preciso ter regras de firewall liberando tráfego de health-check vindo de um conjunto de faixas de IP internas.⁵
- Backend — representa um grupo de endpoints individuais em uma determinada localização. No caso do GKE, nossos backends serão Network Endpoint Groups (NEGs),⁶ um por zona do cluster GKE (no caso do GKE, as NEGs são zonais, mas alguns tipos de backend são regionais).
- Backend Endpoint — é uma combinação de endereço IP e porta — no caso do GKE com container-native load balancing,⁷ apontando para Pods individuais.
Configuração
Vamos configurar um load balancing multi-cluster para dois serviços — Foo e Bar — implantados em dois clusters (fig. 3). Vamos usar regras simples baseadas em path e rotear toda requisição para /foo/* ao serviço Foo, e /bar/* ao serviço Bar.

Fig. 3: GKE Multi-Cluster Foo Bar
Pré-requisitos
- 2 clusters GKE em modo VPC-native; vamos chamá-los de primary e secondary ⁸
- Registro DNS apontando para o IP estático
- Versão recente do gcloud CLI
- Clone do repositório stepanstipl/gke-multi-cluster-native ⁹
git clone https://github.com/stepanstipl/gke-multi-cluster-native.gitcd gke-multi-cluster-native
Implantar aplicações e serviços nos clusters GKE

Fig. 4: K8s Demo App
Vamos começar implantando aplicações de demonstração simples em cada cluster. A aplicação mostra detalhes do cluster e da região que está atendendo a requisição, e o código-fonte está em stepanstipl/k8s-demo-app.
Repita os passos a seguir em cada um dos seus clusters.
Obter credenciais para o kubectl
gcloud container clusters get-credentials [cluster] \
--region [cluster-region]
Implantar as aplicações Foo e Bar
kubectl apply -f deploy-foo.yaml
kubectl apply -f deploy-bar.yaml
Para confirmar que os Pods de ambos os serviços estão no ar, rode kubectl get pods.
Criar Services K8s para as duas aplicações
kubectl apply -f svc-foo.yaml kubectl apply -f svc-bar.yaml
Repare na annotation cloud.google.com/neg: '{"exposed_ports": {"80":{}}}' nos services — é ela que orienta o GKE a criar uma NEG para o Service.
Você pode validar se os services subiram corretamente fazendo um port-forward local com kubectl port-forward service/foo 8888:80 e acessando o serviço em http://localhost:8888/.
Não esqueça de repetir tudo isso em cada um dos seus clusters.
Configurar os componentes de Load Balancing (GCLB)
Criar um Health Check
gcloud compute health-checks create http health-check-foobar \
--use-serving-port \
--request-path="/healthz"
Criar Backend Services
Crie um backend service para cada serviço, mais um adicional que vai servir como backend padrão para o tráfego que não corresponder a nenhuma regra baseada em path.
gcloud compute backend-services create backend-service-default \
--globalgcloud compute backend-services create backend-service-foo \
--global \
--health-checks health-check-foobargcloud compute backend-services create backend-service-bar \
--global \
--health-checks health-check-foobar
Criar URL Map
gcloud compute url-maps create foobar-url-map \
--global \
--default-service backend-service-default
Adicionar path rules ao URL Map
gcloud compute url-maps add-path-matcher foobar-url-map \
--global \
--path-matcher-name=foo-bar-matcher \
--default-service=backend-service-default \
--backend-service-path-rules='/foo/*=backend-service-foo,/bar/*=backend-service-bar'
Reservar um endereço IP estático
gcloud compute addresses create foobar-ipv4 \
--ip-version=IPV4 \
--global
Configurar o DNS
Aponte o seu DNS para o endereço IP estático reservado. Anote o IP que você acabou de solicitar:
gcloud compute addresses list --global
Crie um registro A foobar.[your_domain_name] apontando para esse IP. Você pode usar o Cloud DNS para gerenciar o registro ou qualquer outro serviço de sua preferência. Conclua esta etapa antes de seguir adiante.¹⁰
Criar certificado SSL gerenciado
gcloud beta compute ssl-certificates create foobar-cert \
--domains "foobar.[your_domain_name]"
Criar Target HTTPS Proxy
gcloud compute target-https-proxies create foobar-https-proxy \
--ssl-certificates=foobar-cert \
--url-map=foobar-url-map
Criar Forwarding Rule
gcloud compute forwarding-rules create foobar-fw-rule \
--target-https-proxy=foobar-https-proxy \
--global \
--ports=443 \
--address=foobar-ipv4
Verificar o certificado TLS
O processo de provisionamento do certificado pode demorar um pouco. Para conferir o status:
gcloud beta compute ssl-certificates describe foobar-cert
O managed.status deve passar a ACTIVE em até cerca de 60 minutos — geralmente bem antes — se tudo estiver configurado certinho.
Conectar os Services K8s ao Load Balancer
O GKE provisionou NEGs para cada Service K8s implantado com a annotation cloud.google.com/neg. Agora basta adicionar essas NEGs como backends nos backend services correspondentes.
Obter os nomes das NEGs provisionadas
kubectl get svc \
-o custom-columns='NAME:.metadata.name,NEG:.metadata.annotations.cloud\.google\.com/neg-status'
Anote o nome e as zonas da NEG de cada service.
Repita em todos os seus clusters GKE.
Adicionar NEGs aos Backend Services
Repita o procedimento abaixo para cada NEG e zona dos dois clusters. Use somente as NEGs que pertencem ao service Foo.
gcloud compute backend-services add-backend backend-service-foo \
--global \
--network-endpoint-group [neg_name] \
--network-endpoint-group-zone=[neg_zone] \
--balancing-mode=RATE \
--max-rate-per-endpoint=100
E faça o mesmo para o service Bar, repetindo nos dois clusters, em cada NEG e zona:
gcloud compute backend-services add-backend backend-service-bar \
--global \
--network-endpoint-group [neg_name] \
--network-endpoint-group-zone=[neg_zone] \
--balancing-mode=RATE \
--max-rate-per-endpoint=100
Liberar o tráfego do GCLB
gcloud compute firewall-rules create fw-allow-gclb \
--network=[vpc_name] \
--action=allow \
--direction=ingress \
--source-ranges=130.211.0.0/22,35.191.0.0/16 \
--rules=tcp:8080
Verificar se os backends estão saudáveis
gcloud compute backend-services get-health \
--global backend-service-foo gcloud compute backend-services get-health \
--global backend-service-bar
O esperado é ver 6 backends (3 por cluster,¹¹ 1 por zona) em cada backend service, com healthState: HEALTHY. Pode levar um tempinho até todos os backends ficarem saudáveis depois de adicionar as regras de firewall.
Testar se está tudo funcionando
Faça um curl no seu nome DNS https://foobar.[your-domain] (ou abra no navegador). Você deve receber 502 na raiz, já que não adicionamos nenhum backend ao service padrão.
curl -v "https://foobar.[your-domain]"
Agora faça um curl nos paths de cada service: https://foobar.[your-domain]/foo/ ou https://foobar.[your-domain]/bar/. A resposta deve ser 200, com o conteúdo do service correspondente.
curl -v "https://foobar.[your-domain]/foo/"
curl -v "https://foobar.[your-domain]/bar/"
Repetindo algumas vezes, você verá o tráfego sendo atendido por Pods e clusters diferentes.¹²
Se quiser simular um pouco de tráfego — por exemplo, com uma das minhas ferramentas de CLI favoritas, o vegeta —, dá para acompanhar bem a distribuição entre os backends no GCP Console. Vá em Network services -> seção Load balancing -> selecione seu load balancer -> aba Monitoring e escolha o backend correspondente. Você verá um dashboard parecido com o da fig. 5.

Fig. 5: Console do GKE — Load Balancing (os dois clusters estavam na mesma região, por isso o tráfego é balanceado igualmente entre todos os backends)
Agora é uma boa hora para experimentar. Veja o que acontece com clusters na mesma região e o que muda quando estão em regiões diferentes. Aumente a carga e observe o tráfego transbordando para outra região (dica: lembra do --max-rate-per-endpoint usado lá atrás?). Veja o que acontece se você derrubar um dos clusters. E que tal jogar um terceiro cluster no esquema?
(opcional) `gke-autoneg-controller`
Repare na annotation anthos.cft.dev/autoneg nos Services K8s. Ela não é necessária para o nosso setup, mas, se quiser, você pode implantar o gke-autoneg-controller ¹³ no seu cluster e usá-lo para associar automaticamente as NEGs criadas pelo GKE aos backend services correspondentes. Assim você economiza um trabalho manual chato.
Bom trabalho!
É isso. Explicamos a função de cada componente do GCLB e mostramos como configurar load balancing multi-cluster entre serviços implantados em 2 ou mais clusters GKE em regiões diferentes. Para uso em produção, recomendo automatizar essa configuração com uma ferramenta de gerenciamento de configuração, como o Terraform.
Esse setup aumenta a disponibilidade do seu serviço, já que vários clusters GKE independentes atendem ao tráfego, e também reduz a latência. No caso de HTTPS, o tempo até o primeiro byte fica menor, porque a negociação inicial de TLS acontece no servidor GFE próximo ao usuário. E, com múltiplos clusters, a requisição acaba sendo atendida pelo cluster mais próximo de quem fez a chamada.
Me conta se isso foi útil e qualquer outra dúvida que rolar, aqui mesmo ou em @stepanstipl. 🚀🚀🚀 Sirva rápido e prospere!
- [1] Mais de 90 localizações pelo mundo — Load Balancing — Locations e são encaminhadas via proxy para a região mais próxima com capacidade disponível.
- [2] Deixando o Anthos de lado por enquanto. O Anthos é uma plataforma de gerenciamento de aplicações que permite executar clusters K8s on-prem e em outras nuvens, e também estende a funcionalidade dos clusters GKE, incluindo multi-cluster ingress controller .)
- [3] Os GFEs são sistemas distribuídos, escaláveis e definidos por software, localizados em POPs de borda.
- [4] A porta pode ser 80 ou 8080 quando o target é um proxy HTTP, ou 443 no caso de proxy HTTPS.
- [5] Para External HTTP(S) Load Balancing, essas faixas são
35.191.0.0/16e130.211.0.0/22. - [6] Visão geral de Network endpoint groups
- [7] Container-native load balancing exige o cluster em modo VPC-native e permite que load balancers direcionem o tráfego diretamente para Pods individuais (em vez de mirar nos nós do cluster).
- [8] Usar clusters em regiões diferentes é mais interessante.
- [9] Todos os arquivos referenciados nos comandos deste post estão relativos à raiz desse repositório.
- [10] O registro DNS precisa estar no ar para o provisionamento do certificado SSL gerenciado pelo Google funcionar. Sem isso, o certificado pode ser marcado como falha permanente (já que a Autoridade Certificadora não vai conseguir assiná-lo) e terá que ser recriado.
- [11] Considerando que você usou clusters regionais, cada um implantado em 3 zonas; caso contrário, ajuste conforme necessário.
- [12] Se você tem clusters em regiões diferentes, o GCLB vai preferir atender o tráfego a partir do mais próximo do cliente, então não espere ver o tráfego balanceado igualmente entre as regiões.
- [13] Não vou entrar nos detalhes de como implantar e usar aqui — siga o readme —, mas, em resumo, basta adicionar uma annotation com o nome da NEG no seu service, ex.:
anthos.cft.dev/autoneg: '{"name":"autoneg_test", "max_rate_per_endpoint":1000}'.