| Bellacosa Mainframe apresenta o ansible |
☕ Um Café no Bellacosa Mainframe
Ansible sem Mistérios para Programadores COBOL
Quando um Programador Descobre que Automatizar 500 Servidores Manualmente é um Problema de Lógica — e Também de Sanidade
No começo, havia o operador.
Depois veio o administrador de sistemas.
Em seguida, surgiu o programador COBOL, carregando um JCL debaixo do braço, uma caneca de café na mão e a saudável desconfiança de quem já viu um simples espaço em branco causar um desastre em produção.
Então alguém apresentou o Ansible.
— Com isso você pode administrar centenas de máquinas ao mesmo tempo.
O programador COBOL olhou para a tela, viu um arquivo YAML cheio de espaços e perguntou:
— E onde está a coluna 7?
Foi assim que começou esta viagem.
Este artigo é um guia para programadores COBOL iniciantes que desejam entender Ansible sem precisar abandonar tudo o que já aprenderam sobre lógica, processamento em lote, organização de programas, controle operacional e sobrevivência corporativa.
O Ansible pode parecer uma tecnologia completamente diferente do mainframe. Entretanto, quando observamos com cuidado, encontramos conceitos familiares:
inventários lembram catálogos de recursos;
Playbooks lembram JCLs ou procedimentos operacionais;
Roles lembram PROCs reutilizáveis;
módulos lembram programas utilitários;
variáveis lembram símbolos de JCL;
Handlers lembram rotinas executadas somente quando uma condição ocorre;
pipelines lembram cadeias de JOBs;
idempotência lembra uma operação projetada para não destruir o ambiente ao ser executada novamente.
A principal diferença é que o Ansible foi criado para administrar ambientes distribuídos: Linux, Windows, redes, Cloud, contêineres, APIs e até IBM Z.
Pegue sua toalha, sua caneca e, principalmente, não entre em pânico.
1. O que é Ansible?
Ansible é uma plataforma de automação de tecnologia da informação.
Ele pode ser usado para:
configurar servidores;
instalar softwares;
criar usuários;
publicar aplicações;
alterar arquivos;
administrar serviços;
executar comandos;
provisionar infraestrutura;
automatizar redes;
integrar ambientes de Cloud;
organizar pipelines;
executar operações em z/OS.
Em termos simples, o Ansible permite descrever aquilo que você deseja que aconteça em um ambiente.
Por exemplo:
Quero que o Nginx esteja instalado, iniciado e configurado para subir automaticamente.
Em vez de acessar manualmente cada servidor, o Ansible executa a operação em todas as máquinas definidas.
Considere uma empresa com 300 servidores Linux.
Sem automação, alguém poderia tentar:
Conectar no servidor 1
Instalar o pacote
Copiar o arquivo
Reiniciar o serviço
Conectar no servidor 2
Instalar o pacote
Copiar o arquivo
Reiniciar o serviço
Conectar no servidor 3...
No servidor 137, provavelmente surgiria uma interrupção, uma reunião, uma emergência ou um café particularmente interessante. A partir desse ponto, ninguém teria certeza de quais servidores foram atualizados.
Com Ansible, descrevemos a operação uma vez:
---
- name: Configurar servidores web
hosts: webservers
become: true
tasks:
- name: Garantir que o Nginx esteja instalado
ansible.builtin.package:
name: nginx
state: present
- name: Garantir que o Nginx esteja iniciado
ansible.builtin.service:
name: nginx
state: started
enabled: true
O Ansible se conecta aos servidores, verifica a situação atual e executa apenas as mudanças necessárias.
Essa última parte é fundamental.
2. A ideia de estado desejado
Um script tradicional costuma dizer:
Execute este comando.
O Ansible normalmente diz:
Garanta que o recurso esteja neste estado.
Compare os dois exemplos.
Script imperativo
apt install nginx -y
systemctl start nginx
systemctl enable nginx
O script ordena ações.
Playbook declarativo
- name: Garantir que o Nginx esteja instalado
ansible.builtin.apt:
name: nginx
state: present
- name: Garantir que o Nginx esteja iniciado e habilitado
ansible.builtin.service:
name: nginx
state: started
enabled: true
O Playbook descreve o resultado desejado.
Essa é uma das bases da chamada Infrastructure as Code, ou infraestrutura como código.
A configuração do ambiente deixa de existir apenas na memória do administrador e passa a ser representada por arquivos versionados, revisáveis e executáveis.
Em outras palavras, a documentação começa a trabalhar.
Uma raridade tão impressionante quanto encontrar uma impressora corporativa que funcione na primeira tentativa.
3. Agentless: o Ansible não exige um agente permanente
Uma das principais características do Ansible é sua arquitetura normalmente classificada como agentless.
Isso significa que, na maioria dos casos, não é necessário instalar um agente dedicado em cada máquina administrada.
O Ansible utiliza mecanismos já existentes.
Em Linux e Unix, geralmente:
SSH
Em Windows:
WinRM
PowerShell
Em equipamentos de rede:
SSH
APIs
NETCONF
HTTPAPI
CLI
Em z/OS, dependendo da Collection e da operação:
SSH
ZOAU
APIs
z/OSMF
O computador de onde o Ansible é executado recebe o nome de Control Node.
As máquinas administradas são chamadas de:
Managed Nodes
A arquitetura básica é:
CONTROL NODE
Ansible
|
-----------------------
| | |
SSH SSH SSH
| | |
Servidor1 Servidor2 Servidor3
O Control Node contém:
Ansible;
inventários;
Playbooks;
variáveis;
Roles;
Collections;
credenciais;
arquivos de configuração.
Os Managed Nodes recebem as tarefas.
Curiosidade importante
“Agentless” não significa que absolutamente nada seja necessário na máquina remota.
Muitos módulos para Linux dependem da presença de Python. Outros dispositivos utilizam APIs ou bibliotecas específicas. No z/OS, determinadas automações podem depender do Z Open Automation Utilities.
A ideia correta é:
Não existe normalmente um agente Ansible permanente funcionando em cada host.
4. Inventory: o mapa da galáxia
Antes de viajar, precisamos saber para onde estamos indo.
O Inventory é a lista dos sistemas que serão administrados pelo Ansible.
Um inventário simples no formato INI pode ser:
[webservers]
web01
web02
web03
[databases]
db01
db02
Também podemos usar YAML:
---
all:
children:
webservers:
hosts:
web01:
web02:
web03:
databases:
hosts:
db01:
db02:
Os grupos permitem executar tarefas em conjuntos específicos.
Exemplo:
ansible webservers -m ping
Somente os servidores do grupo webservers serão testados.
Variáveis no inventário
Podemos informar endereços e usuários:
---
all:
children:
webservers:
hosts:
web01:
ansible_host: 192.168.10.11
web02:
ansible_host: 192.168.10.12
vars:
ansible_user: automation
ansible_port: 22
O nome web01 funciona como uma identidade lógica.
O endereço real está em:
ansible_host: 192.168.10.11
Isso é semelhante à diferença entre um nome simbólico e o recurso físico correspondente.
5. Inventário estático e inventário dinâmico
Um inventário estático é escrito manualmente.
Ele funciona bem quando os servidores mudam pouco.
Entretanto, ambientes modernos podem crescer e diminuir automaticamente.
Em uma Cloud, hoje podemos ter 40 máquinas. Amanhã, 120. Depois de amanhã, 17, porque algum gerente finalmente percebeu a conta.
Para esses ambientes existe o Dynamic Inventory.
O Ansible consulta uma fonte externa, como:
AWS;
Azure;
Google Cloud;
VMware;
OpenStack;
IBM Cloud;
CMDB;
ServiceNow;
scripts;
APIs internas.
O inventário é gerado em tempo de execução.
Assim, não precisamos editar manualmente o arquivo sempre que uma máquina nasce, muda ou desaparece no grande buraco negro do autoscaling.
6. Comandos Ad-Hoc
Os comandos Ad-Hoc são úteis para operações rápidas.
Por exemplo, testar conectividade:
ansible all -m ping
É importante observar que o módulo ping do Ansible não é o mesmo comando ICMP tradicional.
Ele verifica se o Ansible consegue:
conectar;
autenticar;
executar um módulo;
receber uma resposta.
Podemos consultar o uptime:
ansible all -m command -a "uptime"
Consultar espaço em disco:
ansible all -m shell -a "df -h"
Copiar um arquivo:
ansible all \
-m copy \
-a "src=aviso.txt dest=/tmp/aviso.txt"
Reiniciar um serviço:
ansible webservers \
-m service \
-a "name=nginx state=restarted" \
--become
Os comandos Ad-Hoc são excelentes para diagnóstico e intervenções pontuais.
Porém, se uma operação precisa ser:
repetida;
auditada;
versionada;
revisada;
executada novamente no futuro;
ela provavelmente deve virar um Playbook.
7. Playbooks: o JCL da automação distribuída
Um Playbook é um arquivo YAML que descreve uma ou mais automações.
Para um programador COBOL, podemos fazer uma analogia aproximada:
JCL define uma execução em mainframe.
Playbook define uma automação em um conjunto de hosts.
Um Playbook básico:
---
- name: Configurar servidores de aplicação
hosts: appservers
become: true
tasks:
- name: Instalar Java
ansible.builtin.package:
name: java-17-openjdk
state: present
- name: Criar diretório da aplicação
ansible.builtin.file:
path: /opt/minha-app
state: directory
owner: app
group: app
mode: "0750"
Os principais elementos são:
name:
hosts:
become:
vars:
tasks:
handlers:
roles:
name
É a descrição do Play ou da tarefa.
name: Instalar Java
Escolha nomes claros. Quando algo falhar às três da manhã, “Executar coisa” não será uma descrição reconfortante.
hosts
Define os alvos:
hosts: appservers
become
Solicita elevação de privilégio:
become: true
É semelhante ao uso de sudo.
tasks
Contém as tarefas a executar.
8. YAML: o universo onde os espaços têm poder
YAML é uma linguagem de serialização de dados muito utilizada em automação.
Ela é legível, mas possui uma característica inquietante:
A indentação faz parte da estrutura.
Exemplo correto:
tasks:
- name: Instalar Nginx
ansible.builtin.package:
name: nginx
state: present
Exemplo incorreto:
tasks:
- name: Instalar Nginx
ansible.builtin.package:
name: nginx
Para quem conhece COBOL, isso não deveria causar tanto choque. Afinal, fomos treinados por décadas a respeitar colunas, níveis, pontos e estruturas.
Regras práticas
Use espaços, não TAB.
Mantenha uma indentação consistente, normalmente dois espaços.
Inicie arquivos com:
---
Use aspas quando um valor puder ser interpretado incorretamente:
mode: "0644"
Valide a sintaxe:
ansible-playbook playbook.yml --syntax-check
Use análise de qualidade:
ansible-lint playbook.yml
Easter egg para veteranos
YAML significa originalmente “Yet Another Markup Language”.
Posteriormente, o significado passou a ser “YAML Ain’t Markup Language”, uma sigla recursiva.
Ou seja, a própria linguagem entrou em uma discussão existencial sobre o que ela é. Algo perfeitamente normal no universo da tecnologia.
9. Módulos: os utilitários do Ansible
Os módulos são unidades de trabalho.
Exemplos:
package
apt
dnf
copy
template
file
user
group
service
systemd
uri
command
shell
debug
assert
fail
Um módulo realiza uma operação específica.
Exemplo:
- name: Criar usuário
ansible.builtin.user:
name: vagner
state: present
shell: /bin/bash
A forma totalmente qualificada:
ansible.builtin.user
é chamada de FQCN, ou Fully Qualified Collection Name.
Ela mostra exatamente de onde vem o módulo.
Isso evita ambiguidades entre módulos com nomes semelhantes.
command ou shell?
command executa diretamente um programa:
- name: Consultar uptime
ansible.builtin.command:
cmd: uptime
shell executa por meio de um shell:
- name: Procurar processo
ansible.builtin.shell:
cmd: "ps -ef | grep nginx"
Use shell apenas quando precisar de:
pipes;
redirecionamento;
curingas;
expansão de variáveis;
operadores como
&&.
Sempre que existir um módulo específico, prefira o módulo.
Ruim:
- name: Criar usuário
ansible.builtin.shell:
cmd: useradd vagner
Melhor:
- name: Garantir que o usuário exista
ansible.builtin.user:
name: vagner
state: present
10. Idempotência: executar novamente sem destruir o universo
Idempotência é uma das palavras centrais no Ansible.
Uma operação idempotente produz o mesmo estado final mesmo quando executada várias vezes.
Considere:
- name: Garantir que o diretório exista
ansible.builtin.file:
path: /opt/app
state: directory
Na primeira execução:
Diretório não existe.
Ansible cria.
Resultado: changed
Na segunda:
Diretório já existe.
Nenhuma alteração.
Resultado: ok
Na terceira:
Continua existindo.
Resultado: ok
Esse comportamento é vital em automação.
Um Playbook não deve depender da esperança de que alguém se lembre se ele já foi executado.
Analogia com COBOL
Imagine um programa batch que recebe um arquivo e insere registros sem verificar duplicidade.
Executá-lo duas vezes pode produzir registros duplicados.
Um processamento idempotente verifica se o dado já existe ou utiliza uma chave que impede duplicação.
No Ansible, os módulos são projetados para verificar o estado antes de agir.
11. Variáveis
Variáveis tornam os Playbooks flexíveis.
vars:
package_name: nginx
service_name: nginx
http_port: 80
Uso:
- name: Instalar pacote
ansible.builtin.package:
name: "{{ package_name }}"
state: present
As chaves duplas:
{{ package_name }}
indicam uma expressão Jinja2.
Variáveis podem vir de diversos lugares:
Playbook;
Inventory;
group_vars;host_vars;Role;
linha de comando;
arquivos externos;
facts;
Vault.
group_vars e host_vars
Variáveis para um grupo:
group_vars/webservers.yml
---
http_port: 8080
package_name: nginx
Variáveis para um host:
host_vars/web01.yml
---
http_port: 9090
O host web01 poderá usar um valor específico.
12. Facts: o Ansible investigando o sistema
Facts são informações coletadas dos hosts.
Exemplos:
hostname;
sistema operacional;
versão;
kernel;
CPU;
memória;
interfaces;
endereços IP;
discos;
arquitetura.
Podemos visualizar facts:
ansible all -m setup
No Playbook:
- name: Mostrar distribuição
ansible.builtin.debug:
msg: "Sistema: {{ ansible_facts['distribution'] }}"
Podemos tomar decisões:
- name: Instalar Apache em sistemas Red Hat
ansible.builtin.dnf:
name: httpd
state: present
when: ansible_facts['os_family'] == 'RedHat'
Outro exemplo:
- name: Instalar Apache em Debian
ansible.builtin.apt:
name: apache2
state: present
when: ansible_facts['os_family'] == 'Debian'
Facts permitem escrever Playbooks adaptáveis.
Entretanto, coletar facts possui custo.
Quando não forem necessários:
gather_facts: false
Em milhares de máquinas, evitar uma coleta desnecessária pode economizar bastante tempo.
13. Condicionais
A cláusula when decide se uma tarefa será executada.
- name: Reiniciar serviço somente em produção
ansible.builtin.service:
name: app
state: restarted
when: environment == "production"
Verificar se uma variável existe:
when: app_port is defined
Verificar se não existe:
when: app_port is not defined
Comparação numérica:
when: free_space_mb | int < 1000
Para quem vem do COBOL:
IF condição
EXECUTE tarefa
END-IF
No Ansible:
when: condição
O princípio é o mesmo. Apenas trocaram o END-IF por uma indentação que observa você em silêncio.
14. Loops
Loops repetem tarefas.
- name: Instalar pacotes
ansible.builtin.package:
name: "{{ item }}"
state: present
loop:
- nginx
- git
- curl
Para um programador COBOL, isso lembra:
PERFORM VARYING WS-I FROM 1 BY 1
UNTIL WS-I > 3
Podemos trabalhar com estruturas:
- name: Criar usuários
ansible.builtin.user:
name: "{{ item.name }}"
groups: "{{ item.groups }}"
state: present
loop:
- name: ana
groups: developers
- name: bruno
groups: operations
- name: carla
groups: auditors
Cada item possui propriedades.
15. Register: guardando o resultado
A palavra register armazena o resultado de uma tarefa.
- name: Consultar espaço em disco
ansible.builtin.command:
cmd: df -P /opt
register: disk_result
changed_when: false
Depois:
- name: Mostrar saída
ansible.builtin.debug:
var: disk_result.stdout
Um resultado pode conter:
stdout
stderr
rc
changed
failed
results
Podemos reagir ao código de retorno:
- name: Falhar quando o comando retornar erro
ansible.builtin.fail:
msg: "A verificação falhou."
when: disk_result.rc != 0
Essa lógica é familiar para qualquer pessoa que já analisou RETURN-CODE, MAXCC, SQLCODE ou um ABEND que decidiu surgir cinco minutos antes do fim do expediente.
16. Handlers: agir apenas quando algo mudou
Handlers são tarefas executadas quando notificadas por outra tarefa.
Exemplo:
tasks:
- name: Publicar configuração do Nginx
ansible.builtin.template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
notify: Reiniciar Nginx
handlers:
- name: Reiniciar Nginx
ansible.builtin.service:
name: nginx
state: restarted
O Handler somente será acionado quando o arquivo for alterado.
Se não houver mudança:
Nenhum restart.
Se dez tarefas notificarem o mesmo Handler:
O Handler normalmente executa uma vez ao final do Play.
Isso evita reinicializações desnecessárias.
Analogia
Imagine dez etapas atualizando parâmetros de uma aplicação.
Sem Handler:
Altera parâmetro.
Reinicia.
Altera outro parâmetro.
Reinicia.
Altera certificado.
Reinicia.
Com Handler:
Executa todas as alterações.
Reinicia uma vez.
Menos indisponibilidade, menos risco e menos oportunidades para o servidor desenvolver personalidade própria.
17. Tags
Tags permitem executar partes específicas do Playbook.
- name: Instalar aplicação
ansible.builtin.package:
name: minha-app
state: present
tags:
- install
- application
Execução:
ansible-playbook site.yml --tags install
Pular tarefas:
ansible-playbook site.yml --skip-tags debug
Tags são úteis para:
manutenção;
instalação;
configuração;
validação;
depuração;
operações seletivas.
Porém, use com cuidado.
Executar apenas uma etapa pode ignorar dependências anteriores.
Um Playbook deve continuar coerente mesmo quando dividido por tags.
18. Roles: organizando a automação
Quando um Playbook cresce, ele pode virar uma criatura de milhares de linhas que ninguém deseja encontrar em um corredor escuro.
Roles resolvem esse problema.
Uma Role organiza arquivos por finalidade:
roles/
└── webserver/
├── tasks/
│ └── main.yml
├── handlers/
│ └── main.yml
├── defaults/
│ └── main.yml
├── vars/
│ └── main.yml
├── templates/
├── files/
├── meta/
│ └── main.yml
└── README.md
Diretórios principais
tasks contém as tarefas.
handlers contém os Handlers.
defaults contém variáveis padrão de baixa precedência.
vars contém variáveis da Role.
templates contém arquivos Jinja2.
files contém arquivos estáticos.
meta pode declarar dependências.
Uso:
---
- name: Configurar servidores web
hosts: webservers
become: true
roles:
- common
- security
- webserver
Analogia com mainframe
Uma Role pode ser comparada a uma PROC ou componente reutilizável.
Em vez de repetir passos em todos os Playbooks, centralizamos a lógica.
19. Templates e Jinja2
Templates permitem gerar arquivos diferentes para cada máquina.
Exemplo:
server {
listen {{ http_port }};
server_name {{ inventory_hostname }};
location / {
proxy_pass http://127.0.0.1:{{ app_port }};
}
}
O arquivo pode ser chamado:
nginx.conf.j2
A tarefa:
- name: Gerar configuração
ansible.builtin.template:
src: nginx.conf.j2
dest: /etc/nginx/conf.d/app.conf
owner: root
group: root
mode: "0644"
notify: Recarregar Nginx
O mesmo template produz configurações diferentes com base nas variáveis de cada host.
Condicionais no template
{% if environment == "production" %}
log_level error;
{% else %}
log_level debug;
{% endif %}
Loops no template
{% for server in backend_servers %}
server {{ server }};
{% endfor %}
Filtros
{{ app_name | upper }}
{{ user_name | lower }}
{{ value | default('desconhecido') }}
Jinja2 transforma dados em arquivos de configuração.
É como uma combinação de STRING, edição de relatórios, geração de parâmetros e um toque de magia burocrática.
20. Ansible Vault
Nunca grave senhas diretamente no Playbook.
Não faça isto:
db_password: admin123
Também não faça isto seguido da frase:
Depois eu removo.
Essa frase é uma das principais causas de segredos permanentes em repositórios.
O Ansible Vault criptografa arquivos ou variáveis.
Criar arquivo:
ansible-vault create secrets.yml
Criptografar arquivo existente:
ansible-vault encrypt secrets.yml
Editar:
ansible-vault edit secrets.yml
Visualizar:
ansible-vault view secrets.yml
Executar Playbook:
ansible-playbook site.yml --ask-vault-pass
Também podemos usar um arquivo de senha controlado:
ansible-playbook site.yml \
--vault-password-file /caminho/protegido/vault.pass
Segurança adicional
Em tarefas que manipulam segredos:
- name: Configurar credencial
ansible.builtin.debug:
msg: "{{ db_password }}"
no_log: true
O no_log impede a exibição do conteúdo sensível.
Entretanto, ele também reduz informações de diagnóstico. Use somente onde necessário.
Vault não resolve tudo
Ainda é necessário controlar:
quem possui a senha;
rotação de credenciais;
segregação entre ambientes;
auditoria;
armazenamento seguro;
acesso da pipeline.
Em ambientes maiores, podem ser usados:
HashiCorp Vault;
CyberArk;
AWS Secrets Manager;
Azure Key Vault;
IBM Cloud Secrets Manager;
credenciais protegidas do Jenkins;
Ansible Automation Platform Credentials.
21. Tratamento de erros com Block, Rescue e Always
Ansible possui uma estrutura semelhante ao tratamento de exceções.
- name: Atualizar aplicação
block:
- name: Publicar nova versão
ansible.builtin.copy:
src: app.jar
dest: /opt/app/app.jar
- name: Reiniciar aplicação
ansible.builtin.service:
name: app
state: restarted
rescue:
- name: Restaurar versão anterior
ansible.builtin.copy:
src: app.jar.backup
dest: /opt/app/app.jar
- name: Informar falha
ansible.builtin.debug:
msg: "Falha detectada. Rollback executado."
always:
- name: Registrar encerramento
ansible.builtin.debug:
msg: "Processo de atualização encerrado."
block contém a operação principal.
rescue executa quando uma tarefa do bloco falha.
always executa independentemente do resultado.
Outros controles
Ignorar erro:
ignore_errors: true
Use com extrema cautela.
Definir falha personalizada:
failed_when: disk_result.rc != 0
Definir mudança personalizada:
changed_when: false
Retry:
- name: Aguardar aplicação responder
ansible.builtin.uri:
url: http://localhost:8080/health
status_code: 200
register: health
retries: 10
delay: 5
until: health.status == 200
Isso tenta até dez vezes, aguardando cinco segundos entre as tentativas.
22. Ansible Galaxy e Collections
Ansible Galaxy é um catálogo de conteúdo reutilizável.
Podemos encontrar:
Roles;
Collections;
módulos;
plugins;
exemplos;
documentação.
Instalar uma Role:
ansible-galaxy role install geerlingguy.nginx
Instalar uma Collection:
ansible-galaxy collection install community.general
Uma Collection agrupa diferentes tipos de conteúdo.
Exemplos:
community.general
ansible.posix
amazon.aws
azure.azcollection
community.vmware
ibm.ibm_zos_core
Role versus Collection
Role:
Automação organizada para uma finalidade.
Collection:
Pacote maior contendo módulos, plugins, Roles, documentação e outros recursos.
requirements.yml
Dependências devem ser declaradas:
---
collections:
- name: community.general
version: 10.4.0
- name: ansible.posix
version: 1.6.2
roles:
- name: geerlingguy.nginx
version: 3.2.0
Instalação:
ansible-galaxy install -r requirements.yml
Fixar versões aumenta a previsibilidade.
Sem isso, uma atualização externa pode transformar uma pipeline estável em uma aventura filosófica sobre compatibilidade.
Cuidado com conteúdo externo
Antes de usar uma Role ou Collection, avalie:
autor;
reputação;
documentação;
atualização;
testes;
código;
licenciamento;
versões suportadas;
dependências;
permissões exigidas.
Não execute conteúdo desconhecido com privilégios administrativos apenas porque ele possui um ícone simpático.
23. Estrutura profissional de projeto
Um projeto organizado pode ter:
ansible-project/
├── ansible.cfg
├── requirements.yml
├── README.md
├── inventories/
│ ├── dev/
│ │ ├── hosts.yml
│ │ └── group_vars/
│ ├── test/
│ │ ├── hosts.yml
│ │ └── group_vars/
│ └── prod/
│ ├── hosts.yml
│ └── group_vars/
├── playbooks/
│ ├── site.yml
│ ├── deploy.yml
│ └── rollback.yml
├── roles/
│ ├── common/
│ ├── security/
│ ├── webserver/
│ └── application/
├── templates/
└── files/
Essa estrutura separa:
ambientes;
código;
configurações;
dados;
dependências;
documentação.
Dica
Nunca misture produção e desenvolvimento no mesmo inventário sem uma razão extremamente boa, três aprovações e talvez a presença de um adulto responsável.
24. Boas práticas
Use módulos idempotentes
Prefira:
ansible.builtin.user
ansible.builtin.package
ansible.builtin.service
ansible.builtin.copy
em vez de comandos arbitrários.
Utilize FQCN
Prefira:
ansible.builtin.copy
em vez de:
copy
Escreva nomes claros
Ruim:
- name: Fazer ajuste
Melhor:
- name: Publicar configuração TLS do portal corporativo
Valide arquivos antes de substituir
- name: Publicar configuração do Nginx
ansible.builtin.template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
validate: "nginx -t -c %s"
O Ansible valida o arquivo antes de colocá-lo em produção.
Use privilégio mínimo
Evite aplicar:
become: true
em tudo quando apenas algumas tarefas precisam de privilégios.
Documente
Mantenha um README.md com:
finalidade;
requisitos;
variáveis;
exemplos;
dependências;
procedimento de execução;
rollback;
responsáveis.
Teste antes da produção
Use:
ansible-playbook site.yml --syntax-check
Depois:
ansible-playbook site.yml --check --diff
Por fim, execute em um ambiente de teste.
O modo Check ajuda, mas não é perfeito. Nem todos os módulos simulam integralmente as mudanças.
25. Desempenho
Facts
Desative quando não forem necessários:
gather_facts: false
Forks
Em ansible.cfg:
[defaults]
forks = 30
Isso controla quantos hosts podem ser processados paralelamente.
Aumentar o número pode acelerar a execução, mas também pode:
sobrecarregar o Control Node;
saturar a rede;
sobrecarregar APIs;
atingir limites dos servidores;
aumentar o impacto de uma falha.
SSH Multiplexing
[ssh_connection]
ssh_args = -o ControlMaster=auto -o ControlPersist=60s
pipelining = True
Isso permite reutilizar conexões SSH.
Serial
Atualize grupos menores:
- name: Atualização gradual
hosts: webservers
serial: 5
O Ansible processa cinco servidores por vez.
Essa estratégia é importante em produção.
26. Git, Jenkins e Ansible
Um fluxo DevOps comum é:
Desenvolvedor altera código
↓
Git recebe a mudança
↓
Pull Request é revisado
↓
Jenkins inicia a pipeline
↓
Sintaxe é validada
↓
Lint é executado
↓
Playbook é testado
↓
Ansible executa o deploy
↓
Resultado é registrado
Git armazena e versiona.
Jenkins coordena.
Ansible executa.
Podemos resumir assim:
Git = fonte oficial
Jenkins = maestro
Ansible = executor
Inventory = mapa
Playbook = plano operacional
Exemplo de pipeline
pipeline {
agent any
stages {
stage('Checkout') {
steps {
git url: 'https://git.example/ansible.git'
}
}
stage('Syntax Check') {
steps {
sh '''
ansible-playbook \
playbooks/deploy.yml \
--syntax-check
'''
}
}
stage('Lint') {
steps {
sh 'ansible-lint playbooks/deploy.yml'
}
}
stage('Dry Run') {
steps {
sh '''
ansible-playbook \
-i inventories/test/hosts.yml \
playbooks/deploy.yml \
--check --diff
'''
}
}
stage('Deploy') {
steps {
sh '''
ansible-playbook \
-i inventories/prod/hosts.yml \
playbooks/deploy.yml \
--serial 2
'''
}
}
}
}
27. Rolling Update
Em produção, raramente devemos atualizar todos os servidores de uma vez.
Um fluxo seguro pode ser:
retirar servidor do balanceador;
parar aplicação;
instalar versão;
iniciar aplicação;
testar saúde;
recolocar servidor;
avançar para o próximo.
Exemplo:
---
- name: Atualização gradual
hosts: webservers
serial: 1
become: true
pre_tasks:
- name: Retirar host do balanceador
ansible.builtin.uri:
url: "https://lb.example/api/remove/{{ inventory_hostname }}"
method: POST
delegate_to: localhost
tasks:
- name: Publicar aplicação
ansible.builtin.copy:
src: app.jar
dest: /opt/app/app.jar
notify: Reiniciar aplicação
handlers:
- name: Reiniciar aplicação
ansible.builtin.service:
name: app
state: restarted
post_tasks:
- name: Aguardar aplicação responder
ansible.builtin.uri:
url: "http://{{ inventory_hostname }}:8080/health"
status_code: 200
register: health
retries: 10
delay: 5
until: health.status == 200
- name: Recolocar host no balanceador
ansible.builtin.uri:
url: "https://lb.example/api/add/{{ inventory_hostname }}"
method: POST
delegate_to: localhost
Isso é uma implantação controlada, não uma aposta coletiva.
28. Troubleshooting: quando a nave não responde
Erro de YAML
Valide:
ansible-playbook site.yml --syntax-check
Use:
ansible-lint site.yml
Problemas de inventário
Mostrar estrutura:
ansible-inventory \
-i inventories/prod/hosts.yml \
--graph
Mostrar host:
ansible-inventory \
-i inventories/prod/hosts.yml \
--host web01
Listar hosts:
ansible webservers \
-i inventories/prod/hosts.yml \
--list-hosts
Problemas de SSH
ansible all -m ping -vvv
Verifique:
endereço;
DNS;
porta;
usuário;
chave;
senha;
firewall;
Python remoto;
sudo;jump host;
host key.
Erros de permissão
Use become quando necessário:
become: true
Mas também investigue:
dono;
grupo;
modo;
ACL;
SELinux;
AppArmor;
filesystem somente leitura;
espaço em disco.
Nem todo Permission denied é resolvido adicionando mais privilégio. Às vezes isso apenas transforma um pequeno erro em um erro com autoridade.
Debug
- name: Mostrar variável
ansible.builtin.debug:
var: minha_variavel
Limitar execução
ansible-playbook site.yml --limit web01
Verbosidade
ansible-playbook site.yml -v
ansible-playbook site.yml -vv
ansible-playbook site.yml -vvv
ansible-playbook site.yml -vvvv
Quanto mais letras v, mais detalhes.
Eventualmente você descobrirá informações que não sabia que existiam e algumas que preferiria continuar não sabendo.
29. Precedência de variáveis
Ansible pode receber a mesma variável de diversos lugares.
Por exemplo:
defaults da Role
Inventory
group_vars
host_vars
facts
Playbook
task
set_fact
extra-vars
Quando vários lugares definem o mesmo nome, uma regra de precedência decide qual valor vence.
Linha de comando:
ansible-playbook site.yml -e "http_port=9090"
extra-vars possui precedência elevada.
Isso é útil, mas pode causar resultados inesperados.
Para descobrir o valor:
- name: Exibir porta
ansible.builtin.debug:
var: http_port
Para inspecionar variáveis de um host:
ansible-inventory \
-i inventory.yml \
--host web01
Dica
Evite reutilizar o mesmo nome de variável em muitos níveis.
Um nome claro reduz conflitos:
webserver_http_port
database_connection_port
application_health_port
30. Ansible no IBM Z
Ansible também pode automatizar z/OS.
Uma Collection importante é:
ibm.ibm_zos_core
Ela permite trabalhar, dependendo do ambiente e da configuração, com operações como:
datasets;
membros de PDS e PDSE;
USS;
JCL;
JOBs;
comandos;
cópia de arquivos;
encode e decode;
módulos específicos de z/OS.
Exemplo: submeter JCL
---
- name: Executar JOB no z/OS
hosts: zos
gather_facts: false
tasks:
- name: Submeter JCL de compilação
ibm.ibm_zos_core.zos_job_submit:
src: USER.JCL(COMPILE)
location: data_set
wait_time_s: 60
return_output: true
register: job_result
- name: Mostrar resultado
ansible.builtin.debug:
var: job_result
Validar retorno
- name: Interromper se o retorno for maior que 4
ansible.builtin.fail:
msg: "Compilação COBOL falhou."
when:
- job_result.jobs is defined
- job_result.jobs | length > 0
- job_result.jobs[0].ret_code.code | int > 4
Possível pipeline COBOL
Código COBOL alterado
↓
Commit no Git
↓
Jenkins inicia pipeline
↓
Ansible envia fontes
↓
Ansible submete JCL
↓
Compilação é monitorada
↓
Return Code é validado
↓
Testes são executados
↓
LOADLIB é promovida
↓
CICS é atualizado
O Ansible não substitui COBOL, JCL, Db2, CICS ou z/OS.
Ele coordena e automatiza tarefas ao redor deles.
31. Ansible, COBOL e a arte de pensar em processos
O programador COBOL possui uma vantagem inesperada ao aprender Ansible.
COBOL ensina:
organização;
clareza;
processamento determinístico;
controle de retorno;
separação de responsabilidades;
atenção ao formato;
preocupação com reinício;
auditabilidade;
tratamento de erros;
previsibilidade operacional.
Essas qualidades são essenciais em automação.
Um bom Playbook precisa ser:
Legível
Repetível
Idempotente
Testável
Versionado
Auditável
Seguro
Recuperável
Em outras palavras, Ansible moderno precisa exatamente da disciplina que os ambientes mainframe cultivam há décadas.
A indústria às vezes apresenta infraestrutura como código como uma descoberta revolucionária.
O programador mainframe olha para JCLs, PROCs, parâmetros, bibliotecas controladas e processamento automatizado e pensa:
Interessante. Agora colocaram YAML.
32. Perguntas comuns de entrevistas
O que é Ansible?
Ansible é uma plataforma de automação usada para configuração, implantação, provisionamento e orquestração. Normalmente utiliza SSH ou mecanismos remotos semelhantes e descreve automações em Playbooks YAML.
Por que é agentless?
Porque normalmente não exige um agente Ansible permanente nos hosts administrados. Utiliza SSH, WinRM, APIs ou conexões específicas.
Inventory e Playbook são iguais?
Não.
Inventory informa onde executar.
Playbook informa o que executar.
Módulo e Role são iguais?
Não.
Módulo executa uma operação específica.
Role organiza uma automação completa e reutilizável.
command e shell são iguais?
Não.
command executa diretamente um programa.
shell passa o comando por um shell, permitindo pipes e redirecionamentos.
Variáveis e facts são iguais?
Variáveis são valores definidos ou recebidos.
Facts são informações coletadas dos hosts.
O que é Vault?
É o recurso de criptografia de dados sensíveis do Ansible.
O que são Handlers?
São tarefas executadas quando notificadas, normalmente em resposta a uma mudança.
O que é idempotência?
É a propriedade de atingir o mesmo estado final mesmo quando a automação é executada repetidamente.
33. Laboratório inicial passo a passo
Passo 1 — Instalar Ansible
Em distribuições baseadas em Debian ou Ubuntu:
sudo apt update
sudo apt install ansible -y
Validar:
ansible --version
Passo 2 — Criar diretório
mkdir -p ~/ansible-lab
cd ~/ansible-lab
Passo 3 — Criar inventário
# inventory.ini
[local]
localhost ansible_connection=local
Passo 4 — Testar
ansible all -i inventory.ini -m ping
Resultado esperado:
localhost | SUCCESS
Passo 5 — Criar Playbook
# primeiro-playbook.yml
---
- name: Primeiro laboratório Ansible
hosts: local
gather_facts: true
tasks:
- name: Mostrar sistema operacional
ansible.builtin.debug:
msg: >
Estou executando em
{{ ansible_facts['distribution'] }}
{{ ansible_facts['distribution_version'] }}
- name: Criar diretório de laboratório
ansible.builtin.file:
path: /tmp/ansible-lab
state: directory
mode: "0755"
- name: Criar arquivo
ansible.builtin.copy:
dest: /tmp/ansible-lab/mensagem.txt
content: |
Não entre em pânico.
O Ansible chegou até aqui.
mode: "0644"
Passo 6 — Verificar sintaxe
ansible-playbook \
-i inventory.ini \
primeiro-playbook.yml \
--syntax-check
Passo 7 — Simular
ansible-playbook \
-i inventory.ini \
primeiro-playbook.yml \
--check --diff
Passo 8 — Executar
ansible-playbook \
-i inventory.ini \
primeiro-playbook.yml
Passo 9 — Executar novamente
ansible-playbook \
-i inventory.ini \
primeiro-playbook.yml
Na primeira execução, algumas tarefas terão:
changed
Na segunda, deverão retornar:
ok
Você acabou de observar idempotência funcionando.
34. Curiosidades e Easter Eggs
O nome Ansible
O termo “ansible” ficou conhecido na ficção científica como um dispositivo de comunicação instantânea entre grandes distâncias.
O nome combina bem com uma ferramenta que envia instruções para sistemas remotos.
A maioria dos problemas não está no YAML
Quando um Playbook falha, o instinto inicial é culpar a indentação.
Muitas vezes o verdadeiro problema é:
DNS;
SSH;
permissão;
variável;
pacote inexistente;
caminho incorreto;
serviço com outro nome;
Python ausente;
firewall;
sistema operacional diferente.
Ou, como diria um operador veterano:
O erro está exatamente onde o sistema disse que está, exceto quando não está.
changed não significa necessariamente sucesso funcional
Uma tarefa pode alterar um arquivo corretamente e ainda assim produzir uma configuração inválida para a aplicação.
Por isso, use:
validate;testes;
health checks;
asserts;
rollback;
ambiente de homologação.
Automação ruim automatiza erros
Se um procedimento manual ruim for transformado em código sem revisão, teremos apenas um erro mais rápido, mais consistente e capaz de atingir centenas de máquinas simultaneamente.
A automação amplifica competência.
Infelizmente, também amplifica incompetência.
A resposta para tudo não é 42
Em Ansible, frequentemente é:
--check --diff -vvv
Não resolve tudo, mas oferece boas pistas.
35. O verdadeiro salto mental
O aprendiz pergunta:
Qual comando devo usar?
O profissional pergunta:
Qual estado desejo garantir?
O aprendiz escreve:
shell: systemctl restart nginx
O profissional pergunta:
Por que reiniciar? Houve mudança? Posso validar antes? Posso recarregar em vez de reiniciar?
O aprendiz cria um Playbook para funcionar uma vez.
O profissional cria uma automação para:
executar repetidamente;
falhar com clareza;
registrar evidências;
preservar segurança;
limitar impacto;
permitir rollback;
ser compreendida por outra pessoa.
Esse é o ponto em que Ansible deixa de ser uma coleção de arquivos YAML e se torna engenharia.
Conclusão — Não entre em pânico, versione o Playbook
Ansible não é apenas uma ferramenta para executar comandos em vários servidores.
Ele representa uma forma estruturada de administrar sistemas.
Com ele, podemos transformar operações manuais em processos:
repetíveis;
previsíveis;
auditáveis;
seguros;
versionados;
testáveis;
reutilizáveis.
Para um programador COBOL, muitos conceitos são menos alienígenas do que parecem.
O Inventory define os destinos.
O Playbook organiza a execução.
As Tasks representam passos.
Os módulos realizam operações.
As variáveis parametrizam.
Os Facts descrevem o ambiente.
Os Handlers reagem às mudanças.
As Roles organizam componentes.
As Collections distribuem funcionalidades.
O Vault protege segredos.
Git registra a história.
Jenkins coordena o fluxo.
Ansible executa.
E o z/OS, apesar de observar toda essa modernidade com a serenidade de quem já sobreviveu a inúmeras previsões de extinção, também pode participar dessa automação.
O melhor caminho para aprender é começar pequeno.
Crie um inventário.
Execute um ping.
Escreva um Playbook.
Crie um arquivo.
Instale um pacote.
Use uma variável.
Adicione uma condição.
Implemente um Handler.
Transforme o código em uma Role.
Coloque no Git.
Adicione testes.
Integre a uma pipeline.
Automatize um processo real.
Depois, execute tudo novamente.
Se o resultado continuar previsível, você estará no caminho correto.
Se o ambiente desaparecer, verifique se usou:
state: absent
em algum lugar particularmente inconveniente.
No universo da automação, como no mainframe, toda grande jornada começa com uma pequena instrução.
No COBOL:
PROCEDURE DIVISION.
No Ansible:
---
E em qualquer viagem técnica realmente perigosa:
Não entre em pânico. Faça backup, valide a sintaxe e nunca teste pela primeira vez em produção.
Sem comentários:
Enviar um comentário