☕ Um Café no Bellacosa Mainframe
Gostou do conteúdo? Ajude a manter o café quente, o COBOL compilando e o mainframe acordado. 😄
☕ Pague um café ao Bellacosa

Translate

Mostrar mensagens com a etiqueta Infrastructure as Code. Mostrar todas as mensagens
Mostrar mensagens com a etiqueta Infrastructure as Code. Mostrar todas as mensagens

terça-feira, 26 de novembro de 2024

Ansible : Quando um Programador Descobre que Automatizar 500 Servidores Manualmente é um Problema de Lógica — e Também de Sanidade

 

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:

  1. retirar servidor do balanceador;

  2. parar aplicação;

  3. instalar versão;

  4. iniciar aplicação;

  5. testar saúde;

  6. recolocar servidor;

  7. 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.

quinta-feira, 23 de agosto de 2018

DevOps Muito Além do Botão "Deploy"

 

Bellacosa Mainframe devops muito alem do botao deploy

☕ Um Café no Bellacosa Mainframe

DevOps Muito Além do Botão "Deploy"

O Que Todo Programador COBOL Padawan Precisa Saber Sobre CI/CD, Containers, Kubernetes, Infrastructure as Code, Pipelines, Monitoramento e Como os Grandes Bancos Automatizam Milhões de Transações por Dia

"Programar é apenas escrever código. Engenharia de Software é garantir que esse código chegue à produção com qualidade, segurança, repetibilidade e confiabilidade."


Durante muitos anos, o mundo Mainframe e o mundo Open pareciam universos completamente diferentes.

De um lado estavam os programadores COBOL, PL/I, Natural e Assembler trabalhando em ambientes IBM Z, produzindo aplicações que movimentam bancos, seguradoras, bolsas de valores, cartões de crédito, governos e empresas de telecomunicações.

Do outro lado estavam Linux, Docker, Kubernetes, Git, Jenkins, Cloud, Terraform e dezenas de ferramentas modernas que pareciam pertencer apenas às startups do Vale do Silício.

Mas existe uma verdade que poucos contam.

Os princípios são exatamente os mesmos.

O que muda são as ferramentas.

O objetivo continua sendo entregar software confiável, rapidamente, sem causar indisponibilidade.

E isso é exatamente o que os profissionais de Mainframe fazem há décadas.

Hoje vamos tomar mais um café e entender por que DevOps não substitui o Mainframe. Na verdade, ele complementa uma filosofia que o IBM Z já pratica há muito tempo.


O maior problema da Engenharia de Software

Imagine um banco em 1995.

Existem cinquenta programadores COBOL.

Cada um altera dezenas de programas durante a semana.

Na sexta-feira chega o momento mais temido.

Alguém diz:

"Vamos subir tudo para produção."

Começa então um ritual que muitos veteranos conhecem.

Primeiro é necessário localizar todos os fontes.

Depois recompilar.

Executar o Link-Edit.

Gerar os módulos de carga.

Executar o BIND dos pacotes DB2.

Atualizar CICS.

Atualizar PROCs.

Atualizar JCL.

Executar testes.

Cruzar os dedos.

Quando algo falhava, ninguém sabia exatamente qual alteração havia provocado o problema.

Esse cenário ficou conhecido no mundo da engenharia como Integration Hell.

Era caro.

Demorado.

Arriscado.

E completamente dependente de trabalho manual.

Foi exatamente para resolver esse problema que nasceu o DevOps moderno.


DevOps não é uma ferramenta

Um dos maiores erros dos iniciantes é acreditar que DevOps seja um software.

Alguns dizem:

"Estamos usando Jenkins."

Logo concluem:

"Então fazemos DevOps."

Não.

Jenkins não é DevOps.

Docker não é DevOps.

Git não é DevOps.

Kubernetes não é DevOps.

Terraform não é DevOps.

Ansible não é DevOps.

Todos eles são apenas ferramentas.

DevOps é uma filosofia de engenharia.

É uma maneira diferente de pensar.

A pergunta deixa de ser:

"Como faço o deploy?"

E passa a ser:

"Como faço milhares de deploys sem interromper o negócio?"

Essa mudança de mentalidade transforma completamente uma equipe.


A filosofia DevOps

Imagine uma corrida de revezamento.

Se um corredor correr muito rápido, mas demorar para entregar o bastão ao próximo, toda a equipe perde.

Em desenvolvimento de software acontece exatamente a mesma coisa.

Não adianta o desenvolvedor produzir código rapidamente se os testes levam semanas.

Não adianta testar rapidamente se a implantação depende de dezenas de procedimentos manuais.

Não adianta implantar rapidamente se ninguém monitora a aplicação depois.

DevOps conecta todas essas etapas em um fluxo contínuo.

É uma esteira de produção de software.


CI — Continuous Integration

A primeira etapa dessa esteira chama-se Integração Contínua.

No passado, cada desenvolvedor trabalhava isoladamente durante dias.

Quando finalmente entregava seu código, surgiam conflitos gigantescos.

Hoje a ideia é completamente diferente.

Cada pequena alteração é enviada ao repositório imediatamente.

A partir desse momento começa um processo totalmente automatizado.

O servidor baixa o código.

Compila.

Executa testes.

Analisa qualidade.

Verifica segurança.

Se tudo estiver correto, aceita a alteração.

Caso contrário, rejeita automaticamente.

Quanto menores forem as mudanças, menor será o risco de incompatibilidades.

Essa é a essência da Integração Contínua.


Como isso acontece no IBM Z

Muitos imaginam que isso exista apenas para Java ou Python.

Não existe essa limitação.

Em um ambiente IBM Z moderno, um commit pode disparar automaticamente:

  • compilação COBOL;

  • compilação PL/I;

  • compilação Assembler;

  • geração de módulos de carga;

  • execução de BIND DB2;

  • criação de artefatos;

  • testes automatizados;

  • análise de impacto;

  • geração de relatórios;

  • publicação para homologação.

Ferramentas como IBM Dependency Based Build (DBB), Jenkins e Git permitem automatizar todo esse fluxo.

O programador continua escrevendo COBOL.

O restante passa a acontecer automaticamente.


Continuous Delivery

Depois da integração vem a entrega.

Aqui existe uma diferença importante.

O software está totalmente pronto para produção.

Todos os testes passaram.

Os artefatos já foram gerados.

A documentação foi atualizada.

Os relatórios estão disponíveis.

Mas ainda existe uma aprovação humana.

Isso é muito comum em bancos.

Uma equipe de Change Management analisa a mudança.

Se aprovada, a implantação acontece.

Caso contrário, ela permanece aguardando.

Esse modelo recebe o nome de Continuous Delivery.


Continuous Deployment

Existe um passo além.

Nenhuma aprovação humana.

O commit entra no Git.

Os testes passam.

O deploy acontece automaticamente.

Empresas como Netflix, Spotify, Amazon e Google fazem isso milhares de vezes por dia.

É claro que nem toda empresa pode seguir esse modelo.

Bancos, seguradoras e órgãos governamentais normalmente exigem aprovações formais por questões regulatórias.

Mesmo assim, o restante do processo continua totalmente automatizado.


O Pipeline

Imagine uma linha de montagem de automóveis.

Cada estação realiza uma atividade específica.

Motor.

Pintura.

Suspensão.

Acabamento.

Inspeção.

Com software acontece exatamente a mesma coisa.

Essa linha de montagem recebe o nome de Pipeline.

Cada etapa agrega qualidade ao produto.

Um pipeline moderno normalmente executa:

  • obtenção do código-fonte;

  • compilação;

  • geração dos executáveis;

  • testes unitários;

  • testes de integração;

  • análise estática;

  • análise de segurança;

  • geração dos pacotes;

  • publicação;

  • deploy;

  • smoke tests;

  • monitoramento inicial.

Quanto menos intervenção humana existir, menor será a probabilidade de erro.


O papel do Git

Git não serve apenas para armazenar código.

Ele registra toda a história do projeto.

Quem alterou.

Quando alterou.

Por que alterou.

É possível retornar para qualquer versão anterior.

Essa característica transforma o Git em um verdadeiro diário da aplicação.

No mundo Mainframe, ele substitui antigas bibliotecas de controle de versões e integra naturalmente o desenvolvimento COBOL às práticas modernas.


Containers

Agora chegamos a um conceito que costuma gerar bastante confusão.

Um container não é uma máquina virtual.

Ele também não é um servidor.

Pense nele como uma caixa completamente fechada.

Dentro dessa caixa existem:

  • aplicação;

  • bibliotecas;

  • dependências;

  • arquivos de configuração;

  • variáveis de ambiente;

  • executáveis;

  • tudo o que a aplicação precisa para funcionar.

A grande vantagem é simples.

Se funciona dentro do container, funcionará em qualquer ambiente compatível.

Acabou aquela famosa frase:

"Na minha máquina funciona."


Docker

Docker foi a tecnologia que popularizou os containers.

Em vez de instalar dezenas de programas manualmente, descrevemos tudo em um arquivo chamado Dockerfile.

Esse arquivo funciona como uma receita.

Toda vez que ele é executado, produz exatamente o mesmo ambiente.

É repetível.

Auditável.

Versionável.

Esse conceito é extremamente importante na engenharia moderna.


Uma analogia para o Programador COBOL Padawan

Imagine um PROC JCL extremamente completo.

Ele já referencia todas as bibliotecas.

Possui todos os parâmetros.

Aponta para os datasets corretos.

Possui utilitários.

Define as variáveis necessárias.

Qualquer operador consegue executá-lo.

Esse PROC lembra bastante a ideia de um container.

Tudo o que é necessário já está preparado.


Kubernetes

Se containers resolvem o problema da execução, Kubernetes resolve o problema da administração.

Imagine uma empresa executando cinco mil containers.

Quem decide onde cada um será executado?

Quem reinicia um container que falhou?

Quem aumenta automaticamente a capacidade quando chegam mais usuários?

Quem reduz recursos durante a madrugada?

Quem distribui a carga entre vários servidores?

Quem realiza atualizações sem interromper o serviço?

A resposta para todas essas perguntas é Kubernetes.

Ele funciona como um maestro coordenando milhares de músicos.


Os Pods

No Kubernetes, normalmente não administramos containers diretamente.

Administramos Pods.

Um Pod pode conter um ou mais containers trabalhando em conjunto.

É a menor unidade de execução dentro do cluster.


O Control Plane

O cérebro do Kubernetes chama-se Control Plane.

Ele conhece todo o ambiente.

Sabe quais máquinas existem.

Quantos recursos possuem.

Quais aplicações estão executando.

Quais precisam ser reiniciadas.

Ele toma decisões automaticamente.


Os Worker Nodes

São os servidores que realmente executam as aplicações.

Enquanto o Control Plane decide, os Worker Nodes trabalham.

Essa separação aumenta a confiabilidade e a escalabilidade.


Healing

Imagine que um servidor apresente defeito.

No modelo tradicional alguém recebe um chamado.

Analisa logs.

Reinicia processos.

No Kubernetes tudo isso acontece automaticamente.

O sistema percebe que um container deixou de responder.

Cria outro.

Redireciona o tráfego.

O usuário muitas vezes nem percebe que ocorreu uma falha.


Auto Scaling

Durante uma promoção da Black Friday o número de acessos pode multiplicar por dez.

Kubernetes detecta esse crescimento.

Cria novas instâncias.

Distribui os usuários.

Quando a demanda diminui, remove os recursos excedentes.

Tudo automaticamente.


O equivalente no IBM Z

Embora Kubernetes seja uma tecnologia diferente, a filosofia lembra diversos recursos tradicionais do Mainframe.

O IBM Workload Manager (WLM) distribui cargas conforme prioridades.

O Parallel Sysplex compartilha processamento entre vários sistemas.

O Sysplex Distributor realiza balanceamento de carga.

A ideia continua sendo utilizar os recursos disponíveis da forma mais eficiente possível.


Infrastructure as Code

Durante décadas administradores criaram servidores manualmente.

Clicavam em dezenas de telas.

Criavam usuários.

Configuravam rede.

Firewall.

Discos.

Permissões.

Esse processo era demorado e sujeito a erros.

Hoje escrevemos infraestrutura como escrevemos software.

Esse conceito recebe o nome de Infrastructure as Code.


Terraform

Terraform tornou-se um dos maiores representantes dessa filosofia.

Em vez de clicar em interfaces gráficas, descrevemos a infraestrutura em arquivos de texto.

Esses arquivos ficam armazenados no Git.

São revisados.

Versionados.

Auditados.

Automatizados.

Se for necessário reconstruir todo o ambiente, basta executar novamente o código.


Ansible

Enquanto Terraform normalmente cria infraestrutura, Ansible costuma configurá-la.

Ele instala programas.

Atualiza configurações.

Cria usuários.

Distribui certificados.

Reinicia serviços.

Executa comandos remotamente.

No IBM Z, Ansible já é utilizado para administrar USS, CICS, MQ, Db2, RACF, z/OSMF e diversas outras tecnologias.


Configuration Management

Agora imagine mil servidores.

Todos deveriam possuir exatamente a mesma configuração.

Na prática isso quase nunca acontece quando o trabalho é manual.

Um servidor possui Java 17.

Outro possui Java 21.

Um utiliza uma biblioteca diferente.

Outro perdeu um certificado.

Esse fenômeno chama-se Configuration Drift.

Ferramentas de gerenciamento de configuração eliminam esse problema.

Elas garantem que todos os ambientes permaneçam idênticos.

Isso reduz drasticamente erros difíceis de reproduzir.


Observabilidade e Monitoramento

Muitos acreditam que o deploy encerra o trabalho.

Na verdade ele marca o início da fase mais importante.

Depois que o sistema entra em produção é necessário observar continuamente seu comportamento.

CPU.

Memória.

Latência.

Tempo de resposta.

Quantidade de erros.

Uso de disco.

Rede.

Número de usuários.

Tudo precisa ser medido.

Não se gerencia aquilo que não se mede.


Logs, Métricas e Traces

A observabilidade moderna costuma ser baseada em três pilares.

Os logs registram eventos e mensagens geradas pelas aplicações.

As métricas mostram números agregados, como uso de CPU, quantidade de requisições e tempo médio de resposta.

Os traces acompanham uma única transação atravessando diversos serviços, permitindo identificar exatamente onde ocorreu uma lentidão.

Juntos, esses três elementos fornecem uma visão muito mais completa do ambiente do que um simples monitor de CPU.


Monitoramento no IBM Z

Quem trabalha com Mainframe sabe que monitoramento não é novidade.

Ferramentas como RMF, SMF, OMEGAMON, SDSF e monitores específicos de CICS, IMS e Db2 acompanham o comportamento do sistema há décadas.

A diferença é que hoje essas informações também podem alimentar plataformas modernas de observabilidade, permitindo que aplicações distribuídas e aplicações no IBM Z sejam analisadas de forma integrada.


Segurança no Pipeline

Outra característica importante do DevOps moderno é que segurança deixou de ser uma etapa isolada.

Ela passou a fazer parte da própria esteira de desenvolvimento.

Esse movimento ficou conhecido como DevSecOps.

Durante o pipeline podem ser executadas análises de vulnerabilidades, verificação de dependências, inspeção de imagens de containers, análise estática de código e validação de políticas de conformidade.

O objetivo é detectar problemas o mais cedo possível, quando ainda são baratos de corrigir.


Cultura DevOps

Talvez este seja o conceito mais importante de todo o artigo.

Ferramentas podem ser compradas.

Servidores podem ser instalados.

Softwares podem ser atualizados.

Cultura não.

Ela precisa ser construída.

No modelo tradicional existiam silos.

O desenvolvedor escrevia o código.

A equipe de testes encontrava erros.

A equipe de operações implantava.

Quando algo dava errado começava o jogo da culpa.

DevOps rompe essa barreira.

Todos compartilham a responsabilidade pelo sucesso do produto.

Desenvolvimento, testes, segurança e operações deixam de atuar como departamentos isolados e passam a funcionar como uma única equipe.


DevOps no mundo Mainframe

Existe um mito de que Mainframe é incompatível com DevOps.

Nada poderia estar mais distante da realidade.

Hoje é perfeitamente possível integrar aplicações COBOL ao Git, automatizar compilações com Jenkins ou GitHub Actions, executar testes automatizados, versionar infraestrutura, administrar ambientes com Ansible, disponibilizar APIs por meio do z/OS Connect e monitorar tudo em tempo real.

Na prática, o IBM Z apenas incorporou ferramentas modernas a uma plataforma que sempre foi reconhecida por sua estabilidade, disponibilidade e capacidade de processamento.


O que o Programador COBOL Padawan deve aprender primeiro?

Se você está iniciando sua jornada, não tente aprender todas as ferramentas ao mesmo tempo.

Construa uma base sólida.

Comece entendendo Git e controle de versão.

Depois estude CI/CD e pipelines.

Aprenda como containers funcionam e por que eles resolveram o problema da portabilidade.

Entenda o papel do Kubernetes na orquestração.

Conheça Infrastructure as Code e Configuration Management.

Por fim, aprofunde-se em observabilidade, segurança e cultura DevOps.

As ferramentas mudam com o tempo.

Os princípios permanecem.


Conclusão

Existe uma frase muito conhecida na engenharia de software:

"Automatize tudo o que puder. Padronize tudo o que automatizar. Monitore tudo o que colocar em produção."

Ela resume perfeitamente a essência do DevOps.

Para um Programador COBOL Padawan, compreender esses conceitos não significa abandonar o Mainframe. Significa ampliar sua visão de engenharia. O COBOL continua escrevendo regras de negócio que movimentam bilhões de reais diariamente. O IBM Z continua oferecendo níveis de disponibilidade difíceis de igualar. O que muda é a forma como esse software é desenvolvido, testado, implantado, configurado e observado.

Os grandes bancos já não enxergam fronteiras entre "Mainframe" e "Open". Eles enxergam uma cadeia única de entrega de software, na qual aplicações COBOL, Java, Python, APIs REST, containers e serviços em nuvem convivem em uma arquitetura integrada. Nesse cenário, o profissional mais valorizado não é aquele que domina apenas uma linguagem, mas aquele que compreende o ciclo completo de vida do software.

Assim como um mestre Jedi conhece muito mais do que apenas o sabre de luz, um verdadeiro engenheiro de software precisa entender muito mais do que apenas escrever código. Ele precisa dominar automação, integração contínua, entrega contínua, infraestrutura como código, observabilidade, segurança e colaboração entre equipes.

No fim das contas, DevOps não é sobre Docker, Kubernetes ou Jenkins. É sobre construir sistemas que possam evoluir continuamente, com qualidade, segurança e confiança. E essa sempre foi — e continuará sendo — uma das maiores virtudes do ecossistema IBM Mainframe.


Vagner Renato Bellacosa, IBM Champion e especialista em IBM Mainframe
IBM Z17 SYSTEM ONLINE
Sobre o autor

Vagner Renato Bellacosa

IBM Champion 2026 • Especialista em IBM Mainframe

Vagner Renato Bellacosa trabalha com IBM Mainframe desde 1988 , é IBM Champion e especialista em COBOL, CICS, Db2, z/OS e IBM Z. Compartilha experiências profissionais, conhecimento técnico, história da computação e práticas do universo mainframe para aproximar novas gerações das tecnologias que sustentam empresas, bancos e governos ao redor do mundo.

IBM Champion IBM Z COBOL CICS Db2 z/OS Mainframe desde 1988
GitHub LinkedIn
Inicializando conteúdo...