Práticas de Engenharia · CI/CD

Por Que Eu Separo o Provisionamento do Deploy da Aplicação

Infraestrutura e código de aplicação mudam em ritmos muito diferentes. Fazer o deploy dos dois juntos deixa os pipelines mais lentos, mais arriscados e mais difíceis de depurar.

Por que separar o deploy de infra e de aplicação

Não existe certo ou errado em engenharia de software, apenas trade-offs. Quando você decide fazer algo, está decidindo não fazer outra coisa. Misturar o provisionamento de infraestrutura com o deploy da aplicação é uma dessas decisões, e é comum vermos times tomarem essa decisão sem perceber o custo.

Os Ciclos de Vida São Completamente Diferentes

Imagine uma aplicação com o seu próprio banco de dados, um service bus, um App Service plan e um App Service. Depois de criar tudo isso e configurar as connection strings, com que frequência você muda esses recursos?

Muito raramente.

Agora, se você faz deploy com frequência (o que eu recomendo), está rodando essa mudança de infraestrutura junto com cada deploy da aplicação. Por que estamos verificando se a fundação mudou toda vez que publicamos uma correção de bug?

A melhor analogia que tenho é um prédio. A infra é a fundação, as paredes, até a iluminação. A aplicação é a mobília. A mobília muda de lugar o tempo todo. A fundação fica parada.

Nos meus projetos, o repositório de provisionamento (Bicep ou Terraform) muda uma vez a cada poucas semanas. O código da aplicação muda várias vezes por dia.

“Mas Como Eu Lido com os Ambientes?”

Esse é o argumento mais comum para colocar tudo no Bicep. No .NET, você não precisa. Você tem appsettings.Production.json, appsettings.Staging.json, appsettings.Test.json. A única coisa que a infra fornece é uma variável de ambiente por ambiente, e a aplicação escolhe a configuração certa.

A vantagem é significativa: tudo fica visível no código da aplicação. Apareceu um problema em produção? Aponte a variável de ambiente para a configuração de produção localmente, e a sua aplicação fica configurada exatamente como em produção.

E os segredos e as connection strings? Raramente eles devem ficar na configuração. Eles ficam no Key Vault (ou no KMS, na AWS) e a configuração guarda apenas uma referência a eles. Se precisar depurar localmente, você precisa de acesso aos segredos, e só.

Misturar os Dois Complica o Seu Pipeline

Um pipeline que roda Bicep, roda testes unitários, compila o código, publica pacotes e publica imagens Docker fica cada vez mais complexo. Na minha experiência, a parte de provisionamento representa de 30 a 40% desse pipeline, em tempo de execução e em YAML. Tire essa parte e o pipeline fica menor, mais rápido e menos instável.

Pense em quanto tempo de pipeline vai para validar e fazer deploy de scripts Bicep que não tiveram nenhuma mudança. Estamos fazendo deploy de uma nova versão de algo que não mudou, toda vez.

E existe um risco ainda pior. Se você roda Terraform ou Bicep em todo deploy, também corre o risco de apagar recursos em todo deploy. Rodar um script que pode apagar o seu banco de dados só para publicar um botão novo é um risco que vale a pena revisitar.

O Que Quebrou?

Você faz o deploy em produção e algo falha. Foi o Bicep ou o código da aplicação? As permissões foram aplicadas? Algum recurso foi recriado?

Se o deploy contém apenas código da aplicação, normalmente você sabe na hora. Gerenciar complexidade é uma das coisas mais importantes que fazemos em desenvolvimento de software, e essa é uma complexidade que você pode simplesmente remover.

Sim, você introduz o risco de a infra e a aplicação divergirem. Isso é administrável e, na maioria dos casos, bem mais barato do que a alternativa.

Deixe a Aplicação Criar as Próprias Filas

Outro padrão comum que vale a pena revisitar: usar Bicep para criar filas e tópicos.

Eu prefiro que a aplicação crie esses recursos na inicialização. Os nomes das filas, os tópicos, o número de partições, as subscriptions: tudo isso é responsabilidade da aplicação. Se o Bicep é dono deles, você passa a ter que coordenar duas coisas toda vez que adiciona uma fila, e essa coordenação existe mesmo que os dois estejam no mesmo repositório. Se a aplicação é dona, não há nada para coordenar. Ela só precisa da permissão certa da managed identity no service bus.

Muito mais simples, muito mais fácil.

Como Eu Faço

Dois repositórios:

  • provision: o Terraform ou Bicep. Faz o deploy dos recursos. Muda a cada poucas semanas.
  • application: o código. Faz o deploy em cima dos recursos provisionados. Muda todo dia.

Rode o provision primeiro, depois faça o deploy da aplicação. Dá para fazer os dois no mesmo repositório, criar um ambiente novo e fazer o deploy de uma vez só? Claro, dá para fazer. Só que isso adiciona complexidade a todo deploy para otimizar algo que raramente acontece.

Para Fechar

“Não existe certo ou errado, apenas trade-offs.” Thomas Sowell

Manter infra e aplicação juntas é conveniente no primeiro dia. O trade-off são pipelines mais lentos, mais instáveis e maiores, um raio de impacto mais arriscado e uma depuração mais difícil em todo deploy depois disso.

Quanto do seu pipeline está fazendo deploy de coisas que raramente mudam?