Todos os aplicativos, independentemente de sua função, complexidade ou linguagem de programação, precisam de sistemas confiáveis para serem executados. Sem sistemas confiáveis, não teríamos a infraestrutura de computação em rede em grande escala que temos hoje. Mas o que realmente significa confiabilidade em termos de tecnologia e sistemas?
O que é um sistema confiável?
Confiabilidade é a capacidade de um sistema permanecer disponível por um período de tempo. Sistemas confiáveis são capazes de atender o tráfego de clientes de forma consistente, sem erros ou interrupções. Embora a tecnologia confiável sempre tenha sido importante – como comprovado pela crescente prática da engenharia de confiabilidade do site (SRE) – ela está se tornando cada vez mais importante para as aplicações modernas.
A razão é que o mundo moderno é executado em sistemas distribuídos. Usamos esses sistemas para gerenciar tudo, desde serviços bancários on-line até telecomunicações e assistência médica. À medida que esses sistemas desempenham papéis cada vez mais importantes na vida cotidiana, as expectativas dos clientes quanto à disponibilidade também estão aumentando. As interrupções não afetam apenas nossa capacidade de gerar receita, elas também afetam a vida de nossos clientes, seja voos atrasados causados por uma falha de computador ou um erro operacional que desativou os principais serviços bancários. De acordo com o Gartner, as empresas perdem em média US$ 336.000 por hora de inatividade e, para empresas que prestam serviços críticos ou estão em setores regulamentados, esses custos são ainda maiores.
Por que construir sistemas confiáveis é difícil
A engenharia de sistemas distribuídos confiáveis é um desafio, e mesmo os sistemas mais bem projetados são propensos a falhas inesperadas. Isso se deve a dois fatores principais: aumentar a velocidade de desenvolvimento e aumentar a complexidade do sistema.
A velocidade de desenvolvimento de software está aumentando
DevOps e os métodos ágeis aceleraram rapidamente o ciclo de vida de desenvolvimento de software, permitindo que as organizações inovem e forneçam valor aos clientes mais rápido do que nunca. No entanto, esse aumento de velocidade exige que mudemos a maneira como testamos o software. As práticas tradicionais de garantia de qualidade (QA) não podem mais acompanhar o ritmo e a complexidade do desenvolvimento de software moderno, nem podem testar comportamentos emergentes ou falhas em nível de infraestrutura. Isso resulta em um aumento da taxa de falhas entrando em produção.
Os sistemas estão se tornando mais complexos
A computação em nuvem e as arquiteturas nativas da nuvem, como microsserviços, tornaram nossos aplicativos muito mais dinâmicos e escaláveis, mas também adicionaram uma complexidade significativa aos nossos ambientes. Substituímos monólitos estáticos e de longa duração por contêineres discretos e pouco acoplados. Substituímos os data centers locais provisionados manualmente por plataformas de nuvem automatizadas que gerenciam nossos servidores para nós. Substituímos as implantações manuais por ferramentas de CI/CD que compilam, testam e implantam nossos aplicativos. Nossos ambientes estão maiores do que nunca e estão sendo gerenciados por plataformas automatizadas que orquestram, dimensionam e mantêm nossas cargas de trabalho sem nossa intervenção.
A automação eliminou grande parte da sobrecarga administrativa dos sistemas de gerenciamento, mas resultou em nossos sistemas comportamentos distintos. Esses comportamentos são difíceis de prever, especialmente com medidas de teste tradicionais. As ferramentas automatizadas não são apenas imperfeitas, mas nem sempre entendemos como elas funcionarão em todas as situações. Além disso, muitas de nossas cargas de trabalho são efêmeras: os serviços iniciam e param constantemente com base na demanda ou nos recursos disponíveis. Isso torna ainda mais difícil solucionar problemas, pois um componente com falha pode não existir mais quando os engenheiros detectarem a falha. Combine isso com o fato de que as plataformas de nuvem limitam nossa capacidade de gerenciar e observar a infraestrutura, e a confiabilidade se torna um problema muito maior.
Tudo isso aumenta a complexidade da manutenção de aplicativos e, à medida que a complexidade aumenta, aumenta também o risco de falha. Cada nova ferramenta automatizada, plataforma, serviço de orquestração e dependência adicionada aos nossos ambientes aumenta o risco de uma interrupção, pois uma falha em qualquer componente pode derrubar todo o sistema. Mesmo pequenas alterações nas configurações e nos processos de implantação podem afetar os aplicativos de maneiras inesperadas. No entanto, esperamos que os engenheiros de confiabilidade do site (SREs) mantenham esses sistemas e serviços funcionando com o mínimo de tempo de inatividade.
Como tornamos nossos sistemas mais confiáveis?
Exploramos os fatores subjacentes que causam baixa confiabilidade, mas ainda não temos uma imagem clara de como a baixa confiabilidade se manifesta nos sistemas. Como nossos sistemas e aplicativos falham e como abordamos e mitigamos essas falhas?
A confiabilidade do sistema é um tópico amplo que varia dependendo do ambiente e da equipe, mas podemos resumi-lo em categorias distintas. Essas categorias – que chamamos de princípios de confiabilidade – destinam-se a orientar os esforços de engenharia de confiabilidade para que possamos identificar e abordar as falhas com mais eficácia. Isso elimina as suposições da confiabilidade, destacando possíveis falhas e problemas de confiabilidade, fornecendo objetivos claros e ações corretivas e orientando os SREs no processo de abordá-los. Esses princípios incluem falhas de dependência, dimensionamento, autorrecuperação e redundância e recuperação de desastres.
Falhas de dependência
Dependências são componentes de software que fornecem funcionalidade adicional a um aplicativo ou serviço. Eles incluem serviços internos prestados por outras equipes da organização; serviços gerenciados de terceiros (por exemplo, software como serviço ou SaaS); e serviços externos autogerenciados, como aqueles hospedados em plataforma como serviço (PaaS) ou infraestrutura como serviço (IaaS). As dependências criam pontos de falha adicionais que podem causar falhas em nossos próprios serviços, a menos que os projetemos para tolerar falhas de dependência.
As estratégias para mitigar as falhas de dependência incluem:
- Utilizar verificações de integridade automatizadas — solicitações periódicas enviadas para verificar a disponibilidade e a capacidade de resposta de um serviço — para detectar dependências com falha ou não íntegras.
- Implementação de lógica de repetição e tempo limite em torno de chamadas para dependências.
- Falha nas dependências de backup ou caminhos de código alternativos em caso de interrupção.
Escala
Escalabilidade é a capacidade de alocar dinamicamente recursos para um serviço em resposta a mudanças na demanda. Os sistemas distribuídos geralmente usam dimensionamento vertical (aumentando a capacidade de um único host) e dimensionamento horizontal (aumentando a capacidade total de um serviço distribuindo-o por vários hosts).
As estratégias para mitigar falhas de dimensionamento incluem:
- Utilizar mecanismos de dimensionamento automático para ajustar dinamicamente a capacidade em resposta à demanda.
- Validar regras de escalonamento automático e comportamento de escalonamento.
- Implementar e configurar o balanceamento de carga.
Autorecuperação
A autorrecuperação é a capacidade de um serviço detectar e recuperar automaticamente de falhas internas. Os serviços que exigem intervenção humana para se recuperar de incidentes resultam em interrupções mais longas, colocam mais estresse em suas equipes de resposta a incidentes e correm maior risco de falha na recuperação.
As estratégias para mitigar falhas de autorrecuperação incluem:
- Detectar e responder automaticamente a serviços com falha, como reimplantar cargas de trabalho em hosts íntegros.
- Restaurar ou substituir um serviço ou host com falha.
- Manter a disponibilidade do serviço quando um host está offline.
Redundância e recuperação de desastres
Redundância é o processo de replicação de dados e serviços para fornecer uma opção de contingência em caso de falha. Ela reduz o risco de uma falha do sistema se tornar uma interrupção, espalhando o risco por várias réplicas. Com os mecanismos de tolerância a falha adequados, os sistemas redundantes podem continuar operando durante uma falha sem interrupções de serviço ou perda de dados.
A recuperação de desastres é a prática de restaurar as operações após um evento disruptivo, como uma grande interrupção ou desastre natural. As equipes que realizam o planejamento de recuperação de desastres (DRP) estão mais bem preparadas para responder a esses eventos e colocar seus serviços online mais rapidamente. A redundância é uma parte essencial do planejamento de recuperação de desastres, pois ajuda as organizações a reduzir seu objetivo de tempo de recuperação (RTO), objetivo de ponto de recuperação (RPO) e tempo médio de recuperação (MTTR).
As estratégias para mitigar falhas de redundância incluem:
- Utilizar ferramentas de observabilidade para detectar automaticamente grandes interrupções, como uma interrupção regional ou de uma zona.
- Replicar serviços e dados em vários data centers, zonas de disponibilidade ou regiões e usar ferramentas de balanceamento de carga para redirecionar o tráfego durante interrupções.
- Planejar e testar proativamente os problemas da região.
- Criar e validar manuais de recuperação de desastres.
Como aplicamos esses princípios?
Esses princípios fornecem orientação sobre como identificar e evitar falhas, mas mesmo que projetemos nossos sistemas com o maior número possível de mecanismos de resiliência, não saberemos sua eficácia até experimentarmos um incidente ou testá-los proativamente. As formas tradicionais de teste não são abrangentes o suficiente para testar nossos sistemas dinâmicos, complexos e modernos e, portanto, precisamos de uma nova abordagem. Essa abordagem é a Engenharia do Caos.
O que é Engenharia do Caos?
A Engenharia do Caos é a prática de experimentar intencionalmente um sistema injetando falhas, observando como o sistema responde e usando nossas observações para melhorar a resiliência do sistema. A Engenharia do Caos nos permite simular condições que podem resultar em falhas, como consumo excessivo de recursos, latência de rede e interrupções do sistema, de maneira segura e controlada. Isso ajuda a expor falhas latentes e inesperadas ocultas em nossos sistemas, permitindo implementar correções e validar nossa resiliência antes de implantar na produção.
Com a Engenharia do Caos, podemos aplicar os princípios de confiabilidade acima a cenários do mundo real, como:
- Degradar o desempenho da rede entre nosso serviço e uma dependência para simular uma falha de dependência.
- Interromper um recurso como um pod do Kubernetes ou instância de máquina virtual para validar mecanismos de recuperação automática.
- Consumir recursos de computação para acionar regras de dimensionamento automático.
- Descartando todo o tráfego para um cluster, zona de disponibilidade ou região de computação em nuvem para simular uma interrupção regional.
Uma abordagem segura para melhorar a confiabilidade
A Engenharia do Caos fornece uma abordagem segura e controlada para testes de confiabilidade. Em vez de causar falhas aleatórias e descontroladas, estruturamos nossos testes em torno de experimentos de caos. Esses são experimentos cuidadosamente projetados que testam nossa compreensão de como nossos sistemas funcionam com o objetivo de torná-los mais resilientes.
Um experimento de caos começa com uma hipótese sobre como esperamos que nossos sistemas se comportem sob certas condições. Uma hipótese pode abranger qualquer cenário, mas podemos usar os princípios de confiabilidade listados acima para orientar nossos experimentos iniciais. Podemos fazer perguntas como “O que acontece com meu serviço se…”
- …perde a conexão com uma dependência crítica, como um banco de dados? Ele continua atendendo a solicitações ou retorna erros para nossos usuários?
- …o cluster fica sem capacidade de computação? Podemos aumentar a capacidade sem ter que parar, reiniciar ou reimplantar nossos serviços?
- …o host em que nosso serviço está sendo executado falha? Podemos replicar o serviço para outro host e redirecionar os usuários sem interrupções?
- …o data center em que nossos serviços estão sendo executados foi desativado por um incêndio, terremoto ou inundação? Temos sistemas redundantes em outro local para o qual podemos fazer recuperação a falha? Nossos engenheiros estão preparados para executar um plano de recuperação de desastres?
Em seguida, determinamos a melhor maneira de testar essa hipótese. Por exemplo, ao testar uma conexão com uma dependência crítica, precisamos de uma forma de simular uma falha na conexão de rede entre nosso serviço e nossa dependência. Tradicionalmente, isso significaria alterar as regras do firewall ou bloquear uma porta em um roteador ou switch. Ferramentas de engenharia do caos como Gremlin simplificam isso fornecendo uma estrutura para injetar falhas em sistemas de maneira controlada, para que possamos testar nossos sistemas sob condições de falha sem causar danos reais.
As ferramentas da Engenharia do Caos nos dão controle total sobre como injetamos a falha, incluindo o tipo de falha, o número de sistemas afetados (chamado raio de alcance), a gravidade da falha (chamada magnitude) e a duração. Ao começar com a Engenharia do Caos, mantenha o raio e a magnitude do alcance baixos para focar o teste de confiabilidade em um único sistema, aplicação ou serviço. À medida que aprendemos mais sobre nossos sistemas e trabalhamos na construção de sua resiliência, podemos expandir gradualmente o escopo de nossos testes aumentando o raio e a magnitude do alcance. Isso nos dá a chance de encontrar e descobrir problemas gradualmente, em vez de testar todo o sistema de uma só vez.
A segurança também é uma parte crítica da Engenharia do Caos. A injeção de falha vem com o risco de causar inadvertidamente uma falha maior do que o pretendido. É por isso que é fundamental ter uma maneira de interromper e reverter rapidamente um experimento. Com o Gremlin, podemos interromper experimentos manualmente ou usar verificações de status automáticas para monitorar continuamente nossos sistemas quanto a falhas e interromper experimentos que crescem fora de controle.
À medida que executamos experimentos e descobrimos novas falhas, devemos acompanhar nossas descobertas e nossas correções. É assim que acompanhamos as melhorias incrementais de confiabilidade ao longo do tempo e vemos como nossos sistemas estão se tornando mais confiáveis como resultado de nossa iniciativa de confiabilidade. Depois de concluir um experimento e corrigir as falhas podemos automatizar nossos experimentos de caos como parte de nosso pipeline de CI/CD para verificar continuamente as regressões.
Com o Gremlin, você pode validar continuamente a confiabilidade de seus sistemas e serviços em relação a essas e outras categorias de falhas. O Gremlin facilita o projeto e a execução de experimentos em seus sistemas, o agendamento de ataques para validação contínua e a integração com sua plataforma de CI/CD. O Gremlin inclui um conjunto completo de Cenários para testar a resiliência a falhas comuns, incluindo falhas de dependência, falhas de dimensionamento automático, falhas de host, interrupções de DNS e evacuação de região. Você pode começar solicitando uma avaliação gratuita interagindo no nosso chatbot.
Para resumir…
- Confiabilidade é a capacidade de um sistema permanecer disponível por um período de tempo.
- Melhorar a confiabilidade em sistemas distribuídos é um desafio por dois motivos principais:
- Velocidade: O ritmo de desenvolvimento de software está aumentando. Quanto mais mudamos nossos aplicativos e sistemas, maior a probabilidade de introduzirmos falhas.
- Complexidade: Os sistemas modernos são extremamente complexos e estão sempre mudando. Ninguém sabe como tudo funciona, e ambientes como plataformas de nuvem limitam a observabilidade.
- A confiabilidade pode ser categorizada em quatro princípios:
- Falha de dependência
- Recuperação automática
- Escala
- Recuperação de desastres
- A Engenharia do Caos é a prática de injetar danos medidos em um sistema e observar sua resposta para melhorar sua resiliência.
- Um experimento de caos é uma injeção controlada de dano.
- O raio da alcance é o número de sistemas afetados por um único experimento de caos.
- A magnitude é a gravidade ou intensidade do experimento.
- Antes de executar um experimento de caos, certifique-se de poder interromper e reverter o impacto para evitar consequências não intencionais em seus sistemas.
- Automatize experimentos de caos em seu pipeline de CI/CD para validar continuamente sua confiabilidade.