Rollen sind eine leistungsstarke Methode, um Ansible-Playbooks modular und wiederverwendbar zu gestalten. Sie ermöglichen es, Playbook-Logik in kleinere, überschaubare Einheiten zu zerlegen, die unabhängig voneinander entwickelt, getestet und wiederverwendet werden können. Rollen bündeln Aufgaben, Variablen, Handler, Dateien und Templates in einer strukturierten, wiederverwendbaren Form und fördern die Wiederverwendbarkeit von Code, was besonders in großen oder komplexen IT-Umgebungen von Vorteil ist.
Eine Rolle in Ansible folgt einer vordefinierten Verzeichnisstruktur, die bestimmte Standardverzeichnisse und Dateien enthält:
my_role/
├── tasks/ # Hauptaufgaben (Tasks) der Rolle
│ └── main.yml
├── handlers/ # Handler, die von der Rolle aufgerufen werden
│ └── main.yml
├── templates/ # Jinja2-Templates für dynamische Konfigurationsdateien
├── files/ # Statische Dateien, die die Rolle verwendet
├── vars/ # Variablen mit höherer Priorität
│ └── main.yml
├── defaults/ # Standardvariablen für die Rolle (niedrigste Priorität)
│ └── main.yml
├── meta/ # Metadaten über die Rolle (z.B. Abhängigkeiten)
│ └── main.yml
└── tests/ # Tests für die Rolle
├── inventory
└── test.yml
tasks/: Enthält die Hauptaufgaben
(Tasks), die die Rolle ausführt. Die Datei main.yml wird
standardmäßig ausgeführtdefaults/: Enthält die
Standardvariablen der Rolle, die die niedrigste Priorität haben und
leicht überschreibbar sindvars/: Enthält Variablen, die in der
Rolle verwendet werden und eine höhere Priorität als die in
defaults/ definierten habenhandlers/: Enthält Handler, die von
den Tasks in der Rolle aufgerufen werden können (z.B., zum Neustarten
eines Dienstes nach einer Konfigurationsänderung)templates/: Enthält Jinja2-Templates,
die von der Rolle verwendet werden können, um Konfigurationsdateien
dynamisch zu erstellenfiles/: Enthält statische Dateien, die
von der Rolle auf das Zielsystem kopiert werden sollenmeta/: Enthält Metadaten über die
Rolle, wie z.B. Abhängigkeiten von anderen Rollentests/: Enthält einfache Tests und ein
Testinventar, um die Rolle zu prüfen| Merkmal | Playbook | Rolle |
|---|---|---|
| Fokus | Gesamtablauf und Orchestrierung | Wiederverwendbare Teilschritte |
| Struktur | Frei definierbar | Standardisierte Ordnerstruktur |
| Wiederverwendung | Selten | Explizit vorgesehen |
| Kontext | Umgebungsspezifisch | Umgebungsunabhängig |
| Zweck | Orchestrierung mehrerer Rollen | Modularisierung spezifischer Funktionalitäten |
| Wartbarkeit | Schwieriger bei Komplexität | Einfacher durch Modularisierung |
Playbooks orchestrieren den Gesamtablauf und definieren, welche Aufgaben auf welchen Hosts ausgeführt werden. Rollen kapseln spezifische Funktionalitäten als wiederverwendbare Module.
ansible-galaxy init my_roleDieser Befehl erstellt eine neue Rolle mit der kompletten Standardverzeichnisstruktur.
Schritt 1: Aufgaben definieren
(tasks/main.yml)
---
- name: Installiere Apache
apt:
name: apache2
state: present
notify: Starte Apache neu
- name: Kopiere Apache-Konfiguration
template:
src: apache.conf.j2
dest: /etc/apache2/apache2.conf
notify: Starte Apache neu
- name: Starte und aktiviere Apache
service:
name: apache2
state: started
enabled: yesSchritt 2: Standardvariablen definieren
(defaults/main.yml)
---
http_port: 80
https_port: 443
max_clients: 100
server_name: localhost
apache_modules:
- rewrite
- sslSchritt 3: Handler definieren
(handlers/main.yml)
---
- name: Starte Apache neu
service:
name: apache2
state: restarted
- name: Lade Apache-Konfiguration neu
service:
name: apache2
state: reloadedSchritt 4: Template erstellen
(templates/apache.conf.j2)
ServerRoot /etc/apache2
Listen {{ http_port }}
{% if https_port is defined %}
Listen {{ https_port }} ssl
{% endif %}
ServerName {{ server_name }}
MaxRequestWorkers {{ max_clients }}
{% for module in apache_modules %}
LoadModule {{ module }}_module modules/mod_{{ module }}.so
{% endfor %}
---
- name: Webserver einrichten
hosts: webservers
roles:
- common # Grundkonfiguration
- apache # Webserver
- php # PHP-UmgebungRollen können durch Variablen an unterschiedliche Umgebungen angepasst werden:
---
- name: Webserver mit spezifischer Konfiguration
hosts: webservers
roles:
- role: apache
vars:
http_port: 8080
max_clients: 200
server_name: "{{ inventory_hostname }}"
- role: php
php_version: "8.1"
when: install_php | default(true)In größeren Projekten empfiehlt sich eine strukturierte Herangehensweise:
ansible-project/
├── site.yml # Haupt-Playbook
├── group_vars/
│ ├── webservers.yml
│ └── dbservers.yml
├── host_vars/
├── inventories/
│ ├── production/
│ └── staging/
└── roles/
├── common/
├── nginx/
├── apache/
├── php/
├── mysql/
└── monitoring/
Beispiel für site.yml:
---
- name: Konfiguriere alle Webserver
hosts: webservers
vars:
environment_type: production
roles:
- common
- apache
- php
- role: monitoring
when: environment_type == "production"
- name: Konfiguriere Datenbankserver
hosts: dbservers
roles:
- common
- mysql
- monitoringRollen können Abhängigkeiten von anderen Rollen definieren, die automatisch vor der aktuellen Rolle ausgeführt werden:
# meta/main.yml
---
dependencies:
- role: common
- role: firewall
firewall_allowed_ports:
- 80
- 443
- role: monitoring
when: enable_monitoring | default(false)Ansible bietet zwei Mechanismen, um Rollen in Playbooks einzubinden:
| Kriterium | import_role |
include_role |
|---|---|---|
| Zeitpunkt der Verarbeitung | Zur Parsing-Zeit (statisch) | Zur Laufzeit (dynamisch) |
| Bedingte Ausführung | Eingeschränkt | Vollständig unterstützt |
| Performance | Schneller | Etwas langsamer |
| Tags | Übernimmt Tags vom Playbook | Unterstützt eigene Tags |
| Loops | Nicht unterstützt | Vollständig unterstützt |
| Anwendungsfall | Statische Rolleneinbindung | Bedingte/dynamische Einbindung |
Beispiel import_role:
- name: Statische Rolleneinbindung
import_role:
name: apache
vars:
http_port: 8080Beispiel include_role:
- name: Dynamische Rolleneinbindung
include_role:
name: apache
vars:
http_port: 8080
when: install_webserver | default(true)
- name: OS-spezifische Rollen
include_role:
name: "{{ ansible_os_family | lower }}_webserver"rolename_variable)defaults/main.yml# Gutes Beispiel: Modulare Rollenverwendung
- name: Komplettes Webserver-Setup
hosts: webservers
vars:
environment_type: production
roles:
# Basis-Konfiguration für alle Server
- role: common
# Webserver-spezifische Konfiguration
- role: nginx
nginx_worker_processes: "{{ ansible_processor_vcpus }}"
nginx_worker_connections: 1024
# Application Server
- role: php
php_version: "8.1"
when: install_php | default(true)
# Monitoring nur in Production
- role: monitoring
when: environment_type == "production"# Molecule für eine Rolle initialisieren
molecule init role my_role
# Tests ausführen
molecule test
# Testumgebung erstellen und testen
molecule create
molecule converge
molecule verify
molecule destroy# .ansible-lint Konfiguration
exclude_paths:
- .cache/
- .github/
rules:
- yaml[line-length]
- name[casing]
- risky-file-permissions# GitHub Actions Beispiel
name: Test Ansible Role
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: 3.9
- name: Install dependencies
run: |
pip install ansible molecule[docker]
- name: Run Molecule tests
run: molecule test