Ansible mit Rocky: Unterschied zwischen den Versionen
Zur Navigation springen
Zur Suche springen
(Die Seite wurde neu angelegt: „= Ansible auf Rocky Linux = Ansible ist ein agentenloser Automatisierungsdienst – es wird nur auf dem Control Node installiert, die verwalteten Maschinen br…“) |
|||
| (20 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt) | |||
| Zeile 1: | Zeile 1: | ||
= Ansible auf Rocky Linux = | = Ansible auf Rocky Linux = | ||
| − | Ansible ist ein agentenloser Automatisierungsdienst | + | Ansible ist ein agentenloser Automatisierungsdienst: Es wird nur auf dem '''Control Node''' installiert, die verwalteten Maschinen ("Managed Nodes") brauchen lediglich SSH-Zugang und Python – kein Agent, kein zusätzlicher Dienst. Das unterscheidet Ansible von Werkzeugen wie Puppet oder Chef, die einen dauerhaft laufenden Agenten auf jedem Zielsystem voraussetzen. |
| − | = Installation = | + | Im Labor übernimmt '''desktop.it2XX.int''' die Rolle des Control Node und verwaltet von dort aus die DMZ-Server (''fw'', ''ns'', ''www''; ''ldap'' und der Container folgen später als eigene Gruppe). Gearbeitet wird durchgehend als unprivilegierter User '''kit''' – root-Login ist auf allen Systemen deaktiviert, privilegierte Aktionen laufen über ''sudo''. |
| − | ;Ansible wird | + | |
| − | * dnf install -y ansible | + | == Voraussetzungen == |
| + | ;Auf jedem Zielsystem muss ein kit-User mit passwortlosem sudo existieren. Ohne NOPASSWD würde Ansible bei jedem privilegierten Task nach einem sudo-Passwort fragen und den automatisierten Ablauf unterbrechen. | ||
| + | * sudo visudo | ||
| + | <pre> | ||
| + | kit ALL=(ALL) NOPASSWD: ALL | ||
| + | </pre> | ||
| + | |||
| + | = Installation des Control Node = | ||
| + | ;Ansible wird ausschließlich auf desktop.it2XX.int installiert. Die Managed Nodes brauchen keine Ansible-Installation, nur SSH und Python – das ist der Kern des agentenlosen Modells. | ||
| + | * sudo dnf install -y ansible | ||
= SSH-Schlüssel vorbereiten = | = SSH-Schlüssel vorbereiten = | ||
| − | ; | + | ;kit braucht auf dem Control Node einen eigenen SSH-Schlüssel, der auf allen Zielsystemen beim kit-User hinterlegt wird. Ansible nutzt diesen Schlüssel für jede Verbindung – ohne ihn müsste bei jedem Task ein Passwort eingegeben werden. |
| − | * ssh-keygen -t ed25519 -C " | + | * ssh-keygen -t ed25519 -C "kit@it2XX.int" |
| − | ;Schlüssel auf | + | |
| − | * ssh-copy-id | + | ;Schlüssel als kit auf die DMZ-Server verteilen – NICHT als root, da PermitRootLogin auf den Zielsystemen bereits deaktiviert ist. Ein Versuch mit root@... schlägt deshalb fehl, ssh-copy-id muss den tatsächlichen Verbindungsuser kit verwenden. |
| − | * ssh-copy-id | + | * ssh-copy-id kit@fw.it2XX.int |
| − | * ssh-copy-id | + | * ssh-copy-id kit@ns.it2XX.int |
| + | * ssh-copy-id kit@www.it2XX.int | ||
| + | |||
| + | = Projektverzeichnis und Inventory = | ||
| + | ;kit hat keine Schreibrechte auf /etc/ansible – deshalb arbeiten wir im Home-Verzeichnis statt mit sudo im systemweiten Pfad. Das vermeidet unnötige root-Eingriffe für reine Konfigurationsdateien. | ||
| + | * mkdir -p ~/ansible | ||
| + | * cd ~/ansible | ||
| + | |||
| + | ;ansible.cfg legt fest, wo das Inventory liegt – dann ist kein -i-Parameter mehr nötig. Wichtig: Der relative Pfad ./hosts wirkt nur, wenn Ansible aus genau diesem Verzeichnis heraus aufgerufen wird; aus Unterverzeichnissen (z.B. roles/) wird die Datei nicht gefunden. | ||
| + | * vi ~/ansible/ansible.cfg | ||
| + | <pre> | ||
| + | [defaults] | ||
| + | inventory = ./hosts | ||
| + | </pre> | ||
| − | + | ;Inventory anlegen – Maschinen nach Rolle gruppiert, kit als Verbindungsuser, sudo für privilegierte Tasks. Die dmz:vars-Sektion gilt für alle Hosts der Gruppe gleichzeitig, statt sie einzeln pro Host wiederholen zu müssen. | |
| − | ; | + | * vi ~/ansible/hosts |
| − | |||
| − | * vi | ||
<pre> | <pre> | ||
[dmz] | [dmz] | ||
| + | fw.it2XX.int | ||
ns.it2XX.int | ns.it2XX.int | ||
www.it2XX.int | www.it2XX.int | ||
| − | |||
[dmz:vars] | [dmz:vars] | ||
| − | ansible_user= | + | ansible_user=kit |
| + | ansible_become=true | ||
| + | ansible_become_method=sudo | ||
</pre> | </pre> | ||
= Erster Test = | = Erster Test = | ||
| − | ;Alle Maschinen anpingen – Ansible nutzt dafür das ping-Modul, nicht ICMP | + | ;Alle Maschinen anpingen – Ansible nutzt dafür das ping-Modul, nicht ICMP. Das Modul prüft, ob eine SSH-Verbindung inklusive Python-Interpreter auf der Gegenseite funktioniert, nicht nur ob der Host im Netzwerk erreichbar ist. |
* ansible all -m ping | * ansible all -m ping | ||
ns.it2XX.int | SUCCESS => { | ns.it2XX.int | SUCCESS => { | ||
| Zeile 37: | Zeile 59: | ||
} | } | ||
| − | ;Ad-hoc Befehl auf allen Maschinen ausführen | + | |
| + | ;sudo-Rechte prüfen – mit -b (become) sollte root erscheinen. Das bestätigt, dass ansible_become und das passwortlose sudo auf den Zielsystemen korrekt zusammenspielen. | ||
| + | * ansible dmz -b -m command -a "whoami" | ||
| + | |||
| + | ;Ad-hoc Befehl auf allen Maschinen ausführen. Ad-hoc-Kommandos eignen sich für schnelle Einzelaktionen und Debugging, nicht für wiederholbare Konfiguration – dafür sind Playbooks gedacht. | ||
* ansible all -m command -a "hostname" | * ansible all -m command -a "hostname" | ||
| − | ;Nur die DMZ-Gruppe ansprechen | + | ;Nur die DMZ-Gruppe ansprechen. Gruppenfilter im Inventory erlauben es, gezielt Teilmengen der Infrastruktur anzusprechen, statt immer alle Hosts zu treffen. |
* ansible dmz -m command -a "uptime" | * ansible dmz -m command -a "uptime" | ||
= Playbooks = | = Playbooks = | ||
| − | ;Ein Playbook ist eine YAML-Datei die Tasks in einer | + | ;Ein Playbook ist eine YAML-Datei, die Tasks in fester Reihenfolge auf einer Zielgruppe ausführt. Im Gegensatz zu Ad-hoc-Befehlen sind Playbooks wiederholbar, versionierbar und dokumentieren den gewünschten Zielzustand. |
| − | ;Einfaches Beispiel – Paket installieren und | + | ;Einfaches Beispiel – Paket installieren und eine harmlose Testdatei anlegen, läuft dank ansible_become automatisch mit sudo. Nichts hiervon verändert bestehende Konfiguration, das Beispiel dient nur zum Kennenlernen der Playbook-Syntax. |
| − | * vi / | + | * vi ~/ansible/test.yml |
| − | < | + | <syntaxhighlight lang="yaml"> |
--- | --- | ||
- name: Testplaybook | - name: Testplaybook | ||
hosts: dmz | hosts: dmz | ||
tasks: | tasks: | ||
| − | - name: | + | - name: htop installieren |
dnf: | dnf: | ||
| − | name: | + | name: htop |
state: present | state: present | ||
| − | </ | + | |
| − | * ansible-playbook / | + | - name: Testdatei mit Zeitstempel anlegen |
| + | copy: | ||
| + | content: "Ansible-Testlauf: {{ ansible_date_time.iso8601 }}\n" | ||
| + | dest: /tmp/ansible-test.txt | ||
| + | mode: '0644' | ||
| + | </syntaxhighlight> | ||
| + | * ansible-playbook ~/ansible/test.yml | ||
| + | |||
| + | ;Idempotenz zeigen – zweiter Lauf meldet "changed=0", da nichts mehr zu tun ist. Das ist ein zentrales Ansible-Prinzip: Ein Playbook kann beliebig oft ausgeführt werden, ohne den Zielzustand erneut zu verändern. | ||
| + | * ansible-playbook ~/ansible/test.yml | ||
| + | |||
| + | ;Ergebnis prüfen. Zeigt, dass die Testdatei tatsächlich mit dem korrekten Zeitstempel auf den Zielsystemen angekommen ist. | ||
| + | * ansible dmz -m command -a "cat /tmp/ansible-test.txt" | ||
= Rollen = | = Rollen = | ||
| − | ;Rollen sind wiederverwendbare Ansible-Strukturen – | + | ;Rollen sind wiederverwendbare Ansible-Strukturen – Tasks, Templates und Handler in einem festen Verzeichnisschema. Das feste Schema erlaubt es Ansible, Dateien wie templates/sssd.conf.j2 automatisch zu finden, ohne dass der Pfad in jedem Task ausgeschrieben werden muss. |
| − | |||
roles/ | roles/ | ||
└── rollenname/ | └── rollenname/ | ||
| Zeile 74: | Zeile 111: | ||
└── main.yml | └── main.yml | ||
| − | ;Rollengerüst automatisch erstellen | + | ;ansible-galaxy ist das mit Ansible mitgelieferte CLI-Tool zum Verwalten von Rollen. Zwei Funktionen: (1) Skelett einer neuen Rolle generieren – das nutzen wir hier, (2) fertige Rollen von galaxy.ansible.com herunterladen – nicht Teil dieses Kurses, da die Rollen hier bewusst selbst geschrieben werden. |
| − | * mkdir -p | + | ;Rollengerüst automatisch erstellen – legt tasks/, handlers/, defaults/, templates/ mit leeren main.yml-Dateien an, die anschließend gefüllt werden. |
| − | * cd | + | * mkdir -p ~/ansible/roles |
| + | * cd ~/ansible/roles | ||
* ansible-galaxy init sssd | * ansible-galaxy init sssd | ||
| − | |||
= Rolle: SSSD = | = Rolle: SSSD = | ||
| − | ;Diese Rolle installiert SSSD auf allen DMZ-Servern und | + | ;Diese Rolle installiert SSSD auf allen DMZ-Servern und bindet sie gegen den LDAP-Server an. Damit können sich Benutzer aus dem zentralen Verzeichnis auf jedem DMZ-Server anmelden, statt lokale Konten pro Host pflegen zu müssen. |
== tasks/main.yml == | == tasks/main.yml == | ||
| − | * vi | + | * vi ~/ansible/roles/sssd/tasks/main.yml |
| − | < | + | <syntaxhighlight lang="yaml"> |
--- | --- | ||
- name: Pakete installieren | - name: Pakete installieren | ||
| Zeile 109: | Zeile 146: | ||
command: authselect select sssd with-mkhomedir --force | command: authselect select sssd with-mkhomedir --force | ||
changed_when: false | changed_when: false | ||
| + | |||
| + | - name: sudoers-Eintrag in user-nsswitch.conf setzen | ||
| + | lineinfile: | ||
| + | path: /etc/authselect/user-nsswitch.conf | ||
| + | regexp: '^sudoers:' | ||
| + | line: 'sudoers: files sss' | ||
| + | state: present | ||
| + | notify: authselect anwenden | ||
- name: oddjobd starten | - name: oddjobd starten | ||
| Zeile 115: | Zeile 160: | ||
enabled: true | enabled: true | ||
state: started | state: started | ||
| − | </ | + | </syntaxhighlight> |
| + | |||
| + | ;Merksatz: authselect generiert /etc/nsswitch.conf komplett neu aus dem gewählten Profil und aus /etc/authselect/user-nsswitch.conf – direkte Einträge in /etc/nsswitch.conf werden dabei überschrieben. Änderungen gehören deshalb in user-nsswitch.conf und werden über authselect apply-changes aktiv geschaltet. Reihenfolge zwingend: erst authselect select, danach den sudoers-Eintrag setzen – sonst wird er beim nächsten select wieder verworfen. | ||
== templates/sssd.conf.j2 == | == templates/sssd.conf.j2 == | ||
| − | ;Das Template nutzt Ansible-Variablen – so funktioniert dieselbe Rolle für jeden Studenten | + | ;Das Template nutzt Ansible-Variablen – so funktioniert dieselbe Rolle für jeden Studenten, ohne den Code anzufassen. Nur defaults/main.yml oder group_vars müssen pro Umgebung angepasst werden. |
| − | * vi | + | * vi ~/ansible/roles/sssd/templates/sssd.conf.j2 |
<pre> | <pre> | ||
[sssd] | [sssd] | ||
| Zeile 149: | Zeile 196: | ||
== handlers/main.yml == | == handlers/main.yml == | ||
| − | * vi | + | ;Handler laufen nur, wenn ein Task mit notify sie tatsächlich auslöst, und erst am Ende des Playbook-Durchlaufs. Das verhindert unnötige Neustarts von Diensten, wenn sich an der Konfiguration nichts geändert hat. |
| − | < | + | * vi ~/ansible/roles/sssd/handlers/main.yml |
| + | <syntaxhighlight lang="yaml"> | ||
--- | --- | ||
- name: sssd neu starten | - name: sssd neu starten | ||
| Zeile 156: | Zeile 204: | ||
name: sssd | name: sssd | ||
state: restarted | state: restarted | ||
| − | </ | + | |
| + | - name: authselect anwenden | ||
| + | command: authselect apply-changes | ||
| + | </syntaxhighlight> | ||
== defaults/main.yml == | == defaults/main.yml == | ||
| − | ;Standardwerte – werden durch group_vars oder host_vars überschrieben | + | ;Standardwerte – werden durch group_vars oder host_vars überschrieben, ohne dass die Rolle selbst verändert werden muss. Das ist der Mechanismus, der dieselbe Rolle für unterschiedliche Studenten-Domains (it201, it202, ...) wiederverwendbar macht. |
| − | * vi | + | * vi ~/ansible/roles/sssd/defaults/main.yml |
| − | < | + | <syntaxhighlight lang="yaml"> |
--- | --- | ||
domain: "it2XX.int" | domain: "it2XX.int" | ||
| Zeile 167: | Zeile 218: | ||
dc2: "int" | dc2: "int" | ||
ldap_password: "123Start$" | ldap_password: "123Start$" | ||
| − | </ | + | </syntaxhighlight> |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | + | ;Für den produktiven Einsatz: Passwort niemals im Klartext in defaults/main.yml – stattdessen mit ansible-vault verschlüsseln. Im Kursumfeld mit Wegwerf-Passwörtern ist das Klartext-Passwort didaktisch vertretbar, in Produktion nicht. | |
| − | + | * ansible-vault encrypt_string '123Start$' --name 'ldap_password' | |
| − | |||
| − | |||
| − | - name | ||
| − | |||
| − | |||
| − | |||
| − | |||
= Playbook: DMZ ausrollen = | = Playbook: DMZ ausrollen = | ||
| − | ;Ein Playbook das | + | ;Ein Playbook, das die Rolle auf die dmz-Gruppe anwendet – der Tag sssd erlaubt es, sie gezielt einzeln auszuführen, statt immer das komplette Playbook zu starten. |
| − | * vi | + | * vi ~/ansible/dmz.yml |
| − | < | + | <syntaxhighlight lang="yaml"> |
--- | --- | ||
- name: DMZ-Server konfigurieren | - name: DMZ-Server konfigurieren | ||
hosts: dmz | hosts: dmz | ||
roles: | roles: | ||
| − | - sssd | + | - { role: sssd, tags: ['sssd'] } |
| − | + | </syntaxhighlight> | |
| − | </ | ||
| − | |||
| − | |||
| − | |||
| − | ; | + | ;SSSD ausrollen und testen. |
| − | * ansible-playbook | + | * ansible-playbook ~/ansible/dmz.yml --tags sssd |
| − | ;Dry-run – zeigt was sich ändern würde ohne es anzuwenden | + | ;Dry-run – zeigt was sich ändern würde, ohne es anzuwenden. Nützlich um vor einem echten Lauf zu prüfen, welche Tasks als changed markiert würden. |
| − | * ansible-playbook | + | * ansible-playbook ~/ansible/dmz.yml --check |
= Kontrolle = | = Kontrolle = | ||
| − | ;SSSD auf einem Server prüfen | + | ;SSSD auf einem Server prüfen. getent fragt über nsswitch.conf alle konfigurierten Quellen ab (hier: files und sss) – erscheint der Benutzer, funktioniert die LDAP-Anbindung. |
* ansible ns.it2XX.int -m command -a "getent passwd thomas" | * ansible ns.it2XX.int -m command -a "getent passwd thomas" | ||
| − | ; | + | ;nsswitch.conf prüfen – sudoers-Zeile muss sss enthalten. Fehlt sie, liest das System keine sudo-Regeln aus LDAP, selbst wenn sssd.conf korrekt konfiguriert ist. |
| − | * ansible dmz -m command -a "grep | + | * ansible dmz -m command -a "grep sudoers /etc/nsswitch.conf" |
| − | ;Alle Fakten eines Servers anzeigen – nützlich zur Fehlersuche | + | ;Alle Fakten eines Servers anzeigen – nützlich zur Fehlersuche. Das setup-Modul liefert Systeminformationen (IP, OS, Hardware), auf die auch in Templates über Variablen wie ansible_date_time zugegriffen werden kann. |
* ansible ns.it2XX.int -m setup | * ansible ns.it2XX.int -m setup | ||
| − | = Logs = | + | = Logs und Debugging = |
| − | + | ;-v, -vv und -vvv erhöhen die Ausgabe-Ausführlichkeit von ansible-playbook schrittweise – von den Task-Ergebnissen bis hin zu den vollständigen Modul-Argumenten und Verbindungsdetails. Bei unklaren Fehlern liefert -vvv meist den entscheidenden Hinweis. | |
| − | * ansible-playbook | + | * ansible-playbook ~/ansible/dmz.yml -v |
| − | * ansible-playbook | + | * ansible-playbook ~/ansible/dmz.yml -vvv |
Aktuelle Version vom 9. Juli 2026, 13:36 Uhr
Ansible auf Rocky Linux
Ansible ist ein agentenloser Automatisierungsdienst: Es wird nur auf dem Control Node installiert, die verwalteten Maschinen ("Managed Nodes") brauchen lediglich SSH-Zugang und Python – kein Agent, kein zusätzlicher Dienst. Das unterscheidet Ansible von Werkzeugen wie Puppet oder Chef, die einen dauerhaft laufenden Agenten auf jedem Zielsystem voraussetzen.
Im Labor übernimmt desktop.it2XX.int die Rolle des Control Node und verwaltet von dort aus die DMZ-Server (fw, ns, www; ldap und der Container folgen später als eigene Gruppe). Gearbeitet wird durchgehend als unprivilegierter User kit – root-Login ist auf allen Systemen deaktiviert, privilegierte Aktionen laufen über sudo.
Voraussetzungen
- Auf jedem Zielsystem muss ein kit-User mit passwortlosem sudo existieren. Ohne NOPASSWD würde Ansible bei jedem privilegierten Task nach einem sudo-Passwort fragen und den automatisierten Ablauf unterbrechen.
- sudo visudo
kit ALL=(ALL) NOPASSWD: ALL
Installation des Control Node
- Ansible wird ausschließlich auf desktop.it2XX.int installiert. Die Managed Nodes brauchen keine Ansible-Installation, nur SSH und Python – das ist der Kern des agentenlosen Modells.
- sudo dnf install -y ansible
SSH-Schlüssel vorbereiten
- kit braucht auf dem Control Node einen eigenen SSH-Schlüssel, der auf allen Zielsystemen beim kit-User hinterlegt wird. Ansible nutzt diesen Schlüssel für jede Verbindung – ohne ihn müsste bei jedem Task ein Passwort eingegeben werden.
- ssh-keygen -t ed25519 -C "kit@it2XX.int"
- Schlüssel als kit auf die DMZ-Server verteilen – NICHT als root, da PermitRootLogin auf den Zielsystemen bereits deaktiviert ist. Ein Versuch mit root@... schlägt deshalb fehl, ssh-copy-id muss den tatsächlichen Verbindungsuser kit verwenden.
- ssh-copy-id kit@fw.it2XX.int
- ssh-copy-id kit@ns.it2XX.int
- ssh-copy-id kit@www.it2XX.int
Projektverzeichnis und Inventory
- kit hat keine Schreibrechte auf /etc/ansible – deshalb arbeiten wir im Home-Verzeichnis statt mit sudo im systemweiten Pfad. Das vermeidet unnötige root-Eingriffe für reine Konfigurationsdateien.
- mkdir -p ~/ansible
- cd ~/ansible
- ansible.cfg legt fest, wo das Inventory liegt – dann ist kein -i-Parameter mehr nötig. Wichtig
- Der relative Pfad ./hosts wirkt nur, wenn Ansible aus genau diesem Verzeichnis heraus aufgerufen wird; aus Unterverzeichnissen (z.B. roles/) wird die Datei nicht gefunden.
- vi ~/ansible/ansible.cfg
[defaults] inventory = ./hosts
- Inventory anlegen – Maschinen nach Rolle gruppiert, kit als Verbindungsuser, sudo für privilegierte Tasks. Die dmz
- vars-Sektion gilt für alle Hosts der Gruppe gleichzeitig, statt sie einzeln pro Host wiederholen zu müssen.
- vi ~/ansible/hosts
[dmz] fw.it2XX.int ns.it2XX.int www.it2XX.int [dmz:vars] ansible_user=kit ansible_become=true ansible_become_method=sudo
Erster Test
- Alle Maschinen anpingen – Ansible nutzt dafür das ping-Modul, nicht ICMP. Das Modul prüft, ob eine SSH-Verbindung inklusive Python-Interpreter auf der Gegenseite funktioniert, nicht nur ob der Host im Netzwerk erreichbar ist.
- ansible all -m ping
ns.it2XX.int | SUCCESS => {
"changed": false,
"ping": "pong"
}
- sudo-Rechte prüfen – mit -b (become) sollte root erscheinen. Das bestätigt, dass ansible_become und das passwortlose sudo auf den Zielsystemen korrekt zusammenspielen.
- ansible dmz -b -m command -a "whoami"
- Ad-hoc Befehl auf allen Maschinen ausführen. Ad-hoc-Kommandos eignen sich für schnelle Einzelaktionen und Debugging, nicht für wiederholbare Konfiguration – dafür sind Playbooks gedacht.
- ansible all -m command -a "hostname"
- Nur die DMZ-Gruppe ansprechen. Gruppenfilter im Inventory erlauben es, gezielt Teilmengen der Infrastruktur anzusprechen, statt immer alle Hosts zu treffen.
- ansible dmz -m command -a "uptime"
Playbooks
- Ein Playbook ist eine YAML-Datei, die Tasks in fester Reihenfolge auf einer Zielgruppe ausführt. Im Gegensatz zu Ad-hoc-Befehlen sind Playbooks wiederholbar, versionierbar und dokumentieren den gewünschten Zielzustand.
- Einfaches Beispiel – Paket installieren und eine harmlose Testdatei anlegen, läuft dank ansible_become automatisch mit sudo. Nichts hiervon verändert bestehende Konfiguration, das Beispiel dient nur zum Kennenlernen der Playbook-Syntax.
- vi ~/ansible/test.yml
---
- name: Testplaybook
hosts: dmz
tasks:
- name: htop installieren
dnf:
name: htop
state: present
- name: Testdatei mit Zeitstempel anlegen
copy:
content: "Ansible-Testlauf: {{ ansible_date_time.iso8601 }}\n"
dest: /tmp/ansible-test.txt
mode: '0644'
- ansible-playbook ~/ansible/test.yml
- Idempotenz zeigen – zweiter Lauf meldet "changed=0", da nichts mehr zu tun ist. Das ist ein zentrales Ansible-Prinzip
- Ein Playbook kann beliebig oft ausgeführt werden, ohne den Zielzustand erneut zu verändern.
- ansible-playbook ~/ansible/test.yml
- Ergebnis prüfen. Zeigt, dass die Testdatei tatsächlich mit dem korrekten Zeitstempel auf den Zielsystemen angekommen ist.
- ansible dmz -m command -a "cat /tmp/ansible-test.txt"
Rollen
- Rollen sind wiederverwendbare Ansible-Strukturen – Tasks, Templates und Handler in einem festen Verzeichnisschema. Das feste Schema erlaubt es Ansible, Dateien wie templates/sssd.conf.j2 automatisch zu finden, ohne dass der Pfad in jedem Task ausgeschrieben werden muss.
roles/
└── rollenname/
├── tasks/
│ └── main.yml
├── templates/
├── handlers/
│ └── main.yml
└── defaults/
└── main.yml
- ansible-galaxy ist das mit Ansible mitgelieferte CLI-Tool zum Verwalten von Rollen. Zwei Funktionen
- (1) Skelett einer neuen Rolle generieren – das nutzen wir hier, (2) fertige Rollen von galaxy.ansible.com herunterladen – nicht Teil dieses Kurses, da die Rollen hier bewusst selbst geschrieben werden.
- Rollengerüst automatisch erstellen – legt tasks/, handlers/, defaults/, templates/ mit leeren main.yml-Dateien an, die anschließend gefüllt werden.
- mkdir -p ~/ansible/roles
- cd ~/ansible/roles
- ansible-galaxy init sssd
Rolle: SSSD
- Diese Rolle installiert SSSD auf allen DMZ-Servern und bindet sie gegen den LDAP-Server an. Damit können sich Benutzer aus dem zentralen Verzeichnis auf jedem DMZ-Server anmelden, statt lokale Konten pro Host pflegen zu müssen.
tasks/main.yml
- vi ~/ansible/roles/sssd/tasks/main.yml
---
- name: Pakete installieren
dnf:
name:
- sssd
- sssd-ldap
- oddjob
- oddjob-mkhomedir
state: present
- name: sssd.conf schreiben
template:
src: sssd.conf.j2
dest: /etc/sssd/sssd.conf
owner: root
group: root
mode: '0600'
notify: sssd neu starten
- name: authselect konfigurieren
command: authselect select sssd with-mkhomedir --force
changed_when: false
- name: sudoers-Eintrag in user-nsswitch.conf setzen
lineinfile:
path: /etc/authselect/user-nsswitch.conf
regexp: '^sudoers:'
line: 'sudoers: files sss'
state: present
notify: authselect anwenden
- name: oddjobd starten
systemd:
name: oddjobd
enabled: true
state: started
- Merksatz
- authselect generiert /etc/nsswitch.conf komplett neu aus dem gewählten Profil und aus /etc/authselect/user-nsswitch.conf – direkte Einträge in /etc/nsswitch.conf werden dabei überschrieben. Änderungen gehören deshalb in user-nsswitch.conf und werden über authselect apply-changes aktiv geschaltet. Reihenfolge zwingend: erst authselect select, danach den sudoers-Eintrag setzen – sonst wird er beim nächsten select wieder verworfen.
templates/sssd.conf.j2
- Das Template nutzt Ansible-Variablen – so funktioniert dieselbe Rolle für jeden Studenten, ohne den Code anzufassen. Nur defaults/main.yml oder group_vars müssen pro Umgebung angepasst werden.
- vi ~/ansible/roles/sssd/templates/sssd.conf.j2
[sssd]
config_file_version = 2
services = nss, pam, sudo
domains = {{ domain }}
[domain/{{ domain }}]
id_provider = ldap
auth_provider = ldap
chpass_provider = ldap
access_provider = permit
sudo_provider = ldap
ldap_uri = ldaps://ldap.{{ domain }}
ldap_search_base = dc={{ dc1 }},dc={{ dc2 }}
ldap_sudo_search_base = ou=sudo,dc={{ dc1 }},dc={{ dc2 }}
ldap_default_bind_dn = cn=admin,dc={{ dc1 }},dc={{ dc2 }}
ldap_default_authtok = {{ ldap_password }}
ldap_tls_cacert = /etc/pki/tls/certs/ca-bundle.crt
ldap_tls_reqcert = hard
cache_credentials = True
[nss]
filter_users = root,daemon,bin,sys,sync,games,man,lp,mail,news,uucp,proxy,nobody,systemd-network,systemd-resolve,dbus,polkitd,unbound,tss,sssd,chrony,sshd,rngd
[pam]
offline_credentials_expiration = 2
handlers/main.yml
- Handler laufen nur, wenn ein Task mit notify sie tatsächlich auslöst, und erst am Ende des Playbook-Durchlaufs. Das verhindert unnötige Neustarts von Diensten, wenn sich an der Konfiguration nichts geändert hat.
- vi ~/ansible/roles/sssd/handlers/main.yml
---
- name: sssd neu starten
systemd:
name: sssd
state: restarted
- name: authselect anwenden
command: authselect apply-changes
defaults/main.yml
- Standardwerte – werden durch group_vars oder host_vars überschrieben, ohne dass die Rolle selbst verändert werden muss. Das ist der Mechanismus, der dieselbe Rolle für unterschiedliche Studenten-Domains (it201, it202, ...) wiederverwendbar macht.
- vi ~/ansible/roles/sssd/defaults/main.yml
---
domain: "it2XX.int"
dc1: "it2XX"
dc2: "int"
ldap_password: "123Start$"
- Für den produktiven Einsatz
- Passwort niemals im Klartext in defaults/main.yml – stattdessen mit ansible-vault verschlüsseln. Im Kursumfeld mit Wegwerf-Passwörtern ist das Klartext-Passwort didaktisch vertretbar, in Produktion nicht.
- ansible-vault encrypt_string '123Start$' --name 'ldap_password'
Playbook: DMZ ausrollen
- Ein Playbook, das die Rolle auf die dmz-Gruppe anwendet – der Tag sssd erlaubt es, sie gezielt einzeln auszuführen, statt immer das komplette Playbook zu starten.
- vi ~/ansible/dmz.yml
---
- name: DMZ-Server konfigurieren
hosts: dmz
roles:
- { role: sssd, tags: ['sssd'] }
- SSSD ausrollen und testen.
- ansible-playbook ~/ansible/dmz.yml --tags sssd
- Dry-run – zeigt was sich ändern würde, ohne es anzuwenden. Nützlich um vor einem echten Lauf zu prüfen, welche Tasks als changed markiert würden.
- ansible-playbook ~/ansible/dmz.yml --check
Kontrolle
- SSSD auf einem Server prüfen. getent fragt über nsswitch.conf alle konfigurierten Quellen ab (hier
- files und sss) – erscheint der Benutzer, funktioniert die LDAP-Anbindung.
- ansible ns.it2XX.int -m command -a "getent passwd thomas"
- nsswitch.conf prüfen – sudoers-Zeile muss sss enthalten. Fehlt sie, liest das System keine sudo-Regeln aus LDAP, selbst wenn sssd.conf korrekt konfiguriert ist.
- ansible dmz -m command -a "grep sudoers /etc/nsswitch.conf"
- Alle Fakten eines Servers anzeigen – nützlich zur Fehlersuche. Das setup-Modul liefert Systeminformationen (IP, OS, Hardware), auf die auch in Templates über Variablen wie ansible_date_time zugegriffen werden kann.
- ansible ns.it2XX.int -m setup
Logs und Debugging
- -v, -vv und -vvv erhöhen die Ausgabe-Ausführlichkeit von ansible-playbook schrittweise – von den Task-Ergebnissen bis hin zu den vollständigen Modul-Argumenten und Verbindungsdetails. Bei unklaren Fehlern liefert -vvv meist den entscheidenden Hinweis.
- ansible-playbook ~/ansible/dmz.yml -v
- ansible-playbook ~/ansible/dmz.yml -vvv