Pontos Principais
- Mudanças de cultura e de processo são necessárias, ao invés de alterarmos apenas as ferramentas, para que as equipes gerenciem os serviços de maneira sustentável.
- Podemos reduzir a quantidade de chamados com objetivos de nível de serviço (SLO, Service Level Objectives) que medem a experiência do cliente e alertas de falhas críticas que impactam o cliente.
- A observabilidade, através da coleta e consulta de rastros e eventos, permite que as equipes depurem e compreendam os sistemas mais complexos.
- As equipes devem poder colaborar com a segurança e discutir os riscos para trabalhar de maneira eficaz.
- Os serviços funcionam sem problemas quando a análise quantitativa de riscos permite que as equipes priorizem as correções.
Equipes de site reliability engineering, conhecido pela sigla SRE, e de desenvolvimento precisam estar dispostas a resolver os problemas e identificar pontos de tensão que precisam ser redefinidos. Parte do trabalho da SRE é ajudar a manter a excelência da produção diante das mudanças que são necessárias para os negócios.
- Sheerin et al., The Site Reliability Workbook.
A tomada de responsabilidade da produção, coloca as equipes de desenvolvedores que criaram os componentes ou serviços de plantão em relação a esses serviços. Uma prática recomendada para garantir um software de alta qualidade e com isso reforçar os ciclos de feedback de desenvolvimento. Se bem feito, a responsabilidade poderá fornecer aos engenheiros o poder e a autonomia para que alimentem o nosso desejo natural por ação e trabalho de alto impacto, podendo proporcionar aos usuários uma melhor experiência.
Mas, na prática, as equipes geralmente concluem o plantão sem o treinamento e proteções adequadas para o bem-estar delas. A mudança repentina das responsabilidades da equipe piora a confiabilidade do serviço, acaba com a moral da equipe e cria incentivos para evitar responsabilidades. Os membros da equipe não terão habilidades críticas, terão dificuldades para acompanhar, e não terão mais tempo para aprender. O problema é que terão responsabilidade sem empoderamento. Apesar do instinto de gastar dinheiro para solucionar um problema, a compra de ferramentas não pode resolver questões de capacidades ou estruturas das equipes. As ferramentas apenas podem ajudar a automatizar os fluxos de trabalho existentes, e não ensinar novas habilidades ou adaptar processos para resolver os atuais problemas.
Para ter sucesso, uma equipe precisa de um roadmap para desenvolver as habilidades necessárias para executar os sistemas de produção. Não precisamos somente da responsabilidade de produção, necessitamos também da excelência na produção, que nada mais é que um conjunto de habilidades que as equipes podem utilizar para se adaptar às mudanças das circunstâncias com confiança. Requer mudanças nas pessoas, na cultura e no processo, ao invés de apenas mudar as ferramentas.
Crédito: Emily Griffin (@emilywithcurls)
Isolar as operações não funciona
As equipes de desenvolvimento que terceirizam as operações ao invés de praticar a responsabilidade de produção lutam contra o desalinhamento dos incentivos em relação a entrega da qualidade esperada. Essas equipes priorizam o desenvolvimento mais rápido dos recursos em detrimento da operabilidade. A necessidade de intervenção humana por operadores cresce mais rápido do que as equipes conseguem oferecer. Equipes com foco operacional, que devem manter o sistema funcionando, são deixadas para arrumar a bagunça causada, sem analisar os custos humanos relacionados a distração, as madrugadas e turnos de horas extras. Um trabalho que fornece tudo para que seus colaboradores que foram designados à operá-lo tenham a síndrome de burnout não é sustentável no longo prazo.
Crédito: Emily Griffin (@emilywithcurls)
Quando os desenvolvedores e o pessoal de infra e de apoio ficam jogando a responsabilidade um para o outro, perdem o contexto das necessidades do desenvolvedor e do operador/infra. As entregas necessitam de teste manual, e o provisionamento requer uma ação humana, as falhas exigem investigação manual e as interrupções complexas demoram mais tempo para serem resolvidas devido a escalonamento entre as equipes. As equipes acabam trabalhando com várias ações manuais, tediosas e propensas a erros ou desenvolvem automação incorreta que aumenta o risco, como por exemplo, quando reiniciam os processos sem examinar o motivo da parada. Esse tipo de trabalho repetitivo de interrupção/correção, ou trabalhoso, varia de acordo com o tamanho do serviço e exige sangue, suor e lágrimas das equipes. Nas empresas que usam uma estrutura SRE de equipe dedicada, bem como nas que possuem uma equipe sysadmin mais tradicional, os times podem ficar sobrecarregadas operacionalmente muito rápido.
Com o tempo, os desafios operacionais também atrasam o desenvolvimento do produto, pois o conhecimento e as ferramentas desconectadas entre os desenvolvedores e as operações, mostram que as equipes desconectadas não conseguem entender e reparar facilmente as falhas em produção ou até mesmo concordar com as prioridades das correções. A tomada da responsabilidade da produção faz sentido: Fecha o ciclo do feedback para que as equipes de desenvolvimento sintam a dor das próprias decisões de operacionalidade e tragam conhecimento operacional para a equipe, em vez de isolá-lo.
Estar 24 horas online não funciona
Colocar as equipes de desenvolvimento de plantão requer preparação para que sejam bem-sucedidas. As empresas de tecnologia dividiram os papéis de operações e desenvolvimento a várias décadas atrás, com o objetivo de encontrar eficiências por meio da especialização. O processo moderno de fundir as duas funções para melhorar a agilidade não irá acontecer de um dia para o outro. As tarefas operacionais às quais a equipe combinada, agora DevOps, precisa realizar, normalmente é totalmente diferente das habilidades e instintos que as equipes de desenvolvimento estão acostumadas. O volume de alertas e intervenções manuais pode ser avassalador, o que reforça a perspectiva que o trabalho de operações não tem valor nenhum. E reduzir o volume de alertas e trabalho manual requer uma combinação de habilidades entre desenvolvimento e operações, de modo que muitos desenvolvedores resistem às tentativas de introduzir responsabilidades pela produção em uma equipe.
Muitas ferramentas comerciais dizem reduzir o atrito do DevOps ou da responsabilidade de produção, mas às vezes, espalham a fonte de verdade e acabam aumentando o ruído no sistema. A menos que exista um plano para educar e envolver todos em relação a produção, todos os problemas não triviais serão encaminhados para um dos poucos especialistas de produção da equipe. Mesmo que esses especialistas estivessem dispostos a compartilhar as informações ao invés de não acumulá-las, as constantes interrupções os impedem de escrever uma documentação completa. As métricas contínuas de integração e entrega são uma armadilha se focarem apenas na taxa de entrega do software, ao invés de analisarem a qualidade.
Crédito: Emily Griffin (@emilywithcurls)
O tempo para encontrar e arrumar os problemas poderá ser longo se as equipes não conseguirem entender as falhas no sistema de produção. Para implantar o software com segurança, as equipes devem garantir que ele não dê problemas durante a implantação em produção. Caso contrário, em um ambiente com uma alta taxa de alteração devido a falhas, o trabalho árduo das equipes é repetidamente revertido ou corrigido em condições de extremo estresse. Embora seja justo distribuir a dor operacional entre todos os membros de uma equipe, o verdadeiro alívio da sobrecarga operacional só pode vir da redução do número de mensagens de SMS e dos chamados de erro e correção.
A especialização em engenharia de sistemas tem valor e leva tempo para se desenvolver, mas historicamente foi desvalorizada. Os desenvolvedores de produtos não possuem necessariamente uma boa estrutura para decidir qual automação escrever ou qual bugs precisa ser corrigidos para obter a maior redução de ruído. Mesmo que houvesse tempo para lidar com o trabalho e outras questões relacionadas a dívida operacional, existe a necessidade de planejamento antecipado. Uma analogia é que o trabalho é o pagamento de juros operacionais sobre dívida técnica. Pagar somente os juros não reduzir a dívida. A responsabilidade pela produção é uma estratégia melhor do que ter uma equipe de operações sem poder, mas o nível de dor na produção irá permanecer o mesmo. Equipes com funções combinadas certamente dividem a dor na produção de maneira mais justa, mas há soluções melhores, que reduzem essa dor. Tanto os clientes quanto às equipes de desenvolvimento se beneficiam quando pagamos dívidas técnicas e operacionais.
Uma abordagem melhor: A excelência em produção
Ao invés de tentar resolver o problema da responsabilidade em produção com ferramentas ou integrações forçadas, é necessária uma abordagem diferenciada e centrada nas pessoas: Na excelência em produção.
A excelência em produção é um conjunto de habilidades e práticas que permitem que as equipes confiem na própria responsabilidade. As habilidades de excelência em produção são frequentemente encontradas nas equipes ou indivíduos com o título de SRE, mas esse domínio não deve ser única e exclusivamente deles. Fechar o ciclo de feedback sobre a responsabilidade de produção exige que espalhemos essas habilidades por todos os membros das equipes. Abaixo da responsabilidade em produção, as operações se tornam responsabilidade de todos, ao invés de ser "um problema de outra pessoa". Todo membro da equipe precisa ter uma fluência básica das operações e da excelência em produção, mesmo que esse não seja o seu foco em tempo integral. E as equipes precisam de apoio ao cultivar essas habilidades e precisam se sentir recompensadas por elas.
Crédito: Emily Griffin (@emilywithcurls)
Existem quatro elementos-chave para formar uma equipe e o serviço que suporta e executa de maneira previsível no longo prazo. Primeiro, as equipes devem concordar sobre quais eventos melhoram a satisfação do usuário, e como podem eliminar os alertas estranhos para que não voltem acontecer. Segundo, precisam melhorar a capacidade de explorar a saúde da produção, começando com sintomas da dor do usuário ao invés de explorar o potencial baseado nas causas. Terceiro, devem garantir que colaborem e compartilhem conhecimento entre si e que possam treinar novos membros. Por fim, precisam de uma estrutura para priorizar quais riscos remediar, para que o sistema seja confiável o suficiente para que as necessidades do cliente possam funcionar de uma maneira sustentável.
1. Avalie o que importa
Tornar os períodos de serviço toleráveis começa com a redução do barulho e a melhoria da correlação entre alertas e problemas reais do usuário. Os objetivos de nível de serviço (SLOs), um dos pilares da prática do SRE, ajudam a criar um ciclo de feedback para manter os sistemas funcionando bem para atender às expectativas de longo prazo dos usuários. A ideia central dos SLOs é que as falhas sejam algo normal, e que precisamos definir um nível aceitável dessas falhas, ao invés de desperdiçar a agilidade no desenvolvimento com foco na perfeição. Como diz Charity Majors, "Seu sistema existe em um estado contínuo de degradação parcial. No momento. Existem tantas coisas erradas e quebradas que ainda não sabemos." Em vez de enviar alertas que seriam ruídos do sistema, devemos abordar padrões mais amplos, relacionados a falhas que arriscam a felicidade dos usuários.
Portanto, precisamos quantificar as expectativas de cada usuário através da qualidade da experiência fornecida cada vez que ele interage com os sistemas. Precisamos medir de forma agregada a satisfação de todos os nossos usuários. Podemos começar a elaborar esse indicador de nível de serviço (SLI) medindo as taxas de latência e de erro, registrando fatores como taxas de abandono, obtendo assim um feedback direto com os usuários.
O ideal é que os gerentes de produto e equipes de sucesso do cliente saibam com quais fluxos de trabalho os usuários mais se preocupam e quais são os limites aproximados de latência ou taxa de erro que induzem a abertura de chamados. Ao transformar essas diretrizes em limites categorizáveis de máquina (por exemplo, "essa interação é boa se for concluída em 300 milissegundos e se for atendida com um código HTTP 200" ou "esse registro de dados é suficientemente novo se foi atualizado nas últimas 24 horas"), com isso podemos analisar o histórico de desempenho do sistema como um todo, em tempo real. Por exemplo, podemos definir uma meta para o sistema de que 99,9% dos eventos selecionados sejam bem-sucedidos em um período de três meses: Um orçamento de erro de um para cada mil eventos, dentro de cada período.
Crédito: Emily Griffin (@emilywithcurls)
Ao definir metas de desempenho e estabelecer uma margem de erros esperados ao longo do tempo, torna-se possível ajustar os sistemas para ignorar pequenos bugs auto solucionáveis e enviar alertas apenas se o sistema exceder significativamente os limites nominais. Se e somente a taxa de erros atual estiver nos empurrando para o limite de erros nas próximas horas, e o sistema alertará um humano. E podemos experimentar as prioridades de engenharia para verificar se há tolerância de reposição e mais velocidade disponível ou podemos focar novamente no trabalho de confiabilidade, e se estamos excedendo os níveis aceitáveis de falha. Se uma equipe ficar aquém da margem de erro e se os usuários estiverem reclamando, talvez a equipe precise priorizar as correções de infraestrutura ao invés de desenvolver novos recursos.
Um compromisso de equipe escrito para defender o SLO em perigo, fornece suporte institucional ao trabalho de confiabilidade. Um SLO que atinge um certo equilíbrio deve deixar que o usuário cometa um erro raro e tente novamente mais tarde, ao invés dele ligar para o suporte e cancelar o contrato porque o serviço está constantemente inativo.
Crédito: Emily Griffin (@emilywithcurls)
Os SLOs podem mudar à medida que as expectativas do usuário mudam e à medida que diferentes mudanças entre velocidade e confiabilidade se tornam possíveis. É melhor focar em qualquer SLO orientada ao usuário, não importa quão rústico seja, do que ter muitas métricas desprovidas de correlação com o impacto do usuário que nos deixam cegos e surdos.
2. Debugando com observabilidade
Após eliminar os alertas de baixo nível, o que devemos fazer se o sistema mostrar que nosso serviço não está funcionando de acordo com os SLOs? Precisamos ter a capacidade de depurar e detalhar para entender quais subconjuntos de tráfego estão enfrentando ou causando problemas. Crie hipóteses sobre como mitigá-los e resolvê-los, depois realize testes para certificar se as coisas voltaram ao normal.
A capacidade de depurar está intimamente relacionada à ideia de observabilidade, de ter o sistema produzindo telemetria suficiente para nos permitir entender o estado interno sem precisar perturbá-lo ou modificar o código. Com conhecimento suficiente do sistema e do desempenho, esperamos testar as hipóteses para explicar e resolver a variação dos resultados para os usuários com problemas. O que há de diferente entre as solicitações que estão levando 500 milissegundos agora, com as solicitações de 250 milissegundos? Podemos fechar a lacuna identificando e resolvendo o problema de desempenho que faz com que o subconjunto de solicitações demore mais?
Crédito: Emily Griffin (@emilywithcurls)
Apenas medir e reunir todos os dados não é suficiente. Devemos ser capazes de examinar os dados pelo contexto e usarmos novas maneiras para diagnosticar os problemas. Precisamos de observalidade, porque não podemos depurar os sistemas apenas no que pensamos em medir com antecedência. As falhas complexas dos sistemas geralmente surgem devido a novas combinações de causas, e não de um conjunto finito e fixo delas. Como consequência, por muitas vezes não podemos reproduzir as falhas de produção em ambientes de teste de menor escala e não podemos prever com antecedência.
Independentemente da nossa abordagem da observabilidade, é é necessário obtermos informações suficientes de como as solicitações chegam até os nossos sistemas distribuídos. Cada local que uma solicitação atravessa um microservice é um possível ponto de falha que devemos monitorar. Isso pode assumir a forma de eventos amplos com metadados, rastreamentos distribuídos, métricas ou logs. Cada abordagem tem suas vantagens e desvantagens com relação às ferramentas de suporte, granularidade de dados, flexibilidade e contexto. Muitas vezes precisamos que as ferramentas funcionem juntas para fornecer um conjunto de recursos necessários. E os problemas irão atrapalhar até mesmo o solucionador mais competente, se não pudermos seguir rastrear até as instâncias mais específicas que estão falhando nos fluxos de trabalho do usuário.
Ao registrar a telemetria com flexibilidade e fidelidade suficiente, não precisamos manter o problema para analisar o comportamento. Podemos restaurar o serviço aos usuários o mais rápido possível, confiantes de que poderemos reproduzir o problema e depurá-lo quando tivermos tempo. Isso nos permite mitigar automaticamente classes inteiras de problemas, como reverter implementações ruins, e fazer uma investigação humana durante o horário normal de trabalho sobre o que deu errado. A operabilidade do sistema melhora quando os humanos não precisam depurar totalmente e resolver cada falha em tempo real.
3. Colaboração e desenvolvimento de habilidades
Mesmo com um conjunto perfeito de SLOs e instrumentação para observabilidade não resulta necessariamente em um sistema sustentável. As pessoas são obrigadas a depurar e executar os sistemas. Ninguém nasce sabendo como depurar, então todo engenheiro deve aprender isso em algum momento. À medida que os sistemas e as técnicas evoluem, todos precisam evoluir de maneira contínua, criando novos insights.
É importante desenvolver programas de treinamentos, escrever documentação completa e atualizada sobre pontos de partida comuns para o diagnóstico e manter as retrospectivas impecáveis. A responsabilidade pelo serviço não significa criar egoísmo e silos, pelo contrário, temos que compartilhar os conhecimentos com o passar do tempo. Acima de tudo, as equipes devem promover uma atmosfera de segurança psicológica, na qual os membros da equipe e os que estão fora dela possam fazer perguntas. Isso capacita os indivíduos a aprofundar sua compreensão e trazer novas perspectivas para os problemas.
As interações entre equipes podem abranger não apenas as relações entre níveis hierárquicos, tanto de cima pra baixo quanto de baixo para cima, mas também entre as funções, como suporte ao cliente, desenvolvimento de produtos e SRE. Se um engenheiro de suporte ao cliente foi acionado na última vez em que disparou um alarme falso, eles sentirão que não podem escalonar os problemas com segurança, e com isso terão problemas para detectar e resolvê-los.
Crédito: Emily Griffin (@emilywithcurls)
É fundamental para o processo de aprendizado que todos tenham alguma maneira de expor as falhas de produção. No entanto, muitas abordagens à responsabilidade de produção são infinitamente claras, como colocar todos os desenvolvedores de plantão 24 horas por dia, sete dias por semana. Os desenvolvedores se opõem a participar de processos estressantes e não adaptados às suas vidas. O medo de mudar as tarefas de cada cargo ou de serem percebidos como pessoas que evitam as atividades e se não cumprirem irão prejudicar a moral da equipe.
A produção precisa ser de responsabilidade dos engenheiros de todas as áreas, e não apenas daqueles que se encaixam em um molde específico. O envolvimento em produção não precisa ser uma escolha binária de fazer plantões ou não , afinal, pode assumir formas variadas, como triagem dos chamados do suporte para uma pessoa que não pode lidar com o estresse de ser chamado no do dia ou ficar de plantão apenas durante o horário comercial para aqueles que possuem responsabilidades familiares no decorrer da noite. Outros exemplos podem ser um colaborador que é judeu devoto e que não pode ficar de plantão durante o sábado, ou o plantão vespertino de um gerente que não deseja que ligações inesperadas interrompam seu horário comercial individual. Juntos, uma equipe pode colaborar para compartilhar de maneira justa o fardo da responsabilidade de produção com base nos contextos e necessidades de cada um.
4. Análise de Risco
O elemento final da excelência na produção é a capacidade de se antecipar e resolver os problemas estruturais que representam um risco para o desempenho do sistema. Podemos identificar gargalos de desempenho e classificar as falhas antes que se tornem críticas. Ser proativo significa, saber como substituir dependências complicadas por dependências mais simples antes que comecem a falhar. Da mesma forma, não devemos esperar que os usuários comecem a se queixar de que o sistema está muito lento antes de otimizar os caminhos mais críticos. Ainda precisamos de uma parte do nosso orçamento de erros para lidar com novas falhas do sistema, mas isso não nos impede de lidar com os riscos já conhecidos.
O truque é identificar quais riscos são os mais críticos e fazer sua correção. Na década de 1960, o programa americano de pouso na lua da Apollo reuniu uma lista de riscos conhecidos e trabalhou para garantir que eles se acumulassem dentro dos parâmetros de segurança do programa. Hoje, as equipes do Google SRE defendem a análise e a priorização de riscos. Propõem ainda, uma estrutura de análise quantitativa de riscos usando o tempo para detectar e reparar, multiplicado pela gravidade do impacto e pela frequência ou probabilidade de acontecer novamente.
Nem sempre podemos controlar a frequência dos eventos, mas podemos reduzir os tempos de resposta, diminuir a gravidade do impacto ou até mesmo reduzir o número de usuários que serão afetados. Por exemplo, podemos escolher implantações canárias ou sinalizadores de recursos para reduzir o impacto de alterações ruins para os usuários e acelerar a reversão, se necessário. O sucesso de uma melhoria é a redução do tempo com problemas para o usuário médio. Uma estratégia de implantação canária pode reduzir as interrupções relacionadas à implantação em 100% dos usuários por duas horas uma vez por mês (120 minutos com problemas por usuário por mês) para afetar 5% dos usuários por 30 minutos uma vez por mês (1,5 minutos com problemas por usuário por mês).
Crédito: Emily Griffin (@emilywithcurls)
Qualquer risco isolado que possa gastar uma parte significativa da nossa cota de erros é algo que deve ser resolvido muito rapidamente, pois isso pode causar uma falha catastrófica no sistema e nos forçar a usar toda a cota. Podemos abordar as outras fontes menores de risco posteriormente, se ainda estivermos excedendo o orçamento de erros. E com uma análise quantitativa enumerando a fração do orçamento de erros que cada risco consumirá, fica mais fácil argumentar sobre quais são prioridades ou ainda quando abordar os riscos existenciais ao invés de desenvolver novos recursos.
A análise dos risco individuais, não é só flores. Ela falha geralmente ao encontrar temas que são comuns a todos os riscos. A falta de medição, de observabilidade e de colaboração (os três aspectos principais que faltavam da excelência em produção) representam riscos sistemáticos que pioram todos os demais, tornando as interrupções mais longas e difíceis de descobrir.
O suporte à produção não precisa ser doloroso
As abordagens bem-sucedidas de longo prazo na responsabilidade da produção e do DevOps requerem mudanças culturais na forma da excelência em produção. As equipes são mais sustentáveis se tiverem medidas bem definidas de confiabilidade, capacidade de depurar novos problemas, uma cultura que promove a disseminação de conhecimento e uma abordagem proativa para mitigar os riscos. Embora as ferramentas possam desempenhar um papel no suporte a um sistema confiável, a cultura e as pessoas são o investimento mais importante.
Sem práticas maduras de observabilidade e colaboração, o sistema desmorona sob o peso da dívida técnica, não importando quantas pessoas e quanto dinheiro seja gasto para fazer a máquina girar. A liderança das equipes de engenharia deve ser responsável pela criação de estruturas de equipe e sistemas técnicos que possam atender de forma sustentável às necessidades dos usuários e à saúde dos negócios. As estruturas de responsabilidade e excelência da produção ajudam as modernas equipes de desenvolvimento a obter sucesso. Não podemos esperar que as equipes de operações sem nenhum poder tenham sucesso por conta própria.
Sobre a autora
Liz Fong-Jones é defensora dos desenvolvedores, organizadora de trabalho e ética, e engenheira de confiabilidade local com mais de 15 anos de experiência. Ela trabalha na Honeycomb.io nas comunidades SRE e de observabilidade, anteriormente trabalhava na SRE dos produtos que variam da Google Cloud Load Balancer ao Google Flights..