Cloud Intelligence™Cloud Intelligence™

Cloud Intelligence™

Como configurar Load Balancing multi-cluster no GKE

By StepanAug 17, 202010 min read

Esta página também está disponível em English, Deutsch, Español, Français, Italiano e 日本語.

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

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ão35.191.0.0/16 e130.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}'.