O blog da AWS
Operando cargas de trabalho resilientes no Amazon EKS
Introdução
Quando a margem de erro é muito pequena, é melhor presumir que qualquer coisa que possa dar errado, dará. Cada vez mais, os clientes da AWS estão criando cargas de trabalho resilientes que continuam operando enquanto toleram falhas nos sistemas. Quando os clientes criam aplicativos de missão crítica na AWS, eles precisam garantir que cada peça do sistema seja projetada de forma que o mesmo continue funcionando em condições adversas.
Clientes da AWS aplicaram o princípio do design em caso de falha na criação de sistemas de missão crítica escaláveis que atendam aos mais altos padrões de confiabilidade. As melhores práticas estabelecidas na estrutura do AWS Well Architected, permitiram que as equipes melhorassem os sistemas continuamente e, ao mesmo tempo, minimizassem as interrupções nos negócios. Vejamos alguns princípios fundamentais de design que vimos clientes usarem para operar cargas de trabalho que não podem arcar com o tempo de inatividade:
- Alta disponibilidade: os aplicativos modernos não devem ter um único ponto de falha
- Tolerância a falhas: o sistema deve ter recursos para contabilizar falhas internas e externas até um nível razoável
- Escalonamento automático: os componentes do sistema devem ser dimensionados de forma independente
- Auto recuperação: o sistema deve ser capaz de se recuperar de erros automaticamente
- Atualizações mais seguras: os desenvolvedores devem ser capazes de enviar código com confiança, empregando estratégias de implantação azul/verde e canárias
- Reversões: deve ser fácil se recuperar de uma implantação com falha
Um sistema é resiliente quando consegue adaptar seu funcionamento em resposta às mudanças nas condições. A Academia Nacional de Ciências define resiliência como “a capacidade de preparar e planejar, absorver, recuperar ou se adaptar com mais sucesso a eventos reais ou potenciais”.
Sem um sistema de orquestração sofisticado como o Kubernetes, praticar esses princípios era um trabalho pesado para a maioria das equipes de engenharia. Com o Kubernetes, é fácil executar, observar, escalar e atualizar cargas de trabalho. Ele foi projetado para ser um sistema de autocura. Como orquestrador de contêineres, ele oferece controles que permitem operar aplicativos altamente disponíveis, tolerantes a falhas e escaláveis. Esses são os motivos pelos quais os clientes estão escolhendo cada vez mais o Amazon Elastic Kubernetes Service (Amazon EKS) para operar serviços confiáveis e resilientes.
Amazon EKS
Uma das tarefas mais árduas para os usuários do Kubernetes é gerenciar o plano de controle (control plane) do cluster do Kubernetes. O Amazon EKS facilita a operação de um cluster Kubernetes fornecendo um plano de controle Kubernetes de nível de produção. Ele foi projetado para ser altamente disponível, tolerante a falhas e escalável. Seguindo as recomendações do Well Architected Framework, o Amazon EKS executa o plano de controle do Kubernetes em várias zonas de disponibilidade (AZ) da AWS para garantir alta disponibilidade. O plano de controle do cluster é escalonado automaticamente com base na carga, e todas as instâncias do plano de controle insalubres são substituídas automaticamente.
Topologia de cluster do Amazon EKS
A equipe do Amazon EKS adquiriu uma imensa experiência no gerenciamento de planos de controle do Kubernetes em grande escala. Essa experiência foi traduzida em práticas operacionais e de engenharia que garantem aos clientes a possibilidade de confiar nos clusters do Amazon EKS para a segurança, o desempenho, a disponibilidade, a confiabilidade e a resiliência do plano de controle do Kubernetes.
A AWS assume a responsabilidade pela disponibilidade do seu plano de controle de cluster do Amazon EKS. Isso significa que os clientes do Amazon EKS podem concentrar todos os seus esforços em garantir que sua carga de trabalho seja implantada de forma resiliente a eventos comuns de falha na infraestrutura.
O Kubernetes é autocurável
O software é onipresente. E os insetos também. Execute qualquer trecho de código por tempo suficiente e, eventualmente, ele terá problemas. As arquiteturas modernas de aplicativos preveem falhas e executam várias cópias de um código para minimizar as interrupções. Mas também precisamos garantir que nem todas as cópias falhem ao mesmo tempo. Por isso, executamos réplicas de aplicativos em vários domínios de falha (nós, AZs, regiões e provedores de serviços) para isolar falhas na infraestrutura subjacente.
Um método típico para aumentar a confiabilidade e a resiliência de uma carga de trabalho é distribuir suas réplicas em vários domínios de falha isolados. Cada domínio de falha adicional adiciona uma camada de proteção, o que torna a carga de trabalho mais robusta contra possíveis falhas. Por exemplo, se ocorrer uma falha em um domínio, os outros domínios poderão continuar a lidar com a carga de trabalho, minimizando o impacto nos usuários ou clientes. Essa abordagem é comumente chamada de tolerância a falhas ou redundância.
No entanto, é importante observar que cada camada adicional de isolamento também acarreta custos maiores. Configurar e manter domínios de falha separados geralmente envolve hardware adicional, infraestrutura de rede e sobrecarga operacional. As organizações precisam encontrar um equilíbrio entre o nível desejado de confiabilidade e os custos associados.
O Kubernetes traz recursos poderosos de orquestração para aprimorar a resiliência da carga de trabalho:
- Replicação e escalabilidade: o Kubernetes permite que você defina o número desejado de réplicas para suas cargas de trabalho, garantindo que várias instâncias do aplicativo sejam executadas simultaneamente. Se uma réplica falhar ou deixar de responder, o Kubernetes a substituirá automaticamente por uma saudável.
- Verificações de saúde e autorrecuperação: o Kubernetes monitora continuamente a integridade de réplicas individuais realizando verificações de integridade. Se uma réplica falhar nessas verificações, o Kubernetes a encerra automaticamente e inicia uma nova em seu lugar. Esse recurso de autorrecuperação garante que a carga de trabalho permaneça disponível e resiliente mesmo na presença de falhas.
- Isolamento de falhas: o Kubernetes permite definir e impor limites e restrições de recursos para cargas de trabalho. Ao definir cotas e limites de recursos, você poderá evitar que uma única carga de trabalho consuma recursos excessivos, reduzindo o risco de esgotamento de recursos e isolando as falhas em cargas de trabalho específicas, ao invés de afetar todo o cluster.
- Atualizações e reversões contínuas: o Kubernetes facilita atualizações contínuas, permitindo a utilização do seu aplicativo sem incorrer em tempo de inatividade. Ao implementar atualizações de forma controlada, o Kubernetes garante que um número mínimo de réplicas esteja disponível e operacional em todos os momentos. Além disso, oferece suporte a reversões que revertem para uma versão anterior de um aplicativo se surgirem problemas durante uma atualização.
- Implantações em vários domínios: o Kubernetes oferece suporte à implantação de cargas de trabalho em vários domínios de falha. Ao implantar réplicas em vários nós, AZs e clusters, haverá o aumento da resiliência de sua carga de trabalho contra falhas de infraestrutura em vários níveis.
Camadas de resiliência no Kubernetes
Vamos começar com a unidade mais baixa de implantação no Kubernetes, um pod, e subir na pilha de infraestrutura para eliminar pontos únicos de falha e resiliência em cada camada.
Resiliência na camada de implantação
Uma carga de trabalho do Kubernetes implantada para ser altamente disponível
Os pods são a menor unidade de computação implantável no Kubernetes. Mas os pods por si só não são resilientes. Uma carga de trabalho implantada como um pod único para de ser executada se o pod for encerrado por qualquer motivo.
É uma prática recomendada implantar cargas de trabalho do Kubernetes como implantações em vez de pods individuais. Se um pod que faz parte de uma implantação (ou de um ReplicaSet) falhar, o Kubernetes tentará reparar a carga de trabalho criando outro pod. Portanto, os clientes devem preferir executar cargas de trabalho usando Deployments para permitir a recuperação automática quando um pod falha.
A recuperação de uma falha no pod pode levar algum tempo. Enquanto isso, o que acontece com os negócios? A empresa não pode arcar com o tempo de inatividade enquanto o aplicativo é reiniciado. Então, executamos várias réplicas da nossa carga de trabalho para garantir que, caso um pod caia, ainda haverão outras réplicas para lidar com as solicitações.
A execução de várias réplicas de um serviço minimiza o impacto nos negócios durante falhas no aplicativo. Os clientes devem implantar várias réplicas de uma carga de trabalho para melhorar a disponibilidade e usar o escalonamento automático horizontal de pods para escalar as réplicas. As equipes também devem considerar o uso de sondas para ajudar o Kubernetes a detectar falhas no código do aplicativo. Consulte a seção de Aplicativos do Guia de Melhores Práticas do EKS para obter mais informações sobre a execução de aplicativos altamente disponíveis.
Geralmente, os clientes não precisam implementar a tolerância a falhas no nível de implantação quando o dimensionamento horizontal estiver operacional. Há uma exceção. Talvez seja necessário provisionar em excesso cargas de trabalho que tenham um alto tempo de inicialização. Se os pods de uma carga de trabalho não puderem ser escalados com rapidez suficiente devido ao alto tempo de inicialização, considere o super provisionamento de réplicas para compensar as falhas do pod.
Resiliência no nível do nó
Uma carga de trabalho do Kubernetes em execução em vários nós de trabalho
Na seção anterior, discutimos os recursos do Kubernetes que você pode usar para implantar sua carga de trabalho de forma resiliente. Podemos melhorar ainda mais a resiliência de uma carga de trabalho executando réplicas em vários domínios de falha. Vamos mudar nosso foco para os recursos computacionais que executam cargas de trabalho, os Nodes.
Depois de tornar nossa carga de trabalho altamente disponível e tolerante a falhas, precisamos garantir que o plano de dados do Kubernetes também seja altamente disponível e escalável. Para que o plano de dados seja resiliente, deve haver uma forma de detectar e substituir automaticamente instâncias insalubres do Amazon Elastic Compute Cloud (Amazon EC2) e escalar os nós com base nos requisitos da carga de trabalho. Um plano de dados resiliente e escalável garante que nossas cargas de trabalho permaneçam operacionais mesmo quando os nós ficarem indisponíveis.
Adicionar um Auto scaling Kubernetes, como o Cluster Autoscaler e o Karpenter, garante que o plano de dados seja dimensionado à medida em que as cargas de trabalho se expandem. Para detectar falhas nos nós, pode-se instalar o node-problem-detector e acoplá-lo ao Descheduler para drenar os nós automaticamente quando ocorrer uma falha.
Você deve provisionar demais a capacidade no nível do Node para tornar seu plano de dados mais tolerante a falhas? Isso depende do impacto em sua carga de trabalho quando o plano de dados do cluster precisa ser ampliado e do tempo necessário para criar um contêiner em um novo nó. É mais rápido escalar os Nodes se eles tiverem um tempo de inicialização curto. Da mesma forma, contêineres com imagens menores iniciam mais rápido do que imagens maiores.
Há duas coisas que você pode fazer para garantir que seu plano de dados seja escalado mais rapidamente e se recupere agilmente de falhas em nós individuais:
- Capacidade de provisionamento excessivo no nível do Node
- Reduza o tempo de inicialização do Node usando o Bottlerocket ou o Linux otimizado Amazon EKS básico
Para acelerar a inicialização do contêiner, você pode reduzir o tamanho da imagem do contêiner usando técnicas como a criação em vários estágios ou o carregamento lento da imagem.
Ao tornar o plano de dados resiliente, você evita que um Node se torne um único ponto de falha. Quando seu plano de dados estiver resiliente, você poderá distribuir a carga de trabalho em vários nós usando regras de anti afinidade, dispersão de topologia e orçamentos de interrupção.
Resiliência no nível da zona de disponibilidade (clusters únicos versus clusters Multi-AZ)
Uma carga de trabalho do Kubernetes implantada em várias zonas de disponibilidade
Até agora, nossos esforços se concentraram em garantir que as cargas de trabalho e o plano de dados fossem resistentes a falhas. Vamos reduzir o zoom e considerar o cenário em que um data center inteiro se torna insalubre.
Cada região da AWS tem vários locais isolados, conhecidos como AZs, projetados para não serem afetados simultaneamente por um cenário de destino compartilhado, como energia elétrica, interrupção da água, isolamento de fibras, terremotos, incêndios, tornados ou inundações. As AZs estão fisicamente separadas por uma distância significativa, muitos quilômetros, de qualquer outra AZ, embora todas estejam a 100 km (60 milhas) umas das outras.
É uma prática recomendada essencial implantar nós em várias AZs para ser resiliente a falhas em uma única AZ. Ao usar grupos de nós, é recomendável cria-los em várias AZs. Se você provisionar nós usando o Karpenter, já está coberto, pois o comportamento padrão do Karpenter é provisionar nós entre AZs. Quando a capacidade estiver disponível em todas as AZs, você poderá usar as restrições de dispersão da topologia do pod para distribuir as cargas de trabalho em várias AZs.
Aplicativos, como bancos de dados relacionais, que não suportam escalabilidade horizontal para alta disponibilidade são pontos únicos de falha. Considere configurar a recuperação automática para esses tipos de aplicativos. Sempre que possível, use serviços gerenciados como o Amazon RDS, que podem ser transferidos automaticamente para outra AZ quando uma falha é detectada. Em uma arquitetura Multi-AZ ideal, você deve ser capaz de resistir a falhas de infraestrutura em uma das AZs sem prejudicar a produção.
Uma desvantagem do design Multi-AZ é que há um custo associado à transferência de dados entre AZs. Aplicativos como o Cassandra e outros bancos de dados distribuídos trocam grandes volumes de dados entre réplicas. Para evitar o pagamento de taxas de transferência de dados entre AZ, alguns clientes implantam cargas de trabalho em uma única AZ. Comprometendo assim a confiabilidade em relação ao custo. Técnicas como dicas com reconhecimento de topologia e malhas de serviço podem ajudar a manter os dados locais em uma AZ e, ao mesmo tempo, manter a alta disponibilidade em todas as AZs.
Resiliência em nível de cluster (cluster único versus vários clusters)
Um cluster Kubernetes depende de complementos para funções críticas, como rede, segurança e observabilidade. Uma falha em um desses componentes tem o potencial de causar interrupções em todo o cluster. No passado, vimos clientes quebrando seu cluster configurando incorretamente a Interface de Rede de Contêineres (CNI) ou instalando um controlador mal escrito.
Como resultado, muitos clientes implantam suas cargas de trabalho em vários clusters do Amazon EKS para evitar que um cluster Kubernetes seja um único ponto de falha.
Ao adotar uma arquitetura de vários clusters para obter resiliência, é essencial reduzir a sobrecarga operacional do gerenciamento individual destes. A ideia é tratar os clusters como uma unidade. Qualquer alteração feita em um cluster é propagada para todos os clusters.
Há três recursos principais que tornam as implantações de vários clusters bem-sucedidas:
- A capacidade de implantar cargas de trabalho em todo o cluster de forma consistente
- A capacidade de distribuir o tráfego em vários clusters
- A capacidade de remover um cluster do recebimento de tráfego
Gerenciamento de configuração de vários clusters
Ao operar em um ambiente de vários clusters, ter um método automatizado para configurar clusters e implantar cargas de trabalho reduz a carga operacional da equipe da plataforma. Alterações ou atualizações manuais feitas diretamente nos clusters sem documentação ou controle adequados levam à alteração da configuração. O GitOps ou técnicas similares de implantação centralizada se tornam essenciais para evitar inconsistências em ambientes de vários clusters.
O motivo para evitar desvios de configuração no cluster é facilitar as implantações, atualizações e solução de problemas. Sem visibilidade e controle claros sobre as configurações, o gerenciamento de atualizações, o controle de versões e a garantia da consistência em todos os ambientes se tornam cada vez mais complexos. Essa complexidade pode levar a erros, aumentar o tempo necessário para tarefas de gerenciamento e prejudicar os esforços de escalabilidade ou automação.
Caso surja algum problema na implantação, é mais fácil corrigi-lo se todos os clusters compartilharem a mesma versão e configuração da carga de trabalho. Depois de identificar a correção em um cluster, você pode implantá-la com confiança em outros clusters, sem precisar solucionar o problema separadamente em cada um deles.
Roteamento de tráfego em vários clusters
A arquitetura de vários clusters também oferece oportunidades para testes, manutenção e atualizações sem interromper os ambientes de produção. Ao desviar o tráfego ou as cargas de trabalho para um conjunto de clusters durante as atividades de manutenção planejadas, as organizações podem garantir a disponibilidade contínua do serviço e alcançar um tempo de inatividade quase zero.
Os clientes do Amazon EKS usam o Application Load Balancer (ALB) ou o Network Load Balancer (NLB) para distribuir tráfego para réplicas de serviços executados dentro de um cluster. Eles também podem usar balanceadores de carga para distribuir o tráfego em vários clusters.
Ao usar o ALB, os clientes podem criar grupos-alvo dedicados para cada cluster. Usando grupos-alvo ponderados, os clientes podem então controlar a porcentagem de tráfego que cada cluster recebe.
Para cargas de trabalho que usam um NLB, os clientes podem usar o AWS Global Accelerator para distribuir o tráfego em vários clusters.
Resiliência em nível regional
Em alguns casos, cargas de trabalho de missão crítica com requisitos rigorosos de disponibilidade podem operar em várias regiões da AWS. Essa abordagem protege contra desastres de grande escala ou interrupções regionais. No entanto, o custo e a complexidade da implementação dessa configuração podem ser significativamente maiores. Esse padrão de arquitetura geralmente é reservado para recuperação de desastres e continuidade de negócios. Poucos clientes da AWS operam em várias regiões simultaneamente.
As implantações multirregionais se enquadram em duas categorias: ativa/ativa e ativa/passiva. Os clientes usam métricas de objetivo de ponto de recuperação (RTO) e objetivo de tempo de recuperação (RTO) para determinar qual estratégia de implantação multirregional usar. Custo e RPO/RTO são inversamente proporcionais. Portanto, os clientes só usam implantações ativas/ativas quando o custo de estar inativo em uma região compensa o custo de operar a infraestrutura em várias regiões simultaneamente.
Em implantações ativas/passivas, os clientes implantam cargas de trabalho em uma região primária e configuram outra secundária como alternativa caso a região primária fique indisponível.
A escala na qual você implanta a infraestrutura na região secundária depende dos números do Objetivo de Ponto de Recuperação (RPO) e do Objetivo de Tempo de Recuperação (RTO). A maioria dos clientes do Kubernetes com requisitos multirregionais implantam clusters Kubernetes em várias regiões e usa o GitOps para manter a implantação da carga de trabalho e a configuração do cluster em sincronia. Em implantações ativas/passivas, os clientes operam principalmente em uma região e fazem o failover para uma região secundária quando uma falha em grande escala afeta a produção. Nesses casos, os nós de trabalho na região secundária geralmente são reduzidos para economizar custos.
Quando o processo de recuperação de desastres é ativado, o cluster na região secundária é ampliado e o tráfego é transferido da região primária para a região secundária.
Ferramentas de backup e recuperação do Kubernetes, como o Velero, oferecem outra opção relativamente barata para implementar a recuperação de desastres. Tais ferramentas fazem backup dos recursos do cluster e dos volumes persistentes do Kubernetes no Amazon S3. Os backups são replicados para várias regiões usando a replicação entre regiões do Amazon S3. Caso a implantação na região primária fique indisponível, os clientes podem usar o backup para recriar a implantação em um cluster do Amazon EKS em outra região.
As implantações multirregionais funcionam melhor com cargas de trabalho sem estado porque a replicação de dados entre regiões é cara. Esta também pode ter um atraso, dependendo do método de replicação, o que geralmente cria complexidade na camada do aplicativo.
Quando os dados são armazenados em blocos ou em arquivos gerenciados, como Amazon EFS, Amazon S3 e Amazon FSx, os clientes podem usar os métodos de backup ou replicação da AWS fornecidos pelo sistema para copiar dados para outra região.
Para dados armazenados em bancos de dados, os clientes podem usar serviços de banco de dados da AWS, como tabelas globais do Amazon DynamoDB e bancos de dados globais do Amazon Aurora, para replicar dados com o mínimo de atraso. Se a camada de banco de dados em sua arquitetura não facilitar a replicação de dados quase em tempo real, você precisará considerar o atraso na replicação do banco de dados antes de implementar uma arquitetura ativa/ativa multirregional.
Devido ao custo e a complexidade inerentes, as implantações ativas em várias regiões devem ser reservadas para cargas de trabalho de missão crítica. Os aplicativos que poderiam ter essa meta de disponibilidade incluem, por exemplo, certos aplicativos bancários, de investimento, financeiros, governamentais e comerciais essenciais que são o negócio principal de uma empresa geradora de receita extremamente grande. Se sua organização tiver uma carga de trabalho que, se indisponível, resultará em milhares de dólares em perda de receita, essa carga de trabalho pode ser uma candidata adequada para implantação em várias regiões.
Para obter mais informações sobre considerações de implantação em várias regiões, consulte a seção de cenários multirregionais no AWS Well Architected Framework.
Valide a resiliência
Depois de configurar a arquitetura de sua carga de trabalho para ser resiliente, é fundamental validar sua resiliência. A AWS recomenda testar regularmente a resiliência do seu sistema para garantir que ele possa resistir e se recuperar de falhas, interrupções e condições adversas.
Muitos clientes da AWS usam a prática da engenharia do caos para descobrir as fraquezas de seus sistemas. Testar a resiliência do seu sistema de forma proativa ajuda a evitar interrupções nos negócios e impacto no cliente. Os exercícios de engenharia do caos também podem revelar o impacto potencial dos cenários de falha.
Os testes de resiliência oferecem uma oportunidade de simular cenários do mundo real que podem ocorrer na produção. Ao simular diferentes cenários de falha, como interrupções na rede, falhas de hardware ou interrupções no serviço, você podera avaliar o comportamento e a prontidão do sistema nessas situações. Essa preparação permitirá que você refine os procedimentos de resposta a incidentes, treine o pessoal e melhore a arquitetura e o design do sistema.
Conclusão
Neste post, mostramos que, ao entender e usar mecanismos de failover, você pode criar sistemas altamente disponíveis, tolerantes a falhas e que resistam a interrupções para manter a continuidade dos negócios.
A resiliência é implementada em diferentes camadas no Kubernetes. Esta postagem explicou como melhorar a resiliência de uma carga de trabalho implantando-a em vários domínios de falha. Abordamos padrões para implantações de vários nós, Multi-AZ, vários clusters e várias regiões.
Em última análise, a decisão de aumentar o número de domínios de falha para uma carga de trabalho depende de uma avaliação abrangente de fatores como a criticidade da carga de trabalho, o impacto de possíveis falhas, as implicações financeiras e a tolerância geral ao risco da organização.
Os clientes da AWS podem usar o AWS Resilience Hub para receber avaliações e recomendações para melhorar a resiliência. O Resilience Hub pode analisar a resiliência geral de um cluster Amazon EKS e pode examinar implantações, réplicas, replicationControllers e pods do Kubernetes.
Este artigo foi traduzido do Blog da AWS em Inglês.