O gerenciamento de configuração é uma prática fundamental em DevOps que permite automatizar a configuração e o gerenciamento de servidores e infraestrutura de forma consistente e repetível. Em vez de configurar cada máquina manualmente, as ferramentas de gerenciamento de configuração definem o estado desejado dos sistemas em código, que pode ser versionado, revisado e aplicado automaticamente. Isso reduz erros humanos, aumenta a velocidade de provisionamento e garante que todos os ambientes (desenvolvimento, teste, produção) sejam idênticos.

Nesta aula, vamos explorar três das ferramentas mais populares: Ansible, Chef e Puppet. Vamos entender como cada uma aborda o gerenciamento de configuração, comparar seus modelos de operação (push vs pull), e discutir o conceito de idempotência, que é essencial para garantir que a aplicação repetida das configurações não cause efeitos colaterais. Ao final, você terá uma visão clara de quando usar cada ferramenta, com base nas necessidades do seu projeto.

Ansible, Chef, Puppet (panorama)

Ansible, Chef e Puppet são as ferramentas mais consolidadas no mercado de gerenciamento de configuração. Cada uma tem suas particularidades, mas todas compartilham o objetivo de automatizar a configuração de servidores. Vamos conhecer cada uma delas.

Ansible é uma ferramenta open-source desenvolvida pela Red Hat. Ela é agentless, ou seja, não requer a instalação de nenhum software nos servidores gerenciados. Em vez disso, usa SSH (Linux) ou WinRM (Windows) para se conectar e executar tarefas. O Ansible utiliza uma linguagem declarativa baseada em YAML para definir as configurações, chamadas de playbooks. Sua curva de aprendizado é baixa, e é muito popular em orquestração de tarefas, provisionamento e configuração de servidores.

Chef é uma ferramenta mais antiga, escrita em Ruby, que utiliza uma arquitetura client-server. Um servidor Chef centralizado armazena as receitas (recipes) e políticas de configuração, e os nós (clientes) executam periodicamente o chef-client para buscar e aplicar essas configurações. O Chef usa uma linguagem específica baseada em Ruby (DSL) para definir as receitas, o que pode ser mais complexo para iniciantes, mas oferece grande flexibilidade.

Puppet também é uma ferramenta antiga, escrita em Ruby, com arquitetura client-server (ou modo standalone). O Puppet usa uma linguagem declarativa própria para definir os recursos e o estado desejado. O servidor Puppet compila os catálogos e os distribui para os agentes, que aplicam as configurações. O Puppet é conhecido por sua robustez e escalabilidade, sendo usado em grandes empresas.

Para ilustrar a diferença na definição de configurações, vejamos um exemplo simples de instalação do pacote nginx em cada ferramenta:

# Ansible (playbook.yml)
---
- hosts: web
  tasks:
    - name: Instalar nginx
      apt:
        name: nginx
        state: present
# Chef (recipe.rb)
package 'nginx' do
  action :install
end
# Puppet (site.pp)
package { 'nginx':
  ensure => installed,
}

Observe que o Ansible usa YAML, o Chef usa Ruby, e o Puppet usa sua própria DSL. Todos são declarativos, mas com sintaxes distintas.

Push vs pull

Um dos principais pontos de diferenciação entre as ferramentas é o modelo de comunicação: push ou pull.

Modelo push: a ferramenta (geralmente o servidor de controle) se conecta ativamente aos nós gerenciados e envia as configurações. O Ansible é o principal exemplo: ele usa SSH para se conectar e executar os playbooks. Nesse modelo, a execução é imediata e controlada pelo administrador, que pode disparar a configuração quando desejar. É ideal para ambientes onde se quer aplicar mudanças rapidamente, como em deploys contínuos.

Modelo pull: os nós gerenciados têm agentes instalados que periodicamente consultam um servidor central para obter as configurações e aplicá-las. Chef e Puppet usam esse modelo. O agente roda em intervalos definidos (por exemplo, a cada 30 minutos) e busca as novas políticas. Isso garante que os sistemas se auto-ajustem para o estado desejado, mas pode haver um atraso entre a atualização no servidor e a aplicação nos nós. É útil para ambientes com muitos servidores, onde o controle centralizado é necessário e a tolerância a atrasos é aceitável.

Para ficar claro, vejamos um exemplo de como um agente Chef se comporta:

# Comando executado periodicamente no nó (via cron ou agendador)
chef-client --local-mode

Já o Ansible executa tudo a partir do nó de controle:

# Executado no nó de controle, sem agentes nos alvos
ansible-playbook -i hosts playbook.yml

A escolha entre push e pull depende de fatores como: quantidade de servidores, necessidade de aplicação imediata, conectividade de rede (pull é melhor quando os nós estão em redes restritas, pois eles iniciam a conexão), e complexidade da infraestrutura.

Idempotência

Idempotência é um conceito central no gerenciamento de configuração. Uma operação é idempotente se, ao ser executada múltiplas vezes, o resultado é o mesmo que executá-la uma única vez. Em outras palavras, aplicar a configuração repetidamente não causa efeitos adversos, nem altera o estado final do sistema.

Por exemplo, se você define que o pacote nginx deve estar instalado, ao executar a configuração pela primeira vez, ele será instalado. Nas execuções seguintes, a ferramenta verifica que o pacote já está instalado e não faz nada. Isso é essencial para que as ferramentas possam ser executadas com segurança em ciclos contínuos, sem risco de quebrar a configuração.

Todas as três ferramentas são projetadas para serem idempotentes. No Ansible, a maioria dos módulos é idempotente por padrão. No Chef e no Puppet, os recursos também são declarativos, e a ferramenta verifica o estado atual antes de aplicar mudanças. Vejamos um exemplo de idempotência no Ansible:

- name: Garantir que o nginx esteja rodando
  service:
    name: nginx
    state: started

Se o nginx já estiver rodando, o Ansible não faz nada. Se estiver parado, ele o inicia. Isso torna o playbook seguro para ser executado repetidamente.

A idempotência é importante não só para evitar erros, mas também para permitir a convergência: o sistema sempre converge para o estado desejado, independentemente do estado inicial. Isso é um dos pilares da infraestrutura como código.

Quando usar

Escolher a ferramenta certa de gerenciamento de configuração depende do contexto do projeto. Aqui estão algumas diretrizes:

  • Ansible: é ideal para equipes que estão começando com automação, que já têm conhecimento de SSH e YAML, e que precisam de uma solução rápida e sem agentes. É ótimo para provisionamento de servidores, configuração de aplicações, e orquestração de tarefas. Se você precisa de uma aplicação imediata e não quer gerenciar agentes, o Ansible é a escolha natural.
  • Chef: é indicado para ambientes que já possuem uma infraestrutura Ruby e precisam de uma solução robusta e escalável. O Chef é mais complexo, mas oferece grande flexibilidade e é usado em empresas de grande porte. Se você precisa de um controle centralizado forte e tem uma equipe experiente em Ruby, o Chef pode ser uma boa opção.
  • Puppet: também é robusto e escalável, com uma linguagem declarativa própria. É uma boa escolha para grandes parques de servidores, onde a consistência e a conformidade são críticas. O Puppet tem uma comunidade ativa e muitas integrações.

Em resumo, para projetos menores ou equipes enxutas, o Ansible é mais simples e direto. Para projetos grandes com requisitos de conformidade, Chef e Puppet podem ser mais adequados. Muitas vezes, as equipes usam uma combinação: Ansible para tarefas rápidas e provisionamento, e Chef/Puppet para a configuração contínua dos servidores.

Além disso, existem outras ferramentas modernas como SaltStack, mas as três que vimos são as mais tradicionais e continuam em alta demanda.

Boas práticas e observações finais

Independentemente da ferramenta escolhida, algumas boas práticas são universais:

  • Versionar toda a configuração: guarde os playbooks, receitas e manifestos em um repositório Git para ter histórico e permitir revisão.
  • Testar em ambientes de staging: antes de aplicar em produção, teste em um ambiente controlado para evitar surpresas.
  • Usar roles/classes para modularizar: organize as configurações de forma reutilizável, em vez de um arquivo gigante.
  • Documentar as decisões: registre por que certas configurações existem, para que outros membros da equipe entendam.
  • Monitorar a execução: acompanhe os logs e o estado dos nós para detectar falhas rapidamente.

O gerenciamento de configuração é uma habilidade essencial para qualquer profissional de DevOps. Dominar pelo menos uma dessas ferramentas abrirá portas e melhorará a eficiência da sua infraestrutura.

Exercícios

  1. Exercício 1: Explique a diferença entre os modelos push e pull, citando uma ferramenta que usa cada um e uma situação em que cada modelo é mais adequado.
  2. ✓ Resposta: No modelo push, o servidor de controle se conecta ativamente aos nós e aplica as configurações imediatamente, como o Ansible via SSH. É adequado quando se deseja aplicar mudanças rapidamente, como em deploys contínuos. No modelo pull, os nós têm agentes que consultam o servidor central periodicamente, como Chef e Puppet. É adequado para ambientes com muitos servidores, onde os nós podem iniciar a conexão (útil em redes restritas) e onde a aplicação imediata não é crítica.
  3. Exercício 2: O que é idempotência e por que é importante no gerenciamento de configuração? Dê um exemplo.
  4. ✓ Resposta: Idempotência é a propriedade de uma operação que, executada várias vezes, produz o mesmo resultado que uma única execução. No gerenciamento de configuração, isso significa que aplicar a configuração repetidamente não causa erros nem altera o estado final. É importante para que as ferramentas possam ser executadas em ciclos contínuos sem risco de quebrar o sistema. Exemplo: garantir que o pacote nginx esteja instalado — na primeira execução ele instala, nas seguintes ele verifica que já está instalado e não faz nada.
  5. Exercício 3: Escreva um playbook Ansible que garanta que o serviço nginx esteja instalado e rodando em um servidor Ubuntu.
  6. ✓ Resposta:
    ---
    - hosts: web
      become: yes
      tasks:
        - name: Instalar nginx
          apt:
            name: nginx
            state: present
        - name: Iniciar nginx
          service:
            name: nginx
            state: started
            enabled: yes
    
  7. Exercício 4: Quais são as principais diferenças entre Ansible e Puppet em termos de arquitetura e linguagem?
  8. ✓ Resposta: O Ansible é agentless, usa push via SSH, e a linguagem é YAML. O Puppet é agent-based, usa pull com agentes que consultam um servidor central, e a linguagem é uma DSL própria. O Ansible é mais simples de começar, enquanto o Puppet oferece mais robustez e escalabilidade.
  9. Exercício 5: Em que cenário você escolheria Chef em vez de Ansible? Justifique.
  10. ✓ Resposta: Escolheria Chef em cenários onde há uma equipe experiente em Ruby, necessidade de um controle centralizado muito forte, e uma infraestrutura já baseada em Ruby. O Chef permite uma personalização profunda e é adequado para grandes empresas com requisitos complexos de conformidade e auditoria.

Referências