Cloud Intelligence™Cloud Intelligence™

Cloud Intelligence™

Forward vs. Reverse Engineering

By EvgenyJan 7, 20228 min read

Esta página também está disponível em English, Deutsch, Español, Français, Italiano e 日本語.

Assisti há pouco a uma apresentação sobre ferramentas e técnicas de gerenciamento de configuração, e ela acendeu uma ideia que vale a pena explorar.

Todo mundo concorda que ferramentas de gerenciamento de configuração no estilo infrastructure-as-code são essenciais e valiosas, mas, ao mesmo tempo, a frustração ao usá-las é bem alta. E se os mecanismos atuais de gerenciamento de configuração ou infrastructure-as-code deixassem de ser uma bagunça e uma dor de cabeça? Como seria isso?

O Mapa não é o Território — e muita gente confunde os dois

Este artigo explora como o DevOps e o desenvolvimento de software, de modo geral, podem se beneficiar de uma nova maneira de enxergar o provisionamento e a configuração de sistemas, ressignificando termos comuns sob uma nova ótica.

Vamos começar com algumas definições que vão ajudar a entender melhor o mundo ao nosso redor e a abordar alguns dos problemas que tanta gente enfrenta.

Terminologia explicada

Operações: a prática de garantir que sistemas de software estejam funcionando bem e atendendo às necessidades dos usuários. O engenheiro de operações geralmente está menos preocupado em escrever código novo; o foco dele é como o software já existente se comporta dentro de um sistema existente.

Com esses dois termos definidos, dá para explicar a diferença entre "forward engineering" e "reverse engineering".

Forward engineering

Forward engineering é construir um sistema com base em um modelo do que deveria existir nele. Normalmente, no FE cria-se primeiro o modelo e, depois, esse template é implantado e configurado em produção. A expectativa é que o sistema resultante corresponda de perto ao modelo.

Em muitos casos, o modelo declarado é ambíguo, e o sistema pode se comportar de formas inesperadas, fora da intenção original. Isso, por si só, já é um obstáculo significativo para o uso dessas técnicas, especialmente para iniciantes.

Para piorar, o próprio sistema costuma divergir do modelo por causa da interação com o ambiente — por exemplo, quando várias partes alteram a configuração umas das outras, ou quando engenheiros executam procedimentos ad-hoc que mudam o sistema de várias formas.

No forward engineering, não existe uma noção fundamental de feedback para o modelo inicial. O modelo é "gravado em pedra" primeiro e implantado depois. Qualquer feedback recebido posteriormente do sistema sobre seu comportamento pode ser usado em novas iterações de modelos e implantações futuras.

Reverse engineering

Reverse engineering é desenvolver um modelo parcial a partir de um sistema existente e usá-lo como base para fazer modificações. Não há um modelo inicial, e é o estado atual do sistema que permite descobrir como as coisas deveriam funcionar.

As alterações nesse tipo de sistema, em muitos casos, são feitas de forma ad-hoc direto nele, muitas vezes sem um entendimento completo do todo. Aqui, o feedback é imediato, e explorar um sistema é, em grande parte, cutucá-lo e observar a resposta.

Onde encontramos o reverse engineering? Você provavelmente já ouviu que especialistas em segurança usam práticas de RE para vasculhar softwares existentes em busca de falhas. Eles examinam serviços de rede ou memória para identificar comportamentos anormais e exploram essas brechas para fazer o sistema agir de forma não pretendida.

Reverse engineering tem tudo a ver com olhar para um sistema ou software existente e, com base no que ele faz na prática, tentar entender onde estão as lacunas em relação à intenção original.

E onde encontramos essas ideias no mundo do DevOps?

Infrastructure as code

Desde o lançamento da primeira versão do CFEngine, em 1993, a ideia de modelar a infraestrutura como código teve uma popularidade explosiva no mercado de engenharia de software. Tudo começou com a declaração de como deveria ser o conteúdo do sistema operacional de um servidor e foi rapidamente adaptado para descrever o layout e a configuração de recursos de nuvem hoje em dia. Empresas e ferramentas entraram e saíram de cena ao longo dos anos, como Puppet, Chef, Salt, Ansible, CloudFormation, Terraform, CDK, Pulumi e diversas outras soluções caseiras.

O que a maioria dessas ferramentas têm em comum é o fato de serem declarativas. Ferramentas declarativas permitem apenas especificar como as coisas devem ser, sem detalhar os passos para chegar lá. Nos últimos anos, surgiram várias ferramentas que se dizem mais imperativas. Mesmo assim, elas continuam sendo majoritariamente declarativas e bem diferentes das linguagens imperativas tradicionais usadas para escrever código.

Por que a maioria dessas ferramentas é declarativa?

Resumindo: porque essa é a forma mais fácil de criar mapas, modelos e templates. O engenheiro só precisa declarar como as coisas devem ser e onde cada item deve ficar, e delega o trabalho duro de descobrir como encaixar cada peça no lugar certo. Isso permite melhorias iterativas ao longo do tempo e, no fim, leva a sistemas mais robustos e estáveis.

Outra vantagem comum das ferramentas declarativas de infrastructure-as-code é a propriedade da idempotência. Idempotência significa repetir uma ação várias vezes obtendo um resultado consistente. Ao usar uma ferramenta idempotente para alterar um sistema várias vezes, ele acaba chegando ao estado declarado pelo template. Aplicar o mesmo template de novo depois disso não tem mais efeito sobre o sistema. Idempotência é a propriedade que permite aplicar o modelo várias vezes e só ter mudanças quando houver diferenças em relação a ele.

Uma abordagem imperativa exigiria primeiro encontrar todas as diferenças entre o modelo e o sistema e, em seguida, implementar cada passo necessário para cada mudança. As ferramentas declarativas de infrastructure-as-code conseguem isso sem que o desenvolvedor precise escrever todas as ações na mão.

As ferramentas de infrastructure-as-code são populares e essenciais; elas economizam milhares de horas de trabalho ao criar templates reutilizáveis e gerar réplicas de sistemas quase idênticos em diferentes ambientes com esforço marginal mínimo.

Infrastructure-as-code promete que a melhoria iterativa do modelo ao longo do tempo leva a sistemas robustos e estáveis baseados nesse modelo.

Um artigo anterior meu sobre configuração para múltiplos sistemas explica como réplicas de sistemas quase idênticos são benéficas para uma empresa de software.

Mas! Essas ferramentas adotam a mentalidade do forward engineering, já que são declarativas e não têm mecanismos para receber feedback de um sistema em execução. Esse tipo de abordagem deu origem, ao longo dos anos, a vários problemas e reclamações por parte dos usuários — e é isso que vamos explorar.

Problemas do infra-as-code só com forward engineering

Você já ouviu o termo Configuration Drift? Ele acontece quando o modelo declarado não corresponde mais ao estado de um sistema. Todo sistema, com tempo e atualizações suficientes, quase sempre acaba diferente do modelo usado para criá-lo.

O drift pode ocorrer quando um desenvolvedor altera o código do modelo sem atualizar todos os sistemas construídos a partir dele, ou quando um engenheiro faz operações exploratórias ad-hoc e modifica um sistema sem voltar ao template para atualizar o código. Ambas as atividades são essenciais: os desenvolvedores fazem a primeira para introduzir melhorias em iterações futuras de implantações, e os engenheiros de operações costumam fazer a segunda para descobrir problemas desconhecidos e tratá-los.

O configuration drift é, claro, uma armadilha à espreita, e é por isso que todo mundo diz que você deve evitar drift na configuração. Mas é realista proibir os operadores de operar os sistemas para impedir qualquer exploração ad-hoc? Sim. Algumas empresas adotam a regra de que nenhum operador ou desenvolvedor pode mexer em um sistema "em produção viva". Dá para imaginar o que esse tipo de política faz com a métrica de Mean-time-to-Recover desses sistemas. Por experiência própria, quando WTSHTF e um sistema de "produção" quebra por qualquer motivo, essa é a primeira regra que vai pela janela, e a exploração ad-hoc é imediatamente liberada para qualquer um que consiga descobrir o que está acontecendo.

Engenheiros atraídos pela adoção de infrastructure-as-code reclamam que dá trabalho demais remodelar do zero um sistema já existente. Sempre tem alguém criando uma ferramenta para ajudar nisso. O Google tem o GCP Terraformer, a AWS tinha o (já descontinuado) AWS CloudFormer, e até o Azure tem seu ARM espalhado por todo o console da nuvem. Sempre tem alguém construindo uma ferramenta dessas para a sua linguagem favorita de gerenciamento de configuração, porque a demanda é altíssima.

Mas, infelizmente, depois de usar uma dessas ferramentas, o engenheiro costuma sair decepcionado. O resultado ou tem ruído demais e pouco sentido, ou, na melhor das hipóteses, já está obsoleto um dia depois. O melhor que dá para fazer com um template gerado por engenharia reversa é copiar e colar trechos dele em um template escrito manualmente em outro lugar.

Como melhorar o caminho à frente

Este artigo definiu dois termos e mostrou por que o forward engineering puro é subótimo para a operação real de sistemas e como, na maioria dos casos, o reverse engineering continua sendo indispensável para encontrar e resolver problemas.

A proposta agora é criar uma nova geração de ferramentas de Infrastructure-as-Code — ferramentas que coloquem o reverse engineering no centro e permitam que o feedback de sistemas em produção atualize os modelos que os geraram. O operador pode então adotar a mudança ad-hoc ou rejeitá-la, revertendo o sistema ao estado declarado no modelo original.

As ferramentas atuais consideradas padrão de mercado falham em ajudar os engineers a resolver os problemas que surgem na operação dos sistemas. Sim, existem várias ferramentas que auditam seus templates Terraform e avisam sobre erros ou má configuração. Essas auditorias ajudam, mas o real valor desse tipo de apoio está em inspecionar um sistema vivo e existente — não apenas o template que os engineers usaram para criá-lo.

Até onde sei, ainda não temos uma ferramenta boa o suficiente para integrar mais práticas de reverse engineering ao dia a dia dos engenheiros de operações. Temos muitas ferramentas de monitoramento e observabilidade de um lado, e várias ferramentas de infrastructure-as-code do outro, com uma lacuna considerável no meio.

Você tem ideias de como podemos preencher essa lacuna? Conta pra gente!

Imagem de capa criada por Tabea Schimpf no Unsplash.