Ansible ist ein agentenloses Automatisierungstool für Konfigurationsmanagement, Deployment und Orchestrierung. Es nutzt SSH und YAML für einfache, lesbare Automatisierung.

Warum Ansible?

Vorteile

- Agentenlos (nur SSH)
- YAML-basierte Konfiguration
- Idempotent
- Push-basiert
- Große Modul-Bibliothek
- Einfache Lernkurve
- Aktive Community

Ansible vs andere Tools

| Tool | Agent | Sprache | Push/Pull | |------|-------|---------|-----------| | Ansible | Nein | Python/YAML | Push | | Puppet | Ja | Ruby/DSL | Pull | | Chef | Ja | Ruby | Pull | | Salt | Optional | Python | Beide |

Installation

Via pip (empfohlen)

pip install ansible

Debian/Ubuntu

apt install ansible

Version prüfen

ansible --version

Inventory

Einfaches Inventory

# /etc/ansible/hosts oder inventory.ini

[webserver]
web1.example.de
web2.example.de

[database]
db1.example.de
db2.example.de

[production:children]
webserver
database

Mit Variablen

[webserver]
web1.example.de ansible_user=deploy ansible_port=22
web2.example.de ansible_user=deploy

[webserver:vars]
http_port=80
max_clients=200

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

YAML-Format

# inventory.yml

all:
  children:
    webserver:
      hosts:
        web1.example.de:
        web2.example.de:
      vars:
        http_port: 80
    database:
      hosts:
        db1.example.de:
          ansible_user: postgres
        db2.example.de:

Dynamisches Inventory

# AWS
ansible-inventory -i aws_ec2.yml --list

# Plugins aktivieren
# ansible.cfg
[inventory]
enable_plugins = aws_ec2, azure_rm

Ad-hoc-Befehle

Grundlagen

# Ping alle Hosts
ansible all -m ping

# Befehl ausführen
ansible webserver -m shell -a "uptime"

# Datei kopieren
ansible webserver -m copy -a "src=/local/file dest=/remote/file"

# Paket installieren
ansible webserver -m apt -a "name=nginx state=present" -b

# Service starten
ansible webserver -m service -a "name=nginx state=started" -b

Optionen

| Option | Beschreibung | |--------|--------------| | -i | Inventory-Datei | | -m | Modul | | -a | Argumente | | -b | Become (sudo) | | -u | Benutzer | | -k | Passwort-Prompt | | -K | Sudo-Passwort |

Playbooks

Erstes Playbook

# site.yml

---
- name: Webserver konfigurieren
  hosts: webserver
  become: yes

  tasks:
    - name: Nginx installieren
      apt:
        name: nginx
        state: present
        update_cache: yes

    - name: Nginx starten
      service:
        name: nginx
        state: started
        enabled: yes

    - name: Konfiguration kopieren
      template:
        src: templates/nginx.conf.j2
        dest: /etc/nginx/nginx.conf
      notify: Reload Nginx

  handlers:
    - name: Reload Nginx
      service:
        name: nginx
        state: reloaded

Ausführen

ansible-playbook -i inventory.ini site.yml

Mit Optionen

# Check-Modus (Dry-Run)
ansible-playbook site.yml --check

# Verbose
ansible-playbook site.yml -v
ansible-playbook site.yml -vvv

# Limit auf Hosts
ansible-playbook site.yml --limit web1.example.de

# Tags
ansible-playbook site.yml --tags "nginx,config"

# Extra-Variablen
ansible-playbook site.yml -e "version=1.0.0"

Variablen

Im Playbook

- hosts: webserver
  vars:
    http_port: 80
    app_name: myapp

  tasks:
    - name: Template deployen
      template:
        src: config.j2
        dest: "/etc/{{ app_name }}/config.conf"

Group Variables

# group_vars/webserver.yml

http_port: 80
max_clients: 200
ssl_enabled: true

Host Variables

# host_vars/web1.example.de.yml

http_port: 8080
custom_setting: true

Variablen-Hierarchie

1. Extra vars (-e)
2. Task vars
3. Block vars
4. Role vars
5. Play vars
6. Host facts
7. Host vars
8. Group vars
9. Inventory vars
10. Role defaults

Templates (Jinja2)

Template-Datei

# templates/nginx.conf.j2

server {
    listen {{ http_port }};
    server_name {{ ansible_hostname }};

    {% if ssl_enabled %}
    listen 443 ssl;
    ssl_certificate /etc/ssl/{{ domain }}.crt;
    ssl_certificate_key /etc/ssl/{{ domain }}.key;
    {% endif %}

    location / {
        root /var/www/{{ app_name }};
        index index.html;
    }

    {% for backend in backends %}
    upstream {{ backend.name }} {
        server {{ backend.host }}:{{ backend.port }};
    }
    {% endfor %}
}

Im Playbook

- name: Nginx-Konfiguration
  template:
    src: templates/nginx.conf.j2
    dest: /etc/nginx/sites-available/default
    owner: root
    group: root
    mode: '0644'

Conditionals und Loops

When (Bedingungen)

tasks:
  - name: Nur auf Debian
    apt:
      name: nginx
    when: ansible_os_family == "Debian"

  - name: Nur auf RedHat
    yum:
      name: nginx
    when: ansible_os_family == "RedHat"

  - name: Wenn Variable gesetzt
    debug:
      msg: "SSL ist aktiviert"
    when: ssl_enabled | bool

Loops

tasks:
  - name: Mehrere Pakete installieren
    apt:
      name: "{{ item }}"
      state: present
    loop:
      - nginx
      - php-fpm
      - php-mysql

  - name: Benutzer anlegen
    user:
      name: "{{ item.name }}"
      groups: "{{ item.groups }}"
    loop:
      - { name: 'deploy', groups: 'www-data' }
      - { name: 'backup', groups: 'root' }

Rollen

Struktur erstellen

ansible-galaxy init roles/webserver

roles/webserver/
├── defaults/
│   └── main.yml
├── files/
├── handlers/
│   └── main.yml
├── meta/
│   └── main.yml
├── tasks/
│   └── main.yml
├── templates/
├── tests/
└── vars/
    └── main.yml

Rolle verwenden

# site.yml

- hosts: webserver
  roles:
    - common
    - webserver
    - { role: database, when: db_server | bool }

Roles von Galaxy

# Rolle installieren
ansible-galaxy install geerlingguy.docker

# requirements.yml
- src: geerlingguy.docker
  version: 6.1.0

ansible-galaxy install -r requirements.yml

Wichtige Module

Dateien

# Kopieren
- copy:
    src: file.txt
    dest: /path/file.txt
    owner: root
    mode: '0644'

# Template
- template:
    src: config.j2
    dest: /etc/app/config.conf

# Datei erstellen
- file:
    path: /var/log/app
    state: directory
    mode: '0755'

# Zeile in Datei
- lineinfile:
    path: /etc/hosts
    line: "192.168.1.1 server.local"

Pakete

# apt
- apt:
    name: nginx
    state: present
    update_cache: yes

# yum/dnf
- dnf:
    name: httpd
    state: present

# pip
- pip:
    name: django
    version: 4.0

Services

- service:
    name: nginx
    state: started
    enabled: yes

- systemd:
    name: myapp
    state: restarted
    daemon_reload: yes

Benutzer

- user:
    name: deploy
    groups: www-data
    shell: /bin/bash
    generate_ssh_key: yes

Shell/Command

# Befehl
- command: /opt/script.sh

# Shell (für Pipes, Redirects)
- shell: cat /etc/passwd | grep deploy

# Mit Bedingung
- command: /opt/install.sh
  args:
    creates: /opt/installed.flag

Handlers

tasks:
  - name: Nginx-Config ändern
    template:
      src: nginx.conf.j2
      dest: /etc/nginx/nginx.conf
    notify:
      - Reload Nginx
      - Check Config

handlers:
  - name: Check Config
    command: nginx -t
    listen: "Check Config"

  - name: Reload Nginx
    service:
      name: nginx
      state: reloaded
    listen: "Reload Nginx"

Vault (Secrets)

Datei verschlüsseln

# Erstellen
ansible-vault create secrets.yml

# Bearbeiten
ansible-vault edit secrets.yml

# Verschlüsseln
ansible-vault encrypt vars.yml

# Entschlüsseln
ansible-vault decrypt vars.yml

Playbook mit Vault

ansible-playbook site.yml --ask-vault-pass

# Oder mit Passwort-Datei
ansible-playbook site.yml --vault-password-file ~/.vault_pass

Variablen im Vault

# secrets.yml (verschlüsselt)

db_password: geheim123
api_key: abc123xyz
# Playbook
- hosts: database
  vars_files:
    - secrets.yml
  tasks:
    - name: DB-Passwort setzen
      mysql_user:
        name: app
        password: "{{ db_password }}"

ansible.cfg

# ansible.cfg

[defaults]
inventory = inventory.ini
remote_user = deploy
private_key_file = ~/.ssh/deploy_key
host_key_checking = False
retry_files_enabled = False
gathering = smart
fact_caching = jsonfile
fact_caching_connection = /tmp/ansible_facts

[privilege_escalation]
become = True
become_method = sudo
become_user = root
become_ask_pass = False

Zusammenfassung

| Befehl | Funktion | |--------|----------| | ansible all -m ping | Connectivity-Test | | ansible-playbook site.yml | Playbook ausführen | | ansible-galaxy init | Rolle erstellen | | ansible-vault encrypt | Datei verschlüsseln |

| Verzeichnis | Inhalt | |-------------|--------| | group_vars/ | Gruppen-Variablen | | host_vars/ | Host-Variablen | | roles/ | Rollen | | templates/ | Jinja2-Templates |

| Modul | Funktion | |-------|----------| | apt/yum | Paketmanagement | | copy/template | Dateien | | service/systemd | Dienste | | user/group | Benutzer | | file/lineinfile | Dateisystem |

Fazit

Ansible ist das ideale Tool für Server-Automatisierung ohne komplexe Infrastruktur. Die agentenlose Architektur macht den Einstieg einfach. YAML-basierte Playbooks sind lesbar und versionierbar. Mit Rollen lässt sich wiederverwendbarer Code erstellen. Vault schützt sensible Daten. Für Infrastructure as Code ist Ansible eine hervorragende Wahl.