Manejo de fallos con bloques y rescue

AnsibleBeginner
Practicar Ahora

Introducción

Los bloques (blocks) de Ansible permiten agrupar tareas relacionadas. Una sección rescue se ejecuta cuando una tarea dentro del bloque falla, mientras que una sección always se ejecuta en cualquier caso, independientemente de si hubo éxito o fallo.

En este laboratorio, creará un fallo controlado, se recuperará de él y luego volverá a ejecutar el mismo playbook con el fallo desactivado para observar la ruta de éxito.

Crear un proyecto de manejo de fallos

En este paso, creará un pequeño proyecto con un host gestionado local y un directorio de informes para los marcadores de block, rescue y always.

cd /home/labex/project
mkdir -p rhce-ansible/{inventory,playbooks,reports}
cd rhce-ansible
cat > ansible.cfg <<'EOF'
[defaults]
inventory = ./inventory/hosts
host_key_checking = False
retry_files_enabled = False
EOF
cat > inventory/hosts <<'EOF'
[managed]
host ansible_connection=local
EOF

El directorio reports es donde el playbook escribirá marcadores para cada ruta. Esto hace que el comportamiento del bloque sea visible sin depender únicamente de la salida de la terminal.

Escribir un bloque con rescue y always

En este paso, escribirá un playbook con un fallo controlado. El bloque fallará cuando simulate_failure sea verdadero, la sección rescue escribirá un marcador de recuperación y la sección always escribirá un marcador de auditoría. Antes de ejecutar los comandos en este paso, regrese al directorio del proyecto de Ansible. Esto mantiene la estabilidad de los comandos incluso si LabEx ejecuta cada paso por separado.

cd /home/labex/project/rhce-ansible
cat > playbooks/block-rescue.yml <<'EOF'
---
- name: Practice block rescue and always
  hosts: managed
  gather_facts: false
  vars:
    simulate_failure: true
  tasks:
    - name: Remove old markers
      ansible.builtin.file:
        path: "/home/labex/project/rhce-ansible/reports/{{ item }}.txt"
        state: absent
      loop:
        - block-success
        - rescued
        - always

    - name: Protect a risky operation with rescue
      block:
        - name: Run a command that may fail
          ansible.builtin.command: /usr/bin/false
          when: simulate_failure | bool

        - name: Mark block success
          ansible.builtin.copy:
            dest: /home/labex/project/rhce-ansible/reports/block-success.txt
            content: |
              block completed
            mode: '0644'
      rescue:
        - name: Mark rescue path
          ansible.builtin.copy:
            dest: /home/labex/project/rhce-ansible/reports/rescued.txt
            content: |
              rescued controlled failure
            mode: '0644'
      always:
        - name: Mark always path
          ansible.builtin.copy:
            dest: /home/labex/project/rhce-ansible/reports/always.txt
            content: |
              always ran
            mode: '0644'
EOF

El comando de riesgo es /usr/bin/false, el cual siempre termina con un fallo. Cuando simulate_failure es verdadero, el bloque se detiene en esa tarea fallida, la sección rescue escribe rescued.txt y la sección always escribe always.txt en cualquier caso.

ansible-playbook playbooks/block-rescue.yml --syntax-check

Las palabras clave block, rescue y always deben estar alineadas al mismo nivel de sangría. Una verificación de sintaxis es una forma rápida de detectar una sección mal colocada antes de ejecutar el fallo controlado.

Ejecutar la ruta de fallo controlado

En este paso, ejecutará el playbook con el fallo predeterminado habilitado. El resumen del play debería mostrar una tarea rescatada en lugar de un play fallido. Antes de ejecutar los comandos en este paso, regrese al directorio del proyecto de Ansible.

cd /home/labex/project/rhce-ansible
ansible-playbook playbooks/block-rescue.yml | tee reports/failure-path.txt

Se espera que esta ejecución muestre rescued=1 y failed=0 en el resumen. Esto significa que Ansible detectó un fallo en una tarea dentro del bloque, ejecutó las tareas de rescate y no consideró el play general como fallido.

cat reports/rescued.txt reports/always.txt

Los dos archivos de marcador deberían decir rescued controlled failure y always ran. No debería ver block-success.txt en esta ruta porque el bloque no llegó a la tarea del marcador de éxito.

Ejecutar la ruta de éxito con una variable adicional

En este paso, anulará simulate_failure desde la línea de comandos. El bloque debería completarse normalmente, el rescate no debería ejecutarse y la sección always debería ejecutarse de todos modos. Antes de ejecutar los comandos en este paso, regrese al directorio del proyecto de Ansible.

cd /home/labex/project/rhce-ansible
ansible-playbook playbooks/block-rescue.yml -e simulate_failure=false | tee reports/success-path.txt

La opción -e simulate_failure=false anula la variable del playbook solo para esta ejecución. Ahora, el comando false se omite, el bloque normal llega a block-success.txt y la sección de rescate no debería ejecutarse.

cat reports/block-success.txt reports/always.txt

La ruta de éxito debería mostrar block completed y always ran. El playbook elimina los marcadores antiguos al inicio, por lo que rescued.txt ya no debería existir después de esta ejecución.

Comparar la evidencia de fallo y éxito

En este paso, comparará las dos ejecuciones guardadas del playbook. Mantener la evidencia pequeña le ayuda a solucionar problemas sobre qué ruta se ejecutó sin tener que leer toda la salida. Antes de ejecutar los comandos en este paso, regrese al directorio del proyecto de Ansible.

cd /home/labex/project/rhce-ansible
grep -E 'rescued=|failed=' reports/failure-path.txt reports/success-path.txt

El informe de la ruta de fallo debería contener rescued=1, mientras que el informe de la ruta de éxito debería contener rescued=0. Ambos deberían tener failed=0, pero por razones diferentes.

ls -1 reports

La lista de informes debería incluir ambas salidas guardadas del playbook, además de los marcadores de la ruta más reciente. Mantener ambas salidas facilita la comparación de cómo el rescate cambia el resumen.

Resumen

Ha utilizado las secciones block, rescue y always para manejar un fallo controlado, luego ejecutó el mismo playbook a través de una ruta de éxito normal y comparó la evidencia guardada.