Volver a la página principal
lunes 7 octubre 2024
7

Cómo usar Handlers en Ansible

Los handlers en Ansible son tareas que se ejecutan cuando son notificadas por otras tareas. Se utilizan principalmente para llevar a cabo acciones que deben realizarse solo cuando ocurre un cambio en el sistema, como reiniciar servicios, recargar configuraciones o reiniciar aplicaciones. Los handlers ayudan a mantener la idempotencia y eficiencia de los playbooks, ya que solo se ejecutan cuando es necesario.

¿Qué es un Handler en Ansible?

Un handler es una tarea especial que se activa mediante la directiva notify de otra tarea. Los handlers suelen utilizarse para gestionar servicios y recursos dependientes, como reiniciar nginx después de modificar su archivo de configuración. Si una tarea notifica a un handler y no hubo cambios en esa tarea, el handler no se ejecutará.

¿Cómo funciona un Handler?

El flujo de trabajo de un handler es el siguiente:

1. Una tarea dentro del playbook realiza un cambio (por ejemplo, copia un archivo de configuración).

2. La tarea activa un handler utilizando la directiva notify.

3. Si el cambio ocurre, Ansible ejecuta el handler al final de la ejecución del playbook para garantizar que todas las tareas se completen primero.

Sintaxis y Definición de Handlers

Los handlers se definen de manera similar a las tareas (tasks), pero dentro de una sección handlers. Un ejemplo básico de un playbook con un handler:

- name: Configurar un servidor web
  hosts: webservers
  become: yes
  tasks:
    - name: Copiar archivo de configuración de Nginx
      copy:
        src: ./files/nginx.conf
        dest: /etc/nginx/nginx.conf
      notify:  # Se activa el handler si esta tarea cambia algo
        - Reiniciar Nginx

  handlers:
    - name: Reiniciar Nginx
      service:
        name: nginx
        state: restarted

Explicación:

1. Tarea copy: Copia un archivo de configuración de Nginx en el servidor de destino.

2. Directiva notify: Notifica al handler llamado Reiniciar Nginx si el archivo se copia (es decir, si hay un cambio).

3. Handler Reiniciar Nginx: Reinicia el servicio de Nginx solo si el archivo nginx.conf ha sido modificado.

Cómo Definir y Usar Handlers en Ansible

1. Definir un Handler

Los handlers se definen en la sección handlers: dentro de un playbook o en un archivo separado (handlers/main.yml) dentro de un rol. La sintaxis es similar a las tareas estándar:

handlers:
  - name: Reiniciar Apache
    service:
      name: apache2
      state: restarted

2. Notificar un Handler

Para activar un handler, se utiliza la directiva notify dentro de la tarea correspondiente:

- name: Actualizar archivo de configuración de Apache
  template:
    src: apache.conf.j2
    dest: /etc/apache2/apache2.conf
  notify: Reiniciar Apache

En este caso, si el archivo apache2.conf se actualiza, el handler Reiniciar Apache será notificado y se ejecutará al final de la ejecución del playbook.

3. Múltiples Handlers

Puedes notificar a más de un handler desde la misma tarea:

- name: Actualizar configuración de la aplicación
  copy:
    src: app.conf
    dest: /etc/app/app.conf
  notify:
    - Reiniciar Servicio de Aplicación
    - Recargar Firewall

Aquí, la tarea copy notifica a dos handlers: Reiniciar Servicio de Aplicación y Recargar Firewall.

4. Mismo Handler para múltiples tareas

Varios cambios en diferentes tareas pueden notificar al mismo handler. Si un handler es notificado varias veces, se ejecutará solo una vez:

- name: Modificar configuración de Nginx
  copy:
    src: nginx.conf
    dest: /etc/nginx/nginx.conf
  notify: Reiniciar Nginx

- name: Agregar nueva regla al firewall
  command: ufw allow 80/tcp
  notify: Reiniciar Nginx

El handler Reiniciar Nginx solo se ejecutará una vez, al final del playbook, independientemente de cuántas tareas lo hayan notificado.

Ejemplos de Uso de Handlers en Ansible

1. Recargar un servicio tras copiar un archivo

- name: Configurar un servidor MySQL
  hosts: dbservers
  become: yes
  tasks:
    - name: Copiar archivo de configuración de MySQL
      copy:
        src: ./files/my.cnf
        dest: /etc/mysql/my.cnf
      notify: Recargar MySQL

  handlers:
    - name: Recargar MySQL
      service:
        name: mysql
        state: reloaded

En este ejemplo, si my.cnf se actualiza, el servicio de MySQL se recarga para aplicar la nueva configuración.

2. Reiniciar un servicio al actualizar un paquete

- name: Actualizar y configurar el servicio SSH
  hosts: all
  become: yes
  tasks:
    - name: Instalar o actualizar OpenSSH
      apt:
        name: openssh-server
        state: latest
      notify: Reiniciar SSH

  handlers:
    - name: Reiniciar SSH
      service:
        name: ssh
        state: restarted

Si el paquete openssh-server se actualiza, se reinicia el servicio SSH para aplicar la nueva versión.

3. Uso de Handlers dentro de Roles

Los handlers dentro de un rol se definen en el archivo handlers/main.yml. Un ejemplo básico de un rol llamado apache:

Estructura del rol:

apache/
├── tasks/
│   └── main.yml
├── handlers/
│   └── main.yml
└── templates/
    └── apache.conf.j2

Archivo tasks/main.yml:

- name: Instalar Apache
  apt:
    name: apache2
    state: present

- name: Copiar archivo de configuración
  template:
    src: apache.conf.j2
    dest: /etc/apache2/apache2.conf
  notify: Reiniciar Apache

Archivo handlers/main.yml:

- name: Reiniciar Apache
  service:
    name: apache2
    state: restarted

En este caso, el rol apache reinicia el servicio de Apache solo si se modifica el archivo de configuración.

Buenas Prácticas para Usar Handlers

1. Usa nombres descriptivos para los handlers, como Reiniciar Apache o Recargar Firewall, en lugar de nombres genéricos.

2. Evita el uso innecesario de handlers para tareas que no requieren un reinicio o recarga.

3. Agrupa tareas similares en un solo handler para evitar reinicios múltiples de servicios.

4. Verifica la idempotencia de las tareas que notifican a handlers. Asegúrate de que las tareas no generen cambios innecesarios.

5. Usa listen en lugar de name en Ansible 2.7 y posteriores. listen permite asociar varios handlers a un solo nombre, mejorando la organización:

handlers:
  - listen: "restart_services"
    name: Reiniciar Apache
    service:
      name: apache2
      state: restarted

Referencia oficial

Para más detalles, consulta la documentación oficial de Ansible sobre Handlers en Ansible Handlers.

Etiquetas:
ansible
Compartir:
Creado por:
Author photo

Jorge García

Fullstack developer