Ansible: Kennenlernen und effektiv einsetzen

Navigation

Stell dir vor, du müsstest 100 Server manuell konfigurieren – ein zeitraubender und fehleranfälliger Prozess. Ansible ist wie ein zuverlässiger Assistent, der diese Aufgaben automatisch und zuverlässig für dich erledigt. In diesem Guide lernst du Schritt für Schritt, wie du Ansible einrichtest und effektiv nutzt.

Was ist Ansible?

Ansible ist eine Open-Source-Software zur Automatisierung der Konfiguration und Verwaltung von IT-Infrastruktur und -Anwendungen. Dieser Kurs vermittelt Ihnen die wichtigsten Kenntnisse zu diesem leistungsfähigen Tool.

Wie Ansible arbeitet
Markdown
[Control Node] ─────> [Managed Node 1]

      ├─────────────> [Managed Node 2]

      └─────────────> [Managed Node 3]

Control Node: Wo Ansible installiert ist
Managed Nodes: Die Systeme, die du verwaltest
Ansible vs. andere Tools
FeatureAnsiblePuppetChef
Agentless
Einfache Syntax⚠️⚠️
LernkurveFlachSteilSteil
SSH-basiert
Grundlegende Konzepte
Markdown
[Ansible-Struktur]

      ├── [Inventory] (Wo?)
      │   └── Liste der Managed Nodes

      ├── [Playbooks] (Was?)
      │   └── Automation-Rezepte

      └── [Module] (Wie?)
          └── Die Werkzeuge

⚠️ WICHTIG ZU WISSEN:

  • Ansible ist agentlos (keine Installation auf Zielservern nötig)
  • Verwendet SSH für die Verbindung
  • Arbeitet idempotent (wiederholbar, ohne Nebenwirkungen)
  • Verwendet YAML für die Konfiguration

Voraussetzungen und Installation

Hinweis: In diesem Artikel verwenden wir Ubuntu als Beispiel-Distribution. Die grundlegenden Konzepte sind auf allen Linux-Systemen gleich, aber die Installation von Paketen und einige Konfigurationspfade können sich je nach Distribution unterscheiden. Wenn du eine andere Distribution verwendest, konsultiere bitte die entsprechende Dokumentation für die spezifischen Installationsbefehle und Pfade.
Was brauchen wir?

Bevor wir mit Ansible loslegen, müssen wir sicherstellen, dass unser System alle Voraussetzungen erfüllt.

Systemanforderungen

Für den Control Node (dein Ubuntu-System):

Markdown
[Control Node]
├── Ubuntu 24.04 LTS
├── Python 3.x
├── SSH-Client
└── Internetverbindung

Für die Managed Nodes (Zielserver):

Markdown
[Managed Nodes]
├── SSH-Server
├── Python 3.x
└── Sudo-Rechte

Installation

System aktualisieren:
Bash
# Paketquellen aktualisieren
sudo apt update

# System upgraden
sudo apt upgrade -y
Ansible installieren:
Bash
# Benötigte Pakete installieren
sudo apt install software-properties-common

# Ansible Repository hinzufügen
sudo add-apt-repository --yes --update ppa:ansible/ansible

# Ansible installieren
sudo apt install ansible
Installation überprüfen:
Bash
# Version prüfen
ansible --version

Du solltest eine Ausgabe wie diese sehen:

ShellScript
ansible [core 2.14.x]
  config file = /etc/ansible/ansible.cfg
  configured module search path = [...]
  ansible python module location = [...]
  ansible collection location = [...]
  executable location = /usr/bin/ansible
  python version = 3.10.x

SSH-Konfiguration

SSH-Key erstellen:
Bash
# Key generieren
ssh-keygen -t ed25519 -C "ansible"
Markdown
[SSH-Key erstellen]
├── Speicherort bestätigen (Enter)
├── Passwort eingeben (optional)
└── Key wird generiert
Key auf Zielserver kopieren:
Bash
# Key kopieren
ssh-copy-id benutzer@zielserver

⚠️ WICHTIGE HINWEISE:

  • Verwende starke Passwörter
  • Sichere deine SSH-Keys
  • Notiere dir die Zugangsdaten
  • Prüfe die Verbindung

Ansible-Struktur

Wie ist Ansible aufgebaut?

Bevor wir mit den ersten Befehlen starten, lass uns verstehen, wie Ansible strukturiert ist. Denk an Ansible wie an ein Kochbuch: Das Inventory sind deine Zutaten, die Playbooks deine Rezepte, und die Module sind deine Küchenwerkzeuge.

Die Grundstruktur eines Ansible-Projekts
Markdown
ansible-projekt/
├── ansible.cfg           # Konfigurationsdatei
├── inventory/            # Verzeichnis für Inventare
│   ├── production        # Produktionsserver
│   └── staging           # Testserver
├── group_vars/           # Gruppenvariablen
│   └── all.yml           # Gilt für alle Gruppen
├── host_vars/            # Host-spezifische Variablen
│   └── webserver1.yml    # Gilt für einzelnen Host
└── playbooks/            # Deine Automation-Rezepte
    └── webserver.yml     # Beispiel-Playbook

Grundstruktur und Erste Schritte

1. Projekt-Verzeichnis anlegen:
Bash
# Verzeichnisstruktur erstellen
mkdir -p ansible-projekt/{inventory,group_vars,host_vars,playbooks}
cd ansible-projekt
2. Ansible-Konfiguration erstellen:
Bash
# ansible.cfg
[defaults]
inventory = ./inventory/staging
remote_user = dein_benutzer
host_key_checking = False
3. Erstes Inventory erstellen:
Bash
# inventory/staging
[webserver]
webserver1 ansible_host=192.168.1.10
webserver2 ansible_host=192.168.1.11

[database]
db1 ansible_host=192.168.1.20

[all:vars]
ansible_python_interpreter=/usr/bin/python3

Erste Schritte

1. Verbindung testen:
Bash
# Alle Hosts pingen
ansible all -m ping

# Ausgabe sollte so aussehen:
webserver1 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
2. System-Informationen abrufen:
Bash
# Details über die Systeme erhalten
ansible all -m setup | grep ansible_distribution

# Zeigt Betriebssystem-Details

⚠️ WICHTIGE HINWEISE:

  • Stelle sicher, dass SSH-Zugriff auf alle Hosts möglich ist
  • Python muss auf allen Zielservern installiert sein
  • Rechte müssen korrekt gesetzt sein
  • Firewall-Regeln müssen SSH erlauben

Dein erstes Playbook erstellen

Playbooks – Die Automation-Rezepte

Ein Playbook ist wie ein Rezept – es beschreibt Schritt für Schritt, was auf den Zielservern passieren soll. Lass uns ein einfaches Playbook erstellen, das einen Webserver installiert.

Playbook-Struktur
Markdown
[Playbook]

    ├── Name (Was macht es?)
    ├── Hosts (Wo läuft es?)
    ├── Become (Root-Rechte?)
    └── Tasks (Was sind die Schritte?)
         └── Module (Wie wird's gemacht?)

Erstes Playbook erstellen

1. Datei anlegen:
Bash
# Im Projekt-Verzeichnis
cd playbooks
nano webserver.yml
2. Playbook schreiben:
Bash
---
- name: Apache install and start
  hosts: webserver
  become: yes
  tasks:
    - name: Install Apache
      apt:
        name: apache2
        state: latest
        update_cache: yes

    - name: Ensure Apache is running
      service:
        name: apache2
        state: started
        enabled: yes

    - name: Allow Apache through firewall
      ufw:
        rule: allow
        port: 80
        proto: tcp

Playbook verstehen

Was macht jeder Teil?
Markdown
[name: Apache install and start]
└── Beschreibender Name des Playbooks

[hosts: webserver]
└── Läuft auf Hosts in der Gruppe "webserver"

[become: yes]
└── Führt Befehle mit Root-Rechten aus

[tasks:]
├── Install Apache
│   └── Installiert das Paket
├── Ensure Apache is running
│   └── Startet den Dienst
└── Allow Apache through firewall
    └── Öffnet Port 80

Playbook ausführen

1. Syntax prüfen:
Bash
# Prüft, ob das Playbook valide ist
ansible-playbook webserver.yml --syntax-check
2. Testlauf (Dry-Run):
Bash
# Zeigt, was passieren würde
ansible-playbook webserver.yml --check
3. Tatsächliche Ausführung:
Bash
# Führt das Playbook aus
ansible-playbook webserver.yml

Die Ausgabe sollte etwa so aussehen:

Bash
PLAY [Apache install and start] ************

TASK [Install Apache] *********************
changed: [webserver1]
changed: [webserver2]

TASK [Ensure Apache is running] ***********
ok: [webserver1]
ok: [webserver2]

TASK [Allow Apache through firewall] ******
changed: [webserver1]
changed: [webserver2]

PLAY RECAP *******************************
webserver1 : ok=3 changed=2 unreachable=0 failed=0
webserver2 : ok=3 changed=2 unreachable=0 failed=0

⚠️ WICHTIGE HINWEISE:

  • Playbooks sind idempotent (mehrfache Ausführung ist sicher)
  • Reihenfolge der Tasks ist wichtig
  • Einrückung in YAML muss stimmen
  • Fehler werden sofort angezeigt

Erweiterte Playbook-Funktionen

Fortgeschrittene Ansible-Funktionen

Jetzt, wo wir die Grundlagen verstehen, schauen wir uns die erweiterten Funktionen an, die Ansible so mächtig machen.

Handlers

Handler sind spezielle Tasks, die nur ausgeführt werden, wenn sie durch eine Änderung ausgelöst werden:

ShellScript
---
- name: Apache Configuration
  hosts: webserver
  become: yes
  tasks:
    - name: Copy Apache config
      template:
        src: apache.conf.j2
        dest: /etc/apache2/apache2.conf
        mode: '0644'
      notify: Restart Apache

  handlers:
    - name: Restart Apache
      service:
        name: apache2
        state: restarted
Markdown
[Task] ──> [Änderung?] ──> [Handler]

           └── Nein ─────> [Weiter]

Variablen und Templates

1. Variablen definieren:
Bash
---
- name: Webserver Setup
  hosts: webserver
  become: yes
  vars:
    web_root: "/var/www/html"
    server_name: "example.com"
    max_clients: 150
2. Jinja2 Template (apache.conf.j2):
Bash
ServerName {{ server_name }}
DocumentRoot {{ web_root }}
MaxClients {{ max_clients }}

Bedingungen (Conditionals)

Bash
---
- name: Conditional Tasks
  hosts: all
  tasks:
    - name: Install Apache on Ubuntu
      apt:
        name: apache2
        state: present
      when: ansible_distribution == "Ubuntu"

    - name: Install Apache on CentOS
      yum:
        name: httpd
        state: present
      when: ansible_distribution == "CentOS"

Loops

1. Einfache Schleife:
Bash
- name: Create Users
  user:
    name: "{{ item }}"
    state: present
  loop:
    - john
    - jane
    - bob
2. Komplexere Schleife:
Bash
- name: Create Users with Details
  user:
    name: "{{ item.name }}"
    groups: "{{ item.groups }}"
    shell: "{{ item.shell }}"
  loop:
    - { name: 'john', groups: 'admin', shell: '/bin/bash' }
    - { name: 'jane', groups: 'dev', shell: '/bin/zsh' }

⚠️ WICHTIGE HINWEISE:

  • Handler werden nur einmal am Ende ausgeführt
  • Variablen sind Case-sensitive
  • Bedingungen können verschachtelt werden
  • Loops erhöhen die Ausführungszeit

Praktische Beispiele

Reale Anwendungsfälle

Lass uns die gelernten Konzepte in praktischen Beispielen zusammenführen. Wir erstellen ein komplettes Playbook für einen LAMP-Stack (Linux, Apache, MySQL, PHP).

LAMP-Stack Installation
Bash
---
- name: LAMP Stack Setup
  hosts: webserver
  become: yes
  vars:
    mysql_root_password: "secure_password"
    app_user: "webadmin"
    app_group: "www-data"
    web_root: "/var/www/html"
    
  tasks:
    # Update System
    - name: Update apt cache
      apt:
        update_cache: yes
        cache_valid_time: 3600

    # Install Packages
    - name: Install LAMP packages
      apt:
        name: "{{ item }}"
        state: present
      loop:
        - apache2
        - mysql-server
        - php
        - php-mysql
        - python3-pymysql
      notify: Restart Apache

    # Apache Configuration
    - name: Create web root
      file:
        path: "{{ web_root }}"
        state: directory
        owner: "{{ app_user }}"
        group: "{{ app_group }}"
        mode: '0755'

    # MySQL Secure Installation
    - name: Set MySQL root password
      mysql_user:
        name: root
        password: "{{ mysql_root_password }}"
        login_unix_socket: /var/run/mysqld/mysqld.sock
        state: present

    # PHP Test File
    - name: Create PHP info page
      template:
        src: info.php.j2
        dest: "{{ web_root }}/info.php"
        mode: '0644'
      notify: Restart Apache

  handlers:
    - name: Restart Apache
      service:
        name: apache2
        state: restarted

Templates und Konfigurationen

1. PHP Info Template (info.php.j2):
PHP
<?php
phpinfo();
?>
2. Apache VHost Template (vhost.conf.j2):
Bash
<VirtualHost *:80>
    ServerAdmin webmaster@{{ server_name }}
    DocumentRoot {{ web_root }}
    ServerName {{ server_name }}

    <Directory {{ web_root }}>
        Options Indexes FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

Benutzer und Berechtigungen

Bash
---
- name: User Management
  hosts: webserver
  become: yes
  vars:
    users:
      - name: john
        groups: ['admin', 'www-data']
        shell: /bin/bash
      - name: jane
        groups: ['dev', 'www-data']
        shell: /bin/zsh

  tasks:
    - name: Create user groups
      group:
        name: "{{ item }}"
        state: present
      loop:
        - admin
        - dev
        - www-data

    - name: Create users
      user:
        name: "{{ item.name }}"
        groups: "{{ item.groups | join(',') }}"
        shell: "{{ item.shell }}"
        state: present
      loop: "{{ users }}"

    - name: Set up SSH keys
      authorized_key:
        user: "{{ item.name }}"
        key: "{{ lookup('file', 'keys/' + item.name + '.pub') }}"
      loop: "{{ users }}"

Fehlerbehandlung und Debugging

Bash
---
- name: Error Handling Example
  hosts: webserver
  become: yes
  tasks:
    - name: Check Apache status
      command: systemctl status apache2
      register: apache_status
      ignore_errors: yes

    - name: Debug Apache status
      debug:
        var: apache_status.stdout_lines
      when: apache_status.rc == 0

    - name: Handle Apache failure
      block:
        - name: Restart Apache
          service:
            name: apache2
            state: restarted
      rescue:
        - name: Log failure
          debug:
            msg: "Apache restart failed!"
      always:
        - name: Check final status
          command: systemctl status apache2

⚠️ BEST PRACTICES:

Markdown
[Playbook Organisation]
├── Variablen auslagern
├── Templates verwenden
├── Fehlerbehandlung einbauen
└── Idempotenz sicherstellen

[Sicherheit]
├── Sensitive Daten verschlüsseln
├── Berechtigungen prüfen
└── Logging aktivieren

Troubleshooting

Häufige Probleme und Lösungen
Markdown
[Problem-Kategorien]

    ├── [Verbindungsprobleme]
    ├── [Berechtigungsfehler]
    ├── [YAML-Syntax]
    └── [Modul-Fehler]
1. Verbindungsprobleme:
Bash
# Problem: SSH-Verbindung fehlgeschlagen
ansible webserver -m ping
# Fehler: "UNREACHABLE!"

# Lösung: Verbindung testen
ssh benutzer@zielserver

# Debug-Modus aktivieren
ansible webserver -m ping -vvv
2. YAML-Syntax überprüfen:
Bash
# Häufige Fehler:
- name: Falsches YAML
  apt:
  name: apache2    # Falsche Einrückung!
    state: present

# Korrektes YAML:
- name: Korrektes YAML
  apt:
    name: apache2  # Korrekte Einrückung
    state: present
Debugging-Techniken
1. Verbose-Modi:
Bash
# Verschiedene Debug-Level
ansible-playbook playbook.yml -v    # Detail
ansible-playbook playbook.yml -vv   # Mehr Details
ansible-playbook playbook.yml -vvv  # Maximale Details
2. Debug-Module verwenden:
Bash
- name: Debug Task
  debug:
    var: variable_name
    msg: "Debugging Information"
    verbosity: 2  # Nur bei -vv oder höher

Best Practices

1. Projektstruktur:
Markdown
ansible-projekt/
├── ansible.cfg
├── inventory/
│   ├── production/
│   │   ├── hosts
│   │   ├── group_vars/
│   │   └── host_vars/
│   └── staging/
├── roles/
│   ├── common/
│   ├── webserver/
│   └── database/
├── playbooks/
└── README.md
2. Variablen-Management:
Markdown
# group_vars/all.yml - Globale Variablen
---
global_var: "wert"

# group_vars/webserver.yml - Gruppen-spezifisch
---
apache_port: 80
3. Rollen-Struktur:
Markdown
roles/webserver/
├── defaults/
│   └── main.yml    # Standard-Variablen
├── handlers/
│   └── main.yml    # Handler-Definitionen
├── tasks/
│   └── main.yml    # Hauptaufgaben
├── templates/
│   └── vhost.conf.j2
└── vars/
    └── main.yml    # Rollen-Variablen

Sicherheits-Best-Practices

1. Sensitive Daten verschlüsseln
Bash
- name: Geschützter Task
  vars_files:
    - vault/secrets.yml
  tasks:
    - name: Setup Database
      mysql_user:
        name: "{{ db_user }}"
        password: "{{ db_password }}"
2. Vault verwenden:
Bash
# Verschlüsselte Datei erstellen
ansible-vault create secrets.yml

# Verschlüsselte Datei bearbeiten
ansible-vault edit secrets.yml

# Playbook mit Vault ausführen
ansible-playbook site.yml --ask-vault-pass

Performance-Optimierung

Markdown
[Performance-Tipps]
├── Parallele Ausführung
│   └── fork: 10
├── Pipelining aktivieren
│   └── pipelining = True
└── Fact-Gathering begrenzen
    └── gather_facts: no

⚠️ WICHTIGE HINWEIS

1. Dokumentation

Markdown
[Dokumentiere]
├── Playbooks
├── Variablen
├── Abhängigkeiten
└── Besonderheiten

2. Testing

Markdown
[Test-Strategie]
├── Syntax-Check
├── --check (Dry-Run)
├── Staging-Umgebung
└── Idempotenz-Test

3. Versionskontrolle

Markdown
[Git-Struktur]
├── .gitignore
├── Branches
└── Tags für Releases

Übung

Webserver-Deployment mit Ansible
Szenario: Du bist DevOps-Engineer in einem kleinen Unternehmen. Deine Aufgabe ist es, einen Webserver für das Entwicklungsteam einzurichten. Der Server soll Apache, PHP und eine einfache Testseite enthalten.
Aufgabe
  1. Erstelle ein Playbook, das:
    • Apache und PHP installiert
    • Eine individuelle index.php erstellt
    • Die Apache-Konfiguration anpasst
    • Den Dienst startet und aktiviert
  2. Verwende Variablen für:
    • Document Root
    • Server Name
    • PHP-Version
  3. Implementiere einen Handler für Apache-Neustarts
  4. Füge Basic Error Handling hinzu
Mögliche Lösung

1. Verzeichnisstruktur erstellen:

Bash
mkdir -p webserver-uebung/{playbooks,templates}
cd webserver-uebung

2. Inventory erstellen (inventory/hosts):

Bash
[webserver]
testserver ansible_host=192.168.1.10

3. Template erstellen (templates/index.php.j2):

Bash
<?php
echo "<h1>Willkommen auf {{ server_name }}</h1>";
echo "<p>PHP Version: " . phpversion() . "</p>";
echo "<p>Server Zeit: " . date('Y-m-d H:i:s') . "</p>";
?>

4. Playbook erstellen (playbooks/webserver.yml):

Bash
---
- name: Webserver Setup
  hosts: webserver
  become: yes
  vars:
    server_name: "dev.example.com"
    doc_root: "/var/www/html"
    php_version: "8.1"

  tasks:
    - name: Update apt cache
      apt:
        update_cache: yes
      register: apt_update
      ignore_errors: yes

    - name: Install required packages
      apt:
        name:
          - apache2
          - "php{{ php_version }}"
        state: present
      notify: Restart Apache

    - name: Create custom index.php
      template:
        src: templates/index.php.j2
        dest: "{{ doc_root }}/index.php"
        mode: '0644'
      notify: Restart Apache

    - name: Ensure Apache is running
      service:
        name: apache2
        state: started
        enabled: yes

  handlers:
    - name: Restart Apache
      service:
        name: apache2
        state: restarted

5. Ausführen und Testen:

Bash
# Syntax prüfen
ansible-playbook playbooks/webserver.yml --syntax-check

# Testlauf
ansible-playbook playbooks/webserver.yml --check

# Ausführen
ansible-playbook playbooks/webserver.yml
Erwartetes Ergebnis
  • Apache und PHP sind installiert
  • Eine personalisierte index.php ist verfügbar
  • Apache läuft und startet automatisch
  • Die Webseite ist über den Browser erreichbar

⚠️ Lernziele:

  • Verwendung von Templates
  • Arbeit mit Variablen
  • Handler implementieren
  • Fehlerbehandlung
  • Idempotenz verstehen

Wichtige Ressourcen

Offizielle Dokumentation und Hilfen
Nützliche Tools
Community & Support
Lern-Ressourcen

Fazit

Ansible hat sich in den letzten Jahren zu einem der wichtigsten Werkzeuge für IT-Automation entwickelt, und das aus gutem Grund. Seine agentlose Architektur, die lesbare YAML-Syntax und die breite Community-Unterstützung machen es zu einer ausgezeichneten Wahl für Einsteiger und Profis gleichermaßen.

In diesem kleinem Kurs haben wir gesehen, wie Ansible die Komplexität der Systemadministration reduziert und wiederholbare, zuverlässige Deployments ermöglicht. Von der einfachen Installation über die Erstellung von Playbooks bis hin zu fortgeschrittenen Konzepten wie Rollen und Templates – Ansible bietet für jede Automatisierungsaufgabe die passenden Werkzeuge.

Besonders wertvoll ist die Idempotenz von Ansible, die sicherstellt, dass unsere Systeme konsistent bleiben, egal wie oft wir unsere Playbooks ausführen. Dies, kombiniert mit der umfangreichen Modulbibliothek und der aktiven Community, macht Ansible zu einer zukunftssicheren Investition in die IT-Automation.

Die wahre Stärke von Ansible liegt jedoch in seiner Flexibilität:

Ob kleine Homelab-Umgebungen oder große Unternehmensinfrastrukturen, Ansible skaliert mit deinen Bedürfnissen und wächst mit deinen Anforderungen. Mit den in diesem Guide erlernten Grundlagen bist du bestens gerüstet, um deine eigenen Automatisierungsprojekte in Angriff zu nehmen und die Effizienz deiner IT-Infrastruktur zu steigern.

Kommentar verfassen