DevOps & Automatisierung

Ansible Einstieg für Admins: von der Handarbeit zum reproduzierbaren Playbook

Der Einstieg ist unspektakulär: Inventar, ein Playbook, ein paar Rollen, fertig. Der eigentliche Gewinn kommt nicht durch Zeitersparnis beim ersten Lauf, sondern dadurch, dass der zweite, dritte und hundertste Lauf identisch abläuft.

6 Kapitel mit allen Befehlen
Team bespricht eine Deployment-Pipeline an einem großen Monitor
KI-generiertDieses Bild wurde mit KI erzeugt · Yves Hoppe / KI / cmt
Seit 1997 am Markt Präsenz & Live-Online 4,9 aus 503 Google-Bewertungen Auch Inhouse für dein Team
Worum es geht

Warum der Einstieg oft an der falschen Stelle hakt

Der typische Ausgangspunkt sieht so aus: Es gibt eine Handvoll gewachsener Shell-Skripte, ein paar Notizen im Wiki und viel Wissen in den Köpfen. Solange es zehn Server sind, funktioniert das. Sobald Staging und Produktion auseinanderlaufen, ein Paket auf drei von zwanzig Maschinen fehlt oder ein neuer Kollege eine Installation nachvollziehen soll, wird aus fehlender Dokumentation ein Betriebsrisiko. Genau an dieser Stelle wird Configuration Management interessant, und Ansible ist der Einstieg mit der geringsten Hürde, weil es agentenlos über SSH arbeitet und auf den Zielsystemen im Wesentlichen nur einen Python-Interpreter voraussetzt.

Die zweite Hürde ist mental. Viele Admins verschieben den Einstieg, weil sie annehmen, sie müssten erst Python lernen. Das ist ein Missverständnis: Module wie package, service, copy, template, user oder lineinfile sind fertig, du beschreibst in YAML nur den gewünschten Zielzustand. Python brauchst du erst, wenn du eigene Module schreibst, und das ist im Betriebsalltag die Ausnahme. Wer als Admin systemd, Paketverwaltung und Dateirechte versteht, bringt das eigentliche Fachwissen bereits mit.

Typische Anfängerfehler sind dafür recht gut vorhersehbar. Playbooks werden als Skript gedacht und mit command oder shell vollgestopft, statt idempotente Module zu nutzen. Alles landet in einer einzigen langen Datei ohne Rollen. Variablen werden über group_vars, host_vars und Playbook-Definitionen verstreut, bis niemand mehr die Präzedenz nachvollzieht. Und Zugangsdaten liegen im Klartext im Repository, obwohl Ansible Vault genau dafür da ist. Diese Muster lassen sich vermeiden, wenn man sie von Anfang an kennt.

Miniatur-Szene: Endlosschleife als Bahn mit Stationen für Build, Test und Deployment, am Ende eine startende Rakete
KI-generiertDieses Bild wurde mit KI erzeugt · Yves Hoppe / KI / cmt

Vom Handbetrieb zum automatisierten Zielzustand

  1. 01 Control Node und SSH-Key-Auth
  2. 02 Inventory und Gruppen
  3. 03 Ad-hoc-Module testen
  4. 04 Playbook in YAML
  5. 05 Rollen, Variablen, Vault
  6. 06 Check-Mode, Lint, Pipeline
Was du mitnimmst

So sieht ein sauberer Einstieg konkret aus

Du brauchst keinen großen Rollout-Plan, sondern einen kleinen, ehrlichen Anwendungsfall und die richtige Reihenfolge. Die folgenden Schritte bilden den Weg ab, den wir auch in unseren Ansible-Kursen gehen.

Control Node und Inventory aufsetzen

Ansible wird nur auf einer Maschine installiert, von der aus du dich per SSH mit Key-Authentifizierung auf die Ziele verbindest. Das Inventory beschreibt, welche Hosts es gibt und wie sie gruppiert sind, als INI- oder YAML-Datei zum Start und später dynamisch aus CMDB, Cloud-API oder Virtualisierung. Mit ansible all -m ping prüfst du, ob Verbindung und Python-Interpreter auf den Zielen stimmen.

Ad-hoc-Befehle vor dem ersten Playbook

Bevor du YAML schreibst, lohnt sich die Kommandozeile. Aufrufe wie ansible webserver -m package -a "name=nginx state=present" -b zeigen unmittelbar, wie Module, Argumente und Privilege Escalation zusammenspielen. Wer diese Denkweise verstanden hat, liest Playbooks danach deutlich flüssiger.

Idempotenz als Grundprinzip verstehen

Ein Task beschreibt keinen Vorgang, sondern einen Zielzustand. Beim zweiten Lauf meldet Ansible ok statt changed, weil nichts mehr zu tun ist. Deshalb sind package, service oder template den Aufrufen über shell vorzuziehen. Wo du doch einen Befehl absetzen musst, sichern creates, removes oder changed_when die Wiederholbarkeit ab.

Playbooks strukturieren und in Rollen zerlegen

Ein Playbook ordnet Plays einer Hostgruppe zu und ruft Tasks, Handler und Variablen auf. Sobald mehr als ein Dienst dazukommt, ziehst du wiederkehrende Logik in Rollen mit der üblichen Struktur aus tasks, handlers, templates, defaults und vars. Tags und --limit halten die Läufe auch in größeren Umgebungen beherrschbar.

Variablen, Templates und Geheimnisse trennen

Umgebungsspezifisches gehört in group_vars und host_vars, nicht in die Tasks. Konfigurationsdateien erzeugst du aus Jinja2-Templates mit Fakten aus ansible_facts, etwa Hostname, Adressen oder Distribution. Passwörter, Tokens und private Schlüssel verschlüsselst du mit Ansible Vault, damit das Repository unbedenklich bleibt.

Absichern, testen und in den Betrieb bringen

Mit --check und --diff siehst du vor dem Schreibzugriff, was sich ändern würde. ansible-lint fängt typische Fehler früh ab, eine Testumgebung in Vagrant oder in Containern erspart Überraschungen in der Produktion. Danach folgt der Schritt in die Pipeline, damit Playbooks aus Git heraus laufen und nicht vom Laptop.

Tutorial

Vom leeren Verzeichnis zum ersten Rollout

Du baust ein Ansible-Projekt von Grund auf: Control Node einrichten, Inventar anlegen, mit Ad-hoc-Befehlen die Verbindung prüfen, das erste Playbook schreiben und es anschließend in eine Rolle zerlegen. Am Ende steht ein Projekt, das du versionieren und im Team weitergeben kannst.

01

Control Node einrichten und Verbindungen prüfen

Ansible braucht auf den Zielsystemen keinen Agenten, aber sehr wohl SSH, Python und einen Benutzer mit sudo-Rechten. Diese drei Dinge klärst du, bevor du das erste Playbook schreibst.

Ansible auf dem Control Node installieren
# RHEL / Rocky / Alma
sudo dnf install -y ansible-core

# Debian / Ubuntu
sudo apt install -y ansible-core

# Distributionsunabhängig, wenn du eine neuere Version brauchst
pipx install --include-deps ansible

ansible --version   # zeigt Config-Datei, Python-Version und Collection-Pfade

ansible-core bringt nur die Module aus ansible.builtin mit. Alles andere, etwa community.general oder ansible.posix, holst du dir mit ansible-galaxy collection install. Das Paket ansible ist dagegen die große Sammlung mit mehreren hundert Collections.

Zugang für den Automationsbenutzer
ssh-keygen -t ed25519 -C "ansible@control" -f ~/.ssh/id_ed25519_ansible
ssh-copy-id -i ~/.ssh/id_ed25519_ansible.pub ansible@web01.example.internal

# Auf dem Ziel: sudo ohne Passwortabfrage, nur für diesen einen Benutzer
echo 'ansible ALL=(ALL) NOPASSWD:ALL' | sudo tee /etc/sudoers.d/ansible
sudo chmod 0440 /etc/sudoers.d/ansible
sudo visudo -c

visudo -c ist Pflicht, nicht Kür. Eine kaputte Datei in /etc/sudoers.d/ legt sudo auf dem gesamten Host lahm, und zwar auch für dich.

02

Inventar und ansible.cfg an den richtigen Ort legen

Ein Ansible-Projekt lebt in einem eigenen Verzeichnis, nicht in /etc/ansible. Alles, was zum Projekt gehört, liegt darin und geht mit in die Versionsverwaltung.

Projektstruktur anlegen
mkdir -p ~/infra/{group_vars,host_vars,roles,templates}
cd ~/infra && git init

Alles unterhalb dieses Verzeichnisses gehört zum Projekt. Wer stattdessen in /etc/ansible arbeitet, kann sein Setup weder weitergeben noch nachvollziehen, wer wann was geändert hat.

~/infra/ansible.cfg
[defaults]
inventory = ./inventory.yml
remote_user = ansible
callback_result_format = yaml
interpreter_python = auto_silent
host_key_checking = True

[ssh_connection]
pipelining = True

Ansible liest die ansible.cfg aus dem aktuellen Arbeitsverzeichnis, aber nur dann, wenn dieses Verzeichnis nicht für alle schreibbar ist. Liegt dein Projekt in /tmp, wird die Datei stillschweigend ignoriert und du wunderst dich über das falsche Inventar. ansible --version zeigt dir, welche Datei tatsächlich gezogen wurde.

~/infra/inventory.yml
all:
  children:
    web:
      hosts:
        web01.example.internal:
        web02.example.internal:
    db:
      hosts:
        db01.example.internal:
    produktion:
      children:
        web:
        db:

Gruppen dürfen Gruppen enthalten, so baust du Umgebungen aus Rollen zusammen. Variablen gehören nicht ins Inventar, sondern nach group_vars/web.yml und host_vars/web01.example.internal.yml. Prüfen kannst du das Ergebnis mit ansible-inventory --graph und ansible-inventory --host web01.example.internal.

03

Ad-hoc-Befehle und der Unterschied zwischen ok und changed

Ad-hoc-Befehle sind kein Spielzeug, sondern dein Diagnosewerkzeug. Damit klärst du, ob Verbindung, Rechte und Fakten stimmen, bevor du die erste Zeile eines Playbooks schreibst.

Die vier Ad-hoc-Befehle, die du wirklich brauchst
ansible all -m ansible.builtin.ping
ansible web -m ansible.builtin.command -a 'uptime'
ansible all -m ansible.builtin.setup -a 'filter=ansible_distribution*'
ansible db -b -m ansible.builtin.package -a 'name=htop state=present'

-b steht für become, also sudo. setup liefert die Facts, aus denen du später Bedingungen baust, etwa ansible_facts['os_family'] == 'RedHat'. Wer die Facts einmal gelesen hat, schreibt keine Playbooks mehr, die nur auf einer Distribution funktionieren.

Ansible meldet je Task ok, changed, skipped oder failed. Der Prüfstein für jedes Playbook ist der zweite Lauf: Er muss ausschließlich ok liefern. Meldet ein Task dauerhaft changed, beschreibt er keinen Zustand, sondern führt blind eine Aktion aus. Die üblichen Verursacher sind command und shell.

Befehle idempotent machen
- name: Zertifikat nur einmal erzeugen
  ansible.builtin.command:
    cmd: /usr/local/bin/gen-cert.sh
    creates: /etc/pki/tls/certs/app.crt

- name: Cache leeren und Ergebnis auswerten
  ansible.builtin.command: /usr/local/bin/flush-cache
  register: flush
  changed_when: "'geleert' in flush.stdout"

creates und changed_when machen aus einem Befehl eine Zustandsbeschreibung. Ohne sie ist jeder Lauf changed, und echte Änderungen verschwinden im Rauschen.

Statusmeldungen richtig lesen

MeldungBedeutungWas du tun solltest
okDer Zielzustand war bereits hergestelltNichts. Genau so soll der zweite Lauf aussehen
changedAnsible hat das System verändertBeim ersten Lauf normal, beim zweiten ein Fehler im Task
skippedDie when-Bedingung war nicht erfülltBedingung prüfen, meist steckt ein Tippfehler in einem Fact
failedDas Modul meldet einen FehlerMit -vvv wiederholen, die vollständige Modulausgabe steht im JSON
unreachableSSH kam nicht zustandeKein Ansible-Problem. Netz, Schlüssel oder Hostname prüfen
04

Erstes Playbook schreiben und in eine Rolle zerlegen

Ein Playbook beschreibt einen Zustand, kein Vorgehen. Deshalb steht in jedem Task, wie das System aussehen soll, nicht welche Befehle dorthin führen.

~/infra/site.yml
---
- name: Basiskonfiguration Webserver
  hosts: web
  become: true

  tasks:
    - name: Pakete installieren
      ansible.builtin.package:
        name:
          - nginx
          - chrony
        state: present

    - name: Konfiguration ausrollen
      ansible.builtin.template:
        src: templates/nginx.conf.j2
        dest: /etc/nginx/nginx.conf
        owner: root
        group: root
        mode: "0644"
        backup: true
      notify: nginx neu laden

    - name: Dienst dauerhaft aktivieren
      ansible.builtin.service:
        name: nginx
        state: started
        enabled: true

  handlers:
    - name: nginx neu laden
      ansible.builtin.service:
        name: nginx
        state: reloaded

backup: true legt die vorherige Fassung mit Zeitstempel daneben, das ist dein Rückweg ohne Repository-Zugriff. Der Handler läuft nur, wenn sich die Datei tatsächlich geändert hat, und reloaded statt restarted hält bestehende Verbindungen am Leben. Wenn du die Konfiguration vor dem Kopieren prüfen lassen willst, nimm den Parameter validate. Bei nginx prüft das eine temporäre Datei, relative include-Pfade darin können scheitern. Dann prüfst du stattdessen im Handler mit einem vorgeschalteten nginx -t.

Rollenskelett erzeugen
ansible-galaxy init roles/baseline
ls roles/baseline
# defaults  files  handlers  meta  tasks  templates  tests  vars

Standardwerte gehören nach defaults/main.yml, denn nur die lassen sich von außen bequem überschreiben. vars/main.yml hat eine sehr hohe Priorität und ist damit der falsche Ort für alles, was jemand anpassen können soll.

Playbook, das nur noch Rollen aufruft
---
- name: Produktion ausrollen
  hosts: produktion
  become: true
  roles:
    - role: baseline
      tags: [baseline]
    - role: webserver
      tags: [web]
      when: inventory_hostname in groups['web']

Ab hier ist das Playbook nur noch eine Reihenfolge. Die eigentliche Arbeit steckt in Rollen, die du in anderen Projekten wiederverwenden kannst. Mit --tags baseline läuft gezielt nur ein Teil.

05

Variablen, Templates und Geheimnisse trennen

Sobald das zweite System dazukommt, unterscheiden sich Werte. Templates und Variablen halten die Logik an einer Stelle und die Unterschiede an einer anderen.

templates/nginx.conf.j2 (Auszug)
worker_processes {{ nginx_worker_processes | default(ansible_facts['processor_vcpus']) }};

server {
    listen {{ nginx_port | default(80) }};
    server_name {{ inventory_hostname }};
{% for pfad in nginx_aliase | default([]) %}
    location {{ pfad.url }} { alias {{ pfad.ziel }}; }
{% endfor %}
}

default() ist der Unterschied zwischen einer Rolle, die überall läuft, und einer, die bei jedem neuen Host abbricht. Facts wie processor_vcpus liefert Ansible frei Haus, du musst sie nicht pflegen.

Geheimnisse mit ansible-vault
ansible-vault create group_vars/db/vault.yml
# Inhalt der verschlüsselten Datei:
#   vault_db_password: "..."

# group_vars/db/vars.yml bleibt unverschlüsselt und enthält nur die Referenz:
#   db_password: "{{ vault_db_password }}"

ansible-vault view group_vars/db/vault.yml
ansible-vault rekey group_vars/db/vault.yml
ansible-playbook site.yml --vault-password-file ~/.vault-pass

Die Trennung in vars.yml und vault.yml hat einen handfesten Grund: In der unverschlüsselten Datei siehst du im Diff, welche Variablen es überhaupt gibt. Eine komplett verschlüsselte Datei zeigt bei jeder Änderung nur einen neuen Block Zufallszeichen. Die Datei mit dem Vault-Passwort bekommt chmod 600 und einen Eintrag in .gitignore.

Bevor das Projekt ins Repository geht

  • Vault-Passwortdatei, lokale Inventare und *.retry in die .gitignore aufnehmenEin einmal gepushtes Vault-Passwort ist kompromittiert, auch wenn du den Commit später entfernst. Der Verlauf bleibt bei allen, die schon geklont haben.
  • ansible-lint über das gesamte Projekt laufen lassenEs findet fehlende Namen, zu weite Dateirechte und veraltete Modulaufrufe, bevor jemand anderes darüber stolpert.
  • Jeder Task hat ein name-Feld in verständlichem Deutsch oder EnglischOhne Namen zeigt die Ausgabe nur den Modulnamen. Bei zwanzig copy-Tasks weißt du dann nicht, welcher fehlgeschlagen ist.
  • Module mit vollem Namen schreiben, also ansible.builtin.copy statt copyKurznamen lassen sich durch nachinstallierte Collections überschreiben. Der vollständige Name ist eindeutig und bleibt es.
  • Der zweite Lauf meldet ausschließlich okErst dann beschreibt das Playbook einen Zustand. Damit wird es im Betrieb zum Prüfwerkzeug: Was changed meldet, ist von Hand verändert worden.
06

Trockenlauf, Begrenzung und der erste echte Rollout

Zwischen einem funktionierenden Playbook und einem Playbook, das du auf hundert Server loslässt, liegen drei Schalter. Die gewöhnst du dir am besten sofort an.

Die Reihenfolge, die dir den Abend rettet
ansible-playbook site.yml --syntax-check
ansible-lint site.yml roles/

# Trockenlauf mit Änderungsanzeige, zuerst gegen einen einzigen Host
ansible-playbook site.yml --check --diff --limit web01.example.internal

# Danach echt, aber weiterhin begrenzt
ansible-playbook site.yml --limit web01.example.internal

# Rest der Gruppe, den bereits erledigten Host ausgenommen
ansible-playbook site.yml --limit 'web:!web01.example.internal'

--check ist kein perfekter Trockenlauf. Tasks, deren Ergebnis von einem vorher nicht ausgeführten Schritt abhängt, melden im Check-Modus Fehler oder falsche Werte. Module ohne Check-Unterstützung, allen voran command und shell, werden übersprungen. Nimm --diff immer dazu, sonst siehst du nur, dass etwas anders wäre, aber nicht was.

Wissen prüfen

Teste dich und finde deinen Weg

Bevor du einen Kurs buchst, lohnt sich eine ehrliche Standortbestimmung. Die Tests sind kostenlos und ohne Anmeldung.

Gut zu wissen

Häufige Fragen zu Ansible-Grundlagen

Noch etwas offen? Wir sind ohne Warteschleife für dich da.

Frag uns direkt
Brauche ich Python-Kenntnisse, um mit Ansible zu arbeiten?
Für den normalen Betrieb nicht. Du beschreibst den gewünschten Zustand in YAML und nutzt dafür mitgelieferte Module, Python läuft nur im Hintergrund auf Control Node und Zielsystem. Relevant wird Python erst, wenn du eigene Module oder Plugins entwickelst, und das ist in der Systemadministration eher die Ausnahme.
Was ist der Unterschied zwischen Playbook, Rolle und Collection?
Ein Playbook ist die ausführbare Datei, die Hostgruppen und Tasks miteinander verbindet. Eine Rolle bündelt wiederverwendbare Tasks, Handler, Templates und Standardvariablen in einer festen Verzeichnisstruktur. Eine Collection ist die Verteilform darüber und liefert Rollen, Module und Plugins gemeinsam aus, etwa über Ansible Galaxy oder den Automation Hub.
Ersetzt Ansible meine bestehenden Bash-Skripte komplett?
Nein, und das ist auch nicht das Ziel. Für einmalige Ad-hoc-Aufgaben, schnelle Auswertungen oder lokale Hilfsfunktionen bleibt die Shell das passende Werkzeug. Ansible spielt seine Stärke dort aus, wo ein Zustand über viele Systeme hinweg reproduzierbar hergestellt werden soll. In der Praxis existieren beide Ansätze nebeneinander, oft ruft eine Rolle sogar ein bestehendes Skript kontrolliert auf.
Wie viel Vorwissen brauche ich für einen Ansible-Kurs?
Sinnvoll ist solide Linux-Administrationserfahrung: Paketverwaltung, systemd, Dateirechte, SSH und ein Grundverständnis der YAML-Syntax. Wer dort noch unsicher ist, startet besser mit einem Linux-Grundkurs oder mit dem Kompaktkurs Linux Systemadministration und Shell-Scripting und kommt danach zu Ansible.
Welcher cmt-Kurs passt zu welchem Ausgangspunkt?
Der Ansible Kompaktkurs ist der distributionsneutrale Einstieg für Admins, die zügig zu eigenen Playbooks kommen wollen. Configuration Management und Service Operations mit Ansible legt den Schwerpunkt stärker auf den laufenden Betrieb. Wer in einer Red-Hat-Landschaft arbeitet und auf eine Zertifizierung zusteuert, ist mit Red Hat Enterprise Linux Automation with Ansible richtig. Sind bereits Playbooks im Einsatz und die Struktur wird unübersichtlich, hilft Ansible für Fortgeschrittene weiter.

Zuletzt geprüft am 26. Juli 2026.

Das sagen Teilnehmer

Echte Stimmen aus unseren IT-Kursen

Qualitativ sehr guter Kurs. Ruhiger und wertschätzender Umgang. Keine Informationsüberlastung.
Rückmeldung aus dem Kurs „Ansible Kompaktkurs“
Gut vorbereitete professionelle Vermittlung der komplexen Inhalte innerhalb von nur drei Tagen.
Rückmeldung aus dem Kurs „Docker Grundkurs für Einsteiger“
Persönlich für dich da

Deine Ansprechpartner

Du bist dir nicht sicher, welcher Kurs oder welches Level zu dir passt? Wir beraten dich persönlich und kostenlos.

Yves Hoppe

Yves Hoppe

Weiterbildung & Beratung

Hilft dir, aus dem Linux-Programm den passenden Kurs oder Lernpfad zu finden.

Norbert Jansen

Norbert Jansen

Beratung & Inhouse

Plant mit dir Inhouse-Trainings, die exakt auf eure Systemlandschaft und Distributionen zugeschnitten sind.

Nächster Schritt

Steig strukturiert in Ansible ein

In unseren Ansible-Trainings arbeitest du an eigenen Übungssystemen und schreibst vom ersten Tag an Inventories, Playbooks und Rollen, die du anschließend direkt weiterverwenden kannst. Die Termine finden vor Ort oder Live-Online statt. Wenn du unsicher bist, welcher Kurs zu deiner Umgebung und deinem Kenntnisstand passt, melde dich einfach bei uns, wir ordnen das gemeinsam ein.