Sich bei Dutzenden von Servern einzeln anzumelden, um Pakete zu installieren, Konfigurationsdateien zu bearbeiten und Dienste neu zu starten, ist muehsam und fehleranfaellig. Ein vergessener Schritt auf einem Server fuehrt zu Konfigurationsabweichungen, und ploetzlich verhalten sich Ihre “identischen” Server unterschiedlich. Ansible loest dieses Problem, indem es Ihnen ermoeglicht, Ihre gesamte Serverkonfiguration in einfachen YAML-Dateien zu definieren und sie mit einem einzigen Befehl konsistent auf Hunderte von Maschinen anzuwenden. Da Ansible agentenlos ist und ueber SSH kommuniziert, muss auf Ihren verwalteten Servern nichts installiert werden — wenn Sie sich per SSH mit einem Host verbinden koennen, kann Ansible ihn verwalten.
Was ist Ansible?
Ansible ist ein Open-Source-Automatisierungstool von Red Hat, das Serverkonfiguration, Anwendungsbereitstellung und Orchestrierung verwaltet. Im Gegensatz zu Tools, die einen dedizierten Agent auf jedem verwalteten Server erfordern, verwendet Ansible SSH, um sich mit entfernten Hosts zu verbinden und Aufgaben auszufuehren.
Wesentliche Merkmale:
- Agentenlos — Keine Software auf verwalteten Knoten zu installieren oder zu warten. Ansible nutzt bestehende SSH-Verbindungen
- Push-basiert — Der Steuerknoten uebertraegt Konfigurationen bei Bedarf an die verwalteten Hosts, anstatt dass Hosts einen zentralen Server abfragen
- Idempotent — Die mehrfache Ausfuehrung eines Playbooks erzeugt dasselbe Ergebnis. Ansible prueft den aktuellen Zustand, bevor Aenderungen vorgenommen werden
- YAML-basiert — Playbooks werden in menschenlesbarem YAML geschrieben und sind damit fuer jeden zugaenglich, der eine Konfigurationsdatei lesen kann
- Erweiterbar — Tausende integrierter Module zur Verwaltung von Paketen, Dateien, Diensten, Cloud-Ressourcen und mehr
Wie Ansible funktioniert
Ansible folgt einem einfachen Ausfuehrungsmodell:
- Sie schreiben ein Playbook (YAML-Datei), das den gewuenschten Zustand Ihrer Server beschreibt
- Sie definieren ein Inventar, das auflistet, welche Hosts verwaltet werden sollen
- Sie fuehren
ansible-playbookaus, und Ansible verbindet sich ueber SSH mit jedem Host - Ansible uebertraegt kleine Programme namens Module auf den entfernten Host
- Die Module werden ausgefuehrt, setzen den gewuenschten Zustand durch und melden das Ergebnis zurueck
- Ansible entfernt die Module und zeigt eine Zusammenfassung an
Kein Daemon laeuft auf den verwalteten Hosts. Keine Datenbank verfolgt den Zustand. Jede Playbook-Ausfuehrung ist in sich abgeschlossen.
Voraussetzungen
Stellen Sie vor dem Start sicher, dass Sie Folgendes haben:
- Einen Ubuntu 22.04 oder 24.04-Rechner als Steuerknoten (auf dem Ansible laeuft)
- Einen oder mehrere Zielserver, die ueber SSH erreichbar sind
- SSH-Schluesselauthentifizierung, die zwischen Steuerknoten und verwalteten Hosts konfiguriert ist
- Python 3 auf allen verwalteten Knoten installiert (auf den meisten Linux-Distributionen vorinstalliert)
- Ein Benutzerkonto mit sudo-Berechtigungen auf den verwalteten Hosts
Tipp: Wenn Sie die SSH-Schluesselauthentifizierung noch nicht eingerichtet haben, folgen Sie unserem SSH-Haertungsleitfaden, um einen sicheren schluesselbasierten Zugang einzurichten, bevor Sie fortfahren.
Ansible auf Ubuntu installieren
Mit dem System-Paketmanager
sudo apt update
sudo apt install ansible -y
Mit pip (empfohlen fuer die neueste Version)
sudo apt install python3-pip python3-venv -y
python3 -m venv ~/ansible-venv
source ~/ansible-venv/bin/activate
pip install ansible
Installation ueberpruefen
ansible --version
Sie sollten eine Ausgabe mit der Ansible-Version, dem Konfigurationsdateipfad und der Python-Version sehen:
ansible [core 2.16.x]
config file = /etc/ansible/ansible.cfg
configured module search path = ['/home/user/.ansible/plugins/modules']
python version = 3.12.x
Inventardateien
Das Inventar teilt Ansible mit, welche Hosts verwaltet werden sollen. Sie koennen Inventare im INI- oder YAML-Format schreiben.
INI-Format (einfach)
# inventory.ini
[webservers]
web1.example.com
web2.example.com
192.168.1.50
[dbservers]
db1.example.com ansible_port=2222
db2.example.com
[loadbalancers]
lb1.example.com
[production:children]
webservers
dbservers
loadbalancers
[all:vars]
ansible_user=deployer
ansible_ssh_private_key_file=~/.ssh/id_ed25519
YAML-Format
# inventory.yml
all:
vars:
ansible_user: deployer
ansible_ssh_private_key_file: ~/.ssh/id_ed25519
children:
webservers:
hosts:
web1.example.com:
web2.example.com:
192.168.1.50:
dbservers:
hosts:
db1.example.com:
ansible_port: 2222
db2.example.com:
loadbalancers:
hosts:
lb1.example.com:
production:
children:
webservers:
dbservers:
loadbalancers:
Konnektivitaet testen
Ueberpruefen Sie, ob Ansible alle Hosts erreichen kann:
ansible all -m ping -i inventory.ini
Erwartete Ausgabe bei erfolgreicher Verbindung:
web1.example.com | SUCCESS => {
"changed": false,
"ping": "pong"
}
Ihr erstes Playbook
Ein Playbook ist eine YAML-Datei, die ein oder mehrere “Plays” enthaelt. Jedes Play zielt auf eine Gruppe von Hosts ab und definiert auszufuehrende Aufgaben.
Nginx installieren und konfigurieren
# site.yml
---
- name: Webserver konfigurieren
hosts: webservers
become: true
tasks:
- name: Apt-Cache aktualisieren
apt:
update_cache: true
cache_valid_time: 3600
- name: Nginx installieren
apt:
name: nginx
state: present
- name: Nginx-Konfiguration kopieren
copy:
src: files/nginx.conf
dest: /etc/nginx/sites-available/default
owner: root
group: root
mode: "0644"
notify: Nginx neu starten
- name: Nginx-Seite aktivieren
file:
src: /etc/nginx/sites-available/default
dest: /etc/nginx/sites-enabled/default
state: link
notify: Nginx neu starten
- name: Sicherstellen, dass nginx laeuft und aktiviert ist
service:
name: nginx
state: started
enabled: true
handlers:
- name: Nginx neu starten
service:
name: nginx
state: restarted
Playbook ausfuehren:
ansible-playbook -i inventory.ini site.yml
Mit ausfuehrlicher Ausgabe zum Debuggen ausfuehren:
ansible-playbook -i inventory.ini site.yml -v
Einen Trockenlauf durchfuehren, um zu sehen, was sich aendern wuerde, ohne es anzuwenden:
ansible-playbook -i inventory.ini site.yml --check --diff
Ansible-Module
Module sind die Arbeitseinheiten in Ansible. Jedes Modul bearbeitet eine bestimmte Aufgabe. Hier sind die am haeufigsten verwendeten Module:
Paketverwaltung (apt)
- name: Mehrere Pakete installieren
apt:
name:
- nginx
- curl
- ufw
- fail2ban
state: present
update_cache: true
- name: Ein Paket entfernen
apt:
name: apache2
state: absent
purge: true
Dienstverwaltung (service)
- name: Einen Dienst starten und aktivieren
service:
name: nginx
state: started
enabled: true
- name: Einen Dienst neu starten
service:
name: mysql
state: restarted
Dateiverwaltung (copy, template, file)
- name: Eine Datei auf den entfernten Host kopieren
copy:
src: files/app.conf
dest: /etc/app/app.conf
owner: www-data
group: www-data
mode: "0644"
- name: Ein Template mit Variablen bereitstellen
template:
src: templates/vhost.conf.j2
dest: /etc/nginx/sites-available/myapp.conf
owner: root
group: root
mode: "0644"
- name: Ein Verzeichnis erstellen
file:
path: /var/www/myapp
state: directory
owner: www-data
group: www-data
mode: "0755"
Befehlsausfuehrung (command, shell)
- name: Einen Befehl ausfuehren
command: /usr/bin/myapp --init
args:
creates: /var/lib/myapp/initialized
- name: Einen Shell-Befehl mit Pipes ausfuehren
shell: cat /var/log/syslog | grep error | wc -l
register: error_count
changed_when: false
Benutzerverwaltung (user)
- name: Einen Deploy-Benutzer erstellen
user:
name: deployer
groups: sudo,www-data
shell: /bin/bash
create_home: true
state: present
- name: Autorisierten SSH-Schluessel hinzufuegen
authorized_key:
user: deployer
key: "{{ lookup('file', '~/.ssh/id_ed25519.pub') }}"
state: present
Variablen und Facts
Variablen machen Ihre Playbooks flexibel und wiederverwendbar. Ansible unterstuetzt mehrere Variablenquellen.
Variablen in Playbooks definieren
---
- name: Anwendung bereitstellen
hosts: webservers
become: true
vars:
app_name: myapp
app_port: 8080
app_user: www-data
packages:
- nginx
- python3
- python3-pip
tasks:
- name: Erforderliche Pakete installieren
apt:
name: "{{ packages }}"
state: present
- name: App-Verzeichnis erstellen
file:
path: "/var/www/{{ app_name }}"
state: directory
owner: "{{ app_user }}"
mode: "0755"
Gruppenvariablen und Hostvariablen
Erstellen Sie Verzeichnisse fuer gruppen- und hostspezifische Variablen:
project/
inventory.ini
group_vars/
all.yml
webservers.yml
dbservers.yml
host_vars/
web1.example.com.yml
db1.example.com.yml
playbook.yml
# group_vars/webservers.yml
http_port: 80
https_port: 443
document_root: /var/www/html
max_workers: 4
# host_vars/web1.example.com.yml
server_name: web1.example.com
ssl_certificate: /etc/ssl/certs/web1.pem
Facts sammeln
Ansible sammelt automatisch Systemfacts (Betriebssystem, IP-Adressen, Arbeitsspeicher, Festplatten) von verwalteten Hosts. Verwenden Sie sie in Templates und Bedingungen:
- name: Systeminformationen anzeigen
debug:
msg: >
Hostname: {{ ansible_hostname }},
OS: {{ ansible_distribution }} {{ ansible_distribution_version }},
IP: {{ ansible_default_ipv4.address }},
RAM: {{ ansible_memtotal_mb }} MB
- name: Pakete basierend auf dem OS installieren
apt:
name: nginx
state: present
when: ansible_os_family == "Debian"
- name: Pakete auf Red Hat installieren
yum:
name: nginx
state: present
when: ansible_os_family == "RedHat"
Handler und Benachrichtigungen
Handler sind spezielle Aufgaben, die nur ausgefuehrt werden, wenn sie von einer anderen Aufgabe benachrichtigt werden. Sie werden am Ende eines Plays ausgeloest, nachdem alle regulaeren Aufgaben abgeschlossen sind. Dies verhindert unnoetige Dienstneustarts.
---
- name: Webserver konfigurieren
hosts: webservers
become: true
tasks:
- name: Nginx installieren
apt:
name: nginx
state: present
- name: Nginx-Hauptkonfiguration bereitstellen
template:
src: templates/nginx.conf.j2
dest: /etc/nginx/nginx.conf
notify:
- Nginx-Konfiguration validieren
- Nginx neu starten
- name: Virtuellen Host bereitstellen
template:
src: templates/vhost.conf.j2
dest: /etc/nginx/sites-available/{{ domain }}.conf
notify:
- Nginx-Konfiguration validieren
- Nginx neu starten
- name: Virtuellen Host aktivieren
file:
src: /etc/nginx/sites-available/{{ domain }}.conf
dest: /etc/nginx/sites-enabled/{{ domain }}.conf
state: link
notify:
- Nginx-Konfiguration validieren
- Nginx neu starten
handlers:
- name: Nginx-Konfiguration validieren
command: nginx -t
listen: "Nginx-Konfiguration validieren"
- name: Nginx neu starten
service:
name: nginx
state: restarted
listen: "Nginx neu starten"
Obwohl drei Aufgaben die Handler benachrichtigen, wird Nginx neu starten nur einmal am Ende des Plays ausgefuehrt.
Rollen und Verzeichnisstruktur
Rollen organisieren Ihre Playbooks in wiederverwendbare, teilbare Komponenten. Jede Rolle kapselt Aufgaben, Handler, Variablen, Templates und Dateien fuer eine bestimmte Funktion.
Eine Rolle erstellen
ansible-galaxy init roles/webserver
Dies erzeugt die folgende Struktur:
roles/
webserver/
tasks/
main.yml
handlers/
main.yml
templates/
files/
vars/
main.yml
defaults/
main.yml
meta/
main.yml
Rollenaufgaben
# roles/webserver/tasks/main.yml
---
- name: Nginx installieren
apt:
name: nginx
state: present
update_cache: true
- name: Nginx-Konfiguration bereitstellen
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
notify: Nginx neu starten
- name: Virtuellen Host bereitstellen
template:
src: vhost.conf.j2
dest: "/etc/nginx/sites-available/{{ domain }}.conf"
notify: Nginx neu starten
- name: Virtuellen Host aktivieren
file:
src: "/etc/nginx/sites-available/{{ domain }}.conf"
dest: "/etc/nginx/sites-enabled/{{ domain }}.conf"
state: link
notify: Nginx neu starten
- name: Standard-Virtual-Host entfernen
file:
path: /etc/nginx/sites-enabled/default
state: absent
notify: Nginx neu starten
- name: Sicherstellen, dass nginx laeuft
service:
name: nginx
state: started
enabled: true
Rollen-Handler
# roles/webserver/handlers/main.yml
---
- name: Nginx neu starten
service:
name: nginx
state: restarted
Rollen-Standardwerte
# roles/webserver/defaults/main.yml
---
domain: example.com
http_port: 80
https_port: 443
document_root: /var/www/html
worker_processes: auto
worker_connections: 1024
Rollen in einem Playbook verwenden
# site.yml
---
- name: Infrastruktur konfigurieren
hosts: webservers
become: true
roles:
- role: webserver
vars:
domain: knowledgexchange.xyz
- role: security
- role: monitoring
Praktische Beispiele
LAMP-Stack-Bereitstellung
# lamp.yml
---
- name: LAMP-Stack bereitstellen
hosts: webservers
become: true
vars:
mysql_root_password: "{{ vault_mysql_root_password }}"
php_version: "8.3"
tasks:
- name: Apache und PHP installieren
apt:
name:
- apache2
- libapache2-mod-php{{ php_version }}
- php{{ php_version }}
- php{{ php_version }}-mysql
- php{{ php_version }}-curl
- php{{ php_version }}-xml
- php{{ php_version }}-mbstring
state: present
update_cache: true
- name: MySQL-Server installieren
apt:
name: mysql-server
state: present
- name: MySQL starten und aktivieren
service:
name: mysql
state: started
enabled: true
- name: Apache starten und aktivieren
service:
name: apache2
state: started
enabled: true
- name: PHP-Info-Seite zum Testen bereitstellen
copy:
content: "<?php phpinfo(); ?>"
dest: /var/www/html/info.php
owner: www-data
group: www-data
mode: "0644"
Benutzerverwaltung ueber alle Server
# users.yml
---
- name: Benutzerkonten verwalten
hosts: all
become: true
vars:
admin_users:
- name: jcarlos
key: "ssh-ed25519 AAAAC3Nza... jcarlos@workstation"
groups: sudo,adm
- name: deployer
key: "ssh-ed25519 AAAAC3Nza... deployer@ci"
groups: www-data
removed_users:
- oldadmin
- tempuser
tasks:
- name: Admin-Benutzer erstellen
user:
name: "{{ item.name }}"
groups: "{{ item.groups }}"
shell: /bin/bash
create_home: true
state: present
loop: "{{ admin_users }}"
- name: SSH-Schluessel fuer Admin-Benutzer hinzufuegen
authorized_key:
user: "{{ item.name }}"
key: "{{ item.key }}"
exclusive: true
loop: "{{ admin_users }}"
- name: Alte Benutzer entfernen
user:
name: "{{ item }}"
state: absent
remove: true
loop: "{{ removed_users }}"
Sicherheitshaertung
# harden.yml
---
- name: Sicherheitshaertung
hosts: all
become: true
tasks:
- name: Sicherheitspakete installieren
apt:
name:
- ufw
- fail2ban
- unattended-upgrades
state: present
update_cache: true
- name: UFW-Standardrichtlinien konfigurieren
ufw:
direction: incoming
policy: deny
- name: SSH ueber UFW erlauben
ufw:
rule: allow
port: "2222"
proto: tcp
- name: HTTP und HTTPS erlauben
ufw:
rule: allow
port: "{{ item }}"
proto: tcp
loop:
- "80"
- "443"
- name: UFW aktivieren
ufw:
state: enabled
- name: Fail2ban-Konfiguration bereitstellen
copy:
src: files/jail.local
dest: /etc/fail2ban/jail.local
notify: Fail2ban neu starten
- name: Automatische Sicherheitsupdates aktivieren
copy:
content: |
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
APT::Periodic::AutocleanInterval "7";
dest: /etc/apt/apt.conf.d/20auto-upgrades
- name: SSH-Root-Anmeldung deaktivieren
lineinfile:
path: /etc/ssh/sshd_config
regexp: "^PermitRootLogin"
line: "PermitRootLogin no"
notify: Sshd neu starten
handlers:
- name: Fail2ban neu starten
service:
name: fail2ban
state: restarted
- name: Sshd neu starten
service:
name: sshd
state: restarted
Ansible Vault fuer Geheimnisse
Speichern Sie Passwoerter oder API-Schluessel niemals im Klartext. Ansible Vault verschluesselt sensible Daten:
# Eine verschluesselte Variablendatei erstellen
ansible-vault create group_vars/all/vault.yml
# Eine verschluesselte Datei bearbeiten
ansible-vault edit group_vars/all/vault.yml
# Eine bestehende Datei verschluesseln
ansible-vault encrypt secrets.yml
# Ein Playbook mit Vault ausfuehren
ansible-playbook site.yml --ask-vault-pass
# Stattdessen eine Passwortdatei verwenden
ansible-playbook site.yml --vault-password-file ~/.vault_pass
Versehen Sie sensible Variablen in der Vault-Datei mit dem Praefix vault_:
# group_vars/all/vault.yml (verschluesselt)
vault_mysql_root_password: "s3cur3P@ssw0rd"
vault_api_key: "abc123def456"
vault_ssl_private_key: |
-----BEGIN PRIVATE KEY-----
...
-----END PRIVATE KEY-----
Referenzieren Sie Vault-Variablen in Ihrer regulaeren Variablendatei:
# group_vars/all/vars.yml
mysql_root_password: "{{ vault_mysql_root_password }}"
api_key: "{{ vault_api_key }}"
Fehlerbehebung
SSH-Verbindungsfehler
# SSH-Konnektivitaet manuell testen
ssh -i ~/.ssh/id_ed25519 deployer@web1.example.com
# Im ausfuehrlichen Modus ausfuehren, um SSH-Details zu sehen
ansible all -m ping -i inventory.ini -vvvv
# Pruefen, ob Python auf dem entfernten Host verfuegbar ist
ansible all -m raw -a "python3 --version" -i inventory.ini
Zugriffsverweigerungsfehler
# Sicherstellen, dass become (sudo) konfiguriert ist
ansible-playbook site.yml -i inventory.ini --become --ask-become-pass
# Sudo-Konfiguration auf dem entfernten Host pruefen
ssh deployer@web1.example.com "sudo -l"
Modul-nicht-gefunden-Fehler
# Alle verfuegbaren Module auflisten
ansible-doc -l | grep apt
# Dokumentation fuer ein bestimmtes Modul anzeigen
ansible-doc apt
# Ansible-Version fuer Modulkompatibilitaet pruefen
ansible --version
Playbook-Syntaxfehler
# Playbook-Syntax ohne Ausfuehrung validieren
ansible-playbook site.yml --syntax-check
# Playbook auf Best Practices pruefen
pip install ansible-lint
ansible-lint site.yml
Aufgabenausgabe debuggen
- name: Befehl ausfuehren und Ausgabe erfassen
command: systemctl status nginx
register: nginx_status
ignore_errors: true
- name: Ausgabe anzeigen
debug:
var: nginx_status.stdout_lines
Referenz der wichtigsten Befehle
| Befehl | Beschreibung |
|---|---|
ansible --version | Ansible-Version und Konfiguration anzeigen |
ansible all -m ping -i inventory.ini | Konnektivitaet zu allen Hosts testen |
ansible all -m setup -i inventory.ini | Host-Facts sammeln und anzeigen |
ansible webservers -m apt -a "name=nginx state=present" -i inventory.ini --become | Nginx auf Webservern per Ad-hoc-Befehl installieren |
ansible-playbook site.yml -i inventory.ini | Ein Playbook ausfuehren |
ansible-playbook site.yml --check --diff | Trockenlauf mit Diff-Ausgabe |
ansible-playbook site.yml --limit web1.example.com | Playbook auf einem einzelnen Host ausfuehren |
ansible-playbook site.yml --tags "nginx,security" | Nur Aufgaben mit bestimmten Tags ausfuehren |
ansible-playbook site.yml --start-at-task "Install nginx" | Playbook ab einer bestimmten Aufgabe fortsetzen |
ansible-vault create secrets.yml | Eine neue verschluesselte Datei erstellen |
ansible-vault edit secrets.yml | Eine verschluesselte Datei bearbeiten |
ansible-galaxy init roles/myrole | Eine neue Rollenverzeichnisstruktur erstellen |
ansible-galaxy install geerlingguy.nginx | Eine Rolle aus Ansible Galaxy installieren |
ansible-inventory -i inventory.ini --graph | Inventar-Hostgraph anzeigen |
ansible-doc apt | Moduldokumentation anzeigen |
Zusammenfassung
Ansible bietet einen leistungsstarken und zugleich zugaenglichen Weg zur Infrastrukturautomatisierung. Die agentenlose Architektur bedeutet, dass Sie sofort mit der Automatisierung beginnen koennen — wenn Sie sich per SSH mit Ihren Servern verbinden koennen, koennen Sie sie mit Ansible verwalten. Beginnen Sie mit einfachen Ad-hoc-Befehlen, steigen Sie zu Playbooks fuer wiederholbare Aufgaben auf und organisieren Sie komplexe Konfigurationen in Rollen. Die Kombination aus YAML-Lesbarkeit, idempotenter Ausfuehrung und Tausenden integrierter Module macht Ansible zum bevorzugten Werkzeug fuer die Konfigurationsverwaltung in Linux- und Windows-Umgebungen.
Fuer die Bereitstellung der Infrastruktur selbst — das Erstellen von Cloud-Servern, Netzwerken und DNS-Eintraegen vor deren Konfiguration — erkunden Sie unseren Terraform Infrastructure-as-Code-Leitfaden. Um sicherzustellen, dass die von Ansible verwalteten Server von Anfang an sicher sind, folgen Sie unserem SSH-Haertungsleitfaden, um den Fernzugriff mit schluesselbasierter Authentifizierung, fail2ban und Firewall-Regeln abzusichern.