# Ansible installieren und erste Playbooks erstellen

Source: https://forgeone.solutions/de/tech/ansible-installieren-und-erste-playbooks-erstellen
Language: de
Published: 2026-08-28
Updated: 2026-10-22

Von der Installation über Inventory und Playbooks bis zur wiederverwendbaren Chrony-Rolle.

## Ziel dieses Beitrags

## YAML, YML und unsere Schreibweise

YAML ist das Datenformat, in dem Ansible Playbooks, Inventories und Variablendateien üblicherweise beschreibt. Die Dateiendungen .yaml und .yml meinen technisch dasselbe Format; Ansible kann beide Varianten lesen.

Für die ForgeOne-Reihe verwenden wir konsequent .yaml, weil die Schreibweise eindeutig ist und sich in gemischten Dokumentationen besser lesen lässt. Wenn bestehende Rollen main.yml, site.yml oder requirements.yml verwenden, ist das nicht falsch. Neue Beispiele in dieser Reihe schreiben wir aber als hosts.yaml, site.yaml, main.yaml und requirements.yaml.

## YAML, YAML und unsere Schreibweise

YAML ist das Datenformat, in dem Ansible Playbooks, Inventories und Variablendateien üblicherweise beschreibt. Die Dateiendungen .yaml und .yaml meinen technisch dasselbe Format; Ansible kann beide Varianten lesen.

Für die ForgeOne-Reihe verwenden wir konsequent .yaml, weil die Schreibweise eindeutig ist und sich in gemischten Dokumentationen besser lesen lässt. Wenn bestehende Rollen main.yaml, site.yaml oder requirements.yaml verwenden, ist das nicht falsch. Neue Beispiele in dieser Reihe schreiben wir aber als hosts.yaml, site.yaml, main.yaml und requirements.yaml.

## YAML, YAML und unsere Schreibweise

YAML ist das Datenformat, in dem Ansible Playbooks, Inventories und Variablendateien üblicherweise beschreibt. Die Dateiendungen .yaml und .yaml meinen technisch dasselbe Format; Ansible kann beide Varianten lesen.

Für die ForgeOne-Reihe verwenden wir konsequent .yaml, weil die Schreibweise eindeutig ist und sich in gemischten Dokumentationen besser lesen lässt. Wenn bestehende Rollen main.yaml, site.yaml oder requirements.yaml verwenden, ist das nicht falsch. Neue Beispiele in dieser Reihe schreiben wir aber als hosts.yaml, site.yaml, main.yaml und requirements.yaml.

Dieser Beitrag macht Technikthema als praktisches Betriebsthema greifbar: Du erkennst den Nutzen, die wichtigsten Entscheidungen und die Prüfpunkte, die vor produktiver Nutzung stimmen müssen.

## Voraussetzungen

Du brauchst einen Control Node, erreichbare Managed Nodes, SSH-Zugriff, Python auf den Zielsystemen und ein Git-Repository für nachvollziehbare Änderungen.

### Von null zur wiederverwendbaren Chrony-Rolle

[Ansible](https://forgeone.solutions/de/produkte/ansible) ist ein Automatisierungswerkzeug, mit dem ein gewünschter Zustand von Systemen als Code beschrieben und wiederholbar angewendet wird. Dieser Artikel baut Schritt für Schritt ein kleines Chrony-Lab auf: erst Installation, dann Inventory, erster Verbindungstest, Mini-Playbook, Rolle, Variablen, Template, Handler und Ausführung.

Chrony ist dafür ein gutes Lernbeispiel: Der Zweck ist leicht verständlich, der Dienst existiert auf vielen Linux-Distributionen, es gibt Paketinstallation, Service-Management, Konfigurationsdatei, Templates, Defaults, Facts, Conditions, Handler und Inventory-Overrides. Die echte lokale ForgeOne-Rolle chronyd diente als Praxisquelle. Für diesen Artikel wurde daraus eine neutrale Lehrversion abgeleitet: keine internen NTP-Server, keine Kundenhosts, keine internen Repository-URLs, keine Secrets.

## Was ist Ansible?

Ansible läuft auf einem Control Node. Das ist der Rechner, auf dem Sie ansible oder ansible-playbook ausführen. Von dort verbindet sich Ansible per SSH zu Managed Nodes. Managed Nodes sind die Zielsysteme, die konfiguriert werden. Auf den Zielsystemen muss normalerweise kein Agent laufen; Ansible nutzt SSH und führt Module aus. Für viele Linux-Module braucht der Managed Node eine nutzbare Python-Umgebung.

- CONTROL NODE
- | SSH
- MANAGED NODE

- Inventory: beschreibt, wo Automation läuft, also Hosts und Gruppen.
- Playbook: beschreibt, was passieren soll und auf welchen Hosts.
- Task: ein einzelner Schritt in einem Playbook.
- Module: die technische Arbeitseinheit, zum Beispiel package, template oder systemd\_service.
- Role: wiederverwendbare Struktur aus Tasks, Defaults, Templates, Handlern und Metadaten.
- Collection: Paketformat für Module, Rollen, Plugins und Dokumentation.
- FQCN: Fully Qualified Collection Name, zum Beispiel ansible.builtin.package.

Bei einem Lauf wie ansible-playbook playbooks/site.yaml passiert vereinfacht: Ansible liest Konfiguration, lädt das Inventory, bestimmt Hosts und Gruppen, kombiniert Variablen, baut SSH-Verbindungen auf, sammelt Facts, wertet das Playbook aus, lädt Rollen, führt Tasks aus, startet Module auf Managed Nodes, löst bei Änderungen Handler aus und gibt am Ende ein Ergebnis aus. Diese Reihenfolge ist wichtiger als sofort viel YAML zu sehen.

## Ansible installieren

Wählen Sie genau einen Installationsweg für Ihren Control Node. Für erste Tests sind Distributionspakete einfach. pipx ist gut für Admin-Workstations, weil Ansible isoliert im Benutzerkontext installiert wird. Ein Python venv ist gut für Projekt-Repositories und CI, weil Versionen explizit kontrolliert werden.

### Debian und Ubuntu

Debian und Ubuntu nutzen APT. Führen Sie diesen Block auf dem Control Node aus, wenn Ihr Arbeitsrechner oder Ihre Admin-VM Debian oder Ubuntu ist.

```bash
# Debian / Ubuntu: Ansible installieren
sudo apt update
sudo apt install ansible

# Prüfen
ansible --version
```

### Red Hat, Rocky Linux und AlmaLinux

RHEL-kompatible Systeme nutzen DNF. Führen Sie diesen Block auf dem Control Node aus, wenn Ihr Arbeitsrechner Red Hat Enterprise Linux, Rocky Linux oder AlmaLinux verwendet.

```bash
# Red Hat / Rocky Linux / AlmaLinux: Ansible Core installieren
sudo dnf install ansible-core

# Optional, wenn das Community-Paket in den aktivierten Repositories vorhanden ist
sudo dnf install ansible

# Prüfen
ansible --version
```

### SUSE Linux Enterprise und openSUSE

SUSE-Systeme nutzen zypper. Führen Sie diesen Block auf dem Control Node aus, wenn Ihr Arbeitsrechner SUSE Linux Enterprise oder openSUSE verwendet.

```bash
# SUSE Linux Enterprise / openSUSE: Ansible installieren
sudo zypper refresh
sudo zypper install ansible

# Prüfen
ansible --version
```

### pipx und Python venv

pipx installiert Ansible isoliert im Benutzerkontext. Das ist praktisch, wenn das Betriebssystem konservative Paketversionen liefert, Sie aber keine projektlokale virtuelle Umgebung aktivieren wollen.

```bash
# pipx installieren und Ansible isoliert im Benutzerkontext installieren
python3 -m pip install --user pipx
python3 -m pipx ensurepath
pipx install --include-deps ansible

# Neue Shell öffnen oder PATH neu laden, dann prüfen
ansible --version
ansible-community --version
```

Ein projektlokales venv ist sinnvoll, wenn Repository, CI und Team dieselbe Ansible-Version nutzen sollen. Führen Sie den Block im Projektverzeichnis aus.

```bash
# Projektlokales Python venv
python3 -m venv .venv
. .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install ansible ansible-lint

# Prüfen
ansible --version
```

## Lab aufbauen

Jetzt entsteht ein kleines Testprojekt. Am Anfang ist die Struktur absichtlich minimal. Sie wächst im Artikel mit jedem Schritt.

```bash
mkdir -p ansible-chrony-lab
cd ansible-chrony-lab
mkdir -p inventories/lab/group_vars inventories/lab/host_vars playbooks roles
```

Legen Sie danach ansible.cfg an. Diese Datei macht das Projektverhalten reproduzierbar: Ansible weiß, welches Inventory und welchen Rollenpfad es verwenden soll.

```ini
[defaults]
inventory = inventories/lab/hosts.yaml
roles_path = roles
interpreter_python = auto_silent

[ssh_connection]
pipelining = True
timeout = 30
```

```bash
ansible-config view
ansible-config dump --only-changed
```

## Inventory erstellen

Das Inventory sagt primär: Wo läuft Automation? Das Playbook und die Rolle sagen: Was soll passieren? Für das Lab nutzen wir zwei Beispielhosts in einer Gruppe linux. Ersetzen Sie die Hostnamen und den SSH-Benutzer durch Ihre echten Zielsysteme.

```yaml
all:
  children:
    linux:
      hosts:
        node01.example.org:
          ansible_user: admin
        node02.example.org:
          ansible_user: admin
```

all ist die Wurzel des Inventories. children enthält Gruppen. linux ist in diesem Beispiel eine Gruppe. hosts enthält die konkreten Managed Nodes. ungrouped wäre die automatisch verwendete Gruppe für Hosts, die keiner eigenen Gruppe zugeordnet sind. Parent- und Child-Groups ordnen Gruppen hierarchisch; das ist aber noch keine klassische objektorientierte Vererbung.

## Erste Verbindung testen

Bevor wir Chrony konfigurieren, prüfen wir die Verbindung. Das Ansible-ping-Modul ist kein ICMP-Ping. Es testet im Wesentlichen SSH, Python und ob Ansible ein Modul auf dem Managed Node ausführen kann.

```bash
ansible all -m ansible.builtin.ping
```

Wenn das fehlschlägt, prüfen Sie zuerst DNS/Hostname, SSH-Key, Benutzer, sudo-Rechte und Python auf dem Zielsystem. Erst wenn dieser Schritt funktioniert, lohnt sich das nächste Playbook.

## Erstes Mini-Playbook

Das erste Playbook macht nur eine Sache: Es stellt sicher, dass das Paket chrony installiert ist. Damit lernen Sie Play, hosts, become, tasks, name, Modulparameter und state ohne Rollenstruktur.

```yaml
---
- name: Install Chrony for first contact with Ansible
  hosts: linux
  become: true

  tasks:
    - name: Install Chrony package
      ansible.builtin.package:
        name: chrony
        state: present
```

Führen Sie das Playbook zuerst im Check-Modus aus, dann real und danach ein zweites Mal. Beim ersten echten Lauf darf changed erscheinen. Beim zweiten Lauf sollte der Task ok melden, wenn das Paket bereits installiert ist. Das ist Idempotenz: Ansible beschreibt einen Zustand, nicht nur eine Befehlsliste.

```bash
ansible-playbook playbooks/mini.yaml --check --diff
ansible-playbook playbooks/mini.yaml
ansible-playbook playbooks/mini.yaml
```

## Warum daraus eine Rolle wird

Das Mini-Playbook reicht nicht mehr, sobald Debian andere Pfade nutzt als Red Hat, SUSE einen anderen Servicenamen hat, NTP-Server konfigurierbar sein sollen, eine Konfigurationsänderung den Dienst neu starten muss oder dieselbe Logik in zehn Projekten verwendet werden soll. Deshalb bauen wir daraus eine Rolle.

Eine Rollenstruktur ist kein ForgeOne-Sonderweg. ansible-galaxy erzeugt eine Standardstruktur, die Sie danach bewusst vereinfachen können.

```bash
ansible-galaxy role init --init-path roles chrony
```

- roles/chrony/
- ├── defaults/
- ├── files/
- ├── handlers/
- ├── meta/
- ├── tasks/
- ├── templates/
- ├── tests/
- └── vars/

Unsere Lehrrolle braucht defaults, tasks, handlers, templates, meta und README. files bleibt leer, weil die Konfiguration aus Variablen gerendert wird. vars bleibt leer, weil Benutzeroptionen nicht in vars gehören: role vars haben deutlich höhere Precedence als defaults und sind schwerer zu überschreiben. Die nächsten vollständigen Dateien liegen im Lab unter roles/chrony/defaults/main.yaml, roles/chrony/tasks/main.yaml, roles/chrony/tasks/Debian.yaml, roles/chrony/tasks/RedHat.yaml, roles/chrony/tasks/Suse.yaml, roles/chrony/templates/chrony.conf.j2 und roles/chrony/handlers/main.yaml.

## Chrony-Rolle Schritt für Schritt

defaults/main.yaml ist die öffentliche konfigurierbare Schnittstelle der Rolle. Benutzer können diese Werte über group\_vars, host\_vars oder andere Quellen überschreiben. Deshalb stehen Paketnamen, Servicenamen, Pfade, Serverliste und Service-Zustand hier.

```yaml
---
chrony_package_name_map:
  Debian: chrony
  RedHat: chrony
  Suse: chrony

chrony_service_name_map:
  Debian: chrony
  RedHat: chronyd
  Suse: chronyd

chrony_config_path_map:
  Debian: /etc/chrony/chrony.conf
  RedHat: /etc/chrony.conf
  Suse: /etc/chrony.conf

chrony_package_state: present
chrony_service_enabled: true
chrony_service_state: started

chrony_servers:
  - address: 0.pool.ntp.org
    options: iburst
  - address: 1.pool.ntp.org
    options: iburst

chrony_driftfile: /var/lib/chrony/drift
chrony_makestep: "1.0 3"
chrony_rtcsync: true
chrony_logdir: /var/log/chrony
```

tasks/main.yaml sammelt die Logik. Zuerst werden OS-spezifische Werte aus ansible\_facts["os\_family"] berechnet. Danach wird bei unbekannten Systemfamilien sauber abgebrochen, die passende OS-Datei eingebunden, das Template gerendert und der Dienst aktiviert/gestartet.

```yaml
---
- name: Resolve OS-specific Chrony values
  ansible.builtin.set_fact:
    chrony_package_name: "{{ chrony_package_name_map.get(ansible_facts['os_family']) }}"
    chrony_service_name: "{{ chrony_service_name_map.get(ansible_facts['os_family']) }}"
    chrony_config_path: "{{ chrony_config_path_map.get(ansible_facts['os_family']) }}"
  changed_when: false

- name: Stop when the operating system family is unsupported
  ansible.builtin.fail:
    msg: "Unsupported operating system family: {{ ansible_facts['os_family'] }}"
  when: chrony_package_name is not defined or chrony_package_name is none

- name: Run OS-specific Chrony tasks
  ansible.builtin.include_tasks: "{{ ansible_facts['os_family'] }}.yaml"

- name: Render Chrony configuration
  ansible.builtin.template:
    src: chrony.conf.j2
    dest: "{{ chrony_config_path }}"
    owner: root
    group: root
    mode: "0644"
  notify: Restart chrony

- name: Ensure Chrony service state
  ansible.builtin.systemd_service:
    name: "{{ chrony_service_name }}"
    enabled: "{{ chrony_service_enabled }}"
    state: "{{ chrony_service_state }}"
```

Woher kennt Ansible os\_family? Durch gather\_facts. Für Debian/Ubuntu ist der Wert typischerweise Debian, für RHEL-kompatible Systeme RedHat und für SUSE Suse. Prüfen können Sie das gezielt mit dem setup-Modul.

```bash
ansible all -m ansible.builtin.setup -a 'filter=ansible_os_family'
ansible all -m ansible.builtin.setup -a 'filter=ansible_distribution'
```

include\_tasks wird hier verwendet, weil die Datei zur Laufzeit anhand der Facts gewählt wird. import\_tasks ist statisch und wird schon beim Parsen verarbeitet. Für diese Lernrolle ist include\_tasks verständlicher, weil der Zusammenhang zu den gesammelten Facts sichtbar bleibt.

### tasks/Debian.yaml

```yaml
---
- name: Install Chrony on Debian family
  ansible.builtin.package:
    name: "{{ chrony_package_name }}"
    state: "{{ chrony_package_state }}"
```

### tasks/RedHat.yaml

```yaml
---
- name: Install Chrony on Red Hat family
  ansible.builtin.package:
    name: "{{ chrony_package_name }}"
    state: "{{ chrony_package_state }}"
```

### tasks/Suse.yaml

```yaml
---
- name: Install Chrony on SUSE family
  ansible.builtin.package:
    name: "{{ chrony_package_name }}"
    state: "{{ chrony_package_state }}"
```

Das Template erzeugt die Chrony-Konfiguration aus Variablen. {{ variable }} setzt Werte ein, for iteriert über chrony\_servers, if rendert optionale Direktiven. template ist hier richtig, weil die Datei aus Variablen entsteht. copy wäre passend, wenn eine statische Datei unverändert kopiert werden soll.

```jinja2
# Ansible managed
{% for server in chrony_servers %}
server {{ server.address }} {{ server.options | default('iburst') }}
{% endfor %}

driftfile {{ chrony_driftfile }}
{% if chrony_makestep | length > 0 %}
makestep {{ chrony_makestep }}
{% endif %}
{% if chrony_rtcsync | bool %}
rtcsync
{% endif %}
logdir {{ chrony_logdir }}
```

Der Handler startet Chrony nur neu, wenn das Template wirklich geändert wurde. notify markiert die Änderung im Task, der Handler läuft gebündelt am Ende. Das verhindert unnötige Restarts während eines Laufs.

```yaml
---
- name: Restart chrony
  ansible.builtin.systemd_service:
    name: "{{ chrony_service_name }}"
    state: restarted
```

## Playbook mit Rolle ausführen

Jetzt wird das Playbook klein und lesbar. Die wiederverwendbare Logik steckt in der Rolle; das Playbook wählt nur Zielgruppe, Rechte und Rolle aus.

```yaml
---
- name: Configure time synchronization
  hosts: linux
  become: true
  gather_facts: true

  roles:
    - role: chrony
```

Die Gruppe linux kommt aus dem Inventory. become: true bedeutet, dass die Tasks mit erhöhten Rechten laufen, typischerweise über sudo. gather\_facts: true ist wichtig, weil die Rolle os\_family verwendet.

## Variablen und Precedence verstehen

Jetzt entsteht Precedence aus einem echten Problem: Die Rolle hat Defaults, das Lab überschreibt die Zeitserver für alle Hosts, und node01 bekommt eine eigene Ausnahme.

### inventories/lab/group\_vars/all.yaml

```yaml
chrony_servers:
  - address: 0.pool.ntp.org
    options: iburst
  - address: 1.pool.ntp.org
    options: iburst
chrony_makestep: "1.0 3"
chrony_rtcsync: true
```

### inventories/lab/host\_vars/node01.example.org.yaml

```yaml
chrony_servers:
  - address: time.cloudflare.com
    options: iburst
```

node02 verwendet die Server aus group\_vars/all.yaml. node01 verwendet die Server aus host\_vars/node01.example.org.yaml, weil host\_vars in diesem praktischen Fall spezifischer sind. Technisch ist das keine klassische objektorientierte Vererbung. Ansible kombiniert Variablen aus mehreren Quellen nach definierten Precedence-Regeln. Die Inventory-Hierarchie all -> parent group -> child group -> host ist nur ein Teil davon.

| Quelle | Beispiel | Rolle im Beispiel |
| --- | --- | --- |
| Role defaults | chrony\_servers: pool A | Standard der Rolle |
| group\_vars/all | chrony\_servers: pool B | Lab-weite Konfiguration |
| host\_vars/node01 | chrony\_servers: source C | Ausnahme für einen Host |
| play vars | vars: ... | Wert direkt im Play |
| role vars | roles/chrony/vars | interne, starke Rollenwerte |
| set\_fact | chrony\_service\_name | Laufzeitwert aus Facts |
| role params | role: chrony, vars: ... | expliziter Rollenaufruf |
| extra vars | -e key=value | stärkster bewusster Override |

Die Tabelle ist eine praktische Orientierung. Die vollständige Liste ist detaillierter und enthält weitere Quellen und Sonderfälle. Für Details siehe die [offizielle Ansible-Dokumentation zur Variable Precedence](https://docs.ansible.com/projects/ansible/latest/reference_appendices/general_precedence.html).

## Deployment und Ergebnis prüfen

Jetzt ist das Projekt ausführbar. Prüfen Sie zuerst Syntax, dann Dry Run, dann einen einzelnen Host und erst danach die gesamte Gruppe.

```bash
ansible-playbook -i inventories/lab/hosts.yaml playbooks/site.yaml --syntax-check
ansible-playbook -i inventories/lab/hosts.yaml playbooks/site.yaml --check --diff
ansible-playbook -i inventories/lab/hosts.yaml playbooks/site.yaml --limit node01.example.org --diff
ansible-playbook -i inventories/lab/hosts.yaml playbooks/site.yaml
```

Hören Sie nicht beim PLAY RECAP auf. Prüfen Sie auf einem Managed Node, ob der Dienst läuft und ob Chrony Quellen und Tracking-Daten sieht. Der Dienst heißt je nach Distribution chrony oder chronyd; deshalb enthält der Prüfblock beide Varianten für systemctl.

```bash
ssh admin@node01.example.org 'systemctl status chrony || systemctl status chronyd'
ssh admin@node01.example.org 'chronyc sources'
ssh admin@node01.example.org 'chronyc tracking'
```

Führen Sie die Rolle danach erneut aus. Wenn bereits alles korrekt ist, sollte changed möglichst bei 0 liegen. Falls changed wiederholt steigt, suchen Sie nach nicht-idempotenten Tasks oder Templates, die bei jedem Lauf andere Inhalte erzeugen.

```bash
ansible-playbook -i inventories/lab/hosts.yaml playbooks/site.yaml --diff
```

## Die vollständige Beispielstruktur

Alle Dateien aus dem Lab sind hier vollständig enthalten. Es gibt kein Download-Gate und keinen Login. Kopieren Sie jede Datei in den angegebenen Pfad.

```bash
ansible-chrony-lab/
├── ansible.cfg
├── requirements.yaml
├── inventories/
│   └── lab/
│       ├── hosts.yaml
│       ├── group_vars/
│       │   └── all.yaml
│       └── host_vars/
│           └── node01.example.org.yaml
├── playbooks/
│   ├── mini.yaml
│   └── site.yaml
└── roles/
    └── chrony/
        ├── defaults/
        │   └── main.yaml
        ├── handlers/
        │   └── main.yaml
        ├── meta/
        │   └── main.yaml
        ├── tasks/
        │   ├── Debian.yaml
        │   ├── main.yaml
        │   ├── RedHat.yaml
        │   └── Suse.yaml
        ├── templates/
        │   └── chrony.conf.j2
        └── README.md
```

### requirements.yaml

```yaml
---
collections: []

roles: []
```

Dieses Beispiel benötigt keine externe Collection. Alle verwendeten Module stammen aus ansible.builtin. In realen Projekten können externe Collections und Rollen in requirements.yaml versioniert werden.

## Collections, Rollen und Git Submodules

Eine Role ist wiederverwendbare Konfigurationslogik. Eine Collection ist ein Paketformat für Rollen, Module, Plugins, Playbooks und Dokumentation. FQCN wie ansible.builtin.package machen sichtbar, aus welcher Collection ein Modul stammt.

Git Submodules sind etwas anderes: Sie sind eine Git- und Repository-Strategie. ForgeOne nutzt in bestimmten Projekten separat versionierte Rollen-Repositories und bindet sie per Submodule ein. Das ist keine Ansible-Pflicht und kein pauschaler Best-Practice-Zwang, sondern eine Option für Teams, die Rollen unabhängig von Inventories und Playbooks versionieren wollen.

```bash
git submodule add git@example.org:platform/ansible-roles.git roles/shared
git clone --recurse-submodules git@example.org:platform/ansible-project.git
git submodule update --init --recursive
git submodule status
```

Alternativen sind Standalone Roles über requirements.yaml, Collections, private Automation-Hub- oder Galaxy-artige Repositories. Die richtige Wahl hängt von Teamgröße, Release-Prozess, Wiederverwendung und Governance ab.

## Best Practices aus dem Beispiel

- defaults sind die öffentliche Schnittstelle der Rolle.
- group\_vars beschreiben gemeinsame Werte für eine Umgebung oder Gruppe.
- host\_vars bleiben echte Ausnahmen.
- Handler verhindern unnötige Restarts.
- Templates sind richtig, wenn Dateien aus Variablen entstehen.
- FQCN reduziert Namenskonflikte und macht Herkunft sichtbar.
- Module sind shell-Befehlen vorzuziehen, wenn ein passendes Modul existiert.
- Git macht Änderungen reviewbar.
- Dependency Pinning macht Builds reproduzierbarer.
- --check, --diff und --limit reduzieren Risiko vor produktiven Läufen.

Typische Anfängerfehler sind: alles in site.yaml schreiben, Werte hart in Tasks codieren, shell statt Module verwenden, Secrets ins Inventory legen, Benutzeroptionen in vars statt defaults packen, alles per extra-vars überschreiben, Rollen an einzelne Hosts koppeln, Dependencies nicht versionieren, ohne --limit und --check direkt gegen Produktion laufen.

Molecule ist für Rollen-Tests sinnvoll, aber kein Muss für den ersten Artikel. Die lokale ForgeOne-Chrony-Rolle hat eine minimale Molecule-Struktur mit Syntax-Test. Ausführliche Molecule-Tests sind ein eigenes Thema.

## AWX und AAP

Heute reicht ansible-playbook für das Lab. Wenn mehrere Teams, Credentials, RBAC, Inventories, Job Templates, Scheduling, Workflows, Audit, API und Execution Environments gebraucht werden, werden [AWX](https://forgeone.solutions/de/produkte/awx) oder [Red Hat Ansible Automation Platform](https://forgeone.solutions/de/produkte/red-hat-ansible-automation-platform) relevant. Eine AWX-Installation gehört nicht in diesen Grundlagenartikel.

Fachlich passt das in größere [Automation & GitOps](https://forgeone.solutions/de/produkte/automation-gitops) -Architekturen: Infrastruktur kann mit OpenTofu beschrieben werden, während Ansible Systeme, Dienste und Betriebsabläufe konfiguriert.

## Fazit

Wir haben bei null angefangen: Ansible installiert, ein Inventory gebaut, SSH/Python mit ansible.builtin.ping geprüft, Chrony erst mit einem Mini-Playbook installiert und daraus eine wiederverwendbare Rolle entwickelt. Die Rolle nutzt Defaults, Facts, OS-spezifische Includes, Templates, Handler und Inventory-Overrides. Danach haben wir Ausführung, Prüfung, Idempotenz, Collections, Rollen und Git Submodules eingeordnet.

### Professionelle Unterstützung

Wer das Beispiel selbst nachbauen möchte, hat alle notwendigen Dateien und Schritte im Artikel. Wenn daraus eine größere Automatisierungsumgebung, zentrale Rollenbibliothek, CI/CD-Strecke oder AWX/AAP-Plattform werden soll, unterstützt ForgeOne bei Architektur, Umsetzung, Migration und Betrieb.

## Betrieb und Validierung

Für den produktiven Betrieb reicht eine erfolgreiche Installation allein nicht aus. Prüfe Dienste, Logs, Netzwerk, Anmeldung, Updates, Backup und Wiederherstellung so, dass der Zustand wiederholbar und für andere Administratoren nachvollziehbar bleibt.

## Quellen und weiterführende Dokumentation

Nutze für produktive Umsetzung zusätzlich die aktuelle Herstellerdokumentation, Release Notes, Sicherheitsmeldungen und die internen Betriebsstandards. ForgeOne ergänzt diese Quellen mit praktischer Projekterfahrung aus Planung, Umsetzung und Betrieb.

### Automation mit ForgeOne planen

Wir helfen dabei, aus einzelnen Playbooks eine wartbare Rollenbibliothek, CI/CD-Strecke oder AWX/AAP-Plattform zu machen.

- [Automation besprechen](https://forgeone.solutions/de/automation-integration)

## Produktionscheckliste

- Ziel, Scope und Verantwortlichkeiten sind dokumentiert.
- DNS, TLS, Netzwerk, Accounts und Berechtigungen sind geprüft.
- Installation oder Änderung wurde mit UI- und CLI-Signalen validiert.
- Backup, Monitoring, Updates und Rollback sind vor produktiver Nutzung geklärt.
- Lizenzen, Supportwege und Professional Services sind für den Betrieb eingeplant.

## Titelbild

[![Ansible Logo](https://forgeone.solutions/media/Ansible_Logo.webp)](https://forgeone.solutions/media/Ansible_Logo.webp)

## Autor

Mathias Rumbold

## Kategorie

- [Ansible & Automation](https://forgeone.solutions/de/tech/ansible-installieren-und-erste-playbooks-erstellen?category=ansible-automation)

## Tags

- [Ansible](https://forgeone.solutions/de/tech/ansible-installieren-und-erste-playbooks-erstellen?tags=ansible)
- [Automation](https://forgeone.solutions/de/tech/ansible-installieren-und-erste-playbooks-erstellen?tags=automation)
- [Linux](https://forgeone.solutions/de/tech/ansible-installieren-und-erste-playbooks-erstellen?tags=linux)
- [Python](https://forgeone.solutions/de/tech/ansible-installieren-und-erste-playbooks-erstellen?tags=python)
- [Git](https://forgeone.solutions/de/tech/ansible-installieren-und-erste-playbooks-erstellen?tags=git)

## Ansible Automation Schritt für Schritt

Die Reihe bleibt bewusst generisch: Ansible-Grundlagen, Repository-Struktur, Rollen, Vault, Linux-Baselines, Updates, Qualitätssicherung, CI und AWX. Fachthemen wie IdM, FreeIPA, Proxmox oder SUSE Multi-Linux Manager werden in den jeweiligen Spezialreihen behandelt.

1. [Ansible installieren und erste Playbooks erstellen (aktueller Teil)](https://forgeone.solutions/de/tech/ansible-installieren-und-erste-playbooks-erstellen)
2. [Ansible Inventories, Rollen und Vault in der Praxis](https://forgeone.solutions/de/tech/ansible-inventories-rollen-vault-linux-systeme-reproduzierbar-verwalten)
3. [Linux-Baseline mit Ansible ausrollen](https://forgeone.solutions/de/tech/ansible-linux-baseline-pakete-dienste-ssh-abnahme)
4. [Updates, Reboots und Wartungsfenster mit Ansible orchestrieren](https://forgeone.solutions/de/tech/ansible-updates-reboots-wartungsfenster-orchestrieren)
5. [Ansible-Rollen testen, linten und in CI prüfen](https://forgeone.solutions/de/tech/ansible-rollen-testen-linten-ci-pruefen)
6. [Ansible-Repositories versionieren, releasen und nachvollziehbar ändern](https://forgeone.solutions/de/tech/ansible-repositories-versionieren-releasen-nachvollziehbar-aendern)
7. [AWX für wiederholbare Ausführung, Credentials und Job Templates einordnen](https://forgeone.solutions/de/tech/awx-ansible-jobs-credentials-job-templates-einordnen)

## Weiterführende Inhalte

- [OpenTofu](https://forgeone.solutions/de/produkte/opentofu)
- [Argo CD für GitOps und Kubernetes Deployments](https://forgeone.solutions/de/produkte/argo-cd)
