↓Pular para o conteúdo principal
  1. blog/
ARTIGO TÉCNICO

Ansible --limit e blast radius: por que alvo vazio não pode ser detalhe de interface

Como tornar o alvo da automação explícito, bloquear execuções amplas por engano e transformar PLAY RECAP e escalonamento em parte do contrato operacional.

Em Ansible, uma diferença pequena na linha de comando pode mudar completamente o blast radius:

1
ansible-playbook play.yml

versus:

1
ansible-playbook play.yml --limit servidor-alvo

Em um catálogo real de operações executadas via Semaphore, o runbook N1 colocou uma regra simples no topo:

preencher sempre o Limite quando o campo existir. Em branco, a tarefa pode alcançar todos os servidores do inventory.

Isso não é ergonomia.

É controle de risco.

O playbook define hosts; --limit reduz o conjunto #

Um playbook pode declarar:

1
- hosts: all

ou um grupo amplo.

--limit aplica uma restrição adicional ao conjunto resolvido pelo inventory.

Exemplo:

1
2
ansible-playbook maintenance.yml \
  --limit app-123

O problema aparece quando a interface torna o limite opcional para uma operação que não deveria ser ampla.

Campo vazio não deve significar “todos” silenciosamente #

No runbook analisado, o alerta existe justamente porque uma execução sem Limite pode cair no comportamento amplo do playbook/inventory.

Para tarefas de mudança, eu prefiro inverter a lógica:

1
sem alvo explícito → bloquear

em vez de:

1
sem alvo explícito → usar todos

Isso pode ser validado no próprio playbook.

Guardrail dentro do playbook #

Se o target vem como variável:

1
2
3
4
5
6
- name: Exigir alvo explícito
  ansible.builtin.assert:
    that:
      - target | default('') | length > 0
      - target != 'all'
    fail_msg: "Informe um alvo explícito. Execução ampla bloqueada."

Quando o limit é aplicado pelo orquestrador, também vale validar a expectativa de escopo por preflight ou wrappers.

A interface sozinha não deve ser a única barreira.

O risco depende da operação #

Um all pode ser aceitável para um inventário LOW, desde que a concorrência seja conhecida.

Por exemplo:

1
coletar hostname e uptime

Pode ser deliberadamente executado na frota inteira.

Já:

1
2
3
4
restart de container
resize cloud
deploy
alteração Nginx

precisa de uma política muito mais estreita.

O alvo faz parte da classificação de risco.

Blast radius precisa aparecer antes do Run #

O catálogo operacional recuperado descreve tarefas com campos como:

1
2
3
4
5
6
7
Risco
Blast radius
Reversível
Pré-requisitos
Parâmetros
Resultado esperado
Quando escalar

Isso é uma boa interface mental.

Antes de executar, a pessoa consegue responder:

se eu errar, quantos hosts posso afetar?

Uma receita de provisionamento, por exemplo, estava documentada com blast radius de um host novo.

Outras operações cloud podiam variar de risco conforme a ação escolhida.

Survey deve ajudar a reduzir espaço de erro #

Em vez de um texto completamente livre, dependendo do template podemos usar:

  • select com grupos/hosts permitidos;
  • regex para hostname esperado;
  • lista gerada do inventory;
  • bloqueio de all, * ou grupo global;
  • confirmação extra para grupos maiores;
  • defaults vazios, nunca defaults perigosos.

Se o operador precisa digitar um hostname, valide o formato antes de chamar Ansible.

Um alvo válido também precisa existir #

Validar regex evita string absurda.

Não prova que o host existe.

Um preflight pode consultar inventory:

1
ansible-inventory --graph

ou:

1
ansible-inventory --list

E conferir se o alvo resolve.

Outra opção é um smoke:

1
ansible "$TARGET" -m ping --limit "$TARGET"

antes de uma mudança mais crítica.

serial e throttle resolvem outro problema #

--limit responde:

quem pode ser atingido?

serial responde:

quantos ao mesmo tempo?

Exemplo:

1
2
- hosts: app
  serial: 1

Mesmo com um grupo de dez hosts deliberadamente selecionado, talvez a mudança precise passar um por um.

Para operações de frota, eu considero as duas dimensões separadamente:

1
2
3
escopo total
+
concorrência

Resultado esperado precisa estar documentado #

O runbook N1 não termina em “task finished”.

Ele orienta o operador a olhar o PLAY RECAP.

Uma regra operacional documentada:

1
2
failed=0 → sucesso esperado
failed>0 → não repetir sozinho; copiar log e escalar

Isso reduz outra classe de incidente: o loop humano de clicar novamente numa automação que falhou sem entender em qual ponto parou.

Repetir task falha pode piorar estado parcial #

Ansible tende à idempotência quando os módulos/playbooks são escritos para isso.

Mas nem toda task é perfeitamente idempotente.

Um playbook pode ter:

  • shell;
  • API externa;
  • reboot;
  • deploy;
  • operação cloud;
  • side effect fora do host.

Então failed=1 não deveria automaticamente virar:

roda de novo.

Primeiro entender:

1
2
3
4
qual task falhou?
o que já mudou antes da falha?
há rollback?
é seguro repetir?

O log é parte do contrato #

Para N1, a orientação recuperada era acompanhar a aba Log e, em falha, copiar o log completo para escalonamento.

Isso transforma o Semaphore em mais do que botão de execução.

Ele passa a ser também fonte de evidência:

1
2
3
4
5
6
quem executou
qual template
qual alvo
quais parâmetros
qual sequência de tasks
qual PLAY RECAP

Um exemplo de contrato de mudança #

Eu modelaria uma receita HIGH assim:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
Template: CHANGE - Restart Serviço
Risco: HIGH
Blast radius: 1 host
Target: obrigatório
Ambiente: obrigatório
Motivo/ticket: obrigatório
Confirmação: SIM
Preflight: host existe + serviço existe
Execução: --limit target
Concorrência: 1
Validação: health/status depois
Falha: não repetir automaticamente

A automação continua simples.

A governança é que fica explícita.

O que a fonte sustenta #

O runbook operacional recuperado documenta diretamente:

  • categoria e risco por tarefa;
  • blast radius;
  • pré-requisitos;
  • parâmetros;
  • resultado esperado;
  • preenchimento obrigatório de Limite quando aplicável;
  • alerta de que limite vazio pode atingir todos os servidores;
  • acompanhamento de Log;
  • PLAY RECAP failed=0 como critério operacional de sucesso;
  • orientação para não repetir sozinho quando houver falha e escalar com o log.

Nomes de cliente, host, domínio e IP da fonte não são necessários para aplicar o método e foram omitidos.

O principal aprendizado #

Em automação de frota, o alvo não é uma variável qualquer.

É uma fronteira de segurança.

Eu quero que uma mudança só saia do control plane quando três coisas estiverem explícitas:

1
2
3
qual operação
qual alvo
qual critério de sucesso

Se o alvo vazio significa “todo mundo”, a interface está escolhendo o default mais perigoso possível.

TEM UM CENÁRIO PARECIDO?

Me chama.

Manda o contexto, os sintomas e o que já foi testado. Bora organizar as evidências antes de sair mexendo.

Falar com Castro →
Sem enrolação. Com evidência.