ADMIN

2022

04

2022-03-31T12:00:00

Automatisierung

SCHWERPUNKT

060

Automatisierung

Ansible

Automatisierung mit Ansible ab 2.10

Neues Drehbuch

von Andreas Stolzenberger

Veröffentlicht in Ausgabe 04/2022 - SCHWERPUNKT

Die Automatisierungsplattform Ansible setzt in den aktuellen Versionen verstärkt auf verteilte Ausführung in Containern. Die Anwender müssen sich mit neuen Tools auseinandersetzen, die auf den ersten Blick zwar komplex erscheinen, in der Praxis aber eine bessere Performance und mehr Flexibilität versprechen.

Im Herbst 2021 hat Red Hat die Version 2.10 der Ansible Automation Platform vorgestellt. Das Release führt einige grundlegende Änderungen in der Architektur ein und liefert dazu passend eine ganze Reihe neuer Tools. Die Neuerungen betreffen zum einen die Performance der Automation-Platform in großen Umgebungen. Zudem sollen sie es den Entwicklern von Ansible-Code erleichtern, ihre Playbooks auf verschiedenen Systemen laufen zu lassen.
In diesem Workshop stellen wir die Änderungen sowie die neuen Tools vor und gehen auf die nötigen Modifikationen in bestehenden Playbooks ein.
Module und Abhängigkeiten
Das Tool Ansible ist in Python geschrieben. Die eigentliche Automatisierung übernehmen Module, die wie die Instruktionen in einer Programmiersprache funktionieren. Es gibt Basis-Module wie "copy", "uri" oder "user", die mit jedem Ansible-Basis-Setup funktionieren. Darüber hinaus existieren hunderte von Modulen, die sich um bestimmte Funktionen kümmern, wie beispielsweise "cisco.ios", "vmware", "ec2" oder "gcp". Eine Vielzahl dieser erweiterten Module benötigen spezielle Python-Libraries, damit sie funktionieren. Durch die stets wachsende Zahl der Module werden die damit erforderlichen Python-Dependencies immer komplexer.
Im Herbst 2021 hat Red Hat die Version 2.10 der Ansible Automation Platform vorgestellt. Das Release führt einige grundlegende Änderungen in der Architektur ein und liefert dazu passend eine ganze Reihe neuer Tools. Die Neuerungen betreffen zum einen die Performance der Automation-Platform in großen Umgebungen. Zudem sollen sie es den Entwicklern von Ansible-Code erleichtern, ihre Playbooks auf verschiedenen Systemen laufen zu lassen.
In diesem Workshop stellen wir die Änderungen sowie die neuen Tools vor und gehen auf die nötigen Modifikationen in bestehenden Playbooks ein.
Module und Abhängigkeiten
Das Tool Ansible ist in Python geschrieben. Die eigentliche Automatisierung übernehmen Module, die wie die Instruktionen in einer Programmiersprache funktionieren. Es gibt Basis-Module wie "copy", "uri" oder "user", die mit jedem Ansible-Basis-Setup funktionieren. Darüber hinaus existieren hunderte von Modulen, die sich um bestimmte Funktionen kümmern, wie beispielsweise "cisco.ios", "vmware", "ec2" oder "gcp". Eine Vielzahl dieser erweiterten Module benötigen spezielle Python-Libraries, damit sie funktionieren. Durch die stets wachsende Zahl der Module werden die damit erforderlichen Python-Dependencies immer komplexer.
Das abgelöste kommerzielle Tool "Ansible Tower" brachte beispielsweise eine speziell konfigurierte Python-Umgebung (python bubble wrap) mit, die alle offiziell unterstützten Bibliotheken in den passenden Versionen enthielt. Dieses Vorgehen war jedoch wenig flexibel, da diese Umgebung nur alle sechs Monate erneuert wurde, und sorgte außerdem für Inkompatibilitäten. Wer Ansible auf der Kommandozeile verwendet, nutzt die Python-Libraries des lokalen Betriebssystems – je nach Paketmanager und Aktualisierung sogar in verschiedenen Versionen. So kann es dazu kommen, dass ein auf einem Fedora/EL8/Debian-Rechner entwickeltes Playbook auf einem Tower-System (EL7) nicht richtig funktioniert, da beide Systeme mit unterschiedlichen Python-Libraries arbeiten.
Hinzu kommt, dass die Open-Source-Community und kommerzielle Anbieter immer mehr neue Ansible-Module veröffentlichen. Wollte Ansible Tower diese alle unterstützen, müsste es eine sehr große Bubble-Wrap-Umgebung für Python mitbringen. In der Praxis brauchen Anwender aber gar kein so überladenes Setup, da sie ohnehin nur einen Bruchteil aller Ansible-Module einsetzen.
Passgenaue Ausführungsumgebung
Um hier Abhilfe zu schaffen, setzt Ansible künftig auf sogenannte Execution Environments (EE). Dabei handelt es sich um Container-Images für Engines wie Docker, Kubernetes (cri-o) oder Podman, die zum einen die aktuelle Ansible-Runtime sowie vom Nutzer ausgewählte Dependencies erhalten. Diese "EEs" beherbergen also nur die Module und Dependencies, die der Nutzer auch tatsächlich benötigt.
Für unterschiedliche Einsatzbereiche bauen die Administratoren dann eigene EEs, beispielsweise je eines für Operationen mit AWS, GCP und Azure. Zudem kann der Anwender die EEs versionieren. Gibt es neuere Versionen der Module oder Dependencies, baut sich der User ein neues EE, mit dem er in aller Ruhe die Kompatibilität zu den Playbooks testen kann, während die Produktion mit den bestehenden EEs weiterläuft. Nach abgeschlossenen Tests tauschen Admins dann nur noch das EE gegen eine neue Version aus, ohne den Rest der Automatisierung zu behelligen.
Das verkompliziert die Umgebung auf der einen Seite etwas. Nutzer müssen sich erst die passenden Execution Environments mit dem Tool "Ansible Builder" bauen, diese testen und den zugehörigen Automatisierungs-Playbooks zuweisen. Im Zweifelsfall müssen Sie auch den Code der Playbooks anpassen. Die Ausführung von einfachen Playbooks dauert dann etwas länger, weil das System erst einmal einen Container mit dem EE starten und das Automatierungs-Playbook transferieren muss. Auf der anderen Seite vereinfachen EEs die Automatisierung nach der etwas aufwendigeren Vorbereitung. Entwickler verwenden auf ihren Arbeitsstationen das exakt gleiche EE, das später auch in der Produktion zum Einsatz kommt. Zudem lässt sich ein EE in einer großen Umgebung parallelisiert betreiben. Wer ein Playbook mit 100 Zielsystemen ausführt, kann das nun beispielsweise in Gruppen zu je 25 Systemen in vier EE-Containern parallel laufen lassen.
Ansible unterteilt seine Funktionen nun in sogenannte Collections auf. Eine Collection besteht aus Modulen, Rollen und falls nötig Plug-ins. Ein Beispiel: Die Collection "cisco.ios" enthält alle Module, um Cisco-Switche mit dem System "IOS" zu verwalten. Sie bringt aber auch das nötige Plug-in mit, damit Ansible die Verbindung zu einem IOS-Swtich aufbauen kann und dessen CLI-Sprache versteht. Von Juniper kommt im Gegenzug die "Junipernetworks.junos"-Collection, mit den nötigen Connection-Plug-ins und Modulen für Switches von Juniper.
Wer Ansible traditionell auf einer Linux-Workstation mit dem CLI-Tool "ansible-playbook" betreibt, kann sich diese Collection einfach über das Kommando ansible-galaxy collection install cisco.ios einrichten. Das setzt aber voraus, dass Sie zusätzlich die passenden Python-Dependencies installieren, die die Collection benötigt. Die wiederum installiert "ansible-galaxy" nicht mit und überlässt es Ihnen, ob Sie die Python-Bibliotheken mit dem Paketmanager seiner Distribution (apt, dnf) oder dem Python Packet Manager (pip) einrichten. So bleibt also die potenzielle Inkompatibilität der lokalen Umgebung mit dem später zu nutzenden EE bestehen.
Passend zur neuen Architektur erstellen Sie daher eines oder mehrere EEs, in die Sie die Collection integrieren. Die Container-Images laden Sie dann auf eine Container-Registry hoch, auf die auch das produktive Automation-Setup (AWX) Zugriff hat. Jetzt fehlt nur noch das CLI-Tool, das statt der lokalen Ansible Installation das EE nutzt.
Bild 1: Mit dem Ansible Navigator steht ein Tool mit "Text-UI" bereit, das die Ausgabe der Playbooks in einzelnen Schritten darstellt und Anwender komfortabel durch die Anzeige navigieren lässt.
Neue Tools einrichten
Das neue Toolset für Ansible umfasst eine Reihe an Komponenten. Da wäre zum einen der "ansible-navigator" als Ersatz für das bekannte CLI-Tool "ansible-playbook" auf dem Arbeitsplatz des Automation-Entwicklers. Der Navigator beherrscht im Gegensatz zum alten Tool den Umgang mit EEs, dazu später mehr. Der eigentliche Kontrollknoten, der aus seiner komfortablen Web-UI heraus die Automatisierung in der produktiven Umgebung übernimmt, nutzt dann entweder das kommerzielle Tool "Ansible-Controller" oder dessen Open-Source-Upstream-Variante AWX. Die Installation von AWX haben wir bereits mehrfach im IT-Administrator beschrieben [1]. Dieser Artikel geht im weiteren Verlauf aber noch einmal auf das AWX-Setup ein, weil es dazu ein neue, schicke Setupvariante gibt.
Um die EEs so zu verwalten, dass sowohl die Navigator-Workstations als auch die produktiven AWX-Installationen darauf Zugriff erhalten, benötigt der Anwender eine Container-Registry. In einfachen Installationen in einem lokalen Netzwerk genügt dafür bereits eine simple Docker-Registry. Alternativ lässt sich auch ein freier Registry-Service wie beispielsweise der von "gitlab.com" [2] verwenden. Wer neben eigenen EEs auch eigene Collections erstellen möchte, sollte über den Einsatz von Galaxy-NG [3] nachdenken. Dabei handelt es sich um ein Repository-Management mit Pulp3, das sowohl Collections als auch Container-Images verwalten kann.
Wie der Name "Galaxy Next Generation" (Upstream zum kommerziellen Automation Hub) bereits vermuten lässt, handelt es sich dabei um eine Erweiterung des bekannten "galaxy.ansible.com"-Diensts. Diese "Galaxy" hält Open-Source-Rollen und neuerdings auch Collections vor. NG als On-Premises-Setup kann Collections vom Galaxy-Online-Portal cachen und eigene Rollen, Container und Collections sichern und versionieren. Das bietet wiederum den Vorteil, dass der Anwender Neuerungen und Updates in publizierten Collections erst einmal ausprobieren kann. Das eigene NG-Setup hält dabei mehrere Versionen einer Collection vor, die ältere stabile für die Produktion und die neue vorerst nur für Test- und Entwicklungsumgebungen.
Wer auf die neuen Tools und Versionen umsteigen möchte, muss dabei ein paar kleinere Hürden umschiffen. In vielen Online-Dokumentationen steht, dass der Anwender auf einer EL8-Distribution (Rocky, Alma, Centos-Stream) Ansible einfach als RPM-Paket aus dem EPEL-Repository via "dnf install ansible" einrichten kann. Das stimmt leider nicht ganz. Aufgrund der Rückwärtskompatibilität enthält das "ansible.rpm"-Paket nach wie vor Ansible in der Version 2.9 und nicht die aktuelle Version 2.11 (EL8) oder 2.12 (Fedora), die Execution Environments und den Navigator unterstützt (mindestens 2.10). Ähnliches gilt für die "deb"-Pakete bei Ubuntu/Debian. Das neue Paket heißt jetzt "ansible-core", ist aber als RPM/DEB-Datei vorerst nur für Debian 10, Fedora ab 34 und Centos-
Stream-9 verfügbar. Nutzer von EL8- und anderen Distributionen müssen den Umweg über den Python-Paketmanager pip (Version 3) nehmen. Installieren Sie also auf einem EL8-System eine aktuelle Python-Runtime auf Ihrem System (ab 3.8) und richten Sie die Tools ein:
pip3 install ansible ansible-builder ansible-navigator
Um mit EEs arbeiten zu können, benötigen Sie noch die passende Container-Runtime, in unserem Fall Podman: dnf install podman. Für die ersten Tests mit EEs genügt erst einmal eine lokale Registry, die sich per Podman starten lässt. Erstellen Sie zuerst ein lokales Datenverzeichnis, beispielsweise "/var/lib/registry", und starten Sie dann den passenden Container mit
podman run -d \--name registry \-p 5000:5000 \-v /var/lib/registry:/var/lib/registry:Z \docker.io/registry:2
Lokale Images lassen sich dann in dieser Regsitry sichern via
podman push <imagename> localhost:5000/<imagename:tag> --tls-verify=false
Was alles in der lokalen Registry gespeichert ist, listen Sie auf mit
curl localhost:5000/v2/_calagog
Möchten Sie anstatt Curl lieber eine Web-UI verwenden, um den Inhalt der Regsitry zu sehen, starten Sie parallel zum Regsitry-Container "docker.io/registry:2" ein passendes Web-Management wie "docker.io/joxit/docker-registry-ui". Wie dieses Setup funktioniert, ist detailliert auf der GitHub-Seite unter [4] beschrieben.
Zurück aus der Zukunft
Die Ausführung eines Playbooks mit dem Ansible-Navigator verläuft etwas anders, als Sie das von "ansible-playbook" gewohnt sind. Der Navigator liefert eine klassische "TUI", ein textbasiertes User Interface, wie es erfahrenere Admins noch aus ihrer DOS- oder Großrechnerzeit kennen. Doch die Retro-TUI hilft bei der Fehlersuche und -analyse ungemein. Der Playbook-Verlauf rauscht nicht mehr in hoher Geschwindigkeit durch das Fenster. Jeder Schritt belegt eine Zeile im TUI und wenn Sie nähere Informationen zu dem jeweiligen Schritt brauchen, tippen Sie einfach die Zeilennummer ein und der Navigator listet die Details auf. Auch wenn das Navigator-TUI zu Anfang recht altbacken wirkt, kommen Anwender mit den Tasten-Shortcuts innerhalb kurzer Zeit zurecht. Wer sich einmal an so ein TUI gewöhnt hat, kommt nur noch schwer wieder davon los. Das ist wahrscheinlich auch der Grund dafür, warum manche erfahrenere Administratoren noch heute lieber einen Norton-Commander-Klon für das Dateimanagement verwenden als ein Drag-and-Drop-UI.
Erstes Execution Enviroment erzeugen
Legen Sie sich ein Arbeitsverzeichnis für den Builder an und erstellen Sie darin eine simple Konfigurationsdatei namens "execution-environment.yml":
---
version: 1
build_arg_defaults:
   EE_BASE_IMAGE: 'quay.io/ansible/ansible-runner:latest'
 
ansible_config: 'ansible.cfg'
 
dependencies:
    galaxy: requirements.yml
Das EE-Base-Image verweist auf die Vorlage für Ihre Images. Hier können Sie wahlweise auf das offizielle "ansible-runner"- oder das von AWX verwendete "awx-ee"-Image verweisen. Sollten Sie besondere Konfigurationsoptionen für Ihre Umgebung benötigen, schreiben Sie diese in eine "ansible.cfg"-Datei im lokalen Verzeichnis und der Build-Prozess integriert sie in das Image.
Zum Schluss geben Sie eine oder mehrere Dependency-Dateien an. Das Beispiel verweist hier nur auf Ansible-Rollen oder Collections. Soll der Builder Python und System-Dependencies berücksichtigen, könnte hier auch stehen:
dependencies:
    galaxy: requirements.yml
    python: requirements.txt
    system: bindep.txt.
In unserer "requirements.yml" steht:
---
collections:
- awx.awx
- google.cloud
- amazon.aws
Damit beherrscht das EE später Playbooks, die Prozesse auf der Amazon- oder Google-Cloud automatisieren. Das Image erstellen Sie dann einfach via
ansible-builder build --tag my_ee --container-runtime podman
Im Home-Verzeichnis des Anwenders legen Sie dann eine Konfigurationsdatei für den Ansible Navigator namens ".ansible-navigator.yml" an, wobei der Punkt am Anfang des Dateinamens wichtig ist:
---
ansible-navigator:
    execution-environment:
      container-engine: podman
      image: my_ee
      enabled: true
Starten Sie dann Playbooks über "ansible-navigator run" statt wie bisher üblich via "ansible-playbook", führt das Execution Environment die Automatisierung in einem Container durch und nicht das Ansible-Tool auf dem lokalen OS. Wie bereits beschrieben, können Sie das Container-Image auf dem Registry-Server sichern und dann auch von AWX aus nutzen:
podman push my_ee localhost:5000/my_ee:1 --tls-verify=false
Bild 2: Mit "Microshift" als Kubernetes-Unterbau können Anwender das Ansible-Web-UI "AWX" binnen kurzer Zeit über den Operator einrichten und nutzen.
AWX auf Microshift
Das Ansible Web-UI "AWX" vereinfacht dem Anwender den Umgang mit der Automatisierung. Es sortiert die Automation-Playbooks in Teams und Projekte, sichert Zugangsdaten und erlaubt einen sicheren Role-based Access zu der Automatisierung. AWX ist die Weiterentwicklung des früheren kommerziellen Produkts "Ansible Tower" und das Upstream-Projekt dessen Nachfolgers "Ansible Controller".
AWX unterstützt nicht nur Container als EEs. Auch die Kontrollfunktionen von AWX selbst arbeiten in Containern. Die Zielplattform der Wahl ist dabei natürlich Kubernetes. AWX kann zwar auch ohne, muss dann aber in einem etwas eigenwilligen "Podman-Container-in-Docker-Container"-Setup laufen, was sich bestenfalls für einfache Tests eignet. Glücklicherweise gibt es eine Reihe sehr simpler Kubernetes-Implementierungen, wie beispielsweise "Microshift". Dieses ist aber nicht zu verwechseln mit dem veralteten Minishift.
Dieses Open-Source-Tool nutzt ein stark abgespecktes OKD (mehr dazu in unserer Workshopserie "Kubernetes einrichten und betreiben" [5]), dem Upstream des kommerziellen Openshift. Microshift liefert eine weitgehend zu OpenShift kompatible API und beherrscht Operatoren. Das eigentliche Kubernetes-Setup packt Microshift in ein kleines RPM-Paket. Eine gute Wahl für ein AWX-Setup ist daher eine VM mit einem EL8- oder Fedora-OS, auf dem Sie zunächst die simple Container-Runtime "cri-o" aufsetzen und dann den Microshift-Dienst aus dem Copr-Repo per RPM einspielen. Das AWX-Setup erfolgt anschließend über den passenden Operator.
Die genaue Beschreibung für ein Microshift-Setup finden Sie unter [6]. Im Test nutzen wir dazu ein Fedora-35-System mit einem spartanischen Minimalsetup. Als Root starten Sie Microshift in nur sechs Schritten:
dnf module enable -y cri-o:1.21
dnf install -y cri-o cri-tools
 
systemctl enable crio --now
 
dnf copr enable -y @redhat-et/microshift
 
dnf install -y microshift firewalld
 
systemctl enable microshift --now
Nach dem Start dauert es ein paar Minuten, da der Microshift-Dienst nun die nötigen Container-Images aus dem Internet lädt und via cri-o-Engine startet. Nach dem erfolgten Start finden Sie die nötigen Admin-Credentials in der Datei "/var/lib/ microshift/resources/kubeadmin/kubeconfig".
Jetzt können Sie auf dem Microshift-Host die Openshift-CLI-Tools "kubectl" und "oc" einrichten. Die genaue Prozedur, um den AWX-Operator einzurichten, finden Sie unter [7]. Für unser Setup erstellen Sie zunächst den Namespace/Project in Microshift mit oc new-project awx. Falls nicht vorhanden, richten Sie die nötigen Tools auf Ihrem Fedora-Server mittels dnf install git rsync make tar ein und klonen die aktuelle Version des AWX-Operators via git in ein lokales Verzeichnis:
git clone https://github.com/ansible/awx-operator.git
Setzen Sie die Variable "NAMESPACE"auf den Namen Ihres Projekts mit export <NAMESPACE>=awx und erzeugen Sie den Operator durch Eingabe von make deploy. Ein paar Minuten später sollte der Pod mit dem AWX-Operator laufen. Im Anschluss erstellen Sie ein Persistent Volume (PV) mit mindestens 5 GByte Kapazität vom Typ "local" in einem lokalen Verzeichnis, beispielsweise als "pv1.yml":
apiVersion: v1
kind: PersistentVolume
metadata:
    name: pv1
spec:
    capacity:
       storage: 10G
    accessModes:
       - ReadWriteOnce
    local:
       path: /var/hpvolumes/1nodeAffinity:
       required:
          nodeSelectorTerms:
           - matchExpressions:
               - key: kubernetes.io/hostname
                  operator: In values:
                  - <FQDN der Microshift VM>
   persistentVolumeReclaimPolicy:  Recycle
Dann erstellen Sie das PV:
mkdir -p /var/hpvolumes/1
 
oc create -f pv1.yml
Nun rollen Sie eine AWX-Instanz mit dem beim Operator mitgelieferten File "awx-demo.yml" aus: oc create -f awx-demo.yml. Die Microshift-Umgebung startet nun zwei Pods. Einer davon enthält die PostgreSQL-Datenbank und "claimed" das zuvor erstellte Persistent Volume. Der zweite Pod bekommt insgesamt vier Container: "redis", "awx-task", "awx-web" und ein Execution Environment namens "awx-ee". Davon kann das Setup bei Bedarf natürlich mehrere starten oder die vom Anwender selbst erstellten EEs ausrollen. Um zu erfahren, auf welchem Port der AWX-Server läuft, geben Sie oc get service ein und erhalten eine Ausgabe wie diese:
awx-demo-service NodePort 10.43.4.175 <none> 80:30927/TCP
Also können Sie auf Ihr Setup unter der URL "http://<FQDN der Microshift-VM>:30927" zugreifen. Natürlich können Sie auf Ihrem DNS-Server auch eine Wildcard-Domain für das Microshift-Setup anlegen und eine passende Name-based Route zu Ihrem AWX-Server deklarieren. Alternativ schalten Sie dem AWX-Dienst einen Nginx-Reverse-Proxy mit SSL-Terminierung vor. Das automatisch generierte Admin-Passwort der AWX-Installation finden Sie im Secret, passend zum Namen Ihres Rollouts. In unserem Fall wäre das "awx-demo", also:
oc get secret awx-demo-admin-password -o jsonpath="{.data.password}" | base64 –decode
Bild 3: Die Container-Images der Ansible-Execution-Units lassen sich einfach in einer simplen Docker-Registry lagern, sodass AWX und der Navigator darauf Zugriff erhalten.
Code anpassen
Die vielen Änderungen an Ansible zwischen 2.9 ohne und 2.11/2.12 mit EEs brauchen ein paar Anpassungen am Code. Um bei einem Umstieg auf die neuen Versionen und Tools erst einmal ohne Anpassungen sicher weitermachen zu können, sollten Sie sich zuerst einmal ein rückwärtskompatibles EE bauen. Nutzen Sie im Builder dafür das Image-Template:
EE_BASE_IMAGE: 'quay.io/ansible/ansible-runner:stable-2.9-latest'
und packen Sie via "requirements.yml" alle Collections hinein, die Ihre Automatisierung benötigt. Das führt erst einmal zu einem recht umfangreichen Container-Image. Dieses sollte jedoch in der Lage sein, alle mit Ansible 2.9 entwickelten Automation-Playbooks laufen zu lassen. Ein Änderung in Ansible betrifft die Benennung der Module. Um die Module eindeutig einer Collection zuzuordnen, stellt Ansible den Modulnamen den Namen der Collection voran. Aus dem Modul "ec2_instance", das Ressourcen auf der Amazon-Cloud verwaltet, wird künftig also "amazon.aws.ec2_instance". Damit weiß der Anwender zum einen anhand des Codes ganz genau, welche Collections er zur Ausführung des Playbooks braucht.
Zudem kann er zwischen der original und den angepassten Versionen unterscheiden. Sollten Sie beispielsweise den Python-Code des "ec2_instance"-Moduls aus irgendeinem Grund für Ihre Umgebung verändern, können Sie diese modifizierte Variante in eine eigene Collection packen. Dann gäbe es zwei verschiedene Module, die die alte Namensgebung nicht unterscheiden kann: "my.customized.collection.ec2_instance" und "amazon.aws.ec2_instance".
Solange Sie keine eigenen customized Collections bauen, brauchen Sie nicht alle bestehenden Modulaufrufe umzubenennen. Aber gewöhnen Sie sich die neue Namensgebung für alle neuen Playbooks an. Fügen Sie ferner Ihren Projekten stets die passende "requirements.yml" hinzu, die auf die benötigten Collections verweist. Sollten Sie Ihre Automatisierung dann auf einem EE starten, dem die Collections fehlen, fügt Ansible diese beim Start hinzu. Das verlängert allerdings die Erstellung der EEs ein wenig, weswegen Sie besser mit den passenden EEs, die die Collection bereits im Image enthält, an den Start gehen.
Gitops mit AWX
Wer AWX nutzt, kann von verschiedenen Systemen auf bestehende Projekte und Playbooks mithilfe deren Git-Repositories zugreifen. Die Konfiguration von AWX selbst, also das Setup der Templates, Projekte, Workflows, Credentials, mussten die Anwender jedoch stets in der Web-UI der AWX-Applikation vollziehen.
AWX-Installationen lassen sich dank des Operators jedoch sehr zügig ausrollen. Nutzer betreiben daher gerne mehrere separate AWX-Setups für Tests, Development und die Produktion. Dabei ist es sehr lästig, jede AWX-Instanz manuell per Web-UI zu konfigurieren. Aber da AWX alle Funktionen auch via Rest-API bereitstellt, lässt sich dieser Prozess vollständig automatisieren – natürlich mit Ansible selbst. Im ersten Schritt richten Sie via UI erst einmal eine AWX-Instanz ein, die später als Vorlage fungiert. Über das CLI-Tool "awx" (pip install awxkit) können Sie dann die komplette Konfiguration einer Tower/ Controller/AWX-Installation in eine YML-Datei exportieren:
awx export \
--conf.host http://<FQDN Microshift VM>:<Port> \
--conf.username admin \
--conf.password <admin-password> \
--conf.insecure | yq -y > awx_export.yml
In der "awx_export.yml"-Datei finden Sie dann die komplette AWX-Konfiguration, natürlich ohne "Secrets" wie Schlüssel und Passwörter des Vault. Um die Übersicht zu wahren, bietet es sich an, die recht lange "awx_export.yml"-Datei in kleinere YML-Dateien sortiert nach Funktionen aufzuteilen, beispielsweise: "organizations.yml", "projects.yml", "templates.yml" und so weiter. Der Inhalt der YML-Datei ist weitgehend selbsterklärend, sodass Sie Änderungen an der AWX-Konfiguration relativ leicht hier im YML-Text nachvollziehen können. In den meisten Fällen können Sie dabei auf den Array "natural_key" verzichten, den der AWX-Export integriert.
Fügen Sie dann der separaten Datei "secrets.yml" alle Passwörter und Schlüssel hinzu. Natürlich wollen Sie auf keinen Fall ihre Geheimnisse in einer yml-Datei vorhalten. Daher verschlüsseln Sie ihre secrets.yml direkt nach der Erstellung mit ansible-vault.
Jetzt benötigen Sie nur noch ein passendes Playbook mit den Collections "awx.awx" und "redhat_cop.controller_configuration". Am besten packen Sie alle Konfigurationsdateien in ein Unterverzeichnis namens "./config". Ihr Playbook "config-awx.yml", um einen neuen AWX-Server aus dem Export eines anderen aufzubauen, sieht dann in etwa so aus:
---
- hosts: localhost
    gather_facts: no
    collections:
       - awx.awx
       - redhat_cop.controller_configuration
    vars:
       controller_hostname: http://<Neuer AWX-server>:<Port>
       controller_username: admin
       controller_password:  <admin password>
       controller_validate_certs: false
    pre_tasks:
  - name: Include vars from configs directory
       include_vars:
          dir: ./config
          extensions: ["yml"]
       tags:
          - always
 
    roles:
- {role: settings, when: controller_settings is defined, tags: settings}
- {role: organizations, when: controller_organizations is defined, tags: organizations}
Aus Platzgründen zeigen wir das verkürzte Playbook. Eine komplette Vorlage finden Sie beispielsweise unter [8]. Dieses Playbook führen Sie dann auf Ihrer Arbeitsstation mit dem "alten" CLI-Tool aus:
ansible-playbook config-awx.yml --ask-vault-pass
Der Grund für das "ansible-playbook"-Tool an dieser Stelle ist, dass der interaktive Navigator den Schalter "--ask-vault-pass" in dieser Form nicht unterstützt, der den Anwender interaktiv nach dem Vault-Passwort der verschlüsselten Datei "secrets.yml" fragt. Nach wenigen Minuten ist Ihre neue AWX-Instanz dann komplett konfiguriert und nutzbar.
Fazit
Die Unterschiede zwischen Ansible bis 2.9 und AWX vor Version 19 sowie den aktuellen Releases fallen größer aus als bei einem Minor-Release-Update. Der Umstieg auf Execution Environments und separierte Collections bringt mehr Flexibilität. Die Automatisierung parallel in mehreren Containern auszuführen, verspricht zudem eine bessere Performance, allerdings in erster Linie in großen Umgebungen mit vielen Automatisierungsclients. Kleine Umgebungen werden davon weniger profitieren. Als "Programmiersprache" für die Automatisierung bekommt Ansible mit den neuen Tools einen deutlich stärkeren Developer-Anstrich.
(dr)
Link-Codes
[1] Workshopserie "Automatisierung mit AWX" in IT-Administrator 03/2018: https://www.it-administrator.de/magazin/heftarchiv/artikel/256609.html
[4] Setup der Docker-Registry-UI: https://github.com/Joxit/docker-registry-ui
[5] Workshopserie "Kubernetes einrichten und betreiben (2)" in IT-Administrator 9/2020: https://www.it-administrator.de/magazin/heftarchiv/artikel/332805.html
[7] AWX-Operator einrichten: https://github.com/ansible/awx-operator