Wenn du Aufgaben in deiner IT-Infrastruktur automatisierst, kommst du häufig in Situationen, in denen bestimmte Aktionen nur dann ausgeführt werden sollen, wenn sich etwas ändert. Zum Beispiel möchtest du einen Webserver neu starten, wenn eine Konfigurationsdatei aktualisiert wurde, aber nicht bei jeder Ausführung eines Playbooks. Hier kommen Ansible-Handler ins Spiel.
In diesem Blogbeitrag zeige ich dir, wie du Handler in Ansible richtig einrichtest und nutzt, um gezielt Aktionen wie Neustarts oder Benachrichtigungen auszuführen, sobald sich relevante Konfigurationen oder Zustände ändern.
Was sind Handler in Ansible?
Ein Handler ist eine spezielle Art von Aufgabe, die nur dann ausgeführt wird, wenn sie von einer anderen Aufgabe „benachrichtigt“ wird. Diese Benachrichtigung erfolgt, wenn eine Aufgabe erfolgreich einen bestimmten Zustand geändert hat (zum Beispiel das Bearbeiten einer Konfigurationsdatei oder das Installieren eines Pakets).
Handler werden in Playbooks häufig verwendet, um Dienste neu zu starten, zu reloaded oder neu zu konfigurieren, nachdem eine wichtige Änderung vorgenommen wurde.
Wichtige Eigenschaften von Handlers:
- Handler werden nur ausgeführt, wenn sie von einer anderen Aufgabe benachrichtigt werden.
- Sie werden am Ende des Playbooks ausgeführt, also nach allen Aufgaben, die zu Änderungen geführt haben.
- Ein Handler wird pro Ausführung nur einmal aktiviert, auch wenn er mehrmals benachrichtigt wird.
Einrichten eines Handlers
1. Grundlagen eines Handlers
Ein Handler wird wie eine normale Aufgabe definiert, jedoch im Abschnitt handlers
. Er wird durch die Anweisung notify
in anderen Aufgaben aufgerufen.
Beispiel: Apache-Konfigurationsdatei ändern und den Webserver neu starten
---
- hosts: webserver
become: yes
tasks:
- name: Installiere Apache
apt:
name: apache2
state: present
- name: Ändere die Apache-Konfiguration
lineinfile:
path: /etc/apache2/ports.conf
regexp: '^Listen'
line: "Listen 8080"
notify: Starte Apache neu
handlers:
- name: Starte Apache neu
service:
name: apache2
state: restarted
Was passiert hier?
- Im Abschnitt
tasks
wird zunächst Apache installiert und dann die Dateiports.conf
bearbeitet, um Apache auf Port 8080 zu lauschen. - Wenn sich die Datei ändert, wird der Handler
Starte Apache neu
über die Anweisungnotify
benachrichtigt. - Der Handler startet den Apache-Dienst neu, allerdings nur, wenn die Konfigurationsdatei tatsächlich geändert wurde.
2. Mehrere Handler in einem Playbook
Es ist auch möglich, mehrere Handler in einem Playbook zu definieren und sie je nach Bedarf von verschiedenen Aufgaben benachrichtigen zu lassen.
Beispiel: Mehrere Handler für verschiedene Dienste
---
- hosts: webserver
become: yes
tasks:
- name: Installiere Apache
apt:
name: apache2
state: present
notify: Starte Apache neu
- name: Installiere MySQL
apt:
name: mysql-server
state: present
notify: Starte MySQL neu
handlers:
- name: Starte Apache neu
service:
name: apache2
state: restarted
- name: Starte MySQL neu
service:
name: mysql
state: restarted
In diesem Fall gibt es zwei getrennte Dienste: Apache und MySQL. Je nachdem, welche Aufgabe Änderungen durchführt, wird der entsprechende Handler benachrichtigt und nur dieser Dienst neu gestartet.
Verfeinerung der Nutzung von Handlers
1. Nur bei Änderungen ausführen
Der Hauptzweck von Handlers besteht darin, sie nur bei Änderungen auszuführen. Aufgaben, die erfolgreich ausgeführt wurden, aber keinen Zustand ändern (z. B. weil eine Datei bereits die gewünschten Inhalte hat), lösen keine Benachrichtigung an den Handler aus.
Das Modul lineinfile
im vorherigen Beispiel sendet nur dann eine Benachrichtigung an den Handler, wenn es tatsächlich eine Änderung an der Datei vorgenommen hat. Wenn die Datei bereits korrekt konfiguriert ist, wird der Handler nicht ausgeführt.
2. Mehrere Benachrichtigungen pro Handler
Falls mehrere Aufgaben denselben Handler benachrichtigen, wird der Handler nur einmal ausgeführt, selbst wenn mehrere Aufgaben ihn aufrufen.
Beispiel: Mehrere Änderungen, ein Handler
---
- hosts: webserver
become: yes
tasks:
- name: Ändere Apache Port-Konfiguration
lineinfile:
path: /etc/apache2/ports.conf
regexp: '^Listen'
line: "Listen 8080"
notify: Starte Apache neu
- name: Ändere Apache ServerName-Konfiguration
lineinfile:
path: /etc/apache2/apache2.conf
regexp: '^ServerName'
line: "ServerName www.example.com"
notify: Starte Apache neu
handlers:
- name: Starte Apache neu
service:
name: apache2
state: restarted
In diesem Beispiel gibt es zwei Aufgaben, die beide den Apache-Webserver konfigurieren und den Handler Starte Apache neu
benachrichtigen. Selbst wenn beide Aufgaben Änderungen vornehmen, wird der Handler nur einmal nach Abschluss der Aufgaben ausgeführt.
3. Bedingte Handler
Es ist möglich, Handler nur unter bestimmten Bedingungen auszuführen. Du kannst die when
-Bedingung verwenden, um festzulegen, wann ein Handler ausgeführt werden soll.
Beispiel: Apache nur neu starten, wenn es sich um eine Ubuntu-Distribution handelt
handlers:
- name: Starte Apache neu
service:
name: apache2
state: restarted
when: ansible_facts['os_family'] == "Debian"
In diesem Beispiel wird der Handler nur dann ausgeführt, wenn das Betriebssystem auf dem Zielhost zur Debian-Familie gehört, was zum Beispiel bei Ubuntu der Fall ist.
Best Practices für den Einsatz von Handlers
- Nur bei echten Änderungen benachrichtigen: Verwende Handler nur, wenn sich der Zustand tatsächlich ändert. Dies spart Zeit und vermeidet unnötige Neustarts von Diensten.
- Zentrale Handlers für Dienste verwenden: Definiere einen zentralen Handler pro Dienst (z. B. Apache oder MySQL) und benachrichtige diesen bei Bedarf von verschiedenen Aufgaben aus. So bleibt dein Playbook sauber und übersichtlich.
- Handlers nur bei wichtigen Änderungen verwenden: Du solltest nur dann einen Dienst neu starten oder reloaden, wenn es wirklich notwendig ist. Unnötige Neustarts können die Verfügbarkeit deines Systems beeinträchtigen.
- Handlers kombinieren: Du kannst auch Handlers miteinander kombinieren, wenn eine Änderung an mehreren Diensten erforderlich ist. Zum Beispiel kann ein Handler den Neustart mehrerer Dienste übernehmen.
Erweiterte Nutzung von Handlers
1. Notifizierung mehrerer Handlers
In einigen Fällen kann eine Aufgabe mehrere Handler benachrichtigen. Dies ist nützlich, wenn mehrere Aktionen nach einer Änderung ausgeführt werden müssen.
Beispiel: Benachrichtigung mehrerer Handlers
---
- hosts: webserver
become: yes
tasks:
- name: Aktualisiere Apache Konfiguration
lineinfile:
path: /etc/apache2/apache2.conf
regexp: '^ServerName'
line: "ServerName www.example.com"
notify:
- Starte Apache neu
- Starte Firewall neu
handlers:
- name: Starte Apache neu
service:
name: apache2
state: restarted
- name: Starte Firewall neu
service:
name: ufw
state: restarted
Hier wird nach der Änderung der Apache-Konfiguration sowohl der Apache-Dienst als auch die Firewall (ufw) neu gestartet.
2. Verwendung von Handlern in Rollen
Handlers lassen sich auch innerhalb von Ansible-Rollen verwenden, was ihre Wiederverwendbarkeit erhöht. Wenn du Ansible-Rollen verwendest, kannst du Handlers in der handlers/main.yml
Datei definieren.
Fazit
Ansible-Handler sind ein effektives Mittel, um gezielt Aktionen auszuführen, wenn sich etwas ändert, und unnötige Aufgaben zu vermeiden. Sie bieten eine flexible Möglichkeit, deine Playbooks effizienter zu gestalten, insbesondere wenn es darum geht, Dienste wie Webserver oder Datenbanken nach Konfigurationsänderungen neu zu starten oder neu zu laden.
Durch den intelligenten Einsatz von Handlers sparst du Zeit, vermeidest unnötige Neustarts und kannst sicherstellen, dass nur bei echten Änderungen Handlungen vorgenommen werden. So kannst du deine Infrastruktur effizient und zuverlässig verwalten.
Hast du bereits Erfahrungen mit Handlers in Ansible gemacht? Teile deine Erkenntnisse und Best Practices in den Kommentaren!