1. Identificar quem está a ser tratado e onde ocorre o efeito
Uma equipa fictícia precisa de retirar servidores de um pool durante uma atualização. A alteração do pool ocorre num ponto de controlo, mas cada decisão refere um servidor da aplicação. Desenha duas colunas: identidade do servidor tratado e local onde a operação será executada. No laboratório, quatro aliases worker e um alias sink usam a mesma máquina através de ligação local. Os relatórios são escritos através de sink, mantendo inventory_hostname como identidade de origem. Isso permite estudar a associação sem alegar cinco máquinas, SSH ou um balanceador real. Antes de executar uma automação de produção, confirma o inventário resolvido, o destino delegado e as credenciais que esse destino vai usar. O nome apresentado no título de uma tarefa não substitui essa confirmação.
2. Definir o que significa uma vez
No ensaio, serial: 2 divide quatro workers em dois lotes ordenados. Uma tarefa com run_once escreve dois registos, um por lote. Esse comportamento pode estar correto para preparar cada lote e errado para uma migração global. Uma segunda tarefa usa uma condição explícita sobre o primeiro host da seleção total e escreve apenas um registo. Se a seleção for limitada a worker_b e worker_d, esse primeiro host passa a ser worker_b. Não fixes worker_a como líder universal sem considerar limites, falhas e alterações de inventário. Nem run_once nem uma condição num play criam exclusão entre dois processos ansible-playbook independentes. Para uma operação global não repetível, define coordenação externa, idempotência ou um mecanismo de exclusão apropriado, além da seleção local.
3. Evitar colisões no destino comum
Delegar quatro tarefas para o mesmo destino não as transforma numa única tarefa. Se cada worker produzir uma configuração completa do mesmo ficheiro, uma escrita posterior pode substituir a anterior. Reduzir concorrência pode evitar sobreposição temporal, mas não resolve esse erro de composição: quatro substituições sequenciais continuam a poder conservar só o último conteúdo. O laboratório escreve um relatório por origem e verifica a presença dos quatro ficheiros. Uma alternativa de desenho é recolher resultados e gerar um único documento completo num passo coordenado. Define quais hosts entram nesse documento, como tratar hosts que falharam e quando a recolha está pronta. O ensaio não reproduz uma corrida aleatória; demonstra uma estrutura que permite observar cobertura sem partilhar o ficheiro de saída.
4. Dar dono explícito aos valores
Uma tarefa delegada pode produzir informação sobre um sistema diferente daquele que está a ser tratado no play. Por omissão, o set_fact delegado do exercício associa origin_fact ao worker. A tarefa seguinte usa delegate_facts: true e associa sink_fact ao destino sink. Os relatórios mostram ambos os resultados através de hostvars explícitos, evitando confundir identidade de origem, valores do destino e valores globais. Esta distinção importa quando um play da aplicação recolhe informação de uma base de dados ou de um ponto de controlo. Antes de usar o valor noutro template, confirma a que host pertence, quando foi produzido e qual observação representa. Um nome como db_status não demonstra que o valor foi guardado no host da base de dados nem que descreve o estado atual.
5. Transformar a execução em critério de mudança
Para o handover, não entregues apenas um recap sem erros. Regista hosts selecionados, lotes, tarefas globais, destinos delegados, efeitos esperados e resultados por origem. Num serviço fictício com seis nós, dois nós por lote não provam que os quatro restantes conseguem suportar a carga, nem que pertencem a domínios de falha independentes. Essa aceitação depende de capacidade, saúde, tráfego e critérios de retorno medidos no serviço. Usa o laboratório para prever quantas operações serão pedidas, depois ensaia o comportamento do componente real num ambiente autorizado. Se a operação global falhar, a política deve dizer se se interrompe a mudança, se se mantém um estado parcial ou se se recupera. Não inventes um resultado de disponibilidade a partir da sintaxe do playbook.
# Local teaching example; four aliases use one machine. No SSH or services.
# Save the following inventory as inventory.ini:
# [workers]
# worker_a ansible_connection=local
# worker_b ansible_connection=local
# worker_c ansible_connection=local
# worker_d ansible_connection=local
# Run: ansible-playbook -i inventory.ini batches.yml
---
- hosts: workers
gather_facts: false
strategy: linear
order: sorted
serial: 2
tasks:
- name: Observe one result per batch
ansible.builtin.debug:
msg:
origin: "{{ inventory_hostname }}"
batch: "{{ ansible_play_batch }}"
run_once: true
- name: Observe one result for the selected play
ansible.builtin.debug:
msg: "Selected leader: {{ inventory_hostname }}"
when: inventory_hostname == ansible_play_hosts_all[0]
# Repeat with --limit worker_b,worker_d and compare the selected leader.
# debug runs on the controller; this snippet does not demonstrate remote delegation.
Quatro workers, serial 2 e run_once produzem dois registos; a condição sobre a seleção total produz um. Com limit worker_b,worker_d, o líder passa a worker_b.
Armadilhas comuns
Destino comum como execução única; throttle como composição de ficheiro; primeiro host fixo como líder universal; recap como disponibilidade.
Tópicos relacionados: Facts, cache e evidência atual
Separa identidade, execução, frequência e propriedade dos dados antes de aceitar uma mudança coordenada.
Referência: Delegation, execution context and fact ownership · EX294 current objectives inspected 2026-09-30; RHCE in Ansible framework effective 2026-05-11; booking product version not publicly pinned