Ansibel Schulung März 2026

Words
910
Reading
5 min
Listen
Play
6M

Hallo zusammen,

Vom 24.3. - 27.3.2026 haben wir an einer Schulung zum Thema Ansibel mit
dem Dozenten Adrran Sorge teilgenommen.

Hier sind meine subjektiven Mitschriften und Erfahrungen aus dem Kurs.
Keine Garantie für Richtigkeit oder Vollständigkeit:

Was ist Ansible

Ansible ist eine Sammlung von Python Kommandos, die zwar lokal laufen,
aber auf Zielrechnern, sofern dort Python installiert ist, Befehle
ausführen können. Dadurch sind wir in der Lage komplette Rechnersysteme
inklusiver Konfiguration von Servern zentral zu steuern. Die Scripte
werden via einem Git-Repository in sogenannten Playbooks in einer
Yaml-Struktur verwaltet. Dem Playbook Kommando werden dann diese
Playbooks übergeben und im Hintergrund arbeiten dann mächtige
Bibliotheken, die als Open Source zur Verfügung stehen, die gewünschten
Aufgaben, entsprechend der Playbooks ab. Die Dokumentation dieser
Bibliotheken (im Ansible Sprech Module genannt) befindet sich hier:

Ansible Community | Ansible documentation

https://docs.ansible.com/projects/ansible/latest/collections/community/general/ipa_pwpolicy_module.html

grafik.png

Im Folgenden gehen wir durch die Themen durch, so wie wir sie zeitlich
durchgearbeitet haben:

Schulungstag 1

Git

Zuerst mal ein paar Vokabeln:

  • Repository: gemanagte Ordnerstruktur

  • Origin: Standardname für das Default Upstream Repo

  • HEAD: Aktueller Punkt im Graphen, auf dem das Repo zeigt (das
    Stimmt, ich habe es mit Perplexity gecheckt, es muss also nicht der
    letzte (oberste) Datenstand sein).

Git speichert nicht in den Versionen den kompletten Datenstand, sondern
(ähnlich wie bei der Blockchain), es werden nur die Änderung
gespeichert.

Daher sollten keine Binärdateien hochgeladen werden. Und auch möglichst
wenig Bilder, vor allem, wenn die ständig wechseln.

Es gibt LFS (Large File System) bei Git dafür.

Hier eine bewährte Git Staging Strategie:

Auf dem Main Branch liegt der Produktionscode. Auf dem Integration
Branch liegt der zu testende Code. Von ihm werden zur Entwicklung
einzelne Feature Branches abgezweigt.

Es gibt neben .gitignore auch die .gitkeep Datei. Die legt man in leere
Ordner rein, wenn man möchte, dass diese mit nach Github hochgeladen
wird.

In der .gitignore kann man auch bestimmte Dateien negieren. z.B.:
!/drv/.gitkeep

YAML

YAML ist ähnlich wie JSON eine Konfigurations-Sprache. Im Unterschied zu
JSON lebt sie von Einrückungen anstelle von Klammer-Strukturen. Dies hat
Vor- und Nachteile. Details zu YAML siehe hier: https://yaml.org

Ansible

Ansible ist in Python geschrieben. Auf dem ausführenden Server werden
Python Scripte geschrieben.

Auf Windows Systemen ist Powershell genug.

Hie ein paar Vokabeln:

  • Modul - Block der dafür zuständig ist, auf dem Zielsystem Aktionen
    auszuführen

  • Collection - Sammlung von Modulen

  • Task -- Instanz eines Moduls

  • Host -- Host, dem Variablen zugewiesen werden können

  • Inventar - Sammlung von Hosts

  • Playbook - Liste von Tasks, die auf einer Host(Gruppe) ausgeführt
    werden sollen

Details:

Ansible Community | Ansible documentation

https://docs.ansible.com/projects/ansible/latest/collections/community/general/ipa_pwpolicy_module.html

Beispiele einer YAML Datei:

Entnommen aus:
https://docs.ansible.com/projects/ansible/latest/collections/community/general/ipa_pwpolicy_module.html#examples

- name: Modify the global password policy
community.general.ipa_pwpolicy:
maxpwdlife: '90'
minpwdlife: '1'
historylength: '8'
minclasses: '3'
minlength: '16'
maxfailcount: '6'
failinterval: '60'
lockouttime: '600'
ipa_host: ipa.example.com
ipa_user: admin
ipa_pass: topsecret

Selbstgeschriebenes Beispiel:

---
http_port: 80
schulungs_ids:
- schulungs_id: v991423
lieblingsfarbe: blau
schuhe:
groesse: 42
farbe: schwarz
nachbarn:
- Dr. Snuggles (Küken)
- Silke SIlberfisch
- schulungs_id: "andreas"
lieblingsfarbe: "blau"
schuhe:
groesse: 40
farbe: "schwarz"
nachbarn:
- "Irgend Einer"
- "Noch Jemand"

Schulungstag 2

Wir wurden in vier Gruppen aufgeteilt mit folgenden Aufgaben:

●p1-1: Installation von Apache und Kopieren einer Datei, die dann im
Browser angezeigt werden soll

●p1-2: Installation nginx und Kopieren einer Datei, die dann im Browser
angezeigt werden soll

●Je zwei Gruppen pro Server: Apache auf 80 und nginx auf 8080

Unsere Aufgabe war es, das innerhalb der index.html das Wort „Welcome"
zu ersetzen durch „Ansible-101: Projekt 1"

Nachdem wir die Git-Schwierigkeiten gelöst hatten um den Code mit
unserem Ansible Server (Red Had Linux Server) synchronisieren zu können
(ssh Key rüber kopieren mit „ssh-copy-id ansiplab2.plab.kern.drv.drv")
haben wir die Aufgabe wie folgt erledigt:


[v991423@ansiplab1.plab.kern.drv.drv (el9) [0] |
~/git/ansible-101-26 ]
$ ansible-playbook -i inventory.yml httpd.yml --extra-vars
"ansible_remote_tmp=/var/tmp/.ansible-${USER}/tmp"
[WARNING]: Found variable using reserved name: become_flags

PLAY [Webserver auf Remote Host installieren]
********************************************************************************************************************

TASK [Gathering Facts]
*******************************************************************************************************************************************

ok: [ansiplab2.plab.kern.drv.drv]

TASK [Paketliste aktualisieren]
**********************************************************************************************************************************

ok: [ansiplab2.plab.kern.drv.drv]

TASK [Webserver starten und aktivieren]
**************************************************************************************************************************

ok: [ansiplab2.plab.kern.drv.drv]

TASK [kopiere index]
*********************************************************************************************************************************************

changed: [ansiplab2.plab.kern.drv.drv]

PLAY RECAP
*******************************************************************************************************************************************************

ansiplab2.plab.kern.drv.drv : ok=4 changed=1 unreachable=0 failed=0
skipped=0 rescued=0 ignored=0

[v991423@ansiplab1.plab.kern.drv.drv (el9) [0] |
~/git/ansible-101-26 ]
$ curl ansiplab2.plab.kern.drv.drv:80
<body>
<h1>Ansible-101: Projekt 1</h1>

Httpd.yml:

---
- name: Webserver auf Remote Host installieren
hosts: webserver
become: yes
 
vars:
package_name: httpd
become_flags: -i
 
tasks:
- name: Paketliste aktualisieren
ansible.builtin.dnf:
name: "{{ package_name }}"
state: present
 
- name: Webserver starten und aktivieren
ansible.builtin.service:
name: "{{ package_name }}"
state: started
enabled: yes
- name: kopiere index
ansible.builtin.copy:
src: ~/git/ansible-101-26/index.html
dest: /var/www/html/
owner: apache
group: apache

Inventory.yml

all:
children:
webserver:
hosts:
ansiplab2.plab.kern.drv.drv: # Zielserver

weitere Ansible Vokabeln

  • Conditionals - Bedingungen, die zur Laufzeit ausgewertet werden
  • Rolle - Objekt/Container/Klasse welche mehrere Tasks zusammenfasst
    und wiederverwendbar macht
  • Jinja2 Templates - Templates mit Variablen und if Bedingungen
  • Tags - Ermögliht es Teile von Playbooks auszuführen
  • Collections - Sammlung von Rollen, Modulen, Plugins

Die When-Liste bei den Conditionen ist eine UND-Verknüpfung

Ansible-galaxy - Lädt Rollen und Collections runter

Ansible-galaxy role init test <- lädt die Ordnerstruktur init in den
Ordner Test runter

https://jinja.palletsprojects.com/en/stable/templates

Mit lookup können Passwörter in die Templates eingefügt werden

Schulungstag 3

Aufgabe: Wir sollen yml Dateien erstellen, die auf einem Zielserver die
Zertifikate für eine Webseite anlegen

Funktionierendes Ergebnis:

Im Ordner roles/generate_ssl/tasks liegt die Datei main.yml mit
folgendem Inhalt:

---
- name: Erstelle private Verzeichnis
ansible.builtin.file:
path: "{{ ssl_path }}private/"
state: directory
mode: '0755'

- name: Generate an OpenSSL private key with the default values (4096
bits, RSA)

community.crypto.openssl_privatekey:
path: "{{ private_key_path }}"

- name: Generate an OpenSSL Certificate Signing Request
community.crypto.openssl_csr:
path: "{{ ssl_path
}}[www.ansible.com.csr](http://www.ansible.com.csr)"
privatekey_path: "{{ private_key_path }}"
common_name: [www.ansible.com](http://www.ansible.com)

- name: Generate a Self Signed OpenSSL certificate
community.crypto.x509_certificate:
path: "{{ ssl_path }}ansible.com.crt"
privatekey_path: "{{ private_key_path }}"
csr_path: "{{ ssl_path
}}[www.ansible.com.csr](http://www.ansible.com.csr)"
provider: selfsigned
selfsigned_not_after: "+30m"
force: true

- name: Get certificate information
community.crypto.x509_certificate_info:
path: "{{ ssl_path }}ansible.com.crt"
register: result
- ansible.builtin.debug:

msg: "Läuft ab: {{ result.not_after }}"

Im Hauptordner liegt die Datei generate_ssl.yml mit folgendem Inhalt:

---
- name: Webserver auf Remote Host installieren
hosts: webserver
become: yes

vars:
package_name: httpd
become_flags: -i
private_key_path: "/etc/ssl/private/{{ inventory_hostname }}.pem"
ssl_path: /etc/ssl/

roles:
- generate_ssl

Diese ruft die main.yml im Verzeichnis roles/generate_ssl/tasks auf und
führt sie als Task aus.

Ergebnis:

Wir rufen die Dateien wie folgt auf:


[v991423@ansiplab1.plab.kern.drv.drv (el9) [0] |
~/git/ansible-101-26 ]
$ ansible-playbook -i inventory.yml generate_ssl.yml --extra-vars
"ansible_remote_tmp=/var/tmp/.ansible-${USER}/tmp"
[WARNING]: Found variable using reserved name: become_flags

PLAY [Webserver auf Remote Host installieren]
**************************************************************************************************************************

TASK [Gathering Facts]
*************************************************************************************************************************************************

ok: [ansiplab2.plab.kern.drv.drv]

TASK [generate_ssl : Erstelle private Verzeichnis]
*********************************************************************************************************************

ok: [ansiplab2.plab.kern.drv.drv]

TASK [generate_ssl : Generate an OpenSSL private key with the default
values (4096 bits, RSA)]
*************************************************************************

ok: [ansiplab2.plab.kern.drv.drv]

TASK [generate_ssl : Generate an OpenSSL Certificate Signing Request]
**************************************************************************************************

ok: [ansiplab2.plab.kern.drv.drv]

TASK [generate_ssl : Generate a Self Signed OpenSSL certificate]
*******************************************************************************************************

changed: [ansiplab2.plab.kern.drv.drv]

TASK [generate_ssl : Get certificate information]
**********************************************************************************************************************

ok: [ansiplab2.plab.kern.drv.drv]

TASK [generate_ssl : ansible.builtin.debug]
****************************************************************************************************************************
ok: [ansiplab2.plab.kern.drv.drv] => {
"msg": "Läuft ab: 20260326085052Z"
}

PLAY RECAP
*************************************************************************************************************************************************************
**********ansiplab2.plab.kern.drv.drv : ok=7 changed=1
unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

[v991423@ansiplab1.plab.kern.drv.drv (el9) [0] |
~/git/ansible-101-26 ]

Auf dem Zielserver sehen wir:

[v991423@ansiplab2.plab.kern.drv.drv (el9) [0] | /etc/ssl ]
$ sudo openssl x509 -in ansible.com.crt -noout -enddate
notAfter=Mar 22 14:26:49 2036 GMT

Weitere Infos:

Community.Crypto --- Ansible Community
Documentation

https://docs.ansible.com/projects/ansible/latest/collections/community/crypto/

Good Practices for Ansible -
GPA

Handlers

Ist so eine art Unterprogramm. Mit Notify wird das nur dann ausgeführt,
wenn eine Veränderung stattgefunden hat.

Handlers werden immer am Ende eines Plays ausgeführt (auch wenn das
Notify früher steht). Mit Meta Modulen /Flush Handler kann man die
Handler auch zu einem anderen Zeitpunkt starten.

Handlers: running operations on change --- Ansible Community
Documentation

https://docs.ansible.com/projects/ansible/latest/playbook_guide/playbooks_handlers.html

Linter

Dnf install yamllint.noarch python3-ansible-lint.noarch

Damit kann man die Dateien auf Syntaxprobleme überprüfen

System Rollen

Red Hat Enterprise Linux (RHEL) System Roles - Red Hat Customer
Portal

dnf install cockpit

Podman

Podman-compose.yml liegt in den Templates

Über systemd wird dann der Container gestartet

Man kann podman auch über das Container Module in Ansible starten

Mit dem k8s Module arbeiten.


Tag 4

Ansible Automation Platform

Zentrales Management von Playbooks als Dashboard

Ich sehe Ähnlichkeiten zu Jenkins

Man kann die Playbooks dort ausführen oder schedulen.

Debugging

Fazit

Die Schulung war lehrreich und sehr anstrengend für mich als Ansible
Anfänger. Wir haben viele Praxisbeispiele gemacht, was herausfordernd,
aber eben auch griffig und damit bildend war. Natürlich konnten wir nur
an der Oberfläche kratzen, aber wir haben nun einen Startpunkt, auf dem
wir aufsetzen können.

Nachtrag: Ein Nachteil der YAML Struktur ist, dass die Einrückungen beim Konvertieren der Dokumentation verloren gegangen sind. Bei JSON wäre das nicht so schlimm, aber hier ging dann leider auch einiges an Informationen verloren.

Achim Mertens

Ansibel Schulung März 2026 | Ecency