Home Comunidade Eventos YouTube Networks Desafios // produtos Academy News CTI | CVE Contato

04 - Ansible, Chef, Puppet (Configuração)

#ansible#chef#configuracao#puppet#ssh
video explicativo
Video explicativoEspaco reservado para o video desta anotação — adicione video: https://youtu.be/... no frontmatter da nota.

Ansible, Chef, Puppet (Configuração)

Ansible, Chef e Puppet formam a família de ferramentas de gerenciamento de configuração do IaC: enquanto Terraform e CloudFormation criam recursos de nuvem, elas configuram o que roda dentro das máquinas, pacotes, arquivos, serviços, usuários e patches, mantendo o estado convergido ao longo do tempo. Ansible domina o mercado atual com execução sem agente por SSH e playbooks declarativos em YAML; Chef, com receitas escritas em Ruby, e Puppet, com modelo declarativo de agente e servidor, perderam espaço relativo, mas seguem em operações corporativas grandes, em especial onde há investimento histórico em suas plataformas. A distinção conceitual que organiza o módulo é provisioning versus configuration management: provisionar é fazer a máquina existir; configurar é torná-la útil e mantê-la correta. Em arquiteturas imutáveis, o papel dessas ferramentas migra para a construção de imagens e para o bootstrap; em frotas mutáveis de longa vida, elas continuam sendo o mecanismo de convergência contínua. Este arquivo cobre o modelo de cada ferramenta, o papel atual de cada uma no mercado e os critérios de comparação para decisão real.

Conceito: provisioning versus configuration management

Provisionamento cria a infraestrutura: rede, instância, disco, banco. Gerenciamento de configuração transforma a máquina recém-criada em servidor funcional: instala pacotes, escreve arquivos, habilita serviços, aplica hardening e mantém esse estado ao longo do tempo. A fronteira é limpa no desenho e frequente em discussão: Terraform não instala o runtime de aplicação no host, e Ansible não provisiona a VPC de forma idiomática. Operações maduras usam as duas camadas com fronteiras explícitas.

O problema que a camada de configuração resolve é a deriva. Uma frota mutável vive sob mudança contínua, patches, CVEs, ajustes de config, e sem convergência automática cada máquina vira um estado próprio. A ferramenta de configuração declara o estado desejado e reaplica em intervalo ou sob demanda: o servidor que deveria ter o agente de log instalado e não tem recebe o agente na próxima convergência, sem pessoa envolvida.

A distinção também muda com a imutabilidade. Em frota imutável, a configuração é congelada na golden image e o papel do gerenciamento de configuração se concentra na construção da imagem e na parametrização do boot. Em frota mutável, a convergência contínua é o mecanismo central de manutenção. A ferramenta certa depende, em parte, do modelo de frota que a operação adotou.

O problema que resolve

O alvo direto é a configuração manual via SSH, o fluxo em que o operador entra na máquina, edita arquivos e reinicia serviços, acumulando estados irreproduzíveis. Cada intervenção manual é uma diferença entre a máquina real e qualquer descrição que exista dela; cem máquinas sob intervenção manual são cem sistemas diferentes com o mesmo nome de serviço. Gerenciamento de configuração troca a intervenção por declaração e execução automática.

O segundo alvo é a escala da mudança. Atualizar a configuração de TLS em quinhentos servidores manualmente não é caro, é impossível de fazer de forma confiável; com convergência declarativa, é um commit reaplicado pela frota com rollout controlado. O terceiro alvo é a auditoria: com a configuração em código, o estado de qualquer máquina tem origem versionada, e o diff da última convergência responde o que mudou.

Há também o efeito de padronização organizacional. Módulos, roles e receitas compartilhados codificam padrões de segurança e operação: hardening de imagem, configuração de syslog, limites de kernel. O padrão deixa de ser documento para ser código aplicado, e a não conformidade vira problema detectável, não vira descoberta de auditoria seis meses depois.

Ansible: sem agente, SSH e playbooks idempotentes

Ansible executa de fora: um nó de controle conecta nas máquinas alvo por SSH e aplica módulos, sem agente instalado e sem serviço residente. O modelo simplifica adoção radicalmente, qualquer máquina alcançável por SSH é alvo imediato, e explica boa parte da ascensão da ferramenta; o custo é a exigência de conectividade e credenciais em massa, que em ambientes restritos vira projeto de rede e de chaves.

O código vive em playbooks YAML, com tasks que chamam modules idempotentes: package, service, template, copy, command. Inventários definem os grupos de alvo, roles organizam reuso, e variáveis e facts parametrizam a execução por ambiente. A idempotência é responsabilidade do autor, os módulos nativos cuidam disso por padrão, mas o módulo shell exige guarda, e é aí que playbooks mal escritos perdem a propriedade.

O modo ad-hoc é o segundo uso dominante: executar um comando em milhares de hosts de uma vez, com paralelismo controlado, é a rotina de operação que Ansible melhorou de forma mais visível. Reiniciar um serviço em frota, coletar versões, drenar nós, tudo isso vira uma linha de ansible com inventário e flag de paralelismo. Em plataforma de produção, o modo usual é push por CI, com credenciais efêmeras e inventário dinâmico gerado do próprio IaC.

# Playbook Ansible: hardening básico idempotente
- name: Preparar nós de aplicação
  hosts: app_servers
  become: true
  tasks:
    - name: Garantir pacotes base instalados
      ansible.builtin.package:
        name: "{{ item }}"
        state: present            # idempotente: só instala se faltar
      loop:
        - chrony
        - logrotate

    - name: Garantir serviço de tempo ativo
      ansible.builtin.service:
        name: chronyd
        state: started
        enabled: true             # convergência, não ação pontual

    - name: Aplicar limite de arquivos abertos no kernel
      ansible.posix.sysctl:
        name: fs.file-max
        value: "262144"
        sysctl_set: true
        reload: true

    - name: Distribuir configuração do agente de log
      ansible.builtin.template:
        src: agente-log.conf.j2   # template Jinja2 com variáveis
        dest: /etc/agente-log/agente-log.conf
        mode: "0644"
      notify: reiniciar agente    # handler roda só quando muda

Chef: receitas em Ruby e convergência

Chef organiza a configuração em cookbooks e receitas escritas em Ruby, uma DSL sobre uma linguagem de programação real, com resources declarativos, package, service, template, e o poder completo de Ruby quando necessário. A execução é por agente: o chef-client roda no host, em intervalo, busca o estado desejado no servidor Chef, converge o que divergiu e reporta o resultado. O modelo é de convergência contínua por agente, com pull periódico.

A força de Chef é a expressividade: lógica complexa, bibliotecas de helpers, testes em Test Kitchen com instâncias reais, e uma cultura de engenharia forte em torno do pipeline de infraestrutura. O custo é o mesmo poder: receitas mal escritas viram código imperativo difícil de auditar, e a curva de aprendizado é mais alta que Ansible, pois exige conforto com Ruby e com o modelo de execução distribuído.

A plataforma Chef exige infraestrutura própria, servidor de cookbooks, bancos de dados de nós, chaves de cliente, e esse custo operacional é parte do declínio relativo da ferramenta: o valor continuou bom, mas o custo total ficou difícil de justificar frente a modelos sem servidor central e sem agente.

# Receita Chef: convergência declarativa escrita em Ruby
package 'chrony' do
  action :install                 # estado desejado, não comando
end

service 'chronyd' do
  action [:enable, :start]
  supports restart: true
end

template '/etc/chrony.conf' do
  source 'chrony.conf.erb'
  notifies :restart, 'service[chronyd]', :delayed  # reinicia se mudou
end

Puppet: modelo declarativo com agente

Puppet é o modelo declarativo mais puro da tríade: o manifest descreve recursos e relações, package, service, file, com dependências e notificações explícitas, e o agente converge o host para esse estado periodicamente contra o Puppet Server. A linguagem de manifests é declarativa por desenho, com classes, módulos e Hiera para dados por ambiente, e o catálogo compilado para cada nó é o plano de convergência.

A força de Puppet é a governança em escala: catálogo por nó, relatórios de convergência, classificação de nós por regra e camada de dados separada do código com Hiera. É a ferramenta com melhor suporte nativo a auditoria contínua, pois cada run compara realidade com catálogo e reporta drift. O custo é similar ao de Chef: agente residente, servidor central e linguagem própria dominam a curva de adoção.

O desenho Puppet rende melhor quando o modelo é frota de longa vida com baseline forte: servidores corporativos, bancos legados, cargas que não são contêiner. Em plataformas de contêineres e VMs efêmeras, o benefício da convergência periódica diminui, pois as instâncias morrem antes de derivar, e o peso da infraestrutura Puppet deixa de compensar.

# Manifesto Puppet: classe declarativa com dependências explícitas
class base::tempo {
  package { 'chrony':
    ensure => installed,          # estado desejado, não comando
  }
  service { 'chronyd':
    ensure  => running,
    enable  => true,
    require => Package['chrony'],
  }
  file { '/etc/chrony.conf':
    source => 'puppet:///modules/base/chrony.conf',
    notify => Service['chronyd'], # reinicia quando a config muda
  }
}

Papel atual de cada ferramenta no mercado

Ansible é hoje a ferramenta dominante de gerenciamento de configuração e a escolha padrão para automação operacional em geral, com fortaleza em três usos: configuração de hosts, orquestração de mudança em massa e automação de rede. A execução sem agente, o formato YAML e o ecossistema de collections do Galaxy consolidaram a adoção, inclusive em operações que já têm Terraform como camada de provisionamento.

Chef e Puppet mantêm presença sólida em corporações grandes, em especial financeiras e telecom, onde plataformas construídas ao longo de anos continuam valendo e onde a auditoria de convergência contínua é requisito regulatório. O movimento comum das duas é reduzir a superfície da plataforma, versões serverless das ferramentas, integração com nuvens, e coexistir com Ansible nas bordas. Novos projetos, na média do mercado, começam por Ansible ou por modelo imutável sem gerenciamento de configuração.

O recorte de decisão atual tem três perguntas. A frota é imutável em contêineres? Então gerenciamento de configuração é marginal, e o esforço vai para imagens. A frota é mutável de longa vida com baseline de compliance? Ansible cobre a maioria, e Chef ou Puppet valem quando a plataforma histórica existe ou a auditoria contínua por agente é exigência. Precisa de orquestração ad-hoc em massa? Ansible, quase sempre.

Comparação das três ferramentas

Dimensão Ansible Chef Puppet
Modelo de execução Push, sem agente, por SSH Pull, agente contra servidor Chef Pull, agente contra Puppet Server
Linguagem YAML, com Jinja2 Ruby, DSL declarativa DSL de manifests declarativa
Idempotência Responsabilidade do autor, módulos ajudam Resources declarativos Resources declarativos
Convergência contínua Sob demanda ou agente opcional Nativa, runs periódicos Nativa, runs periódicos
Curva de entrada Baixa Alta Alta
Reuso Roles e collections Cookbooks e Test Kitchen Módulos e Hiera
Infraestrutura extra Nenhuma, só nó de controle Servidor Chef Puppet Server
Perfil típico Automação geral e nuvem moderna Corporativo com pipeline Ruby Frota legada com compliance forte

A leitura prática: Ansible pela simplicidade e cobertura, Chef quando o time vive Ruby e quer pipeline de infraestrutura com testes reais, Puppet quando o requisito central é catálogo, classificação e relatório de conformidade contínua em frota estável.

Erros comuns e boas práticas

  • Escrever tasks com shell sem guarda de idempotência; use módulos nativos e, quando o shell for inevitável, proteja com checagem de estado.
  • Misturar provisioning e configuração em uma única camada; Terraform cria, Ansible configura, e a fronteira precisa estar escrita em algum lugar que o time leia.
  • Rodar playbooks com credenciais de longo prazo de máquinas de trabalho; use CI com role efêmera e inventário dinâmico vindo do IaC.
  • Ignorar handlers e notificações; serviço que não reinicia quando a configuração muda é convergência pela metade.
  • Manter segredos em variáveis de texto claro no repositório; use Ansible Vault ou gerenciador externo, e rotacione o que já vazou em histórico de Git.
  • Aplicar convergência na frota inteira de uma vez; rollouts por lote com pausa de verificação são o mínimo de segurança operacional.
  • Deixar a execução sem registro; log de run, diff aplicado e resultado por host são a trilha de auditoria que justifica a ferramenta.
  • Copiar roles entre repositórios em vez de versioná-las; role é código e precisa de versão, changelog e dono, como qualquer biblioteca.