In diesem Kapitel werden Sie lernen, wie Sie mit Ansible arbeiten.
Ziele: In diesem Kapitel wird Folgendes behandelt:
Ansible-Implementierung; Konfigurationsänderungen auf einem Server anwenden; erste Ansible-Playbooks entwerfen;
ansible, module, playbook
Vorkenntnisse: Schwierigkeitsgrad:
Lesezeit: 31 Minuten
Ansible zentralisiert und automatisiert Verwaltungsaufgaben. Ansible ist:
agentenlos (es erfordert keine spezielle Installation auf Clients),
idempotent (das Ergebnis ist bei jedem Lauf identisch).
Es verwendet das SSH-Protokoll, um GNU/Linux-Clients zu konfigurieren oder das WinRM-Protokoll für Windows-Clients. Wenn keines dieser Protokolle verfügbar ist, ist es für Ansible immer möglich, eine API zu verwenden, das Ansible zu einem echten Schweizermesser für die Konfiguration von Servern, Workstations, Docker-Diensten, Netzwerkgeräten usw. macht (praktisch fast alles).
Warnhinweis
Das Öffnen von SSH oder WinRM Kanälen zu allen Clients des Ansible Servers macht es zu einem kritischen Element der Architektur, das sorgfältig überwacht werden muss.
Da Ansible push-basiert ist, wird die Software den Status seiner Zielserver nach jeder seiner Ausführung nicht zwischenspeichern. Im Gegenteil, Ansible wird bei jeder Ausführung eine neue Statusprüfung durchführen. Es wird als zustandslos bezeichnet.
Es wird Ihnen bei folgenden Aufgaben helfen:
Provisionierung (Bereitstellung einer neuen VM),
Verteilung von Applikationen,
Konfigurationsverwaltung,
Automatisierung,
Orchestrierung (wenn mehr als ein Ziel verwendet wird).
Anmerkung
Ansible wurde ursprünglich von Michael DeHaan, dem Erfinder anderer Tools wie Cobbler, geschrieben.
Die früheste erste Version war 0.0.1, veröffentlicht am 9. März 2012.
Am 17. Oktober 2015 wurde AnsibleWorks (das Unternehmen hinter Ansible) von Red Hat für 150 Millionen Dollar übernommen.
Um eine grafische Oberfläche für Ihre tägliche Arbeit mit Ansible bereitzustellen, können Sie einige Tools wie Ansible Tower (Red Hat) installieren, das nicht kostenlos ist, oder sein Open-Source-Gegenstück Awx, oder es können auch andere Projekte wie Jenkins und das hervorragende Rundeck verwendet werden.
Abstrakt
Um diesem Training zu folgen, benötigst du mindestens 2 Server unter Rocky 8:
die erste wird die Management Maschine sein, auf der Ansible installiert wird.
die zweite wird der Server, der zu konfigurieren und zu verwalten ist (ein weiteres Linux als Rocky Linux wird es genauso tun).
In den folgenden Beispielen hat die Administrations-Station die IP-Adresse 172.16.1.10, die Managed-Station 172.16.1.11. Es liegt an Ihnen, die Beispiele entsprechend Ihrem IP-Adressierungs-Schema anzupassen.
Die Verwaltungsmaschine: die Maschine, auf der Ansible installiert ist. Da Ansible agentenlos ist, wird auf den verwalteten Servern keine Software verteilt.
verwaltete Knoten: Die Zielgeräte, die Ansible verwaltet, werden auch „hosts“ genannt. Dabei kann es sich um Server, Netzwerkgeräte oder beliebige andere Computer handeln.
Das Inventar: eine Datei mit Informationen zu verwalteten Servern.
Aufgaben: Eine Aufgabe ist ein Block, der eine auszuführende Prozedur definiert (z. B. einen Benutzer oder eine Gruppe erstellen, ein Softwarepaket installieren usw.).
Ein Modul: ein Modul abstrahiert eine Aufgabe. Viele Module werden zusammen mit Ansible zur Verfügung gestellt.
Die Playbooks: einfache Dateien im Yaml-Format, die die Zielserver und die auszuführenden Aufgaben definieren.
Eine Rolle: Eine Rolle ermöglicht es Ihnen, die Playbooks und alle anderen erforderlichen Dateien (Vorlagen, Skripte usw.) zu organisieren, um die Wiederverwendung von Code zu erleichtern.
Eine Kollektion: Eine Kollektion umfasst einen logischen Satz von Playbooks, Rollen, Modulen und Plugins.
Die Fakten: Hierbei handelt es sich um globale Variablen, die Informationen über das System enthalten (Maschinenname, Systemversion, Netzwerkschnittstelle und Konfiguration, usw.).
Handler: werden verwendet, um zu veranlassen, dass ein Dienst angehalten oder neu gestartet wird, wenn er sich ändert.
Beachten Sie, dass Ansible mit einer eigenen Python-Version geliefert wird, die sich von der Systemversion (hier 3.11.2 gegenüber 3.6.8) unterscheidet. Sie müssen dies berücksichtigen, wenn Sie die für Ihre Installation erforderlichen Python-Module per PIP installieren (z.B., pip3.11 install PyVMomi).
python3-argcomplete wird von EPEL zur Verfügung gestellt. Installieren Sie epel-release, falls Sie dies noch nicht getan haben.
Dieses Paket hilft Ihnen beim Ergänzen von Ansible-Befehlen.
Die manuell installierte Version ist in unserem Fall älter als die durch RPM gepackte Version, da wir eine ältere Python-Version verwendet haben. Diese Beobachtung wird natürlich mit der Zeit und dem Alter der Distribution und der Python-Version variieren.
Die Server-Konfiguration befindet sich unter /etc/ansible.
Es gibt zwei grundlegende Konfigurationsdateien:
Die Hauptkonfigurationsdatei ansible.cfg, in der sich die Befehle, Module, Plugins und die SSH-Konfiguration befinden;
Die hosts-Clientcomputerverwaltungsinventardatei, in der Clients und Clientgruppen deklariert werden.
Die Konfigurationsdatei wird automatisch erstellt, wenn Ansible mit seinem RPM-Paket installiert wurde. Bei einer pip-Installation existiert diese Datei nicht. Wir müssen es manuell mit dem Befehl ansible-config erstellen:
Mit der Option --disabled können Sie den Optionsset auskommentieren, indem Sie ihm ; voranstellen.
Hinweis
Sie können Ihre Ansible-Konfiguration auch in Ihr Code-Repository einbetten, wobei Ansible die gefundenen Konfigurationsdateien in der folgenden Reihenfolge lädt (die erste Datei, auf die es trifft, wird verarbeitet und andere werden ignoriert):
Wenn die Umgebungsvariable $ANSIBLE_CONFIG gesetzt ist, wird die angegebene Datei geladen.
ansible.cfg, wenn es im aktuellen Verzeichnis vorhanden ist.
~/.ansible.cfg, falls vorhanden (im Home-Verzeichnis des Benutzers).
Wird keine dieser drei Dateien gefunden, wird die Standarddatei geladen.
Da Ansible mit allen zu konfigurierenden Geräten arbeiten muss, ist es wichtig, ihm eine (oder mehrere) gut strukturierte Inventardatei(en) zur Verfügung zu stellen, die perfekt zu Ihrem Projekt passen.
Manchmal müssen Sie sorgfältig darüber nachdenken, wie Sie diese Datei gestalten.
Wechseln Sie zur Default-Inventardatei, die sich unter /etc/ansible/hosts befindet. Einige Beispiele werden bereitgestellt und kommentiert:
# This is the default ansible 'hosts' file.
#
# It should live in /etc/ansible/hosts
#
# - Comments begin with the '#' character
# - Blank lines are ignored
# - Groups of hosts are delimited by [header] elements
# - You can enter hostnames or ip addresses
# - A hostname/ip can be a member of multiple groups
# Ex 1: Ungrouped hosts, specify before any group headers:
## green.example.com
## blue.example.com
## 192.168.100.1
## 192.168.100.10
# Ex 2: A collection of hosts belonging to the 'webservers' group:
## [webservers]
## alpha.example.org
## beta.example.org
## 192.168.1.100
## 192.168.1.110
# If you have multiple hosts following a pattern, you can specify
# them like this:
## www[001:006].example.com
# Ex 3: A collection of database servers in the 'dbservers' group:
## [dbservers]
##
## db01.intranet.mydomain.net
## db02.intranet.mydomain.net
## 10.25.1.56
## 10.25.1.57
# Here's another example of host ranges, this time there are no
# leading 0s:
## db-[99:101]-node.example.com
Wie Sie feststellen können, verwendet die als Beispiel bereitgestellte Datei das INI-Format, das bei Systemadministratoren gut bekannt ist. Beachten Sie, dass Sie ein anderes Dateiformat wählen können (z.B., Yaml), aber für erste Tests passt das INI-Format gut in den nächsten Beispielen.
Das Inventar kann automatisch in der Produktion generiert werden, insbesondere wenn Sie über eine Virtualisierungsumgebung wie VMware VSphere oder eine Cloud-Umgebung (AWS, OpenStack oder andere) verfügen.
Erstellen Sie eine Hostgruppe in /etc/ansible/hosts:
Wie Sie vielleicht bemerkt haben, werden Gruppen in eckigen Klammern angegeben. Dann kommen die Elemente, die zu den Gruppen gehören. Sie können beispielsweise eine rocky8-Gruppe erstellen, indem Sie den folgenden Block in die Datei einfügen:
[rocky8]
172.16.1.10
172.16.1.11
Gruppen können innerhalb anderer Gruppen verwendet werden. In diesem Fall müssen Sie mit dem Attribut :children angeben, dass die übergeordnete Gruppe aus Untergruppen besteht, wie in diesem Fall:
Da wir die Authentifizierung auf unseren beiden Testservern noch nicht konfiguriert haben, funktionieren nicht alle der folgenden Beispiele. Sie dienen als Beispiele zum besseren Verständnis und werden später in diesem Kapitel voll funktionsfähig sein.
Listen Sie die Hosts auf, die zur Gruppe „rocky8“ gehören:
ansible rocky8 --list-hosts
Testen Sie eine Gruppe von Hosts mit dem Modul ping:
ansible rocky8 -m ping
Fakten über eine Hostgruppe mit dem setup-Modul anzeigen:
ansible rocky8 -m setup
Führen Sie den Befehl auf der Hostgruppe aus, indem Sie das command-Modul mit den folgenden Argumenten aufrufen:
ansible rocky8 -m command -a 'uptime'
Einen Befehl mit Administratorrechten ausführen:
ansible ansible_clients --become -m command -a 'reboot'
Run a command using a custom inventory file:
ansible rocky8 -i ./local-inventory -m command -a 'date'
Anmerkung
Wie in diesem Beispiel ist es manchmal einfacher, die Deklaration verwalteter Geräte in verschiedene Dateien zu unterteilen (z. B. beim Cloud-Projekt) und Ansible den Pfad zu diesen Dateien bereitzustellen, als eine lange Inventardatei zu pflegen.
Option
Beschreibung
-a 'arguments'
Die Argumente, die an das Modul übergeben werden.
-b -K
Fordert ein Passwort an und führt das Kommando mit höheren Rechten aus.
--user=username
Verwendet diesen Benutzer, um sich mit dem Zielhost zu verbinden, anstatt mit dem aktuellen Benutzer.
--become-user=username
Führt die Operation als diesen Benutzer aus (Standard: root).
-C
Simulation. Macht bitte keine Änderungen am Ziel, sondern testet es um zu sehen, was geändert werden sollte.
Sowohl auf der Verwaltungsmaschine als auch auf den Clients erstellen wir einen ansible-Benutzer, der für die von Ansible ausgeführten Operationen zuständig ist. Dieser Benutzer braucht sudo-Rechte haben und muss daher zur Gruppe wheel hinzugefügt werden.
Dieser Benutzer wird verwendet:
Auf der Admin-Station-Seite: Zum Ausführen von ansible- und SSH-Befehlen für verwaltete Clients.
Auf verwalteten Stationen (hier fungiert der Server, der als Verwaltungsstation fungiert, auch als Client, wird also selbst verwaltet), um die von der Verwaltungsstation gestarteten Befehle auszuführen: Er muss daher über Sudo-Rechte verfügen.
Erstellen Sie auf beiden Maschinen einen ansible-Benutzer, der Ansible gewidmet ist:
Ändern Sie die sudoers-Konfiguration, um Mitgliedern der wheel-Gruppe die Ausführung von sudo ohne Passwort zu ermöglichen:
$ sudo visudo
Unser Ziel ist es, die vorbelegung auszukommentieren und die NOPASSWD-Option zu ändern, sodass diese Zeilen wie folgt aussehen:
## Allows people in group wheel to run all commands
# %wheel ALL=(ALL) ALL
## Same thing without a password
%wheel ALL=(ALL) NOPASSWD: ALL
Warnhinweis
Wenn Sie bei der Eingabe von Ansible-Befehlen die folgende Fehlermeldung erhalten, liegt das wahrscheinlich daran, dass Sie diesen Schritt auf einem Ihrer Clients vergessen haben:
"msg": "Missing sudo password
Wenn Sie ab diesem Zeitpunkt die Verwaltung nutzen, beginnen Sie mit diesem neuen Benutzer zu arbeiten:
Sie werden nach dem „ansible“ Passwort der Remote-Server gefragt, was ein Sicherheitsproblem darstellt...
Hinweis
Wenn Sie folgende Fehlermeldung erhalten:
"msg": "to use the 'ssh' connection type with passwords, you must install the sshpass program",
installieren Sie einfach sshpass auf der Verwaltungstation:
$ sudo dnf install sshpass
Abstrakt
Jetzt können Sie Befehle testen, die zuvor in diesem Kapitel nicht funktionierten.
Der Dual-Key wird mit dem Befehl ssh-keygen auf der Managementstation vom ansible-Benutzer generiert:
[ansible]$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/ansible/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/ansible/.ssh/id_rsa.
Your public key has been saved in /home/ansible/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:Oa1d2hYzzdO0e/K10XPad25TA1nrSVRPIuS4fnmKr9g ansible@localhost.localdomain
The key's randomart image is:
+---[RSA 3072]----+
| .o . +|
| o . =.|
| . . + +|
| o . = =.|
| S o = B.o|
| = + = =+|
| . + = o+B|
| o + o *@|
| . Eoo .+B|
+----[SHA256]-----+
Der öffentliche Schlüssel kann auf die Server kopiert werden:
Kommentieren Sie die folgende Zeile aus dem Abschnitt [defaults] in der Konfigurationsdatei /etc/ansible/ansible.cfg erneut aus, um die Kennwortauthentifizierung zu verhindern:
Es ist kein Passwort erforderlich, die Authentifizierung mit privatem und öffentlichem Schlüssel funktioniert!
Anmerkung
In der Produktionsumgebung sollten Sie jetzt die zuvor festgelegten „ansible“ Passwörter entfernen, um Sicherheit zu gewährleisten (da jetzt kein Authentifizierungspasswort erforderlich ist).
There is a module for almost every need! Wir empfehlen Ihnen daher, statt des shell-Moduls nach einem Modul zu suchen, das Ihren Bedürfnissen entspricht.
Jede Bedarfskategorie hat ihr eigenes Modul. Hier ist eine unvollständige Liste:
Typ
Beispiele
Systemverwaltung
user (Benutzerverwaltung), group (Gruppenverwaltung), etc.
Versuchen Sie, die letzten beiden Befehle zweimal auszuführen. Sie werden feststellen, dass Ansible beim ersten Mal Aktionen ausführt, um den durch den Befehl festgelegten Zustand zu erreichen. Beim zweiten Mal wird nichts getan, da erkannt wurde, dass der Status bereits erreicht wurde!
Um mehr über Ansible zu erfahren und sich mit der Suche in der Ansible-Dokumentation vertraut zu machen, finden Sie hier einige Übungen, die Sie durchführen können, bevor Sie fortfahren:
Erstellen Sie die Gruppen Paris, Tokio, NewYork
Erstellen Sie den Benutzer supervisor
Ändern Sie den Benutzer auf eine UID von 10000
Ändern Sie den Benutzer, so dass er zur Paris-Gruppe gehört
tree-Software installieren
crond-Dienst stoppen
Eine leere Datei mit 644 Rechten erstellen
Client-Distribution aktualisieren
Client neu starten
Warnhinweis
shell-Module vermeiden. Schauen Sie in der Dokumentation nach den passenden Modulen!
System-facts sind Variablen, die von Ansible über das setup-Modul abgerufen werden.
Werfen Sie einen Blick auf die verschiedenen facts Ihrer Clients, um eine Vorstellung davon zu bekommen, wie viele Informationen mit einem einfachen Befehl leicht abgerufen werden können.
Wir werden später sehen, wie wir Fakten in unseren Playbooks nutzen und wie wir eigene Fakten - facts - erstellen können.
Nachdem wir nun gesehen haben, wie man einen Remote-Server mit Ansible über die Befehlszeile einrichtet, können wir das Konzept der Playbooks untersuchen. Playbooks sind eine weitere Möglichkeit, Ansible zu verwenden. Sie sind zwar nicht viel komplexer, erleichtern aber die Wiederverwendung von Code.
Ansible's playbooks describe a policy to be applied to remote systems, to force their configuration. Playbooks sind in einem leicht verständlichen Textformat geschrieben, das eine Reihe von Tasks gruppiert: dem yaml-Format.
Mit dem folgenden Playbook können wir Apache und MariaDB auf unseren Zielservern installieren.
Erstellen Sie eine test.yml-Datei mit folgendem Inhalt:
---
- hosts: rocky8 <1>
become: true <2>
become_user: root
tasks:
- name: ensure apache is at the latest version
dnf: name=httpd,php,php-mysqli state=latest
- name: ensure httpd is started
systemd: name=httpd state=started
- name: ensure mariadb is at the latest version
dnf: name=mariadb-server state=latest
- name: ensure mariadb is started
systemd: name=mariadb state=started
...
<1> Die entsprechende Ziel-Gruppe bzw. der betreffende Ziel-Server muss im Inventar vorhanden sein
<2> Sobald die Verbindung hergestellt ist, wird der Benutzer zum root (standardmäßig über sudo)
Die Ausführung des Playbooks erfolgt mit dem Befehl ansible-playbook:
$ ansible-playbook test.yml
PLAY [rocky8] ****************************************************************
TASK [setup] ******************************************************************
ok: [172.16.1.10]
ok: [172.16.1.11]
TASK [ensure apache is at the latest version] *********************************
ok: [172.16.1.10]
ok: [172.16.1.11]
TASK [ensure httpd is started] ************************************************
changed: [172.16.1.10]
changed: [172.16.1.11]
TASK [ensure mariadb is at the latest version] **********************************
changed: [172.16.1.10]
changed: [172.16.1.11]
TASK [ensure mariadb is started] ***********************************************
changed: [172.16.1.10]
changed: [172.16.1.11]
PLAY RECAP *********************************************************************
172.16.1.10 : ok=5 changed=3 unreachable=0 failed=0
172.16.1.11 : ok=5 changed=3 unreachable=0 failed=0
Für eine bessere Lesbarkeit wird empfohlen, Playbooks im vollständigen yaml-Format zu schreiben. Im vorherigen Beispiel werden die Argumente in derselben Zeile des Formulars angegeben, wobei der Argumentwert auf seinen Namen getrennt durch ein Gleichheitzeichen = folgt. Schauen Sie sich das gleiche Playbook im vollständigen Yaml-Format an:
---
- hosts: rocky8
become: true
become_user: root
tasks:
- name: ensure apache is at the latest version
dnf:
name: httpd,php,php-mysqli
state: latest
- name: ensure httpd is started
systemd:
name: httpd
state: started
- name: ensure mariadb is at the latest version
dnf:
name: mariadb-server
state: latest
- name: ensure mariadb is started
systemd:
name: mariadb
state: started
...
Hinweis
„dnf“ ist eines der Module, das es Ihnen ermöglicht, eine Liste als Argument anzugeben.
Hinweis zu collections: Ansible stellt Module jetzt in Form von Sammlungen bereit. Einige Module werden standardmäßig in der ansible.builtin-collection bereitgestellt, andere müssen manuell installiert werden über:
dabei ist [collectionname] der Name der Kollektion (die eckigen Klammern hier werden verwendet, um hervorzuheben, dass dieser durch einen tatsächlichen Kollektiosnamen ersetzt werden muss, und sind NICHT Teil des Befehls).
Das vorherige Beispiel sollte wie folgt geschrieben werden:
---
- hosts: rocky8
become: true
become_user: root
tasks:
- name: ensure apache is at the latest version
ansible.builtin.dnf:
name: httpd,php,php-mysqli
state: latest
- name: ensure httpd is started
ansible.builtin.systemd:
name: httpd
state: started
- name: ensure mariadb is at the latest version
ansible.builtin.dnf:
name: mariadb-server
state: latest
- name: ensure mariadb is started
ansible.builtin.systemd:
name: mariadb
state: started
...
Ein Playbook ist nicht auf ein Ziel beschränkt:
---
- hosts: webservers
become: true
become_user: root
tasks:
- name: ensure apache is at the latest version
ansible.builtin.dnf:
name: httpd,php,php-mysqli
state: latest
- name: ensure httpd is started
ansible.builtin.systemd:
name: httpd
state: started
- hosts: databases
become: true
become_user: root
- name: ensure mariadb is at the latest version
ansible.builtin.dnf:
name: mariadb-server
state: latest
- name: ensure mariadb is started
ansible.builtin.systemd:
name: mariadb
state: started
...
Sie können die Syntax des Playbooks wie folgt prüfen:
$ ansible-playbook --syntax-check play.yml
Sie können auch ein "linter" für yaml verwenden:
$ dnf install -y yamllint
und dann die yaml-Syntax der Playbooks überprüfen:
$ yamllint test.yml
test.yml
8:1 error syntax error: could not find expected ':' (syntax)