As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.
Balanceamento de carga
dica
Explore as
Os balanceadores de carga recebem o tráfego de entrada e o distribuem entre os destinos do aplicativo pretendido hospedado em um cluster EKS. Isso melhora a resiliência do aplicativo. Quando implantado em um cluster EKS, o controlador do AWS Load Balancer criará e gerenciará os AWS Elastic Load Balancers para esse cluster. Quando um serviço do tipo Kubernetes LoadBalancer é criado, o AWS Load Balancer Controller cria um Network Load Balancer (NLB) que equilibra a carga do tráfego recebido na camada 4 do modelo OSI. Quando um objeto Kubernetes Ingress é criado, o AWS Load Balancer Controller cria um Application Load Balancer (ALB) que equilibra a carga do tráfego na camada 7 do modelo OSI.
Escolhendo o tipo de balanceador de carga
O portfólio do AWS Elastic Load Balancing (ELB) oferece suporte aos seguintes balanceadores de carga: Application Load Balancers (ALB), Network Load Balancers (NLB), Gateway Load Balancers (GWLB) e Classic Load Balancers (CLB). Esta seção de melhores práticas se concentrará no ALB e no NLB, que são os dois mais relevantes para os clusters EKS.
A principal consideração ao escolher o tipo de balanceador de carga são os requisitos de carga de trabalho.
Para obter informações mais detalhadas e como referência para todos os balanceadores de carga da AWS, consulte Comparações de produtos
Escolha o Application Load Balancer (ALB) se sua carga de trabalho for HTTP/HTTPS
Se uma carga de trabalho exigir balanceamento de carga na camada 7 do modelo OSI, o AWS Load Balancer Controller pode ser usado para provisionar um ALB; abordaremos o provisionamento na seção a seguir. O ALB é controlado e configurado pelo recurso de entrada mencionado anteriormente e encaminha o tráfego HTTP ou HTTPS para diferentes pods dentro do cluster. O ALB oferece aos clientes a flexibilidade de alterar o algoritmo de roteamento de tráfego do aplicativo; o algoritmo de roteamento padrão é round robin, com o algoritmo de roteamento de solicitações menos pendentes também como alternativa.
Escolha o Network Load Balancer (NLB) se sua carga de trabalho for TCP ou se sua carga de trabalho exigir a preservação do IP de origem dos clientes
Um balanceador de carga de rede funciona na quarta camada (transporte) do modelo de interconexão de sistemas abertos (OSI). É adequado para cargas de trabalho baseadas em TCP e UDP. O Network Load Balancer também preserva, por padrão, o IP de origem do endereço dos clientes ao apresentar o tráfego ao pod.
Escolha o Network Load Balancer (NLB) se sua carga de trabalho não puder utilizar o DNS
Outro motivo importante para usar o NLB é se seus clientes não podem utilizar o DNS. Nesse caso, o NLB pode ser mais adequado para sua carga de trabalho, pois os IPs em um balanceador de carga de rede são estáticos. Embora seja recomendável que os clientes usem DNS ao resolver nomes de domínio em endereços IP ao se conectarem a balanceadores de carga, se o aplicativo de um cliente não oferecer suporte à resolução de DNS e aceitar apenas IPs codificados, um NLB é mais adequado, pois os IPs são estáticos e permanecem os mesmos por toda a vida útil do NLB.
Provisionando balanceadores de carga
Depois de determinar o balanceador de carga mais adequado para suas cargas de trabalho, os clientes têm várias opções para provisionar um balanceador de carga.
Provisione balanceadores de carga implantando o AWS Load Balancer Controller
Há dois métodos principais de provisionamento de balanceadores de carga em um cluster EKS.
-
Aproveitando o controlador de serviços no provedor de nuvem da AWS (legado)
-
Utilização do AWS Load Balancer Controller (recomendado)
Por padrão, o Kubernetes Service Controller, também conhecido como controlador em árvore, reconcilia o tipo de recurso Kubernetes Service. LoadBalancer Esse controlador é incorporado ao componente
A configuração do Elastic Load Balancer provisionado é controlada por anotações que devem ser adicionadas ao manifesto do Kubernetes Service. As anotações usadas pelo Service Controller
O Service Controller é antigo e atualmente está recebendo apenas correções críticas de erros. Quando você cria um serviço do tipo Kubernetes LoadBalancer, o controlador de serviços cria um AWS CLB por padrão, mas também pode criar o AWS NLB se você usar a anotação correta. É importante notar que o Service Controller não oferece suporte aos recursos do Kubernetes Ingress e também não oferece suporte a IPv6.
Recomendamos usar o AWS Load Balancer Controller em seus clusters EKS para reconciliar o Kubernetes Service e os recursos do Ingress. Você deve usar as anotações corretas no seu Kubernetes Service ou no manifesto do Ingress para que o AWS Load Balancer Controller seja o proprietário do processo de reconciliação. (em vez do Service Controller)
Se você estiver utilizando o EKS Auto Mode, o AWS Load Balancer Controller é fornecido automaticamente; nenhuma instalação é necessária.
Escolhendo o balanceador de carga Target-Type
Registre pods como alvos usando IP Target-Type
Um AWS Elastic Load Balancer: Network & Application envia o tráfego recebido para alvos registrados em um grupo-alvo. Para um cluster EKS, há dois tipos de destinos que você pode registrar no grupo-alvo: Instância e IP. O tipo de destino usado tem implicações sobre o que é registrado e como o tráfego é roteado do balanceador de carga para o pod. Por padrão, o controlador do AWS Load Balancer registrará alvos usando o tipo “Instância” e esse destino será o IP do Worker Node eNodePort, implicação disso, inclui:
-
O tráfego do balanceador de carga será encaminhado para o Worker Node no NodePort, processado pelas regras do iptables (configuradas pelo kube-proxy em execução no nó) e encaminhado para o serviço em seu ClusterIP (ainda no nó). Finalmente, o serviço seleciona aleatoriamente um pod registrado nele e encaminha o tráfego para ele. Esse fluxo envolve vários saltos e pode ocorrer latência extra, especialmente porque o Serviço às vezes seleciona um pod em execução em outro nó de trabalho, que também pode estar em outro AZ.
-
Como o Load Balancer registra o Worker Node como seu destino, isso significa que sua verificação de integridade, que é enviada ao destino, não será recebida diretamente pelo pod, mas pelo Worker Node, NodePort e o tráfego de verificação de integridade seguirá o mesmo caminho descrito acima.
-
O monitoramento e a solução de problemas são mais complexos, pois o tráfego encaminhado pelo balanceador de carga não é enviado diretamente aos pods e você precisaria correlacionar cuidadosamente o pacote recebido no Worker Node com o Service ClusterIP e, eventualmente, com o pod para ter visibilidade total de ponta a ponta do caminho do pacote para uma solução de problemas adequada.
Por outro lado, se você configurar o tipo de destino como “IP”, conforme recomendado, a implicação será a seguinte:
-
O tráfego do balanceador de carga será encaminhado diretamente para o pod, isso simplifica o caminho da rede, pois ignora os saltos extras anteriores dos nós de trabalho e do IP do cluster de serviços, reduz a latência que, de outra forma, teria ocorrido se o serviço encaminhasse o tráfego para um pod em outro AZ e, por fim, remove o processamento indireto das regras iptables nos nós de trabalho.
-
A verificação de integridade do balanceador de carga é recebida e respondida diretamente pelo pod. Isso significa que o status de destino “saudável” ou “não íntegro” é uma representação direta do status de integridade do pod.
-
O monitoramento e a solução de problemas são mais fáceis e qualquer ferramenta usada que capture o endereço IP do pacote revelará diretamente o tráfego bidirecional entre o balanceador de carga e o pod em seus campos de origem e destino.
Para criar um AWS Elastic Load Balancing que usa destinos IP, você adiciona:
-
alb.ingress.kubernetes.io/target-type: ipanotação no manifesto do seu Ingress ao configurar seu Kubernetes Ingress (Application Load Balancer) -
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: ipanotação no manifesto do seu serviço ao configurar seu serviço Kubernetes do tipo LoadBalancer (Network Load Balancer).
Configurando verificações de integridade do balanceador de carga
Embora o Kubernetes forneça seus próprios mecanismos de verificação de integridade (detalhados na próxima seção), recomendamos implementar as verificações de integridade do ELB como uma proteção complementar que funciona fora do plano de controle do Kubernetes. Essa camada independente continua monitorando sua aplicação mesmo durante:
-
Kubernetes controla interrupções no avião
-
Atrasos na execução da sonda
-
Partições de rede entre kubelet e pod
Para cargas de trabalho críticas que exigem disponibilidade máxima e recuperação acelerada durante os cenários mencionados acima, as verificações de integridade do ELB fornecem uma rede de segurança essencial que funciona em conjunto — e não no lugar — dos mecanismos nativos do Kubernetes.
Para configurar e ajustar as verificações de saúde em seu ELB, você deve usar anotações no seu Kubernetes Service ou no manifesto do Ingress que seriam reconciliadas pelo Service Controller ou pelo AWS Load Balancer Controller.
Disponibilidade e ciclo de vida do pod
Durante a atualização de um aplicativo, você deve garantir que seu aplicativo esteja sempre disponível para processar solicitações para que os usuários não tenham nenhum tempo de inatividade. Um desafio comum nesse cenário é sincronizar o status de disponibilidade de suas cargas de trabalho entre a camada Kubernetes e a infraestrutura, por exemplo, balanceadores de carga externos. As próximas seções destacam as melhores práticas para lidar com esses cenários.
nota
As explicações abaixo são baseadas em, EndpointSlices
Use verificações de saúde
Por padrão, o Kubernetes executa a verificação de integridade do processo, na
Consulte a seção Criação de pods no Apêndice abaixo para revisar a sequência de eventos no processo de criação de pods.
Use sondas de prontidão
Por padrão, quando todos os contêineres de um pod estão em execução, success Por outro lado, se a sonda falhar mais abaixo na linha, o pod será removido do EndpointSlice objeto. Você pode configurar uma sonda de prontidão no manifesto do pod para cada contêiner. kubeletO processo em cada nó executa a sonda de prontidão nos contêineres desse nó.
Utilize portas de prontidão para Pod
Um aspecto da sonda de prontidão é o fato de que não há nenhum feedback/influence mecanismo externo nela. O processo kubelet no nó executa a sonda e define o estado da sonda. Isso não tem nenhum impacto nas solicitações entre os próprios microsserviços na camada Kubernetes (tráfego leste-oeste), pois o EndpointSlice controlador mantém a lista de endpoints (pods) sempre atualizada. Por que e quando você precisaria de um mecanismo externo então?
Quando você expõe seus aplicativos usando o tipo de balanceador de carga do Kubernetes Service ou Kubernetes Ingress (para tráfego de norte a sul), a lista de IPs de pod do respectivo serviço Kubernetes deve ser propagada para o balanceador de carga da infraestrutura externa para que o balanceador de carga também tenha uma lista de destinos atualizada. O AWS Load Balancer Controller preenche essa lacuna aqui. Quando você usa o AWS Load Balancer Controller e aproveitatarget group: IP, assim como kube-proxy o AWS Load Balancer Controller também recebe uma atualização (viawatch) e depois se comunica com a API do ELB para configurar e começar a registrar o IP do pod como destino no ELB.
Quando você realiza uma atualização contínua de uma implantação, novos pods são criados e, assim que a condição de um novo pod é “Pronto”, um old/existing pod é encerrado. Durante esse processo, o EndpointSlice objeto Kubernetes é atualizado mais rápido do que o tempo que o ELB leva para registrar os novos pods como destinos, consulte registro de alvos. https://docs.aws.amazon.com/elasticloadbalancing/latest/application/target-group-register-targets.html Por um breve período, você pode ter uma incompatibilidade de estado entre a camada Kubernetes e a camada de infraestrutura, na qual as solicitações do cliente podem ser descartadas. Durante esse período, na camada Kubernetes, novos pods estariam prontos para processar solicitações, mas, do ponto de vista do ELB, não estão.
O Pod Readiness Gates
Encerre os aplicativos com facilidade
Seu aplicativo deve responder a um sinal SIGTERM iniciando seu desligamento normal para que os clientes não tenham nenhum tempo de inatividade. Isso significa que seu aplicativo deve executar procedimentos de limpeza, como salvar dados, fechar descritores de arquivo, fechar conexões de banco de dados, concluir solicitações em andamento normalmente e sair em tempo hábil para atender à solicitação de encerramento do pod. Você deve definir o período de carência como longo o suficiente para que a limpeza possa ser concluída. Para saber como responder ao sinal SIGTERM, você pode consultar os recursos da respectiva linguagem de programação que você usa para seu aplicativo.
Se seu aplicativo não conseguir ser encerrado normalmente após o recebimento de um sinal SIGTERM ou se ele ignores/does não receber o sinal
A sequência geral de eventos é mostrada no diagrama abaixo. Nota: independentemente do resultado do procedimento de desligamento normal do aplicativo ou do resultado do PreStop gancho, os contêineres do aplicativo são eventualmente encerrados no final do período de carência via SIGKILL.
Consulte a seção Exclusão do pod no Apêndice abaixo para revisar a sequência de eventos no processo de exclusão do pod.
Atenda com elegância às solicitações do cliente
A sequência de eventos na exclusão do pod é diferente da criação do pod. Quando um pod é criado, o IP do pod é kubelet atualizado na Kubernetes API e somente então o EndpointSlice objeto é atualizado. Por outro lado, quando um pod está sendo encerrado, a API Kubernetes notifica o kubelet e o controlador ao mesmo tempo. EndpointSlice Inspecione cuidadosamente o diagrama a seguir, que mostra a sequência de eventos.
A forma como o estado se propaga do servidor de API até as regras de iptables nos nós explicadas acima cria uma condição de corrida interessante. Como há uma grande chance de o contêiner receber o sinal SIGKILL muito antes de o kube-proxy em cada nó atualizar as regras locais de iptables. Nesse caso, dois cenários que vale a pena mencionar são:
-
Se seu aplicativo descartar imediatamente e sem rodeios as solicitações e conexões em voo após o recebimento do SIGTERM, isso significa que os clientes verão 50 vezes erros em todos os lugares.
-
Mesmo que seu aplicativo garanta que todas as solicitações e conexões em andamento sejam processadas completamente após o recebimento do SIGTERM, durante o período de carência, novas solicitações de clientes ainda serão enviadas ao contêiner do aplicativo porque as regras do iptables ainda não foram atualizadas. Até que o procedimento de limpeza feche o soquete do servidor no contêiner, essas novas solicitações resultarão em novas conexões. Quando o período de carência termina, essas conexões, que são estabelecidas após o SIGTERM, são interrompidas incondicionalmente, pois o SIGKILL é enviado.
Definir o período de carência na especificação do pod por tempo suficiente pode resolver esse desafio, mas, dependendo do atraso de propagação e do número de solicitações reais do cliente, é difícil prever o tempo necessário para que o aplicativo feche as conexões normalmente. Portanto, a abordagem não tão perfeita, mas mais viável, aqui é usar um PreStop gancho para atrasar o sinal SIGTERM até que as regras do iptables sejam atualizadas para garantir que nenhuma nova solicitação do cliente seja enviada ao aplicativo, em vez disso, apenas as conexões existentes continuem. PreStop hook pode ser um manipulador Exec simples, como. sleep 10
O comportamento e a recomendação mencionados acima seriam igualmente aplicáveis quando você expõe seus aplicativos usando o tipo de Load Balancer do Kubernetes Service ou o Kubernetes Ingress (para tráfego de norte a sul) usando o controlador e a alavancagem do AWS Load Balancer. target group: IP Porque, assim como kube-proxy o AWS Load Balancer Controller, também recebe uma atualização (via watch) sobre o EndpointSlice objeto e, em seguida, ele se comunica com a API do ELB para começar a cancelar o registro do IP do pod no ELB. No entanto, dependendo da carga na API Kubernetes ou na API ELB, isso também pode levar tempo e o SIGTERM pode já ter sido enviado para o aplicativo há muito tempo. Quando o ELB começa a cancelar o registro do alvo, ele para de enviar solicitações para esse destino para que o aplicativo não receba novas solicitações e o ELB também inicia um atraso de cancelamento de registro que é de 300 segundos por padrão. Durante o processo de cancelamento do registro, o alvo é basicamente draining onde o ELB espera que as requests/existing conexões em voo com esse alvo sejam drenadas. Quando o atraso de cancelamento de registro expirar, o alvo não será utilizado e todas as solicitações em voo para esse alvo serão retiradas à força.
Use o orçamento de interrupção do Pod
Configure um orçamento de interrupção de pod
Referências
-
KubeCon Sessão Europa 2019 - Pronto? Um mergulho profundo nos Pod Readiness Gates for Service Health
-
Livro - Kubernetes em ação
-
Blog da AWS — Como escalar rapidamente seu aplicativo com o ALB no EKS (sem perder tráfego)
Apêndice
Criação de pod
É imperativo entender qual é a sequência de eventos em um cenário em que um pod é implantado e, em seguida, passa healthy/ready a receber e processar as solicitações do cliente. Vamos falar sobre a sequência de eventos.
-
Um pod é criado no plano de controle do Kubernetes (ou seja, por meio de um comando kubectl, atualização de implantação ou ação de escalonamento).
-
kube-scheduleratribui o Pod a um nó no cluster. -
O processo kubelet em execução no nó atribuído recebe a atualização (via
watch) e se comunica com o tempo de execução do contêiner para iniciar os contêineres definidos na especificação do pod. -
Quando os contêineres começam a funcionar, o kubelet atualiza a condição do pod
como Readyno objeto do pod na API Kubernetes. -
O EndpointSlice controlador
recebe a atualização da condição do pod (via watch) e adiciona o pod IP/Port como um novo endpoint ao EndpointSliceobjeto (lista de IPs do pod) do respectivo serviço Kubernetes. -
O
processo kube-proxy em cada nó recebe a atualização (via watch) no EndpointSlice objeto e, em seguida, atualiza as regras doiptables em cada nó, com o novo pod. IP/port
Exclusão do pod
Assim como na criação de um pod, é fundamental entender qual é a sequência de eventos durante a exclusão do pod. Vamos falar sobre a sequência de eventos.
-
Uma solicitação de exclusão do pod é enviada ao servidor da API Kubernetes (ou seja, por meio de um
kubectlcomando, atualização de implantação ou ação de escalonamento). -
O servidor da API Kubernetes inicia um período de carência
, que é de 30 segundos por padrão, definindo o campo deletionTimestamp no objeto Pod. (O período de carência pode ser configurado na especificação do Pod por meio terminationGracePeriodSecondsde) -
O
kubeletprocesso em execução no nó recebe a atualização (via watch) no objeto Pod e envia um sinalSIGTERM para o identificador de processo 1 (PID 1) dentro de cada contêiner desse Pod. Em seguida, assiste terminationGracePeriodSecondso. -
O EndpointSlice controlador
também recebe a atualização (via watch) da Etapa 2 e define a condição do endpoint como “terminando” no EndpointSliceobjeto (lista de IPs de pod) do respectivo serviço Kubernetes. -
O
processo kube-proxy em cada nó recebe a atualização (via watch) no EndpointSlice objeto e as regras doiptables em cada nó são atualizadas pelo kube-proxy para parar de encaminhar as solicitações dos clientes para o pod. -
Quando o
terminationGracePeriodSecondsexpirar,kubeletele envia o sinalSIGKILL para o processo principal de cada contêiner no Pod e os encerra à força. -
TheEndpointSliceO controlador
remove o endpoint do EndpointSlice objeto. -
O servidor de API exclui o objeto Pod.