Kapitel 4. Inventarisierung: Beschreibe deine Server
Diese Arbeit wurde mithilfe von KI übersetzt. Wir freuen uns über dein Feedback und deine Kommentare: translation-feedback@oreilly.com
Bis jetzt haben wir nur mit einem Server (oder Host, wie Ansible ihn nennt) gearbeitet. Die einfachste Bestandsaufnahme ist eine kommagetrennte Liste von Hostnamen, die du auch ohne einen Server erstellen kannst:
$ ansible all -i 'localhost,' -a date
In der Realität wirst du mehrere Hosts verwalten. Die Sammlung von Hosts, die Ansible kennt, wird als Inventar bezeichnet. In diesem Kapitel lernst du, wie du eine Reihe von Hosts als Ansible-Inventar beschreibst, indem du ein Inventar erstellst, das mehrere Maschinen enthält.
Deine ansible.cfg-Datei sollte wie Beispiel 4-1 aussehen, in dem alle Inventar-Plug-ins explizit aktiviert sind.
Beispiel 4-1. ansible.cfg
[defaults] inventory = inventory [inventory] enable_plugins = host_list, script, auto, yaml, ini, toml
In diesem Kapitel werden wir ein Verzeichnis namens inventory für die Inventarbeispiele verwenden. Das Ansible-Inventar ist ein sehr flexibles Objekt: Es kann eine Datei (in verschiedenen Formaten), ein Verzeichnis oder eine ausführbare Datei sein, und einige ausführbare Dateien sind als Plug-ins gebündelt. Inventar-Plug-ins ermöglichen es uns, auf Datenquellen wie deinen Cloud-Provider zu verweisen, um das Inventar zu erstellen. Ein Inventar kann getrennt von deinen Playbooks gespeichert werden. Das bedeutet, dass du ein Inventarverzeichnis erstellen kannst, das du mit Ansible auf der Kommandozeile, mit Hosts, die in Vagrant, Amazon EC2, Google Cloud Platform oder Microsoft Azure laufen, oder wo immer du willst, verwenden kannst!
Hinweis
Serge van Ginderachter ist die kompetenteste Person, die man zum Thema Ansible-Inventar lesen kann. In seinem Blog findest du ausführliche Details.
Inventar/Hosts-Dateien
Die Standardmethode, um deine Hosts in Ansible zu beschreiben, ist die Auflistung in Textdateien, den sogenannten Inventory-Hosts-Dateien. Die einfachste Form ist eine Liste von Hostnamen in einer Datei namens hosts, wie in Beispiel 4-2 gezeigt.
Beispiel 4-2. Eine sehr einfache Bestandsdatei
frankfurt.example.com helsinki.example.com hongkong.example.com johannesburg.example.com london.example.com newyork.example.com seoul.example.com sydney.example.com
Ansible fügt standardmäßig einen Host zum Inventar hinzu: localhost. Es versteht, dass localhost
sich auf deinen lokalen Rechner bezieht, mit dem es direkt interagiert, anstatt sich über SSH zu verbinden.
Vorbereitungen: Mehrere Vagrant-Maschinen
Um über das Inventar zu sprechen, musst du mit mehreren Hosts interagieren. Konfigurieren wir Vagrant so, dass er drei Hosts aufruft. Wir nennen sie einfallslos vagrant1
, vagrant2
, und vagrant3
.
Bevor du eine neue Vagrantdatei für dieses Kapitel erstellst, stelle sicher, dass du deine bestehende(n) virtuelle(n) Maschine(n) zerstörst, indem du Folgendes ausführst:
$ vagrant destroy --force
Wenn du die Option --force
nicht angibst, wird Vagrant dich auffordern, zu bestätigen, dass du jede virtuelle Maschine, die in der Vagrantdatei aufgeführt ist, zerstören willst.
Als nächstes erstellst du ein neues Vagrantfile, das wie Beispiel 4-3 aussieht.
Beispiel 4-3. Vagrantfile mit drei Servern
VAGRANTFILE_API_VERSION = "2" Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| # Use the same key for each machine config.ssh.insert_key = false config.vm.define "vagrant1" do |vagrant1| vagrant1.vm.box = "ubuntu/focal64" vagrant1.vm.network "forwarded_port", guest: 80, host: 8080 vagrant1.vm.network "forwarded_port", guest: 443, host: 8443 end config.vm.define "vagrant2" do |vagrant2| vagrant2.vm.box = "ubuntu/focal64" vagrant2.vm.network "forwarded_port", guest: 80, host: 8081 vagrant2.vm.network "forwarded_port", guest: 443, host: 8444 end config.vm.define "vagrant3" do |vagrant3| vagrant3.vm.box = "centos/stream8" vagrant3.vm.network "forwarded_port", guest: 80, host: 8082 vagrant3.vm.network "forwarded_port", guest: 443, host: 8445 end end
Vagrant verwendet ab Version 1.7 standardmäßig einen anderen SSH-Schlüssel für jeden Host. Beispiel 4-3 enthält die Zeile, mit der das frühere Verhalten, den gleichen SSH-Schlüssel für jeden Host zu verwenden, wiederhergestellt wird:
config.ssh.insert_key = false
Die Verwendung desselben Schlüssels auf jedem Host vereinfacht unser Ansible-Setup, da wir einen einzigen SSH-Schlüssel in der Konfiguration angeben können.
Nehmen wir an, dass jeder dieser Server ein Webserver sein kann. Beispiel 4-3 ordnet die Ports 80 und 443 in jedem Vagrant-Rechner einem Port auf dem lokalen Rechner zu.
Wir sollten in der Lage sein, die virtuellen Maschinen zu starten, indem wir Folgendes ausführen:
$ vagrant up
Wenn alles gut geht, sollte die Ausgabe ungefähr so aussehen:
Bringing machine 'vagrant1' up with 'virtualbox' provider... Bringing machine 'vagrant2' up with 'virtualbox' provider... Bringing machine 'vagrant3' up with 'virtualbox' provider... ... vagrant1: 80 (guest) => 8080 (host) (adapter 1) vagrant1: 443 (guest) => 8443 (host) (adapter 1) vagrant1: 22 (guest) => 2222 (host) (adapter 1) ==> vagrant1: Running 'pre-boot' VM customizations... ==> vagrant1: Booting VM... ==> vagrant1: Waiting for machine to boot. This may take a few minutes... vagrant1: SSH address: 127.0.0.1:2222 vagrant1: SSH username: vagrant vagrant1: SSH auth method: private key ==> vagrant1: Machine booted and ready! ==> vagrant1: Checking for guest additions in VM... ==> vagrant1: Mounting shared folders... vagrant1: /vagrant => /Users/bas/code/ansible/ansiblebook/ansiblebook/ch03
Als Nächstes müssen wir wissen, welche Ports auf dem lokalen Rechner auf den SSH-Port (22) innerhalb jeder VM abgebildet sind. Wir können diese Informationen erhalten, indem wir Folgendes ausführen:
$ vagrant ssh-config
Die Ausgabe sollte in etwa so aussehen:
Host vagrant1 HostName 127.0.0.1 User vagrant Port 2222 UserKnownHostsFile /dev/null StrictHostKeyChecking no PasswordAuthentication no IdentityFile /Users/lorin/.vagrant.d/insecure_private_key IdentitiesOnly yes LogLevel FATAL Host vagrant2 HostName 127.0.0.1 User vagrant Port 2200 UserKnownHostsFile /dev/null StrictHostKeyChecking no PasswordAuthentication no IdentityFile /Users/lorin/.vagrant.d/insecure_private_key IdentitiesOnly yes LogLevel FATAL Host vagrant3 HostName 127.0.0.1 User vagrant Port 2201 UserKnownHostsFile /dev/null StrictHostKeyChecking no PasswordAuthentication no IdentityFile /Users/lorin/.vagrant.d/insecure_private_key IdentitiesOnly yes LogLevel FATAL
Viele der Informationen auf ssh-config
wiederholen sich und können reduziert werden. Die Informationen, die sich pro Host unterscheiden, sind, dass vagrant1
den Port 2222, vagrant2
den Port 2200 und vagrant3
den Port 2201 verwendet.
Ansible verwendet standardmäßig deinen lokalen SSH-Client, was bedeutet, dass es alle Aliase versteht, die du in deiner SSH-Konfigurationsdatei einrichtest. Deshalb verwenden wir einen Platzhalter-Alias in der Datei ~/.ssh/config:
Host vagrant* Hostname 127.0.0.1 User vagrant UserKnownHostsFile /dev/null StrictHostKeyChecking no PasswordAuthentication no IdentityFile ~/.vagrant.d/insecure_private_key IdentitiesOnly yes LogLevel FATAL
Ändere deine Inventar-/Hosts-Datei so, dass sie wie folgt aussieht:
vagrant1 ansible_port=2222 vagrant2 ansible_port=2200 vagrant3 ansible_port=2201
Stelle nun sicher, dass du auf diese Rechner zugreifen kannst. Um zum Beispiel Informationen über die Netzwerkschnittstelle von vagrant2
zu erhalten, führe Folgendes aus:
$ ansible vagrant2 -a "ip addr show dev enp0s3"
Deine Ausgabe sollte in etwa so aussehen:
vagrant2 | CHANGED | rc=0 >> 2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/ether 02:1e:de:45:2c:c8 brd ff:ff:ff:ff:ff:ff inet 10.0.2.15/24 brd 10.0.2.255 scope global dynamic enp0s3 valid_lft 86178sec preferred_lft 86178sec inet6 fe80::1e:deff:fe45:2cc8/64 scope link valid_lft forever preferred_lft forever
Parameter des Verhaltensinventars
Um unsere Vagrant-Maschinen in der Ansible-Inventardatei zu beschreiben, mussten wir explizit den Port (2222, 2200 oder 2201) angeben, mit dem sich der SSH-Client von Ansible verbinden sollte. Ansible nennt solche Variablen Verhaltensinventarisierungsparameter, und es gibt mehrere von ihnen, die du verwenden kannst, wenn du die Ansible-Standardeinstellungen für einen Host überschreiben willst (siehe Tabelle 4-1).
Name | Standard | Beschreibung |
---|---|---|
ansible_host |
Name des Gastgebers | Hostname oder IP-Adresse für die SSH-Verbindung |
ansible_port |
22 | Port zu SSH zu |
ansible_user |
$BENUTZER | Benutzer zu SSH als |
ansible_password |
(Keine) | Passwort für die SSH-Authentifizierung |
ansible_connection |
smart | Wie Ansible eine Verbindung zum Host herstellt (siehe folgender Abschnitt) |
ansible_ssh_private_key_file |
(Keine) | Privater SSH-Schlüssel, der für die SSH-Authentifizierung verwendet wird |
ansible_shell_type |
sh | Shell, die für Befehle verwendet werden soll (siehe folgender Abschnitt) |
ansible_python_interpreter |
/usr/bin/python | Python-Interpreter auf dem Host (siehe den folgenden Abschnitt) |
ansible_*_interpreter |
(Keine) | Wie ansible_python_interpreter für andere Sprachen (siehe den folgenden Abschnitt) |
Bei einigen dieser Optionen ist die Bedeutung aus dem Namen ersichtlich, aber andere erfordern mehr Erklärung:
ansible_connection
-
Ansible unterstützt mehrere Transporte, d.h. Mechanismen, die Ansible verwendet, um sich mit dem Host zu verbinden. Der Standardtransport,
smart
, prüft, ob der lokal installierte SSH-Client eine Funktion namensControlPersist
unterstützt. Wenn der SSH-ClientControlPersist
unterstützt, wird Ansible den lokalen SSH-Client verwenden. Ist dies nicht der Fall, greift der intelligente Transport auf eine Python-basierte SSH-Client-Bibliothek namens Paramiko zurück. ansible_shell_type
-
Ansible funktioniert, indem es SSH-Verbindungen zu entfernten Rechnern herstellt und dann Skripte aufruft. Standardmäßig geht Ansible davon aus, dass die entfernte Shell die Bourne-Shell ist, die sich unter /bin/sh befindet, und generiert die entsprechenden Befehlszeilenparameter, die mit dieser Shell funktionieren. Ansible legt temporäre Verzeichnisse an, um diese Skripte zu speichern.
Ansible akzeptiert auch
csh
,fish
und (unter Windows)powershell
als gültige Werte für diesen Parameter. Ansible funktioniert nicht mit eingeschränkten Shells. ansible_python_interpreter
-
Ansible muss wissen, wo sich der Python-Interpreter auf dem entfernten Rechner befindet. Vielleicht möchtest du das ändern und eine Version wählen, die für dich geeignet ist. Der einfachste Weg, Ansible unter Python 3 laufen zu lassen, ist, es mit pip3 zu installieren und dies einzustellen:
ansible_python_interpreter="/usr/bin/env python3"
ansible_*_interpreter
-
Wenn du ein benutzerdefiniertes Modul verwendest, das nicht in Python geschrieben ist, kannst du mit diesem Parameter den Ort des Interpreters angeben (z. B. /usr/bin/ruby). Wir werden dies in Kapitel 12 behandeln.
Verhaltensparameter-Standardwerte ändern
Du kannst einige der Standardwerte der Verhaltensparameter in der Inventardatei oder im Abschnitt defaults
der Datei ansible.cfg überschreiben(Tabelle 4-2). Überlege dir, wo du diese Parameter änderst. Sind die Änderungen eine persönliche Entscheidung oder gelten sie für dein ganzes Team? Braucht ein Teil deines Inventars eine andere Einstellung? Denke daran, dass du die SSH-Einstellungen in der Datei ~/.ssh/config konfigurieren kannst.
Parameter des Verhaltensinventars | ansible.cfg Option |
---|---|
ansible_port |
remote_port |
ansible_user |
remote_user |
ansible_ssh_private_key_file |
ssh_private_key_file |
ansible_shell_type |
executable (siehe den folgenden Absatz) |
Die Option ansible.cfg executable
config ist nicht genau das Gleiche wie der Parameter ansible_shell_type
behavioral inventory. Die ausführbare Datei gibt den vollständigen Pfad der Shell an, die auf dem entfernten Rechner verwendet werden soll (zum Beispiel /usr/local/bin/fish). Ansible schaut sich den Basisnamen dieses Pfads an (in diesem Fall fish) und verwendet diesen als Standardwert für ansible_shell_type
.
Gruppen und Gruppen und Gruppen
Normalerweise wollen wir die Konfiguration für Gruppen von Hosts durchführen und nicht für einen einzelnen Host. Ansible definiert automatisch eine Gruppe namens all
(oder *
), die alle Hosts im Inventar umfasst. Wir können zum Beispiel überprüfen, ob die Uhren auf den Rechnern ungefähr synchronisiert sind, indem wir Folgendes ausführen:
$ ansible all -a "date"
oder
$ ansible '*' -a "date"
Die Ausgabe auf Bas' System sieht folgendermaßen aus:
vagrant2 | CHANGED | rc=0 >> Wed 12 May 2021 01:37:47 PM UTC vagrant1 | CHANGED | rc=0 >> Wed 12 May 2021 01:37:47 PM UTC vagrant3 | CHANGED | rc=0 >> Wed 12 May 2021 01:37:47 PM UTC
Wir können unsere eigenen Gruppen in der Inventar-Hosts-Datei definieren. Ansible verwendet das .ini-Dateiformat für Inventar-Hosts-Dateien; es gruppiert Konfigurationswerte in Abschnitte.
So gibst du an, dass unsere Vagrant-Hosts in einer Gruppe namens vagrant
sind, zusammen mit den anderen Beispielhosts, die am Anfang des Kapitels erwähnt wurden:
frankfurt.example.com helsinki.example.com hongkong.example.com johannesburg.example.com london.example.com newyork.example.com seoul.example.com sydney.example.com [vagrant] vagrant1 ansible_port=2222 vagrant2 ansible_port=2200 vagrant3 ansible_port=2201
Wir könnten die Vagrant-Hosts abwechselnd oben und dann auch in einer Gruppe auflisten, etwa so:
frankfurt.example.com helsinki.example.com hongkong.example.com johannesburg.example.com london.example.com newyork.example.com seoul.example.com sydney.example.com vagrant1 ansible_port=2222 vagrant2 ansible_port=2200 vagrant3 ansible_port=2201 [vagrant] vagrant1 vagrant2 vagrant3
Du kannst Gruppen so verwenden, wie es dir passt: Sie können sich überschneiden oder ineinander verschachtelt sein, wie du willst. Die Reihenfolge spielt keine Rolle, außer für die Lesbarkeit.
Beispiel: Bereitstellen einer Django App
Stell dir vor, du bist für die Bereitstellung einer Django-basierten Webanwendung verantwortlich, die langlaufende Aufträge verarbeitet. Die Anwendung muss die folgenden Dienste unterstützen:
-
Die eigentliche Django-Webanwendung, die von einem Gunicorn HTTP-Server ausgeführt wird
-
Ein NGINX-Webserver, der vor Gunicorn sitzt und statische Inhalte bereitstellt
-
Eine Celery-Warteschlange, die langlaufende Aufträge im Namen der Webanwendung ausführt
-
Eine RabbitMQ-Nachrichtenwarteschlange, die als Backend für Celery dient
-
Eine Postgres-Datenbank, die als persistenter Speicher dient
In späteren Kapiteln werden wir ein detailliertes Beispiel für die Bereitstellung dieser Art von Django-basierter Anwendung durcharbeiten, obwohl unser Beispiel weder Celery noch RabbitMQ verwenden wird. Für den Moment müssen wir diese Anwendung in drei verschiedenen Umgebungen bereitstellen: Production (die echte Umgebung), Staging (zum Testen auf Hosts, auf die unser Team gemeinsamen Zugriff hat) und Vagrant (für lokale Tests).
Wenn wir in die Produktion gehen, wollen wir, dass das gesamte System schnell und zuverlässig reagiert, also tun wir Folgendes:
-
Lass die Webanwendung auf mehreren Hosts laufen, um die Leistung zu verbessern, und schalte einen Load Balancer davor.
-
Betreibe Task-Queue-Server auf mehreren Hosts für bessere Leistung
-
Lege Gunicorn, Celery, RabbitMQ und Postgres auf separate Server
-
Verwende zwei Postgres-Hosts: einen primären und einen Replikat
Angenommen, wir haben einen Load Balancer, drei Webserver, drei Task-Queues, einen RabbitMQ-Server und zwei Datenbankserver, dann sind das 10 Hosts, mit denen wir umgehen müssen(Abbildung 4-1).
Für unsere Staging-Umgebung wollen wir weniger Hosts als in der Produktion verwenden, um Kosten zu sparen, da hier viel weniger Aktivität stattfinden wird als in der Produktion. Nehmen wir an, wir entscheiden uns, nur zwei Hosts für das Staging zu verwenden. Wir stellen den Webserver und die Task Queue auf einen Staging-Host und RabbitMQ und Postgres auf den anderen.
Für unsere lokale Vagrant-Umgebung entscheiden wir uns, drei Server zu verwenden: einen für die Web-App, einen für eine Task-Queue und einen, der RabbitMQ und Postgres enthält.
Beispiel 4-4 zeigt eine Beispielinventardatei, in der die Server nach Umgebung (Produktion, Staging, Vagrant) und Funktion (Webserver, Task Queue usw.) gruppiert sind.
Beispiel 4-4. Inventarisierungsdatei für die Bereitstellung einer Django-App
[production] frankfurt.example.com helsinki.example.com hongkong.example.com johannesburg.example.com london.example.com newyork.example.com seoul.example.com sydney.example.com tokyo.example.com toronto.example.com [staging] amsterdam.example.com chicago.example.com [lb] helsinki.example.com [web] amsterdam.example.com seoul.example.com sydney.example.com toronto.example.com vagrant1 [task] amsterdam.example.com hongkong.example.com johannesburg.example.com newyork.example.com vagrant2 [rabbitmq] chicago.example.com tokyo.example.com vagrant3 [db] chicago.example.com frankfurt.example.com london.example.com vagrant3
Wir hätten zuerst alle Server am Anfang der Inventardatei auflisten können, ohne eine Gruppe anzugeben, aber das ist nicht nötig und hätte diese Datei noch länger gemacht.
Beachte, dass wir die Verhaltensinventarisierungsparameter für die Vagrant-Instanzen nur einmal angeben müssen.
Aliase und Ports
Wir haben unsere Vagrant Hosts wie folgt beschrieben:
[vagrant] vagrant1 ansible_port=2222 vagrant2 ansible_port=2200 vagrant3 ansible_port=2201
Die Namen vagrant1
, vagrant2
und vagrant3
sind Aliasnamen. Sie sind nicht die echten Hostnamen, sondern nur nützliche Namen, um auf diese Hosts zu verweisen. Ansible löst Hostnamen mithilfe des Inventars, deiner SSH-Konfigurationsdatei, /etc/hosts und DNS auf. Diese Flexibilität ist bei der Entwicklung nützlich, kann aber auch zu Verwirrung führen.
Ansible unterstützt auch die <hostname>:<port>
Syntax bei der Angabe von Hosts, so dass wir die Zeile, die vagrant1
enthält, durch 127.0.0.1:2222
ersetzen können(Beispiel 4-5).
Beispiel 4-5. Das funktioniert nicht
[vagrant] 127.0.0.1:2222 127.0.0.1:2200 127.0.0.1:2201
Das, was du in Beispiel 4-5 siehst, können wir jedoch nicht wirklich ausführen. Der Grund dafür ist, dass das Inventar von Ansible nur einen einzigen Host mit 127.0.0.1 verknüpfen kann, sodass die Vagrant-Gruppe nur einen statt drei Hosts enthalten würde.
Gruppen von Gruppen
Mit Ansible kannst du auch Gruppen definieren, die sich aus anderen Gruppen zusammensetzen. Da zum Beispiel sowohl die Webserver als auch die Task Queue Server Django und seine Abhängigkeiten benötigen, könnte es sinnvoll sein, eine Gruppe django
zu definieren, die beide enthält. Diese fügst du der Inventardatei hinzu:
[django:children] web task
Beachte, dass sich die Syntax ändert, wenn du eine Gruppe von Gruppen angibst, im Gegensatz zu einer Gruppe von Hosts. So kann Ansible web
und task
als Gruppen und nicht als Hosts interpretieren.
Nummerierte Wirte (Haustiere vs. Rinder)
Die Inventardatei, die du in Beispiel 4-4 gesehen hast, sieht komplex aus. Sie beschreibt 15 Hosts, was in dieser cloudigen, skalierbaren Welt nicht nach einer großen Zahl klingt. Allerdings kann der Umgang mit 15 Hosts in der Inventardatei mühsam sein, weil jeder Host einen völlig anderen Hostnamen hat.
Bill Baker von Microsoft hat den Unterschied zwischen der Behandlung von Servern als Haustiere und der Behandlung von Servern als Vieh herausgearbeitet.1 Wir geben Haustieren eindeutige Namen und behandeln und pflegen sie als Individuen; bei Rindern hingegen geben wir ihnen eine Identifikationsnummer und behandeln sie wie Vieh.
Der "Rinder"-Ansatz für Server ist viel skalierbarer, und Ansible unterstützt ihn gut, indem es numerische Muster unterstützt. Wenn deine 20 Server zum Beispiel web1.example.com, web2.example.com und so weiter heißen, kannst du sie in der Inventardatei wie folgt angeben:
[web] web[1:20].example.com
Wenn du es vorziehst, dass eine führende Null hat (wie z.B. web01.example.com), gibst du das im Bereich wie folgt an:
[web] web[01:20].example.com
Ansible unterstützt auch die Verwendung von alphabetischen Zeichen, um Bereiche anzugeben. Wenn du die Konvention web-a.example.com, web-b.example.com usw. für deine 20 Server verwenden möchtest, kannst du das unter tun:
[web] web-[a:t].example.com
Hosts und Gruppenvariablen: Innerhalb des Inventars
Erinnere dich daran, wie wir verhaltensbezogenen Inventar Parameter für Vagrant-Hosts festlegen können:
vagrant1 ansible_host=127.0.0.1 ansible_port=2222 vagrant2 ansible_host=127.0.0.1 ansible_port=2200 vagrant3 ansible_host=127.0.0.1 ansible_port=2201
Diese Parameter sind Variablen, die für Ansible eine besondere Bedeutung haben. Wir können auch beliebige Variablennamen und zugehörige Werte für Hosts definieren. Wir könnten zum Beispiel eine Variable mit dem Namen color
definieren und sie für jeden Server auf einen Wert setzen:
amsterdam.example.com color=red seoul.example.com color=green sydney.example.com color=blue toronto.example.com color=purple
Wir könnten diese Variable dann wie jede andere Variable in einem Playbook verwenden. Deine Autoren verknüpfen Variablen nicht oft mit bestimmten Hosts. Andererseits verknüpfen wir Variablen oft mit Gruppen.
Um auf unser Django-Beispiel zurückzukommen, müssen die Webanwendung und der Task-Queue-Dienst mit RabbitMQ und Postgres kommunizieren. Wir gehen davon aus, dass der Zugriff auf die Postgres-Datenbank sowohl auf der Netzwerkebene (so dass nur die Webanwendung und die Task-Queue auf die Datenbank zugreifen können) als auch durch Benutzernamen und Passwort gesichert ist. RabbitMQ ist nur über die Netzwerkebene gesichert.
Um alles einzurichten, kannst du:
-
Konfiguriere die Webserver mit dem Hostnamen, Port, Benutzernamen und Passwort des primären Postgres-Servers und dem Namen der Datenbank.
-
Konfiguriere die Aufgabenwarteschlangen mit dem Hostnamen, dem Port, dem Benutzernamen und dem Passwort des primären Postgres-Servers und dem Namen der Datenbank.
-
Konfiguriere die Webserver mit dem Hostnamen und Port des RabbitMQ-Servers.
-
Konfiguriere die Task-Warteschlangen mit dem Hostnamen und Port des RabbitMQ-Servers.
-
Konfiguriere den primären Postgres-Server mit dem Hostnamen, dem Port sowie dem Benutzernamen und dem Passwort des Replikat-Postgres-Servers (nur Produktion).
Diese Konfigurationsinformationen variieren je nach Umgebung, daher ist es sinnvoll, sie als Gruppenvariablen für die Produktions-, Staging- und Vagrant-Gruppen zu definieren. Beispiel 4-6 zeigt eine Möglichkeit, dies in der Inventardatei zu tun. (Eine bessere Möglichkeit, Passwörter zu speichern, wird in Kapitel 8 besprochen).
Beispiel 4-6. Festlegen von Gruppenvariablen im Bestand
[all:vars] ntp_server=ntp.ubuntu.com [production:vars] db_primary_host=frankfurt.example.com db_primary_port=5432 db_replica_host=london.example.com db_name=widget_production db_user=widgetuser db_password=pFmMxcyD;Fc6)6 rabbitmq_host=johannesburg.example.com rabbitmq_port=5672 [staging:vars] db_primary_host=chicago.example.com db_primary_port=5432 db_name=widget_staging db_user=widgetuser db_password=L@4Ryz8cRUXedj rabbitmq_host=chicago.example.com rabbitmq_port=5672 [vagrant:vars] db_primary_host=vagrant3 db_primary_port=5432 db_name=widget_vagrant db_user=widgetuser db_password=password rabbitmq_host=vagrant3 rabbitmq_port=5672
Beachte, wie die Gruppenvariablen in Abschnitten mit dem Namen [<group name>:vars]
organisiert sind. Außerdem haben wir uns die Gruppe all
zunutze gemacht (die, wie du dich erinnern wirst, von Ansible automatisch erstellt wird), um Variablen festzulegen, die sich nicht zwischen den Hosts ändern.
Host- und Gruppenvariablen: In ihren eigenen Dateien
Die Inventardatei ist ein guter Ort, um Host- und Gruppenvariablen zu speichern, wenn du nicht zu viele Hosts hast. Aber je größer dein Inventar wird, desto schwieriger wird es, die Variablen auf diese Weise zu verwalten. Auch wenn Ansible-Variablen Boolesche Werte, Strings, Listen und Wörterbücher enthalten können, kannst du in einer Inventardatei nur Boolesche Werte und Strings angeben.
Ansible bietet einen skalierbareren Ansatz, um Host- und Gruppenvariablen zu verwalten: Du kannst für jeden Host und jede Gruppe eine eigene Variablendatei erstellen. Ansible erwartet, dass diese Variablendateien im YAML-Format vorliegen.
Es sucht nach Host-Variablendateien in einem Verzeichnis namens host_vars und nach Gruppenvariablendateien in einem Verzeichnis namens group_vars. Ansible erwartet, dass sich diese Verzeichnisse entweder in dem Verzeichnis befinden, das deine Playbooks enthält, oder in dem Verzeichnis neben deiner Inventardatei. Wenn du beide Verzeichnisse hast, hat das erste (das Playbook-Verzeichnis) Vorrang.
Wenn Lorin zum Beispiel ein Verzeichnis mit seinen Playbooks unter /home/lorin/playbooks/ und ein Inventarverzeichnis und eine Hosts-Datei unter /home/lorin/inventory/hosts hat, sollte er die Variablen für den Host amsterdam.example.com in die Datei /home/lorin/inventory/host_vars/amsterdam.example.com und die Variablen für die Produktionsgruppe in die Datei /home/lorin/inventory/group_vars/production legen (siehe Beispiel 4-7).
Beispiel 4-7. group_vars/production
--- db_primary_host: frankfurt.example.com db_primary_port: 5432 db_replica_host: london.example.com db_name: widget_production db_user: widgetuser db_password: 'pFmMxcyD;Fc6)6' rabbitmq_host: johannesburg.example.com rabbitmq_port: 5672 ...
Wir können auch YAML-Wörterbücher verwenden, um diese Werte darzustellen, wie in Beispiel 4-8 gezeigt.
Beispiel 4-8. group_vars/production, mit Wörterbüchern
--- db: user: widgetuser password: 'pFmMxcyD;Fc6)6' name: widget_production primary: host: frankfurt.example.com port: 5432 replica: host: london.example.com port: 5432 rabbitmq: host: johannesburg.example.com port: 5672 ...
Wenn wir uns für YAML-Wörterbücher entscheiden, greifen wir auf die Variablen mit der Punktnotation wie folgt zu:
"{{ db.primary.host }}"
Wir können auf die Variablen im Wörterbuch auch wie folgt zugreifen:
"{{ db['primary']['host'] }}"
Das steht im Gegensatz dazu, wie wir sonst auf sie zugreifen würden:
"{{ db_primary_host }}"
Wenn wir die Dinge noch weiter aufbrechen wollen, können wir mit Ansible group_vars/production als Verzeichnis statt als Datei definieren. Darin können wir mehrere YAML-Dateien mit Variablendefinitionen ablegen. Wir könnten zum Beispiel datenbankbezogene Variablen in eine Datei und die RabbitMQ-bezogenen Variablen in eine andere Datei packen, wie in den Beispielen 4-9 und 4-10 gezeigt.
Beispiel 4-9. group_vars/production/db
--- db: user: widgetuser password: 'pFmMxcyD;Fc6)6' name: widget_production primary: host: frankfurt.example.com port: 5432 replica: host: london.example.com port: 5432 ...
Beispiel 4-10. group_vars/production/rabbitmq
--- rabbitmq: host: johannesburg.example.com port: 6379 ...
Es ist oft besser, einfach anzufangen, als die Variablen auf zu viele Dateien aufzuteilen. In größeren Teams und Projekten steigt der Wert von separaten Dateien, da viele Personen gleichzeitig auf Dateien zugreifen und darin arbeiten müssen.
Dynamisches Inventar
Bis zu diesem Punkt haben wir alle unsere Hosts explizit in unserer Hosts-Inventarisierungsdatei angegeben. Vielleicht hast du aber auch ein System außerhalb von Ansible, das deine Hosts im Auge behält. Wenn deine Hosts zum Beispiel auf Amazon EC2 laufen, verfolgt EC2 die Informationen über deine Hosts für dich. Du kannst diese Informationen über die EC2-Weboberfläche, die Query-API oder über Befehlszeilen-Tools wie awscli
abrufen. Andere Cloud-Provider haben ähnliche Schnittstellen.
Wenn du deine eigenen Server mit einem automatischen Bereitstellungssystem wie Cobbler oder Ubuntu Metal as a Service (MAAS) verwaltest, dann behält dein System bereits den Überblick über deine Server. Vielleicht hast du aber auch eine dieser schicken Konfigurationsmanagement-Datenbanken (CMDBs), in denen all diese Informationen gespeichert sind.
Du willst diese Informationen nicht manuell in deiner Hosts-Datei duplizieren, denn dann stimmt diese Datei nicht mehr mit deinem externen System überein, das die eigentliche Quelle der Informationen über deine Hosts ist. Ansible unterstützt eine Funktion namens dynamische Inventarisierung, mit der du diese Duplizierung vermeiden kannst.
Wenn die Inventardatei als ausführbar markiert ist, nimmt Ansible an, dass es sich um ein dynamisches Inventarskript handelt und führt die Datei aus, anstatt sie zu lesen.
Hinweis
Um eine Datei als ausführbar zu markieren, verwende den Befehl chmod +x
. Zum Beispiel:
$ chmod +x vagrant.py
Inventarisierungs-Plug-ins
Ansible wird mit verschiedenen Plug-ins ausgeliefert, die sich mit verschiedenen Cloud-Systemen verbinden können, sofern du die Voraussetzungen installierst und die Authentifizierung einrichtest. Diese Plug-ins benötigen normalerweise eine YAML-Konfigurationsdatei im Inventarverzeichnis sowie einige Umgebungsvariablen oder Authentifizierungsdateien.
Um die Liste der verfügbaren Plug-ins zu sehen:
$ ansible-doc -t inventory -l
Hier findest du die Plug-in-spezifische Dokumentation und Beispiele:
$ ansible-doc -t inventory <plugin name>
Die Schnittstelle für ein dynamisches Inventarisierungsskript
Ein dynamisches Ansible-Inventarskript muss zwei Befehlszeilenflags unterstützen:
-
--host=<hostname>
zur Anzeige von Gastgeberdetails -
--list
für Listengruppen
Außerdem sollte es eine Ausgabe im JSON-Format mit einer bestimmten Struktur zurückgeben, die Ansible interpretieren kann.
Gastgeberdetails anzeigen
Um die Details des einzelnen Hosts zu erhalten, ruft Ansible ein Inventarskript mit dem Argument --host=
auf:
$ ansible-inventory -i inventory/hosts --host=vagrant2
Hinweis
Ansible enthält ein Skript, das als dynamisches Inventarisierungsskript für das statische Inventar fungiert, das mit dem Kommandozeilenargument -i
bereitgestellt wird: ansible-inventory
.
Die Ausgabe sollte alle hostspezifischen Variablen enthalten, einschließlich der Verhaltensparameter, wie hier:
{ "ansible_host": "127.0.0.1", "ansible_port": 2200, "ansible_ssh_private_key_file": "~/.vagrant.d/insecure_private_key", "ansible_user": "vagrant" }
Die Ausgabe ist ein einzelnes JSON-Objekt; die Namen sind die Variablennamen und die Werte sind die Variablenwerte.
Gruppen auflisten
Dynamische Inventarskripte müssen in der Lage sein, alle Gruppen und Details zu den einzelnen Hosts aufzulisten. Im GitHub-Repository, das diesem Buch beiliegt, gibt es ein Inventarisierungsskript für die Vagrant-Hosts namens vagrant.py. Ansible ruft es wie folgt auf, um eine Liste aller Gruppen zu erhalten:
$ ./vagrant.py --list
In der einfachsten Form könnte die Ausgabe wie folgt aussehen:
{"vagrant": ["vagrant1", "vagrant2", "vagrant3"]}
Diese Ausgabe ist ein einzelnes JSON-Objekt; die Namen sind Ansible-Gruppennamen und die Werte sind Arrays von Hostnamen.
Als Optimierung von kann der Befehl --list
die Werte der Host-Variablen für alle Hosts enthalten, was Ansible die Mühe erspart, einen separaten --host
-Aufruf zu machen, um die Variablen für die einzelnen Hosts abzurufen.
Um diese Optimierung zu nutzen, sollte der Befehl --list
einen Schlüssel namens _meta
zurückgeben, der die Variablen für jeden Host in dieser Form enthält:
"_meta": { "hostvars": { "vagrant1": { "ansible_user": "vagrant", "ansible_host": "127.0.0.1", "ansible_ssh_private_key_file": "~/.vagrant.d/insecure_private_key", "ansible_port": "2222" }, "vagrant2": { "ansible_user": "vagrant", "ansible_host": "127.0.0.1", "ansible_ssh_private_key_file": "~/.vagrant.d/insecure_private_key", "ansible_port": "2200" }, "vagrant3": { "ansible_user": "vagrant", "ansible_host": "127.0.0.1", "ansible_ssh_private_key_file": "~/.vagrant.d/insecure_private_key", "ansible_port": "2201" } }
Ein dynamisches Inventarisierungsskript schreiben
Eine der praktischen Funktionen von Vagrant ist, dass du mit dem Befehl vagrant status
sehen kannst, welche Maschinen gerade laufen. Angenommen, wir haben eine Vagrant-Datei, die wie Beispiel 4-3 aussieht. Wenn wir vagrant status
ausführen, würde die Ausgabe wie in Beispiel 4-11 aussehen.
Beispiel 4-11. Ausgabe von vagrant status
$ vagrant status Current machine states: vagrant1 running (virtualbox) vagrant2 running (virtualbox) vagrant3 running (virtualbox) This environment represents multiple VMs. The VMs are all listed above with their current state. For more information about a specific VM, run 'vagrant status NAME'.
Da Vagrant die Maschinen bereits für uns im Auge behält, müssen wir sie nicht in einer Ansible-Inventardatei auflisten. Stattdessen können wir ein dynamisches Inventarisierungsskript schreiben, das Vagrant abfragt, welche Maschinen laufen. Sobald wir ein dynamisches Inventarisierungsskript für Vagrant eingerichtet haben, müssen wir die Ansible-Inventarisierungsdatei nicht mehr bearbeiten, selbst wenn wir unsere Vagrant-Datei ändern, um eine andere Anzahl von Vagrant-Maschinen zu betreiben.
Gehen wir ein Beispiel für die Erstellung eines dynamischen Inventarisierungsskripts durch, das die Details über die Hosts von Vagrant abruft. Unser dynamisches Inventarskript muss den Befehl vagrant status
aufrufen. Die in Beispiel 4-11 gezeigte Ausgabe ist für Menschen lesbar. Mit dem Flag --machine-readable
können wir eine Liste der laufenden Hosts in einem Format erhalten, das von Computern leichter zu analysieren ist, etwa so:
$ vagrant status --machine-readable
Die Ausgabe sieht wie folgt aus:
1620831617,vagrant1,metadata,provider,virtualbox 1620831617,vagrant2,metadata,provider,virtualbox 1620831618,vagrant3,metadata,provider,virtualbox 1620831619,vagrant1,provider-name,virtualbox 1620831619,vagrant1,state,running 1620831619,vagrant1,state-human-short,running 1620831619,vagrant1,state-human-long,The VM is running. To stop this VM%!(VAGRANT_COMMA) you can run `vagrant halt` to\nshut it down forcefully%!(VAGRANT_COMMA) or you can run `vagrant suspend` to simply\nsuspend the virtual machine. In either case%!(VAGRANT_COMMA) to restart it again%!(VAGRANT_COMMA)\nsimply run `vagrant up`. 1620831619,vagrant2,provider-name,virtualbox 1620831619,vagrant2,state,running 1620831619,vagrant2,state-human-short,running 1620831619,vagrant2,state-human-long,The VM is running. To stop this VM%!(VAGRANT_COMMA) you can run `vagrant halt` to\nshut it down forcefully%!(VAGRANT_COMMA) or you can run `vagrant suspend` to simply\nsuspend the virtual machine. In either case%!(VAGRANT_COMMA) to restart it again%!(VAGRANT_COMMA)\nsimply run `vagrant up`. 1620831620,vagrant3,provider-name,virtualbox 1620831620,vagrant3,state,running 1620831620,vagrant3,state-human-short,running 1620831620,vagrant3,state-human-long,The VM is running. To stop this VM%!(VAGRANT_COMMA) you can run `vagrant halt` to\nshut it down forcefully%!(VAGRANT_COMMA) or you can run `vagrant suspend` to simply\nsuspend the virtual machine. In either case%!(VAGRANT_COMMA) to restart it again%!(VAGRANT_COMMA)\nsimply run `vagrant up`. 1620831620,,ui,info,Current machine states:\n\nvagrant1 running (virtualbox)\nvagrant2 running (virtualbox)\nvagrant3 running (virtualbox)\n\nThis environment represents multiple VMs. The VMs are all listed\nabove with their current state. For more information about a specific\nVM%!(VAGRANT_COMMA) run `vagrant status NAME`
Um Details über eine bestimmte Vagrant-Maschine, z.B. vagrant2
, zu erhalten, würden wir Folgendes ausführen:
$ vagrant ssh-config vagrant2
Die Ausgabe sieht wie folgt aus:
Host vagrant2 HostName 127.0.0.1 User vagrant Port 2200 UserKnownHostsFile /dev/null StrictHostKeyChecking no PasswordAuthentication no IdentityFile /Users/lorin/.vagrant.d/insecure_private_key IdentitiesOnly yes LogLevel FATAL
Unser dynamisches Inventarisierungsskript muss diese Befehle aufrufen, die Ausgaben parsen und das entsprechende JSON ausgeben. Wir können die Paramiko-Bibliothek verwenden, um die Ausgabe von vagrant ssh-config
zu parsen. Installiere zunächst die Python Paramiko-Bibliothek mit pip:
$ pip3 install --user paramiko
Hier ist eine interaktive Python-Sitzung, die zeigt, wie man die Paramiko-Bibliothek dafür verwendet:
$ python3 >>> import io >>> import subprocess >>> import paramiko >>> cmd = ["vagrant", "ssh-config", "vagrant2"] >>> ssh_config = subprocess.check_output(cmd).decode("utf-8") >>> config = paramiko.SSHConfig() >>> config.parse(io.StringIO(ssh_config)) >>> host_config = config.lookup("vagrant2") >>> print (host_config) {'hostname': '127.0.0.1', 'user': 'vagrant', 'port': '2200', 'userknownhostsfile': '/dev/null', 'stricthostkeychecking': 'no', 'passwordauthentication': 'no', 'identityfile': ['/Users/bas/.vagrant.d/insecure_private_key'], 'identitiesonly': 'yes', 'loglevel': 'FATAL'}
Beispiel 4-12 zeigt unser komplettes vagrant.py-Skript.
Beispiel 4-12. vagrant.py
#!/usr/bin/env python3 """ Vagrant inventory script """ # Adapted from Mark Mandel's implementation # https://github.com/markmandel/vagrant_ansible_example import argparse import io import json import subprocess import sys import paramiko def parse_args(): """command-line options""" parser = argparse.ArgumentParser(description="Vagrant inventory script") group = parser.add_mutually_exclusive_group(required=True) group.add_argument('--list', action='store_true') group.add_argument('--host') return parser.parse_args() def list_running_hosts(): """vagrant.py --list function""" cmd = ["vagrant", "status", "--machine-readable"] status = subprocess.check_output(cmd).rstrip().decode("utf-8") hosts = [] for line in status.splitlines(): (_, host, key, value) = line.split(',')[:4] if key == 'state' and value == 'running': hosts.append(host) return hosts def get_host_details(host): """vagrant.py --host <hostname> function""" cmd = ["vagrant", "ssh-config", host] ssh_config = subprocess.check_output(cmd).decode("utf-8") config = paramiko.SSHConfig() config.parse(io.StringIO(ssh_config)) host_config = config.lookup(host) return {'ansible_host': host_config['hostname'], 'ansible_port': host_config['port'], 'ansible_user': host_config['user'], 'ansible_private_key_file': host_config['identityfile'][0]} def main(): """main""" args = parse_args() if args.list: hosts = list_running_hosts() json.dump({'vagrant': hosts}, sys.stdout) else: details = get_host_details(args.host) json.dump(details, sys.stdout) if __name__ == '__main__': main()
Aufteilung des Inventars in mehrere Dateien
Wenn du sowohl eine reguläre Inventarisierungsdatei als auch ein dynamisches Inventarisierungsskript (oder eine beliebige Kombination aus statischen und dynamischen Inventarisierungsdateien) haben möchtest, legst du sie einfach unter im selben Verzeichnis ab und konfigurierst Ansible so, dass es dieses Verzeichnis als Inventar verwendet. Das kannst du mit dem Parameter inventory
in der Datei ansible.cfg oder mit dem Flag -i
in der Befehlszeile tun. Ansible wird alle Dateien verarbeiten und die Ergebnisse in einem einzigen Inventar zusammenführen.
Das bedeutet, dass du ein einziges Inventarverzeichnis erstellen kannst, das du mit Ansible auf der Kommandozeile mit Hosts verwenden kannst, die in Vagrant, Amazon EC2, Google Cloud Platform, Microsoft Azure oder wo immer du sie brauchst, laufen.
Die Verzeichnisstruktur von Bas sieht zum Beispiel so aus:
- inventory/aws_ec2.yml
- inventory/azure_rm.yml
- inventory/group_vars/vagrant
- inventory/group_vars/staging
- inventory/group_vars/production
- Inventar/Hosts
- inventory/vagrant.py
Hinzufügen von Einträgen zur Laufzeit mit add_host und group_by
Mit Ansible kannst du während der Ausführung eines Playbooks Hosts und Gruppen zum Inventar hinzufügen. Das ist nützlich, wenn du dynamische Cluster wie Redis Sentinel verwaltest.
add_host
Das Modul add_host
fügt einen Host zum Inventar hinzu. Dies ist nützlich, wenn du Ansible zur Bereitstellung neuer virtueller Maschineninstanzen in einer Infrastructure-as-a-Service-Cloud verwendest.
Der Aufruf des Moduls sieht folgendermaßen aus:
- name: Add the host add_host name: hostname groups: web,staging myvar: myval
Die Angabe der Liste von Gruppen und zusätzlichen Variablen ist optional.
Hier siehst du den Befehl add_host
in Aktion, mit dem du eine neue Vagrant-Maschine startest und dann konfigurierst:
--- - name: Provision a Vagrant machine hosts: localhost vars: box: centos/stream8 tasks: - name: Create a Vagrantfile command: "vagrant init {{ box }}" args: creates: Vagrantfile - name: Bring up the vagrant machine command: vagrant up args: creates: .vagrant/machines/default/virtualbox/box_meta - name: Add the vagrant machine to the inventory add_host: name: default ansible_host: 127.0.0.1 ansible_port: 2222 ansible_user: vagrant ansible_private_key_file: > .vagrant/machines/default/virtualbox/private_key - name: Do something to the vagrant machine hosts: default tasks: # The list of tasks would go here - name: ping ping: ...
Hinweis
Das Modul add_host
fügt den Host nur für die Dauer der Ausführung des Playbooks hinzu. Es ändert deine Bestandsdatei nicht.
Wenn wir die Bereitstellung in unseren Playbooks vornehmen, teilen wir sie gerne in zwei Schritte auf. Das erste Spiel läuft gegen localhost
und stellt die Hosts bereit, das zweite Spiel konfiguriert die Hosts.
Beachte, dass in dieser Aufgabe das Argument creates: Vagrantfile
verwendet:
- name: Create a Vagrantfile command: "vagrant init {{ box }}" args: creates: Vagrantfile
Damit wird Ansible mitgeteilt, dass der Befehl nicht erneut ausgeführt werden muss, wenn die Vagrantfile-Datei vorhanden ist. Indem du sicherstellst, dass der (potenziell nicht idempotente) Befehl nur einmal ausgeführt wird, erreichst du Idempotenz in einem Playbook, das das Modul command
aufruft. Das Gleiche gilt für das vagrant up
Befehlsmodul.
group_by
Mit dem Modul group_by
von Ansible kannst du neue Gruppen erstellen, während ein Playbook ausgeführt wird. Jede Gruppe, die du erstellst, basiert auf dem Wert einer Variable, die auf jedem Host gesetzt wurde und die Ansible als Fakt bezeichnet.(In Kapitel 5 werden Fakten ausführlicher behandelt.)
Wenn das Ansible Fact Gathering aktiviert ist, ordnet Ansible eine Reihe von Variablen einem Host zu. Zum Beispiel wird die Variable ansible_machine
für 32-Bit x86-Maschinen zu i386
und für 64-Bit x86-Maschinen zu x86_64
. Wenn Ansible mit einer Mischung aus solchen Hosts interagiert, können wir mit der Aufgabe die Gruppen i386
und x86_64
erstellen.
Wenn wir unsere Hosts lieber nach Linux-Distributionen gruppieren möchten (z.B. Ubuntu oder CentOS), können wir die ansible_fact.distribution
Tatsache nutzen:
- name: Create groups based on Linux distribution group_by: key: "{{ ansible_facts.distribution }}"
In Beispiel 4-13 verwenden wir group_by
, um getrennte Gruppen für unsere Ubuntu- und CentOS-Hosts zu erstellen. Dann verwenden wir das Modul apt
, um Pakete auf Ubuntu zu installieren und das Modul yum
, um Pakete auf CentOS zu installieren.
Beispiel 4-13. Ad-hoc-Gruppen basierend auf der Linux-Distribution erstellen
--- - name: Group hosts by distribution hosts: all gather_facts: true tasks: - name: Create groups based on distro group_by: key: "{{ ansible_facts.distribution }}" - name: Do something to Ubuntu hosts hosts: Ubuntu become: true tasks: - name: Install jdk and jre apt: update_cache: true name: - openjdk-11-jdk-headless - openjdk-11-jre-headless - name: Do something else to CentOS hosts hosts: CentOS become: true tasks: - name: Install jdk yum: name: - java-11-openjdk-headless - java-11-openjdk-devel
Fazit
Das war's auch schon mit dem Inventar von Ansible. Es ist ein sehr flexibles Objekt, das dabei hilft, deine Infrastruktur und die Art und Weise, wie du sie nutzen willst, zu beschreiben. Das Inventar kann so einfach wie eine Textdatei oder so komplex sein, wie du es dir vorstellen kannst.
Im nächsten Kapitel geht es darum, wie man Variablen verwendet.
1 Dieser Begriff wurde von Randy Bias von Cloudscaling populär gemacht.
Get Ansible: Up and Running, 3. Auflage now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.