Problem: Standard-Module arbeiten nur auf Zielsystemen. Sie können keine Daten direkt auf dem Control-Node verarbeiten, z. B. Passwörter laden oder IP-Adressen berechnen.
Lösung: Plugins erweitern Ansible um Funktionen, die auf dem Control-Node laufen und Daten flexibel bereitstellen oder transformieren.
| Aspekt | Module | Plugins |
|---|---|---|
| Ausführungsort | Zielsystem (Remote Host) | Control-Node (Ansible-Engine) |
| Zweck | Aktionen ausführen | Daten verarbeiten/bereitstellen |
| Beispiele | package, copy, service |
lookup('file'), selectattr(),
yaml callback |
| Timing | während Task-Ausführung | vor/während/nach Tasks |
Merksatz: Module sind die „Hände“, Plugins das „Gehirn“ von Ansible.
ansible localhost -m debug -a "msg={{ lookup('env', 'HOME') }}"ansible localhost -m debug -a "msg={{ ['web01','db01','web02'] | select('match','web.*') | list }}"ansible localhost -m debug -a "msg=Hello"
ansible localhost -m debug -a "msg=Hello" -e ansible_stdout_callback=yamltest-plugins.yml
- name: Plugin-Grundlagen verstehen
hosts: localhost
gather_facts: false
vars:
servers:
- {name: "web01", role: "web", active: true}
- {name: "web02", role: "web", active: false}
- {name: "db01", role: "database", active: true}
tasks:
- name: Aktueller Benutzer
debug:
msg: "Playbook läuft als: {{ lookup('env', 'USER') }}"
- name: Nur aktive Web-Server
debug:
msg: "Aktive: {{ servers | selectattr('role','equalto','web') | selectattr('active') | map(attribute='name') | list }}"
- name: Home-Verzeichnis analysieren
debug:
msg: "Home hat {{ lookup('env','HOME') | length }} Zeichen"ansible-playbook test-plugins.yml
ansible-playbook test-plugins.yml -e ansible_stdout_callback=yamlReihenfolge der Suche: 1. Built-in (file,
env, default) 2. Collections (z. B.
community.general.dig) 3. Projekt-lokal
(./plugins/lookup/) 4. Global
(~/.ansible/plugins/)
ansible-doc -t lookup -l | head -10Aufgabe: 1. Hostname über Lookup laden 2. Liste von Zahlen filtern (gerade Zahlen) 3. Ausgabe im Standard- und JSON-Format
uebung.yml
- name: Plugin-Übung
hosts: localhost
vars:
numbers: [1,2,3,4,5,6,7,8,9,10]
tasks:
- name: Hostname laden
debug:
msg: "Host: {{ lookup('env','HOSTNAME') | default('unbekannt') }}"
- name: Gerade Zahlen
debug:
msg: "Gerade Zahlen: {{ numbers | select('even') | list }}"ansible-playbook uebung.yml
ansible-playbook uebung.yml -e ansible_stdout_callback=json
# Plugins nutzen
## Leitfrage: Wie nutze ich Plugins in realen Projekten?
Dieser Teil zeigt die praktische Anwendung in drei Stufen: **Einfach** → **Mittel** → **Fortgeschritten**
---
## Beispiel: Einfache Grundoperationen
### Ziel: Externe Dateien und Umgebungsvariablen nutzen
**Szenario**: SSH-Keys deployen und umgebungsabhängig konfigurieren
**Code** (speichern als `stufe1-basics.yml`):
```yaml
---
- name: Stufe 1 - Basis-Lookups
hosts: localhost
gather_facts: false
tasks:
- name: SSH-Key aus Datei laden (falls vorhanden)
debug:
msg: "SSH-Key Länge: {{ ssh_key | length }} Zeichen"
vars:
ssh_key: "{{ lookup('file', ansible_env.HOME + '/.ssh/id_rsa.pub') | default('') }}"
when: ssh_key | length > 0
- name: Umgebung bestimmen
debug:
msg: "Deploying in {{ environment }} Umgebung"
vars:
environment: "{{ lookup('env', 'ANSIBLE_ENV') | default('development') }}"
- name: Passwort generieren oder laden
debug:
msg: "Passwort wurde {{ 'generiert' if password_file.stat.exists else 'neu erstellt' }}"
vars:
password: "{{ lookup('password', '/tmp/demo_password chars=ascii_letters,digits length=12') }}"
password_file: "{{ ansible_env }}"Ausführung:
# Test in verschiedenen Umgebungen
ansible-playbook stufe1-basics.yml
ANSIBLE_ENV=production ansible-playbook stufe1-basics.ymlLernergebnis: Lookup-Plugins für Dateien, Umgebungsvariablen und Passwort-Generierung
Szenario: Aus einer Server-Liste die richtigen Ziele für Deployment ermitteln
Code (speichern als
stufe2-filter.yml):
---
- name: Stufe 2 - Datenverarbeitung
hosts: localhost
gather_facts: false
vars:
servers:
- {name: "web01", env: "prod", role: "frontend", cpu: 4, active: true}
- {name: "web02", env: "prod", role: "frontend", cpu: 2, active: false}
- {name: "api01", env: "prod", role: "backend", cpu: 8, active: true}
- {name: "web03", env: "staging", role: "frontend", cpu: 2, active: true}
- {name: "db01", env: "prod", role: "database", cpu: 16, active: true}
tasks:
- name: Produktions-Server ermitteln
debug:
msg: "Prod-Server: {{ prod_servers | join(', ') }}"
vars:
prod_servers: "{{ servers | selectattr('env', 'equalto', 'prod') | selectattr('active') | map(attribute='name') | list }}"
- name: High-Performance Server finden
debug:
msg: "Leistungsstarke Server: {{ high_perf | join(', ') }}"
vars:
high_perf: "{{ servers | selectattr('cpu', 'gt', 4) | map(attribute='name') | list }}"
- name: Server nach Rollen gruppieren
debug:
msg: "{{ role }}: {{ count }} Server"
vars:
roles_count: "{{ servers | selectattr('active') | groupby('role') | items2dict(key_name='role', value_name='servers') }}"
loop: "{{ roles_count.keys() | list }}"
loop_control:
loop_var: role
vars:
count: "{{ roles_count[role] | length }}"
- name: Deployment-Ziele bestimmen
set_fact:
deploy_targets: |
{{ servers |
selectattr('env', 'equalto', target_env | default('prod')) |
selectattr('role', 'in', ['frontend', 'backend']) |
selectattr('active') |
map(attribute='name') | list }}
- name: Deployment-Plan anzeigen
debug:
msg: "Deploying to: {{ deploy_targets | join(', ') }}"Test mit verschiedenen Umgebungen:
ansible-playbook stufe2-filter.yml
ansible-playbook stufe2-filter.yml -e target_env=stagingLernergebnis: Filter-Kombinationen für komplexe Datenanalysen
Szenario: Service-Discovery über API mit strukturierter Ausgabe
Code (speichern als
stufe3-advanced.yml):
---
- name: Stufe 3 - API-Integration
hosts: localhost
gather_facts: false
tasks:
- name: Service-Discovery via DNS
debug:
msg: "Mail-Server: {{ mail_servers | join(', ') }}"
vars:
mail_servers: "{{ lookup('dig', 'google.com', 'qtype=MX', wantlist=True) | default(['keine gefunden']) }}"
- name: Externes API simulieren (httpbin.org)
set_fact:
api_response: "{{ lookup('url', 'https://httpbin.org/json') | from_json }}"
- name: API-Daten verarbeiten
debug:
msg: "Slideshow hat {{ slide_count }} Folien"
vars:
slide_count: "{{ api_response | json_query('slideshow.slides | length') }}"
- name: Konfiguration aus mehreren Quellen
set_fact:
final_config:
environment: "{{ lookup('env', 'NODE_ENV') | default('development') }}"
debug_mode: "{{ lookup('env', 'DEBUG') | default('false') | bool }}"
api_endpoint: "{{ api_response.slideshow.author | default('localhost') }}"
timestamp: "{{ lookup('pipe', 'date +%Y%m%d-%H%M%S') }}"
- name: Finale Konfiguration
debug:
var: final_configCallback-Test (verschiedene Ausgabeformate):
# Standard-Format
ansible-playbook stufe3-advanced.yml
# Strukturiertes YAML
ansible-playbook stufe3-advanced.yml -e ansible_stdout_callback=yaml
# Kompaktes JSON (für Scripts)
ansible-playbook stufe3-advanced.yml -e ansible_stdout_callback=json
# Minimal (nur Ergebnisse)
ansible-playbook stufe3-advanced.yml -e ansible_stdout_callback=minimalLernergebnis: Integration externer APIs, JSON-Query-Filter, Callback-Plugins für verschiedene Ausgabeformate
Code (speichern als
komplett-workflow.yml):
---
- name: Vollständiger Plugin-Workflow
hosts: localhost
gather_facts: false
vars:
app_name: "{{ lookup('env', 'APP_NAME') | default('demo-app') }}"
tasks:
- name: 1. Deployment-Umgebung laden
set_fact:
deploy_config:
environment: "{{ lookup('env', 'DEPLOY_ENV') | default('staging') }}"
version: "{{ lookup('pipe', 'git rev-parse --short HEAD') | default('unknown') }}"
timestamp: "{{ lookup('pipe', 'date +%Y%m%d-%H%M%S') }}"
- name: 2. Server-Liste aus Datei (simuliert)
set_fact:
available_servers:
- {name: "web01", env: "{{ deploy_config.environment }}", health: "ok"}
- {name: "web02", env: "{{ deploy_config.environment }}", health: "warning"}
- {name: "api01", env: "{{ deploy_config.environment }}", health: "ok"}
- name: 3. Deployment-Ziele filtern
set_fact:
healthy_servers: "{{ available_servers | selectattr('health', 'equalto', 'ok') | map(attribute='name') | list }}"
- name: 4. Deployment-Summary
debug:
msg: |
Deployment Summary:
App: {{ app_name }}
Environment: {{ deploy_config.environment }}
Version: {{ deploy_config.version }}
Targets: {{ healthy_servers | join(', ') }}
Time: {{ deploy_config.timestamp }}Ausführung mit verschiedenen Konfigurationen:
# Staging-Deployment
APP_NAME=myapp DEPLOY_ENV=staging ansible-playbook komplett-workflow.yml -e ansible_stdout_callback=yaml
# Production-Deployment
APP_NAME=myapp DEPLOY_ENV=production ansible-playbook komplett-workflow.yml -e ansible_stdout_callback=jsonAufgabe: Erstellen Sie ein Playbook, das: 1. Ihren
Benutzernamen und das aktuelle Datum lädt 2. Eine Liste von Services
filtert (nur die mit Status “running”) 3. Ein Deployment-Log in
/tmp/deployment.log schreibt
Vorlage:
---
- name: Plugin-Übung fortgeschritten
hosts: localhost
vars:
services:
- {name: "nginx", status: "running", port: 80}
- {name: "apache", status: "stopped", port: 8080}
- {name: "redis", status: "running", port: 6379}
tasks:
- name: Aktuelle Info sammeln
set_fact:
deploy_info:
user: "{{ lookup('env', 'USER') }}"
date: "{{ lookup('pipe', 'date') }}"
running_services: "{{ services | selectattr('status', 'equalto', 'running') | map(attribute='name') | list }}"
- name: Log-Eintrag schreiben
copy:
content: "{{ deploy_info | to_nice_json }}"
dest: /tmp/deployment.log
- name: Ergebnis anzeigen
debug:
var: deploy_info