Engenharia do caos é uma metodologia proativa que introduz intencionalmente interrupções e falhas controladas em um sistema para descobrir fraquezas, aumentar a resiliência e garantir um desempenho robusto diante de interrupções imprevistas.
Tudo falha, o tempo todo — DR. Werner Vogels, CTO Amazon
Esse é o mantra que nós, desenvolvedores, precisamos repetir toda vez que planejamos um sistema distribuído, e é exatamente por isso que a engenharia do caos é tão importante.
Nesta postagem do blog, você aprenderá sobre engenharia de caos e como ela complementa o SDLC (Software Development Lifecycle) tradicional. Abordaremos os desafios de implementar engenharia de caos em arquitetura serverless e revisaremos algumas abordagens com seus prós e contras.
Índice
Introdução do escritor convidado - Koby Aharon
Koby Aharon é um Arquiteto de Software Principal na CyberArk . Ele é um engenheiro profissional prático que adora usar tecnologia para resolver problemas complexos.
Você pode seguir Koby em suas contas do LinkedIn e do Medium .
O desafio com o Serverless
Arquiteturas sem servidor revolucionaram a forma como os aplicativos são desenvolvidos e implantados, oferecendo escalabilidade, custo-benefício e gerenciamento simplificado. No entanto, garantir sua resiliência pode se tornar ainda mais desafiador, embora a AWS os gerencie.
Vejamos a seguinte arquitetura:
Nossa arquitetura de exemplo é uma arquitetura serverless clássica que roda em cima da AWS. Ela é construída a partir dos seguintes componentes:
API hospedada no Amazon API gateway . Nossa API é implantada em duas regiões: us-east-1 e eu-west-1.
Função Lambda - acionada pelo nosso gateway de API (explicado aqui ).
Domínio personalizado registrado no Amazon Route 53 .
Roteamento baseado em latência do Route53 para garantir que nossos clientes usem a API de menor latência disponível.
Verificação de integridade do Route53 para verificar a integridade de nossas APIs.
Dada a nossa arquitetura, como podemos ter certeza de que nossos clientes dos EUA podem acessar nosso sistema em caso de uma falha regional dos EUA? Isso não é teórico. Aconteceu em 13 de junho de 2023 (você pode ler mais aqui ).
Como todos os desenvolvedores, nós executamos testes de integração e E2E (você pode ler mais sobre as melhores práticas aqui ), mas isso é suficiente? A resposta curta é não. Os testes geralmente se concentram em verificar a funcionalidade e o comportamento do sistema; no entanto, queremos verificar a resiliência do nosso sistema. Queremos garantir que nossa arquitetura seja resiliente a uma falha regional e, mesmo que a região dos EUA esteja inativa, nossa API da UE continuará funcionando e atenderá a todos os clientes.
É por isso que a engenharia do caos é essencial. Ao seguir seus princípios, podemos conduzir experimentos que simulam uma falha de região e verificar se nossa API está funcionando conforme o esperado e atende a solicitações de outra região.
Conduzir esses experimentos e introduzir interrupções é relativamente fácil quando você controla a infraestrutura. Você pode “desconectar” uma máquina para simular uma falha. No entanto, usamos serviços gerenciados pela AWS, o que significa que não controlamos (ou mesmo temos acesso) à infraestrutura. Então, como podemos simular uma falha de região?
Vamos aguardar essa pergunta e começar explicando como é um experimento de engenharia do caos.
Experimento do Caos
Um experimento de caos geralmente é construído a partir das seguintes etapas:
Formule uma hipótese (plano),
Introduzir estresse/falhas (fazer),
Observar (verificar),
Melhorar (agir).
1 - Formule uma Hipótese
Vamos usar nossa arquitetura de exemplo e começar formulando uma hipótese:
Dado : temos um gateway de API multirregional por trás do roteamento baseado em latência.
Hipótese : falha em uma região não afeta outras regiões.
2 - Introduzir Falhas
Conforme discutido acima, introduzir estresse e falhas em nossa arquitetura serverless de exemplo pode ser desafiador. Usamos serviços gerenciados pela AWS, o que significa que não controlamos (ou mesmo temos acesso) à infraestrutura. Então, como podemos seguir em frente e introduzir falhas?
O único componente que controlamos é o código da nossa função Lambda. Nossa função Lambda tem duas responsabilidades principais:
Verificação de saúde
Implementação de API
E se mudássemos nossa função de saúde na região dos EUA para retornar 404 (ou qualquer outra resposta de falha)? Vamos ver o que vai acontecer:
A verificação de integridade do Route53 chama nosso Lambda e obtém uma resposta de erro.
Após X tentativas consecutivas (número configurado), o Route53 marcará o ponto de extremidade dos EUA como insalubre.
Após uma solicitação de resolução, o Route53 procurará o ponto de extremidade saudável mais próximo e sempre usará a URL da UE.
Missão cumprida. Agora simulamos uma falha da região dos EUA em nossa arquitetura.
Pararemos aqui com nosso exemplo e discutiremos como podemos alterar nossa função Lambda para retornar um código de erro. Postagens futuras fornecerão um exemplo completo e discutirão todas as etapas.
Injetando falhas na função Lambda
No momento em que escrevo estas linhas, há duas abordagens principais para simular falhas em uma função Lambda:
Use uma biblioteca no seu código Lambda.
Use uma extensão Lambda (também apresentada nesta postagem do blog).
Vamos entrar em mais detalhes e explicar cada abordagem.
Use uma biblioteca em seu código Lambda
Você pode usar uma biblioteca como chaos_lambda ou failure-lambda no seu código Lambda. Adicionar essas bibliotecas permite que você envolva seu manipulador e injete falhas nele quando necessário. Ambas as bibliotecas são configuráveis e suportam o seguinte:
Ativado — Verdadeiro/Falso.
Tipo de falha — código de erro HTTP, exceção e muito mais.
Valor de falha — valor de retorno que corresponde ao tipo. Por exemplo, 404 em caso de tipo de falha HTTP.
Taxa — controla a taxa de falha. 1 significa que a falha é injetada em todas as solicitações, enquanto 0,5 significa que ela é injetada em metade das invocações.
Você pode ler mais sobre os valores de configuração suportados usando os links acima.
Vamos voltar ao nosso exemplo e ver como podemos simular uma falha na região dos EUA:
Adicione uma das bibliotecas à nossa função Lambda na região dos EUA.
Habilite-o e configure o tipo de falha HTTP com um valor 404.
Route53 chama nossa função, invocando a biblioteca.
A biblioteca retorna 404 imediatamente, ignorando o manipulador.
Use uma extensão Lambda
Esta abordagem é semelhante à primeira abordagem. A principal diferença é que a anexamos à nossa função Lambda como uma camada sem alterar seu código.
Podemos usar chaos-lambda-extension como nossa extensão. Para injetar falhas, devemos:
Adicione a extensão como uma camada.
Configure nosso Lambda para usar a extensão definindo a variável de ambiente AWS_LAMBDA_EXEC_WRAPPER (explicada no arquivo README da extensão).
Habilite uma falha de resposta com um código de status 404 definindo variáveis de ambiente adicionais (explicadas no arquivo README da extensão).
E é isso. Agora, podemos simular uma falha 404 como na primeira abordagem.
Vamos agora comparar as duas abordagens.
Comparação de abordagens
Abordagem | Prós | Contras |
Use uma biblioteca em seu código Lambda |
|
|
Use uma extensão Lambda |
|
|
Como você pode ver na tabela acima, a primeira abordagem é mais direta. No entanto, ela pode se encaixar apenas em aplicativos que usam algumas funções Lambda diferentes. Eu prefiro a segunda abordagem e vou focar nela em um post futuro.
Resumo
À medida que arquiteturas sem servidor se tornam cada vez mais comuns, há uma necessidade crescente de verificar a resiliência de nossos sistemas. A engenharia do caos surge como uma aliada vital, oferecendo uma abordagem proativa para validar nossas suposições contra falhas potenciais. Ao adotar a engenharia do caos, as organizações podem navegar com confiança pelas complexidades de ambientes sem servidor, garantindo serviços ininterruptos mesmo diante da adversidade.
Neste post, focamos nos desafios que enfrentamos quando queremos conduzir experimentos de caos em uma arquitetura serverless. Junte-se a mim no meu próximo post, no qual abordarei todos os passos apresentados neste post e fornecerei exemplos de código.