Ansible mit Rocky: Unterschied zwischen den Versionen
Zur Navigation springen
Zur Suche springen
| Zeile 3: | Zeile 3: | ||
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. | 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 ''' | + | 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 == | == Voraussetzungen == | ||
Version vom 9. Juli 2026, 13:08 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 client.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"
}
- Verbindungsuser prüfen – muss kit sein, nicht root. Damit lässt sich schnell verifizieren, dass ansible_user aus dem Inventory tatsächlich greift.
- ansible dmz -m command -a "whoami"
- 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