Im ersten Teil der Workshopserie haben wir Ansible und AWX installiert, unsere Netzwerkautomatisierung konfiguriert und für die korrekten Credentials gesorgt. Bevor der Rakete-Button nun für den Start unseres Automatisierungs-Raumschiffs sorgen kann, warten noch Aufgaben wie Inventarisierung, Jobdefinition und die zeitliche Steuerung der Abläufe.
Die erste Aufgabe, die nach unseren vorbereitenden Maßnahmen aus Teil 1 des Workshops ansteht, ist die Inventarisierung. Dies beschreibt in AWX aber weniger die aus dem Assetmanagement bekannte Sammlung aller Geräte im Netz. Vielmehr geht es um die sinnvolle Gruppierung der Netzwerkgeräte für die Automatisierungsjobs.
Inventories anlegen
Inventories sind bereits aus Ansible bekannt und beinhalten einzelne Hosts oder entsprechend der organisatorischen und technischen Bedürfnisse Gruppen von Hosts. Diese können nach dem Anlegen als Ziel für automatisierte Jobs zum Einsatz kommen. Auch verschachtelte Gruppen sind möglich, wobei die Bezeichnung der untergeordneten Gruppe "Related Group" lautet.
Neben den bekannten statischen Inventories bietet AWX sogenannte Smart Inventories. Diese bilden eine flexible Möglichkeit, um über Bedingungen zu definieren, wie die Gruppierung stattfinden soll. Dies geschieht über Smart-Host-Filter, die auf einer domänenspezifischen Sprache basieren, die wiederum auf der "get_queryset()"-Methode aus dem Django-REST-Framework aufbaut. Ein Beispiel hierfür wäre ein smartes Inventory auf Grundlage eines bestimmten Betriebssystems wie Windows oder Linux beziehungsweise einer spezifischen Version derselben.
Die erste Aufgabe, die nach unseren vorbereitenden Maßnahmen aus Teil 1 des Workshops ansteht, ist die Inventarisierung. Dies beschreibt in AWX aber weniger die aus dem Assetmanagement bekannte Sammlung aller Geräte im Netz. Vielmehr geht es um die sinnvolle Gruppierung der Netzwerkgeräte für die Automatisierungsjobs.
Inventories anlegen
Inventories sind bereits aus Ansible bekannt und beinhalten einzelne Hosts oder entsprechend der organisatorischen und technischen Bedürfnisse Gruppen von Hosts. Diese können nach dem Anlegen als Ziel für automatisierte Jobs zum Einsatz kommen. Auch verschachtelte Gruppen sind möglich, wobei die Bezeichnung der untergeordneten Gruppe "Related Group" lautet.
Neben den bekannten statischen Inventories bietet AWX sogenannte Smart Inventories. Diese bilden eine flexible Möglichkeit, um über Bedingungen zu definieren, wie die Gruppierung stattfinden soll. Dies geschieht über Smart-Host-Filter, die auf einer domänenspezifischen Sprache basieren, die wiederum auf der "get_queryset()"-Methode aus dem Django-REST-Framework aufbaut. Ein Beispiel hierfür wäre ein smartes Inventory auf Grundlage eines bestimmten Betriebssystems wie Windows oder Linux beziehungsweise einer spezifischen Version derselben.
Damit nicht alle AWX-Nutzer alle Projekte, Job-Templates, Credentials und Inventories aufrufen können, beispielsweise um Changes an Core-Komponenten auf einen kleinen geschulten Personenkreis einzuschränken, gibt es die Möglichkeit, einzelnen Nutzern und Teams Berechtigungen zuzuteilen. Dies kann zum Beispiel das Recht "Admin" sein, über das Lesen, Ausführen und Editieren möglich ist. Über die "Use"-Berechtigung erhalten Anwender die Möglichkeit, das Inventory zu nutzen. "Ad Hoc" hingegen erlaubt, einzelne Kommandos auf Komponenten im Inventar anzuwenden, ohne aufwendige Playbooks zu schreiben. Die Berechtigung "Read" erklärt sich von selbst. Als Format für das Hinterlegen von Variablen zu einzelnen Hosts oder Gruppen kann YAML oder JSON zur Anwendung kommen.
Jobs in Projekten und Workflows ausführen
Ein Projekt repräsentiert eine Sammlung von einem oder mehreren Playbooks aus einer bestimmten Quelle. Während vieles komfortabel über die GUI administrierbar ist, muss das Erstellen der Playbooks jedoch auch beim Einsatz von AWX auf der CLI erfolgen. Diese Playbooks können Sie entweder in einem Verzeichnis (Default-Pfad "/var/lib/awx/projects") oder in einem Git-Repository hinterlegen, wobei ein Source-Code-Management (SCM) die präferierte Variante darstellt. Eine Propagierung von Änderungen im SCM erfolgt über eine Synchronisation des Projekts mit dem SCM. Innerhalb des Projekts erfolgt nach der Auswahl des Ablageorts automatisch eine Anzeige der zur Verfügung stehenden Playbooks. Hierfür müssen Sie sicherstellen, dass die Berechtigungen auf das Verzeichnis so gesetzt sind, dass der AWX ausführende Nutzer entsprechende Rechte besitzt.
Nachdem wir nun unsere Quellen für die Playbooks innerhalb des Projekts bereit haben, können wir daran gehen, hier die konkreten Job-Templates anzulegen. Zunächst hinterlegen Sie einen sprechenden Namen und unter "Job Type" definieren Sie, ob der Job im "Check"- oder "Run"-Modus laufen soll. Der Check-Modus bietet sich insbesondere bei weitreichenden Changes an, da er nur prüft, aber keine Ausführung der im Playbook hinterlegten Anweisungen erfolgt. Im Nachgang wählen Sie das Inventory, in dem Sie die entsprechenden Switches hinterlegt haben.
Nach Definition des Inventories und des Projekts erfolgt eine Auswahl des Playbooks gemäß der im Projekt hinterlegten Quelle wie beispielsweise Git oder einem lokalen Verzeichnis. In unserem Beispiel wählen wir das Playbook "cisco_config_generation.yml", in dem das Ansible-Template-Modul ein Jinja2-Template mit den hinterlegten Daten aus dem Inventory rendert und im Nachgang in ein lokales Verzeichnis ablegt. Somit ist es nicht mehr erforderlich, händisch pro Switch Konfigurationsdateien durch Suchen und Ersetzen oder über manuelle Anpassungen zu modifizieren. Die Automatisierung bringt an dieser Stelle auch eine geringere Fehleranfälligkeit mit sich, das Sie Copy-und-Paste vermeiden.
Um einen Job auszuführen, feuern Sie in der Auflistung der Job-Templates die "Rakete" ab, in Bild 2 rot umrandet. Den Status der Job-Ausführung sehen Sie dort auch anhand der grünen Einfärbung im mittleren Bereich. Fehlgeschlagene Jobs erscheinen hier Rot.
Um mehrere Job-Templates zu einem komplexeren Workflow zu verknüpfen und abhängig vom Erfolg der Ausführung eines vorherigen Jobs einen anderen zu starten, nutzen Sie Workflow-Templates. Damit haben Sie die Möglichkeit, über einen visuellen Editor komplette Arbeitsabläufe zu modellieren und zu steuern, was nach einem erfolgreichen oder fehlgeschlagenen Update geschehen soll. So können wir in unserem Beispiel bei erfolgreicher Umsetzung des Config-Generierungs-Jobs eine Kopieraufgabe auf einem Webserver ausführen. Über diesen kann das Bereitstellen der Konfigurationen an andere Administratoren oder das Zero-Touch-Provisioning-System stattfinden. Der Fehlerfall führt zu einem alternativen Job, während im Normalfall eine blaue Linie zu einer immer auszuführenden Aufgabe zeigt. Zusätzlich lassen sich Workflows auf einzelne Benutzergruppen eingrenzen.
Schedules und Notifications zur Steuerung
Eine interessante Funktion bieten Schedules mit der Zeitsteuerung spezifischer Jobs-Templates, beispielsweise für Update-Jobs, um diese in Wartungsfenstern durchzuführen. Bei aller Vorsicht, die Sie bei diesem Thema an den Tag legen sollten, bietet dies in Kombination mit der Benachrichtigung über die Notifications einen flexiblen Ansatz, die Arbeitszeit des Systemadministrators von den Nachtstunden wieder in den Tag zu verlegen und so die vielbeschworene Work-Life-Ba-lance zu verbessern. Schedules können wiederkehrend oder einmalig sein.
Über Notifications lassen Sie sich über den Ausführungsstatus des jeweiligen Jobs informieren. Als Typen der Benachrichtigung stehen zum Beispiel E-Mail, Webhooks, Mattermost, Slack und IRC zur Verfügung. Dazu müssen Sie zunächst die Notification-Ziele hinterlegen und anschließend kann in den einzelnen Job-Templates eine Referenzierung erfolgen. Hierbei stehen Benachrichtigungen beim Start, bei erfolgreicher sowie bei fehlerhafter Ausführung zur Verfügung.
Anbindung an Drittsysteme via REST-API
Eine Anbindung an Drittanbieter, wozu beispielsweise eigene Skripte, aber auch Managementsysteme zählen, nehmen Sie über eine REST-API vor. Die API steht in unserem Beispiel über Port 80 oder per HTTP über 443 für den Webserver unter "http:// <FQDN oder IP-Adresse>/api" bereit. Dort finden Sie zum Kennenlernen eine an den Browser angepasste Darstellung.
Über die REST-API sind Sie in der Lage, jeden über die GUI erreichbaren Parameter anzupassen. Eine Dokumentation der Funktionen steht auch im "Tower API Reference Guide" [1] zur Verfügung. Der Aufruf von http GET auf "http://<FQDN oder IP-Adresse>/api/v2/organizations/" liefert alle angelegten Organisationen.
IT-Administrator Sonderheft Automatisierung
Diesen Artikel und 180 Seiten weitere praxisnahe Beiträge liefert unser neues Sonderheft "Automatisierung – Abläufe programmieren, manuelle Arbeit reduzieren". Das zweite Sonderheft des Jahres 2021 zeigt IT-Verantwortlichen Strategien und Technologien auf, um die IT und ihre Abläufe von der Handarbeit zu befreien.
Dazu widmet sich das Autorenteam zunächst dem Scripting mit PowerShell, BASH und Python – von den ersten Schritten über Best Practices bis hin zur Sicherheit innerhalb der Skripte. Anschließend wendet sich das Sonderheft dem umfangreichen Park an Automatisierungswerkzeugen von Ansible, Puppet und Chef bis hin zu Terraform und den Automatisierungsframeworks von VMware und Red Hat zu. Auf den ersten beiden Abschnitten aufbauend, setzen die Autoren dann im dritten Teil des Sonderhefts konkrete Automatisierungsanforderungen um. Dabei kümmern wir uns um Windows-Server und -Clients, um VMware- und Citrix-Umgebungen und um Netzwerkomponenten.Das Sonderheft ist ab Oktober verfügbar und kostet für Abonnenten des IT-Administrator 24,90 Euro, für Nicht-Abonnenten werden 29,90 Euro fällig.
Backup und Restore
Während Ansible Tower über das mitgelieferte Shell-Skript "setup.sh" und das Argument "-b" (also ./setup.sh -b) ein Backup erstellt, ist dies in AWX nur über einen kleinen Umweg möglich. Hierzu haben wir in der Installation bereits die Tower-CLI mit eingespielt. Die aktuelle Parametrisierung der Tower-CLI zeigt Ihnen tower-cli config auf der Konsole. Im Nachgang passen wir dies in Listing 1 an unsere Bedürfnisse an. Da es sich nur um eine Testinstallation handelt, nutzen wir eine unverschlüsselte Verbindung. Die notwendige Verschlüsselung im produktiven Betrieb erschließt sich jedoch von selbst.
Das eigentliche Backup erfolgt in der Zeile "tower-cli receive --all > awx_backup.json" im JSON-Format. In unseren Tests für diesen Artikel gab es jedoch diverse Bugs in den Backupskripten. Python-Kenntnisse sind also von Vorteil, um im Bedarfsfall ein Troubleshooting auszuführen. Konkret lief das Backup über die Tower-CLI wiederkehrend in eine Exception des Skripts "/usr/lib/python3/ dist-packages/tower_cli/cli/transfer/common.py". Hier half ein eigens erstelltes Exception-Handling im Bereich der Funktion "extract_extra_credentials()".
Optional besteht auch noch die Möglichkeit, ein Datenbank-Dump der PostgreSQL-Datenbank im entsprechenden Docker-Container zu erstellen. Dieses zeigt Listing 1 ebenfalls. In unserem Beispiel erfolgt ein restore mit der Datei "awx_backup.json" und dem CLI-Befehl
tower-cli send awx_backup.json
Für ein alleiniges Restore der Datenbank nutzen Sie pg_restore.
Listing 1: Parametrisierung der Tower-CLI und Erstellen eines Backups
Per Automatisierung gleichzeitig Changes auf einer Vielzahl an Hosts durchzuführen, ist eine Tätigkeit, die mit großer Verantwortung daherkommt. Damit bei eventuell entstehenden Problemen klar ist, welche Änderungen zuvor stattgefunden haben, sollten Sie für ein Logging sowie eine Audit-Möglichkeit sorgen.
Hierfür steht Ihnen eine dedizierte User-Rolle namens "System Auditor" mit reinen Leserechten zur Verfügung. Diese erlaubt, die gesamte Parametrisierung einer Prüfung zu unterziehen. Besonders interessant ist der Activity Stream. In diesem können Sie Veränderungen in AWX selbst und durch automatisierte Jobs nachvollziehen.
Möchten Sie Logs lieber auf einem externen System einsammeln, aufbereiten und anzeigen, steht Ihnen dies über die Integration von Third-Party-Logging-Aggegratoren zur Verfügung. Dazu lassen sich Logstash, Splunk, Loggly und Sumologic nutzen.
Konfiguration von neuen NTP-Servern auf mehreren Routern
Kommen wir nun zur Praxis mit einem Step-by-Step-Konfigurationsbeispiel, das über AWX auf Routern mehrere NTP-Server einrichtet. Im ersten Schritt legen wir auf dem AWX-Host über die CLI das Verzeichnis "/var/lib/awx/projects/ntp-config-deploy/" an. Anschließend deponieren Sie in diesem Verzeichnis das in Listing 2 dargestellte Playbook "ntp-deploy.yaml". In diesem nutzen wir die network_cli-Connection. Die Ziel-Hosts setzen Sie zunächst auf "all", da die Einschränkung der Ziel-Hosts später über AWX erfolgt. Im Playbook kommt das Ansible-Modul "ios_ config" zum Einsatz, das sowohl der Konfigurationsänderung als auch der Speicherung dient.
Listing 2: Playbook zum Erstellen von zwei NTP-Servern unter Cisco-IOS-XE
---
- hosts: all
gather_facts: no
connection: network_cli
tasks:
- name: TASK - DEPLOY NTP
ios_config:
lines:
- ntp server 192.0.2.1 prefer
- ntp server 192.0.2.2
- name: TASK - SAVE IF NECESSARY
ios_config:
save_when: modified
Jetzt wechseln Sie ins Webinterface von AWX, zunächst als Admin-User. Dort legen Sie eine Organisation und anschließend die benötigten Teams an, in unserem Beispiel "Junior Consultants" und "Senior Consultants". Nachdem Sie dann einen normalen Benutzer (kein Auditor oder Administrator) angelegt haben, erfolgt das Zuweisen zum Team "Senior Consultants". Über diesen Nutzer soll im Nachgang die Ausführung des Config-Changes stattfinden.
Um später auf die Router und Switches zugreifen zu können, bedarf es im nächsten Schritt des Anlegens der benötigten Credentials. In unserem Fall mit dem Connection-Modus "network_cli" und dem Cisco-ios_config-Modul kommt der Credential-Typ "Machine" zum Einsatz. Als "Privilege Escalation Method" nutzen wir "enable", wie es bei Cisco-IOS-Systemen der Standard ist.
Ad-Hoc-Kommandos
Um nicht für jede Kleinigkeit ein Playbook schreiben zu müssen, stehen für einzelne Module wie zum Beispiel command, shell, ping oder win_ping Ad-Hoc-Kommandos zur Verfügung. Hierfür genügt ein Aufruf des Inventories, die Auswahl der Zielsysteme, auf denen das Kommando laufen soll, die Auswahl des Moduls und der zugehörigen Argumente sowie die Referenz auf die benötigten Credentials für das Zielsystem.
In unserem bestehenden Router-Inventory legen wir den Router "R2" mit zwei Variablen an, um das Minimum abbilden zu können (ansible_host: 192.168.178.254 und ansible_network_os: ios). Sie geben den benötigten Teams "Use"-, "Read"- und "Ad Hoc"-Berechtigungen, damit diese es lesen und nutzen, aber nicht bearbeiten dürfen.
Zusätzlich erzeugen Sie ein neues Projekt mit dem lokalen Pfad als Playbook Directory. Auch für dieses Projekt geben Sie den entsprechenden Teams die Berechtigung. Nun erstellen Sie ein Job-Template namens "NTP Deployment" und hinterlegen zusätzlich eine Notifications-Regel, sodass Sie bei erfolgreicher oder fehlgeschlagener Ausführung eine Information per E-Mail erhalten. Bei Bedarf könnte das erstellte Job-Template auch über einen Scheduler zu einer bestimmten Zeit, wie beispielsweise in einem Wartungsfenster, zur Ausführung kommen. Nach dem Anlegen können Sie den Job über einen Klick auf "Launch Job" direkt ausführen.
Ist der Job durchgelaufen, sehen Sie das Ergebnis: An der grünen Einfärbung oben links erkennen Sie einen erfolgreichen Job. Bei einer roten Einfärbung ist das Playbook fehlgeschlagen. Welche Komponenten angepasst wurden, erkennen Sie ebenfalls an dieser Darstellung. In unserem Beispiel haben wir nur einen Router im Inventory. Jedoch wäre es nun einfach über Erweiterung des Inventories möglich, eine große Anzahl gleichartiger Router zu parametrisieren.
Fazit
AWX erspart dem Administrator weder die Einarbeitung in die Ansible-Module noch das Erstellen der Playbooks für Prüfungen oder Konfigurationsanpassungen. Allerdings bietet die benutzerfreundliche GUI die Zeitsteuerung von Jobs, die Abbildung eines Rechte- und Rollenmodells sowie Auditfunktionen. Insbesondere das Rechte- und Rollenmodell bringt den Vorteil mit sich, die Komplexität einzelner Changes und die Einarbeitung in Playbooks vor bestimmten Benutzergruppen verbergen zu können. Auch die verschlüsselte Ablage der Credentials stellt eine sehr sinnvolle Ergänzung dar. Somit muss der Administrator sich nicht mehr selbst Gedanken über deren Sicherheit machen. Jedoch sind für die Einrichtung auch zusätzliche Kenntnisse zu Docker und Git sinnvoll.