Open Source Software Ansible - Continuous 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 –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
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:
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.
Let´s play ansible
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.
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).
Die Wetteraussichten
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
[1] Produktseite Ansible https://www.ansible.com
[2] Pressemitteilung RedHat https://www.redhat.com/en/about/press-releases/red-hat-acquire-it-automation- and-devops-leader-ansible
[3] Produktseite Jenkins https://jenkins.io
[4] Git Plugin https://wiki.jenkins-ci.org/display/JENKINS/Git+Plugin
[5] Ansible Plugin https://wiki.jenkins-ci.org/display/JENKINS/Ansible+Plugin
[6] AnsiColor Plugin https://wiki.jenkins-ci.org/display/JENKINS/AnsiColor+Plugin
Principal Consultant bei ORDIX
Bei Updates im Blog, informieren wir per E-Mail.
Kommentare