Introdução
Roles organizam uma unidade funcional de automação para que os consumidores possam fornecer dados sem duplicar a implementação. Você criará uma role com valores padrão públicos, renderizará páginas específicas por host, manterá a validação da configuração e o comportamento de recarga dentro da role e a reutilizará em dois grupos do inventário. Arquivos gerenciados reais e respostas HTTP verificarão que a role é realmente invocada.
Criar e invocar uma role com valores padrão
Nesta etapa, você moverá a automação do site para uma role e a invocará por um playbook curto usando entradas padrão reutilizáveis.
Uma role agrupa tarefas relacionadas, variáveis padrão, modelos e handlers em um diretório padrão. Seu tasks/main.yml é o ponto de entrada das tarefas; defaults/main.yml fornece valores de baixa precedência que os consumidores podem substituir. As origens dos modelos ficam em templates, e handlers/main.yml conterá posteriormente ações de serviço acionadas por alterações.
O inventário preparado já coloca web1 em canary e web2 em stable, sob o grupo pai sites. O nginx está instalado como pré-requisito. Inspecione os grupos:
cd /home/labex/project
ansible-inventory --graph
Crie os diretórios da role com mkdir -p. Vários argumentos de caminho criam cada diretório nomeado:
mkdir -p roles/managed_site/tasks roles/managed_site/defaults roles/managed_site/templates roles/managed_site/handlers
Use o prefixo site_ nas variáveis públicas da role para deixar clara sua finalidade. Comece com padrões compartilhados que qualquer consumidor possa usar:
cat > roles/managed_site/defaults/main.yml <<'YAML'
site_environment: training
site_port: 8080
site_maintenance: false
YAML
O modelo da página usa a entrada da role junto ao nome de cada destino e à distribuição coletada:
cat > roles/managed_site/templates/page.txt.j2 <<'JINJA'
host={{ inventory_hostname }}
environment={{ site_environment }}
distribution={{ ansible_facts.distribution }}
JINJA
Crie o ponto de entrada das tarefas da role. Dentro de uma role, src: page.txt.j2 é resolvido no diretório templates dessa role; o destino continua sendo um caminho gerenciado absoluto:
cat > roles/managed_site/tasks/main.yml <<'YAML'
- name: Prepare the role-managed website directory
ansible.builtin.file:
path: /var/www/role-site
state: directory
owner: root
group: root
mode: "0755"
- name: Render the role-managed page
ansible.builtin.template:
src: page.txt.j2
dest: /var/www/role-site/index.html
owner: root
group: root
mode: "0644"
YAML
Invoque a role com a palavra-chave roles. O play que a envolve seleciona os destinos, coleta fatos e solicita become; a role fornece as tarefas reutilizáveis:
cat > site.yml <<'YAML'
- name: Apply the managed site role with defaults
hosts: sites
gather_facts: true
become: true
roles:
- managed_site
YAML
Valide e execute a role por seu playbook consumidor:
ansible-playbook site.yml --syntax-check
ansible-playbook site.yml
Inspecione as páginas reais criadas pela role:
ansible sites -m ansible.builtin.command -a 'cat /var/www/role-site/index.html'
Ambas devem mostrar environment=training a partir do padrão, com seus próprios nomes de host e distribution=Ubuntu. Apenas criar os diretórios da role não a executaria nem criaria esses arquivos gerenciados.
Manter modelos e handlers dentro da role reutilizável
Nesta etapa, você fará a role configurar e executar o site, incluindo a validação do candidato e seu próprio handler de recarga.
Coloque o modelo nginx completo junto à origem da página. Ele usa as entradas site_ da role, o filtro upper já praticado e um ramo booleano:
cat > roles/managed_site/templates/nginx.conf.j2 <<'JINJA'
events {}
http {
server_tokens off;
server {
listen {{ site_port }};
root /var/www/role-site;
index index.html;
add_header X-Environment "{{ site_environment | upper }}" always;
{% if site_maintenance %}
add_header X-Maintenance "enabled" always;
{% else %}
add_header X-Maintenance "disabled" always;
{% endif %}
}
}
JINJA
Acrescente tarefas da role que validem a configuração renderizada antes da substituição e mantenham explicitamente o nginx iniciado. A configuração alterada notifica o handler nomeado da role:
cat >> roles/managed_site/tasks/main.yml <<'YAML'
- name: Render and validate the role-managed nginx configuration
ansible.builtin.template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
owner: root
group: root
mode: "0644"
validate: /usr/sbin/nginx -t -c %s
notify: Reload managed site
- name: Keep the role-managed service running
ansible.builtin.service:
name: nginx
state: started
YAML
Escreva o handler no ponto de entrada de handlers da role, em vez de duplicá-lo em cada playbook consumidor:
cat > roles/managed_site/handlers/main.yml <<'YAML'
- name: Reload managed site
ansible.builtin.service:
name: nginx
state: reloaded
YAML
Execute o playbook consumidor inalterado. A role agora fornece seu comportamento completo de implantação:
ansible-playbook site.yml
Os dois hosts devem iniciar seus próprios sites na porta padrão 8080. Inspecione cada destino por seu próprio endereço de loopback:
ansible sites -m ansible.builtin.command -a 'curl --fail --silent --show-error -i http://127.0.0.1:8080/'
Cada corpo deve identificar seu próprio host e environment=training. Os cabeçalhos devem incluir X-Environment: TRAINING e X-Maintenance: disabled. A saída vem de serviços em execução configurados pela role, em vez de uma demonstração apenas no controlador.
Reutilizar a mesma role com substituições por variáveis de grupo
Nesta etapa, você aplicará a mesma role a dois contextos de grupos sem editar seus padrões reutilizáveis nem seus arquivos de tarefas.
Os padrões da role têm baixa precedência deliberadamente. As variáveis de grupo do inventário podem substituir essas entradas públicas, mantendo a mesma implementação. Mantenha defaults/main.yml inalterado e crie os dados consumidores de cada grupo:
cat > group_vars/canary.yml <<'YAML'
site_environment: development
site_port: 8081
site_maintenance: true
YAML
cat > group_vars/stable.yml <<'YAML'
site_environment: production
site_port: 8082
site_maintenance: false
YAML
Substitua o playbook consumidor por dois plays que invocam a mesma role managed_site. Cada grupo recebe suas próprias entradas resolvidas. Não duplique o diretório da role para cada ambiente:
cat > site.yml <<'YAML'
- name: Apply the shared role to canary
hosts: canary
gather_facts: true
become: true
roles:
- managed_site
- name: Apply the shared role to stable
hosts: stable
gather_facts: true
become: true
roles:
- managed_site
YAML
Valide e aplique os dois contextos:
ansible-playbook site.yml --syntax-check
ansible-playbook site.yml
Os dois ambientes devem carregar suas configurações alteradas pelo handler local da role. Inspecione os destinos reais em suas novas portas configuradas:
ansible canary -m ansible.builtin.command -a 'curl --fail --silent --show-error -i http://127.0.0.1:8081/'
ansible stable -m ansible.builtin.command -a 'curl --fail --silent --show-error -i http://127.0.0.1:8082/'
Canary deve identificar web1 e development, com cabeçalhos DEVELOPMENT/enabled. Stable deve identificar web2 e production, com cabeçalhos PRODUCTION/disabled. Essas diferenças vêm das entradas de grupo, enquanto uma role compartilhada continua responsável pelos padrões, tarefas, modelos e handlers.
Repita o mesmo playbook consumidor:
ansible-playbook site.yml
As duas linhas do resumo devem informar changed=0, unreachable=0 e failed=0, sem handler agendado. Uma role reutilizável precisa ser invocada e produzir um estado gerenciado convergido correto; apenas uma estrutura de diretórios não é uma implantação.
Resumo
Você organizou padrões, tarefas, modelos e handlers em uma role invocada. Padrões de baixa precedência permitiram substituições por consumidores, e dois grupos do inventário reutilizaram a mesma implementação para produzir serviços reais distintos. A validação de candidatos, as recargas acionadas por alterações e a execução repetida sem alterações continuaram fazendo parte da unidade reutilizável.


