Open Source Software Ansible - Continous Ansible mit Jenkins

Open Source Software Ansible - Continous Ansible mit Jenkins

Die Open Source Software Ansible bietet Konfigurationsmanagement, Orchestrierung und Provisionierung für unterschiedliche Plattformen. Mithilfe von Jenkins können Builds, Deployments und Automatisierungen mittels einer Open Source Software realisiert werden. Damit bietet sich Jenkins auch für die Automatisierung von Ansible Playbooks an. So erhält der Nutzer eine Weboberfläche, die den Zustand aller konfigurierten Ansible Playbooks oder ad-hoc-Kommandos grafisch darstellt und deren Kern die Operationen auch automatisiert ausführen kann.

Die Werkzeuge

Ansible [1] ist eine Open Source Software, lizensiert unter der GPL v3. Mit Ansible können Systeme konfiguriert und orchestriert werden. Provisionierung und sogenannte „Zero-Downtime"-Deployments sind ebenfalls möglich. Mittlerweile ist Ansible ein Teil von Red Hat, welches die dahinter stehende Firma AnsibleWorks 2015 nur 2 Jahre nach deren Gründung 2013 [2] übernommen hat. Als Zielsysteme werden Linux/Unix, Solaris, Windows und MacOS unterstützt.

Jenkins [3] ist ein Fork von Hudson, welches ursprünglich bei SUN Microsystems entwickelt wurde. Nach der Übernahme durch Oracle wurde mit Jenkins die offene Weiterentwicklung fortgeführt. Jenkins ist in Java implementiert und bietet ein durch Plugins erweiterbares webbasiertes System für Continous Integration, Continous Delivery oder automatisiertes Testen. Durch die Erweiterbarkeit bietet Jenkins viele Möglichkeiten, nahezu beliebige Aufgaben zu automatisieren, beispielsweise Softwarebuilds mit ant oder make. Die dazu notwendigen Quellen können aus bestehenden SCMs wie Git, SVN etc. bezogen werden. Sämtliche Aufgaben können zeitlich gesteuert oder von extern ausgelöst werden. Zusätzlich existieren nach der Beendigung der Aufgabe weitere Optionen zur Verarbeitung oder lediglich Benachrichtigungen der Anwender.

Nun liegt es nahe, diese beiden Werkzeuge eine Beziehung eingehen zu lassen. So besteht die Möglichkeit, die Ansible-Konfigurationen in einem Git-Repository zu hinterlegen. Bei jeder Änderung im Repository sollen diese dann auf die Zielsysteme angewandt werden. Dies kann später auch noch mit dem anschließenden Deployment auf Produktivsysteme gekoppelt werden, wenn das Deployment und diverse Funktionstests in der Testlandschaft erfolgreich sind. Dieser zweite Zusatz ist allerdings nicht Bestandteil dieses Artikels, stellt aber eine Möglichkeit zur weiteren Verwendung der Werkzeuge dar.

Ansible – ein kurzer Überblick

Ansible verarbeitet wahlweise einzelne Kommandos oder komplexe Abläufe, die in sogenannten Playbooks definiert werden. Die anzusteuernden Zielsysteme werden in Inventories konfiguriert. Dabei handelt es sich um einfache Textdateien im Stil einer INI-Datei (siehe Abbildung 1). Ansible verbindet sich per SSH mit allen Zielsystemen. Dabei ist es möglich, unterschiedliche User Accounts auf verschiedenen Systemen in einem Lauf zu verwenden. Zusätzlich stehen unterschiedliche Optionen zur Verfügung, um sich auf dem Zielsystem weiterführende Rechte (üblicherweise per sudo) zu verschaffen. Folgendes Kommando führt den Befehl uptime auf allen Hosts aus:

ansible –i hosts all –m command –a uptime

Die notwendigen Hosts werden aus dem Inventory hosts gelesen. Statt dem Bezeichner all kann hier auch eine Gruppe genannt werden, beispielsweise ntp-clients oder webserver.
[ntp-clients]
192.168.33.100
192.168.33.101

[webserver]
192.168.33.100 
Abb. 1: Ein Inventory für Ansible
192.168.33.101 | SUCCESS | rc=0 >>
09:55:38 up 9 min, 1 user, load average: 0.00, 0.04, 0.05

192.168.33.100 | SUCCESS | rc=0 >>
09:55:37 up 10 min, 1 user, load average: 0.08, 0.07, 0.06 

Das von Ansible verwendete Modul ist command, das Argument für das Modul lautet uptime. Das Resultat der Verbindung zeigt Abbildung 2. Durch die Playbooks besteht die Möglichkeit, mehrere Tasks aneinanderzureihen und in Abhängigkeit zu vorangegangenen Ergebnissen oder Optionen auf dem Zielsystem auszuführen. Solche Playbooks werden in YAML-Dateien gespeichert, eine Ausführung wird kurz als „Play" bezeichnet. Das Playbook webserver.yml (siehe Abbildung 3) stellt vereinfacht die Installation, den Start von httpd (Apache2 unter Red Hat) sowie die Bereitstellung der Datei index.html mittels eines Template dar. Solch ein Playbook wird mittels ansible-playbook ausgeführt: 

ansible-playbook –i hosts webserver.yml 

Hier wird auch wieder das Inventory übergeben, eine Definition der Hosts im Playbook selbst ist auch möglich. Ausgehend davon, dass der Inhalt in der index.html, bzw. im entsprechenden Template in einem Git-Repository gepflegt wird, stellt sich die Frage: Wie kommen Änderungen aus dem Repository automatisch auf alle konfigurierten Webserver? Entweder wird hier der entsprechende Aufruf von Ansible per cron geplant oder als manueller Schritt vorgesehen. Solch ein manueller Vorgang wird selbstverständlich gerne vergessen. Eine Automatisierung per cron erlaubt aber keine einfach zu konfigurierenden komplexen Abläufe, wie das Deployment auf Produktivsysteme im Erfolgsfalle. Genau hier wird eine Integration in Jenkins interessant.

Abb. 2: Resultat des ad-hoc-Kommandos uptime

hosts: webserver
become: true
tasks:
- name: install httpd
package: name=httpd state=latest
- name: install template
template: src=index.html.j2 dest=/var/www/html/index.html
- name: start and activate httpd service
service: name=httpd state=started enabled=yes 

Abb. 3: webserver.yml – ein Ansible Playbook

Jenkins herrichten

Die Nutzung von Ansible via Jenkins kann auf zwei Arten erfolgen. Entweder wird jeder entsprechende Job per Build-Schritt Execute shell geplant oder das komfortablere Plugin Ansible wird genutzt. Für die Integration von Git und Ansible sollten folgende Plugins in Jenkins installiert werden:

  • Git [4
  • Ansible [5
  • AnsiColor [6]

Das Plugin Git übernimmt den Bezug der Playbooks aus einem Git-Repository. Das Plugin Ansible stellt zwei neue Build-Schritte zur Verfügung:

  • Invoke Ansible ad-hoc command
  • Invoke Ansible Playbook

Ersteres wird genutzt um z.B. das Ausführen einmaliger Kommandos per Ansible durchzuführen (analog dem oben genannten uptime). Der Schritt für die Playbooks hingegen erlaubt dann das Ausführen komplexer Abläufe. Die farbliche Aufbereitung der Ausgabe wird dann vom Plugin AnsiColor übernommen. Dadurch werden erfolgreiche Schritte Grün, fehlerhafte Rot und Warnungen in Gelb ausgegeben. Dieses Plugin sollte auch genutzt werden, wenn Ansible als Execute shell ausgeführt wird, hier sollte direkt zu Beginn der Shell-Schritte noch die Angabe von export ANSIBLE_FORCE_COLOR=true gesetzt werden, damit Ansible die farbliche Hervorhebung realisiert. Bei Verwendung des Plugin für Ansible geschieht dies automatisch.

Ein Ansible ad-hoc-Kommando in Jenkins definieren

Soll nun das erwähnte uptime per Jenkins ausgeführt werden, wird das entsprechende ad-hoc-Kommando konfiguriert (siehe Abbildung 4). Dazu wird in der Weboberfläche von Jenkins ein New Item erstellt, der Typ des Projektes ist ein Freestyle project und der Name uptime. Zusätzlich muss sich das übergebene Inventory (hier /opt/ansible/hosts) auf dem Jenkins selbst befinden. 

Zu den Optionen gehört die Aktivierung von sudo. Der von Ansible genutzte User wird dann auf dem Zielsystem per sudo die notwendigen erweiterten Rechte anfordern. Die erweiterten Einstellungen erlauben dann auch die Anzahl der parallel abzuarbeitenden Hosts zu verändern, 5 ist hier der Standard. 

Die Einstellung Check host SSH key weist den von Ansible genutzten SSH-Client an, den Host Key des Zielsystems mit den ihm bekannten Host Keys zu vergleichen. Nach Möglichkeit sollte diese Option aktiviert sein, allerdings müssen die Keys dafür auf den Jenkins Host importiert werden. So kann aber das Verbinden via SSH auf unbekannte/unberechtigte Hosts verweigert werden und entsprechend die Sicherheit gesteigert werden. 

Zusätzlich sollte noch die Option Colorized stdout aktiviert werden, dies sorgt dafür, dass Ansible die Schritte farbig hervorhebt. In Kombination mit der Option Color ANSI Console Output im Abschnitt Build Environment wird dann für jeden Build eine grafische Ausgabe erzeugt.

Nach dem Speichern kann der Build erstmalig ausgelöst werden, die Ausgabe sollte analog dem Aufruf in Abbildung 2 sein, allerdings eingebettet in die Weboberfläche von Jenkins.

Abb. 4: Ansible ad-hoc „uptime“ in Jenkins

Let´s play ansible

Ebenso einfach ist die Konfiguration eines Jobs in Jenkins, der ein Ansible Playbook ausführt. In dieser Konfiguration selbst wird dann auch direkt Git als SCM verwendet​.
Einen Ablauf stellt Abbildung 5 dar. Der oder die User ändern den Inhalt eines Playbook oder auch nur den Inhalt eines Template und checken die Änderungen in ein Git Repository ein. Dieses Repository wird in regelmäßigen Abständen von Jenkins auf Änderungen geprüft. Haben sich Änderungen ergeben, so wird der Build-Prozess ausgelöst und Ansible versorgt (Deployment) die definierten Hosts mit dem neuen Inhalt. Haben sich keine Änderungen im Repository ergeben wird nichts unternommen.
In der Beispielkonfiguration (siehe Abbildung 6) findet die zeitliche Prüfung alle 15 Minuten statt. Zusätzlich ist Git als SCM ausgewählt, die Repository URL entspricht einem regulären Zugriff per SSH auf den Host, der das Repository anbietet.

Abb. 5: Ablauf des Playbook webserver.yml mit Git und Jenkins
Abb. 6: Konfiguration von Git sowie der Intervalle unter Jenkins

Als Build-Schritt wird nun Invoke Ansible Playbook ausgewählt. Der Pfad zum Playbook kann relativ angegeben werden, normalerweise ist die Basis für den Job unter /var/lib/jenkins/jobs//workspace. Somit ist der Checkout des Repository auch direkt in diesem Verzeichnis. Das Git-Repository enthält ein Unterverzeichnis namens webserver, darin enthalten ist das eigentliche Playbook webserver.yml. Somit ergibt sich der vereinfachte Pfad zum Playbook: webserver/webserver.yml.

In der eigentlichen Build-Sektion (siehe Abbildung 7) werden nun die Einstellungen für die Ausführung des Plays vorgenommen. Das Inventory muss wieder angegeben werden, sofern im Playbook selbst die Hosts nicht definiert sind. Dieses Inventory zeigt auf die Datei /opt/ansible/hosts. Hier ist Obacht geboten: eine Änderung am Inventory (bspw. Hinzufügen eines Host) löst keinen neuen Build aus. Erst ein neuer Commit in das Git-Repository würde auch den httpd auf dem hinzugefügten Host installieren! Entweder wird das entsprechende Inventory auch im Git- Repository abgelegt oder über ein git submodul mehreren Git-Repositories hinzugefügt. Dies würde die Pflege der vollständigen Hosts an zentraler Stelle ermöglichen. Für die Benutzeranmeldung wird wieder auf sudo zurückgegriffen, dies ist aber konfigurierbar. Die Ausführung des entsprechenden Build erfolgt dann unter der Ausgabe der einzelnen Schritte, dies beinhaltet den Git-Checkout sowie das Ausführen des Playbook (siehe Abbildung 8).

Abb. 7: Der Aufruf des Ansible Playbook unter Jenkins
Abb. 8: Die Konsolenausgabe des Playbook webserver.yml

Die Wetteraussichten

Die in die Weboberfläche integrierte Übersicht (siehe Abbildung 9) von Jenkins erlaubt einen schnellen Blick auf die Liste der Builds. Dabei erleichtern Symbole wie Sonnenschein, bewölkt oder Gewitter das Erfassen der Zustände. Sind die letzten 5 Builds eines Jobs fehlgeschlagen, so wird hier eine Gewitterwolke dargestellt. Schlägt ein Build in den letzten 5 Anläufen fehl, so ist der Himmel bewölkt, die erfolgreiche Ausführung hingegen verheißt Sonnenschein. Zeiten für den letzten Fehlschlag, den letzten erfolgreichen Build sowie die Dauer des Build werden in der Standardansicht dargestellt. Zusätzlich kann auch direkt die Konsolenausgabe des letzten Build kontrolliert werden.
Abb. 9: Neues zur Wetterlage: Build-Übersicht in Jenkins

Fazit

Die Integration von Ansible als Buildstep in Jenkins eröffnet neue Möglichkeiten für Continous Delivery. Durch die Gestaltung von abhängigen Schritten können erfolgreich geprüfte Versionen in die nächste Umgebung, beispielsweise die Produktion, gehoben werden. Die Optionen zur Benachrichtigung im Fehlerfall und die einfache Übersicht erlauben eine komfortable Administration. Somit können Entwickler durch das Einchecken in ein Repository ihre Neuerungen über nachvollziehbare Schritte durch mehrere Stufen in das Produktivsystem bringen.

Glossar

Ansible

Ansible ist eine Open Source Software von Red Hat zur IT-Automatisierung. 

Continous Delivery 

Dauerhafte Auslieferung einer Software bei Erreichen einer bestimmten Qualität. 

Continous Integration 

Stetiges Integrieren von Softwareteilen zu einem Ganzen, stellt bereits beim Einpflegen mögliche Probleme fest.

Fork
Die Abspaltung eines Softwareprojektes von einem bestehenden Projekt. 

Git
Verteilte Versionsverwaltung von Dateien, mit dieser Software wird u.a. der Quellcode des Linux-Kernels verwaltet. 

Inventory
Eine Datei die definiert, zu welchen Zielen per Ansible eine Verbindung aufgebaut werden soll. Die Hosts werden gruppiert. Eine Angabe weitere Verbindungsparameter (Benutzernamen, Ports, etc.) ist möglich. 

Jenkins
Webbasierte Open Source Software für Continous Integration, Delivery und automatisiertes Testen. 

Playbook
Die Zusammenfassung von mehreren Aufgaben für Ansible, können u.a. mit Abhängigkeiten gesteuert werden.

Play
Die Ausführung eines Playbook mit Ansible. 

SCM
Source Code Management, eine Software zur Verwaltung von Quellcode (z.B. Git, Subversion). 

YAML
Eine (für Menschen) leicht lesbare Sprache für Datenserialisierung.

Links

 

Kommentare

Derzeit gibt es keine Kommentare. Schreibe den ersten Kommentar!
Gäste
Samstag, 21. September 2019

Sicherheitscode (Captcha)