↓Pular para o conteúdo principal
  1. blog/
ARTIGO TÉCNICO

Automatizando ativação de servidores Linux com um padrão reproduzível

Como transformar ativação de servidor Linux em uma rotina reproduzível com Ansible, parâmetros explícitos, blast radius controlado, PLAY RECAP e critérios claros de validação e escalação.

Ativar servidor manualmente funciona.

Até o dia em que existem dez pessoas fazendo a mesma coisa de dez jeitos diferentes.

Um instala o pacote que lembra. Outro copia um arquivo antigo. Um terceiro esquece o monitoramento. O quarto termina tudo certo, mas ninguém consegue dizer exatamente qual receita foi aplicada.

Foi por isso que eu passei a tratar provisionamento como produto operacional, não como uma sequência de comandos.

A ideia é simples: receber um host novo, escolher uma receita, preencher parâmetros conhecidos e terminar com um estado que possa ser validado e repetido.

O que eu queria eliminar #

Um servidor novo normalmente precisa de várias peças antes de estar pronto para receber aplicação:

  • configuração base do Linux;
  • Docker quando a stack usa containers;
  • Nginx;
  • TLS/SSL;
  • monitoramento;
  • aplicação ou runtime correspondente;
  • ajustes de acesso;
  • validação final.

Fazer isso por checklist manual não é errado. O problema é que checklist não garante execução idêntica.

A automação precisa resolver outra pergunta:

como eu sei que dois servidores ativados em momentos diferentes passaram pelas mesmas regras?

O template precisa começar pelo alvo #

No Semaphore, uma das regras mais importantes do runbook é preencher explicitamente o campo de limite/alvo antes de rodar uma tarefa que altera ambiente.

Isso existe por um motivo bem pouco glamouroso: em automação, um parâmetro em branco pode mudar o blast radius inteiro.

A operação de ativação foi classificada internamente como risco médio e blast radius de um host novo.

Esse detalhe é mais importante que o playbook bonito.

Antes de perguntar “o que a task instala?”, eu quero saber:

1
2
3
4
5
6
Onde ela roda?
Quantos hosts ela pode atingir?
O que ela muda?
É reversível?
Como eu confirmo o resultado?
Quando eu paro e escalo?

Uma entrada pequena, uma receita conhecida #

Em vez de expor dezenas de variáveis para quem executa a ativação, o template trabalha com um conjunto menor de parâmetros operacionais.

Conceitualmente:

1
2
3
4
tipo_ativacao: receita desejada
projeto: nome do host/projeto
ip: endereço do servidor novo
dominio: opcional

O tipo_ativacao seleciona a receita adequada para aquele servidor.

Isso permite manter diferenças reais entre stacks sem transformar cada ativação em um playbook completamente novo.

A mesma ideia vale para qualquer operação com perfis distintos:

1
2
3
4
5
base comum
  ├── receita A
  ├── receita B
  ├── receita C
  └── receita D

O que for igual fica na base. O que realmente muda fica na receita.

Compatibilidade também precisa ser explícita #

Outro padrão que apareceu nos playbooks foi normalizar arquitetura e distribuição antes de chamar roles mais antigas.

Um exemplo simplificado:

1
2
3
4
5
6
server_arch: >-
  {{
    'amd64' if ansible_architecture in ['x86_64', 'amd64']
    else 'arm64' if ansible_architecture in ['aarch64', 'arm64']
    else ansible_architecture
  }}

Parece burocracia, mas evita que cada role tente interpretar arquitetura por conta própria.

Em ambientes mistos, essa camada de normalização vale muito.

Separar roles deixa a intenção legível #

Para um servidor de banco dedicado, por exemplo, a composição pode ficar próxima de:

1
2
3
4
roles:
  - common
  - monitoring
  - database_role

Isso ajuda em duas frentes.

Primeiro, fica claro o que pertence à base do servidor e o que pertence à função específica dele.

Segundo, a mesma role de monitoring pode ser aplicada em vários tipos de host sem copiar task de Zabbix para cada playbook.

A automação começa a escalar quando reuso deixa de significar copiar YAML.

Monitoramento entra no provisionamento, não depois #

Uma das escolhas que considero mais importantes é instalar monitoramento como parte da ativação.

Servidor não deveria chegar ao status de “pronto” e só depois alguém lembrar que ainda precisa cadastrá-lo na observabilidade.

Se o monitoramento é requisito operacional, ele faz parte da definição de pronto.

A mesma lógica vale para:

  • Nginx válido;
  • serviço habilitado;
  • firewall coerente;
  • certificado quando aplicável;
  • acesso administrativo;
  • aplicação respondendo.

PLAY RECAP virou contrato de execução #

No runbook, a execução termina com uma checagem simples e objetiva: olhar o PLAY RECAP.

O padrão operacional é:

1
2
failed=0  → a execução terminou sem task falhar
failed>0  → parar, coletar log e escalar

Isso não significa que failed=0 prova sozinho que a aplicação está funcional.

Ele prova uma coisa mais limitada: o Ansible completou as tasks sem registrar falha.

Depois ainda entram testes funcionais compatíveis com a receita.

Essa separação é saudável porque evita transformar um sinal de automação em uma promessa maior do que ele realmente significa.

Reboot automático muda a classificação de risco #

A rotina documentada termina com reboot do servidor.

Nesse caso específico, o alvo é um host novo. Mesmo assim, isso torna a ação parcialmente reversível e merece aparecer no runbook.

Se a mesma task pudesse atingir um host atendendo produção, a classificação de risco seria completamente diferente.

É por isso que eu gosto de documentar junto do template:

1
2
3
4
5
6
Risco
Blast radius
Reversibilidade
Pré-requisitos
Resultado esperado
Quando escalar

Automação segura não é só código correto. É contexto operacional embutido no processo.

Nem toda automação pronta tecnicamente está liberada para rotina #

Um detalhe importante da fonte desse caso: a tarefa estava em revalidação parcial.

O playbook existia, havia passado por correções, mas o runbook ainda exigia executar e registrar cada tipo de receita antes de considerar o fluxo liberado para uso rotineiro.

Isso é uma distinção que vale preservar:

  • código existe;
  • código passa syntax check;
  • execução terminou;
  • cenário foi testado;
  • rotina está homologada.

São estados diferentes.

Chamar tudo de “pronto” só porque o YAML está no repositório é pedir para descobrir a diferença em produção.

O que eu considero definição de pronto #

Para esse tipo de provisionamento, eu espero no mínimo:

  1. alvo explicitamente limitado;
  2. parâmetros validados;
  3. arquitetura/distribuição reconhecidas;
  4. roles executadas sem falha;
  5. monitoramento incluído;
  6. reboot, se previsto, concluído;
  7. host voltando acessível;
  8. serviços esperados ativos;
  9. endpoint funcional quando houver;
  10. log preservado para auditoria.

Se uma receita ainda não passou por execução real controlada, isso precisa estar escrito.

O ganho de verdade #

O principal benefício não é economizar os minutos de instalar Nginx ou Docker.

É conseguir responder:

“Como esse servidor foi ativado?”

E a resposta não depender da memória de quem estava de plantão.

Quando provisionamento vira receita versionada, com parâmetros explícitos, limite de alvo, validação e runbook, a operação fica menos artesanal.

Não elimina incidente.

Mas elimina uma categoria inteira de diferenças acidentais entre servidores — aquelas que só aparecem meses depois, quando dois hosts que deveriam ser iguais se comportam de formas completamente diferentes.

TEM UM CENÁRIO PARECIDO?

Me chama.

Manda o contexto, os sintomas e o que já foi testado. Bora organizar as evidências antes de sair mexendo.

Falar com Castro →
Sem enrolação. Com evidência.