Ansible via Semaphore: 4 armadilhas que dão erro silencioso, não crash
O ansible.cfg do seu repo provavelmente não é o que roda em produção no Semaphore, become nunca é default, e a diferença entre 'Extra Variables' e 'Environment Variables' que não dá erro nenhum — só silenciosamente não funciona.
Por que isso importa #
O pior tipo de bug em automação não é o que quebra na hora — é o que
parece configurado e não faz efeito nenhum. Rodar Ansible via
orquestrador (Semaphore, no meu caso) em vez de ansible-playbook direto
introduz uma camada de indireção que gera exatamente esse tipo de
armadilha, repetidas vezes.
1. Seu ansible.cfg local provavelmente não é o de produção #
Sintoma: playbook com roles: funciona liso rodando local, mas falha
no orquestrador com “role not found” mostrando um path de busca default
puro do Ansible, sem nenhum roles_path customizado.
Causa raiz: o Semaphore normalmente define seu próprio ansible.cfg
fixo no host onde ele roda — completamente independente do ansible.cfg
que existe dentro do repositório do projeto. Ansible só procura
ansible.cfg no diretório atual (ou via ANSIBLE_CONFIG), nunca sobe a
árvore de diretórios.
Fix que generaliza bem: não depender de roles_path customizado
nenhum. Ansible sempre tenta <diretório do playbook>/roles
automaticamente, independente de qualquer ansible.cfg. Se os
playbooks vivem em playbooks/ e as roles em roles/ como irmãos, um
symlink resolve pra sempre:
| |
2. become: true nunca é default — nem no seu ambiente, nem em nenhum #
Sintoma: Permission denied numa task que claramente precisa de root,
mesmo com credencial SSH correta.
Causa raiz: become: true não é o default do Ansible. Se o
ansible.cfg de dev tem become = True na seção de privilege escalation,
os testes locais escondem esse requisito — e o ansible.cfg real de
produção pode não ter essa seção, quebrando na primeira task com sudo.
Fix: todo play com qualquer task que precisa de privilégio declara
become: true explicitamente, no play ou na task — nunca dependendo
de default herdado.
3. “Extra Variables” ≠ “Environment Variables” — e não dá erro nenhum #
A armadilha mais traiçoeira das quatro. O Semaphore tem dois campos fáceis de confundir:
- Extra Variables (
jsonna API) → viraansible-playbook --extra-vars. Só cria variável Jinja dentro do playbook ({{ minha_var }}) — não afeta o processo Ansible em si. - Environment Variables (
envna API) → essas sim viram variável de ambiente real do processo.
Se a variável precisa mudar comportamento do próprio Ansible
(ANSIBLE_ROLES_PATH, config file, credencial que uma lib externa lê de
os.environ), ela tem que estar em Environment Variables, não em Extra
Variables. Colocar no campo errado não dá erro — só silenciosamente não
faz efeito. Parece configurado. Não está.
4. Variável customizada em add_host pode sumir na play seguinte #
Injetar host em memória via add_host com uma variável customizada (ex.:
hostname: "{{ algo }}") e depois não conseguir acessá-la na próxima
play, mesmo via hostvars[inventory_hostname] — nome de variável que
colide com atributo especial do Ansible (hostname é um dos candidatos
clássicos) se perde silenciosamente no meio do caminho. Prefixar
variável customizada injetada por add_host evita a colisão.
O padrão geral #
Nenhuma dessas quatro dá crash óbvio. Todas dão comportamento que parece certo até você notar que não é. A lição que generaliza: quando automação via orquestrador se comporta diferente de rodar local, a primeira suspeita não deveria ser “bug no playbook” — deveria ser “o que o orquestrador está fazendo de diferente do que eu assumi”.
Tecnologias #
Ansible · Ansible Semaphore
Me chama.
Manda o contexto, os sintomas e o que já foi testado. Bora organizar as evidências antes de sair mexendo.