Introducción
La idempotencia significa que un playbook puede ejecutarse repetidamente y solo realizará cambios en el sistema cuando el estado deseado no exista o sea diferente al actual.
En este laboratorio, utilizará módulos comunes de Ansible para crear directorios y archivos de configuración para alias de hosts, y luego ejecutará el playbook dos veces para demostrar que la segunda ejecución es estable.
Crear un proyecto de práctica de idempotencia
En este paso, creará un pequeño proyecto de Ansible con dos alias de hosts gestionados locales. Cada alias escribe en su propio directorio para que pueda ver los resultados específicos de cada host mientras permanece dentro de una única máquina virtual RHEL 10.
Comience desde el espacio de trabajo predeterminado de LabEx.
cd /home/labex/project
La opción -p le indica a mkdir que cree los directorios principales cuando sea necesario y que finalice correctamente si el directorio ya existe.
mkdir -p rhce-ansible/{inventory/group_vars,playbooks,managed,reports}
cd rhce-ansible
Cree los valores predeterminados del proyecto que apuntan Ansible a su inventario y mantienen los archivos de reintento (retry files) deshabilitados.
cat > ansible.cfg <<'EOF'
[defaults]
inventory = ./inventory/hosts
host_key_checking = False
retry_files_enabled = False
EOF
El directorio managed contendrá los archivos producidos por el playbook, mientras que reports guardará la salida del playbook. Mantenerlos separados facilita la comparación del contenido deseado con la evidencia de ejecución de Ansible.
Definir hosts gestionados locales y variables
En este paso, creará un inventario y variables de grupo. Los alias utilizan ansible_connection=local, lo que significa que Ansible apunta a los hosts nombrados mientras se ejecuta de forma segura en esta máquina virtual.
Antes de ejecutar los comandos en este paso, regrese al directorio del proyecto de Ansible. Esto mantiene los comandos estables incluso cuando LabEx ejecuta cada paso por separado.
cd /home/labex/project/rhce-ansible
Cree dos alias de hosts de aplicación en un grupo.
cat > inventory/hosts <<'EOF'
[app]
app1 ansible_connection=local
app2 ansible_connection=local
EOF
Las variables de grupo describen el estado deseado compartido por cada host en el grupo.
cat > inventory/group_vars/app.yml <<'EOF'
app_owner: labex
app_environment: training
app_message: Managed by Ansible common modules
EOF
Confirme que Ansible puede ver los dos hosts.
ansible app --list-hosts
La salida debería listar app1 y app2. Esta comprobación es útil antes de escribir un playbook, ya que una ejecución (play) dirigida a app solo puede afectar a los hosts que el inventario resuelve en ese grupo.
Escribir un playbook de estado deseado
En este paso, escribirá un playbook que utiliza file, copy y lineinfile. Estos módulos describen el estado final en lugar de ejecutar comandos de shell manualmente.
Antes de ejecutar los comandos en este paso, regrese al directorio del proyecto de Ansible. Esto mantiene los comandos estables incluso cuando LabEx ejecuta cada paso por separado.
cd /home/labex/project/rhce-ansible
Cree el playbook. Las rutas incluyen {{ inventory_hostname }} para que cada alias obtenga su propio directorio de salida.
cat > playbooks/common-modules.yml <<'EOF'
---
- name: Configure app host directories with common modules
hosts: app
gather_facts: false
tasks:
- name: Ensure host directory exists
ansible.builtin.file:
path: "/home/labex/project/rhce-ansible/managed/{{ inventory_hostname }}"
state: directory
mode: '0755'
- name: Install base application configuration
ansible.builtin.copy:
dest: "/home/labex/project/rhce-ansible/managed/{{ inventory_hostname }}/app.conf"
content: |
owner={{ app_owner }}
environment={{ app_environment }}
message={{ app_message }}
mode: '0644'
- name: Ensure managed message is present
ansible.builtin.lineinfile:
path: "/home/labex/project/rhce-ansible/managed/{{ inventory_hostname }}/app.conf"
line: "message={{ app_message }}"
create: true
mode: '0644'
EOF
La tarea file crea el directorio, la tarea copy escribe la configuración completa y la tarea lineinfile demuestra cómo asegurar una línea específica. Estos módulos comparan el estado actual con el estado deseado, razón por la cual pueden ser idempotentes.
Utilice la comprobación de sintaxis antes de ejecutar un nuevo playbook.
ansible-playbook playbooks/common-modules.yml --syntax-check
Ejecutar el playbook e inspeccionar los archivos
En este paso, ejecutará el playbook de estado deseado por primera vez. La primera ejecución debería informar cambios porque los archivos de destino aún no existen. Antes de ejecutar los comandos en este paso, regrese al directorio del proyecto de Ansible. Esto mantiene los comandos estables incluso cuando LabEx ejecuta cada paso por separado.
cd /home/labex/project/rhce-ansible
Ejecute el playbook y guarde la salida para una comparación posterior.
ansible-playbook playbooks/common-modules.yml | tee reports/first-run.txt
La primera ejecución debería informar cambios porque los directorios de host y los archivos app.conf son nuevos. tee le permite observar la ejecución mientras guarda la misma salida para la comprobación de idempotencia.
Inspeccione los archivos específicos del host que creó Ansible.
cat managed/app1/app.conf managed/app2/app.conf
Ambos archivos deberían contener los mismos valores de propietario, entorno y mensaje, pero residen en directorios de alias de host diferentes. Esto demuestra que el playbook aplicó el mismo estado deseado a cada host del inventario.
Ejecutar el playbook nuevamente para probar la idempotencia
En este paso, ejecutará el mismo playbook nuevamente. Debido a que los archivos ya coinciden con el estado deseado, Ansible debería informar cero cambios para ambos hosts. Antes de ejecutar los comandos en este paso, regrese al directorio del proyecto de Ansible. Esto mantiene los comandos estables incluso cuando LabEx ejecuta cada paso por separado.
cd /home/labex/project/rhce-ansible
Ejecute el playbook por segunda vez y guarde la salida.
ansible-playbook playbooks/common-modules.yml | tee reports/second-run.txt
Busque changed=0 en las líneas de resumen.
grep -E 'app[12].*changed=0' reports/second-run.txt
changed=0 en la segunda ejecución es la señal clave de idempotencia. Significa que los módulos inspeccionaron los archivos existentes y determinaron que no era necesaria ninguna reparación.
Resumen
Ha construido un proyecto de Ansible, utilizado módulos comunes para describir el estado deseado, ejecutado el playbook y demostrado la idempotencia con una segunda ejecución que no informó cambios.


