Entwicklungsumgebungen automatisiert erstellen mit Ansible

1
Mit Ansible stellen sich Entwickler einfach ihr „Menü“ für ihre Entwicklungsumgebung zusammen

Mit Ansible stellen sich Entwickler einfach ihr „Menü“ für ihre Entwicklungsumgebung zusammen

Software-Entwickler kennen das: Jeder verwendet seine eigene virtuelle Maschine mit Entwicklungsumgebung über einen langen Zeitraum hinweg, was zur Folge hat, dass alle eine abweichende Umgebung verwenden, mit unterschiedlichen Versionsnummern oder gar Betriebssystemen. Um diesen Problemen zu entgehen, setzen wir bei der Entwicklung unserer Monitoring-Software openITCOCKPIT Ansible ein.

Aber warum trennen sich Entwickler so ungern von ihrer Entwicklungsumgebung? Im Gegensatz z.B. zu einem Webshop greift openITCOCKPIT auf eine Vielzahl von Open Source Tools zurück. Diese müssen alle installiert und konfiguriert bereit stehen. Ein einfaches „apt-get install“ reicht nicht aus, um sie herunterzuladen und zu installieren. Außerdem müssen sich IP-Adresse gemerkt, SSH-Key hinterlegt oder vorhandene Templates ohne Anpassung weiter verwendet werden. Das heißt, als Entwickler ist man einfach froh, wenn „alles funktioniert“ und man nicht ständig Softwareupdates durchführen muss.

Entwicklungsumgebung auf Knopfdruck
Speziell für openITCOCKPIT haben wir ein „Ansible Playbook“ erstellt. In diesem Playbook hält man alle Aufgaben fest, die ausgeführt werden müssen, um eine openITCOCKPIT-Entwicklungsumgebung zu erstellen.

Leider ist das für Entwickler nicht so komfortabel wie für Anwender, die openITCOCKPIT mühelos mit Hilfe des Paket-Managers „apt“ installieren können. Entwickler möchten jederzeit die Möglichkeit haben, Komponenten zu entfernen oder durch eine neue Version zu ersetzen. Das ist aber nur bedingt möglich, wenn „apt“ im Spiel ist.

Zur Verdeutlichung hier ein Auszug aus dem Playbook für openITCOCKPIT:

Playbook
– hosts: all
remote_user: vagrant
become: yes
strategy: debug
vars_files:
– vars/all.yml
roles:
– server
– mySQL
– xdebug
– naemon
– oitc
– oitcmodules
– statusengine
– nginx
– autodns
– monitoring
– systemutils
– nfs

Zusätzlich kann der Entwickler über eine Konfigurationsdatei entscheiden, welche Version von openITCOCKPIT, Naemon oder Statusengine installiert werden soll:

Konfiguration für Versionen

oitc:
branch: development
debian_version: trusty
oitc_system:
branch: master
statusengine:
branch: master
naemon:
version: 1.0.5

Ansible bekommt als Ziel die IP-Adresse einer frischen Ubuntu 14.04 Installation übergeben und beginnt anschließend direkt mit seiner Arbeit. Als erstes werden Basiskomponenten wie Nginx, MySQL und PHP installiert:

user@machine~# ansible-playbook playbook.yml -i inventories/openitc

Zusätzlich werden auf jeder Maschine Naemon, Statusengine sowie die Monitoring-Plugins kompiliert und installiert.

IP-Adressen merkt sich keiner gerne, besonders, wenn sie oft wechseln. Aus diesem Grund erstellt Ansible für jede neue Maschine einen Eintrag im DNS-Server.

Natürlich soll auch auf einer kurzlebigen Entwicklungsmaschine alles problemlos funktionieren. Deshalb richtet Ansible die Überwachung der neuen virtuellen Maschine in einer zentral bereitstehenden openITCOCKPIT-Installation ein (über die REST-API). Sollten Probleme auftauchen, sieht sie der Entwickler auf dem Dashboard. Dieser Screenshot zeigt, welche Services automatisch überwacht werden:

openitcockpit_dashboard

Ansible richtet die Überwachung der neuen virtuellen Maschine in einer zentral bereitstehenden openITCOCKPIT-Installation ein.

Zu guter Letzt wird noch ein NFS-Share eingerichtet und die Maschine ist einsatzbereit. Die ganze Prozedur dauert in der Regel keine zehn Minuten.

Nun kann der Entwickler mit seiner Arbeit beginnen. Möchte er etwas ausprobieren, eine neue Version testen oder prüfen, ob ein Update von Ubuntu gefahrlos ausgeführt werden kann, ist es nicht schlimm, wenn ein Fehler auftritt. Denn eine neue Maschine ist schnell erstellt und das Problem kann behoben werden. Da alle Entwickler ihre Maschinen regelmäßig austauschen, laufen alle Systeme mit der gleichen Konfiguration und dem gleichen Betriebssystem.

Achtung, Zombie-Apokalypse!
Wenn Entwicklungssysteme automatisch einen DNS-Eintrag bekommen und in ein Monitoring-System integriert werden, diese Systeme aber nur eine kurze Lebensdauer haben, dann besteht die Gefahr, dass Systeme weiter leben die längst nicht mehr vorhanden sind.
Um solche „System-Zombies“ zu verhindern, läuft auf dem openITCOCKPIT-System, das die Entwicklerinfrastruktur überwacht, ein Cronjob, der alle Systeme aus dem DNS-Server und dem Monitoring löscht, die seit mehr als fünf Tagen nicht erreichbar sind. Sollte doch einmal ein System gelöscht werden, das bewusst vor fünf Tagen ausgeschaltet wurde, kann es durch einen erneuten Aufruf von Ansible wieder angelegt werden.

Warum Ansible und nicht Puppet?
openITCOCKPIT verwendet Ansible, weil Puppet dem Client-Server-Prinzip folgt. Das heißt: Ändert man etwas auf dem Server, wird es automatisch auf alle Clients übertragen. Dieses Verhalten ist für Admins sehr praktisch, schränkt die Entwickler jedoch ein.
Bei Ansible hat jeder Entwickler eine Kopie des Playbooks. Damit hat er selbst die Kontrolle über den Prozess. Er kann im Playbook nach Belieben Aufgaben erweitern oder überspringen, wenn sie zu Testzwecken nicht ausgeführt werden sollen. Das Playbook sollte in einem Versionskontrollsystem wie „git“ liegen, damit Änderungen nachvollzogen werden können und jeder Entwickler auf dem gleichen Stand ist.

Stolpersteine bei der Verwendung von Ansible
Leider kann Ansible erst ab Version 2.2 ein Archiv auf einem entfernen System öffnen. Das Monitoring der Entwicklungsmaschinen erfolgt aber mit Hilfe des NRPE. Deshalb mussten wir an dieser Stelle einen Workaround zum Entpacken verwenden. Dabei wird das Archiv auf das Zielsystem kopiert und danach mit der Anweisung „command“ geöffnet:

– name: copy nrpe.tar.gz to remote host
copy:
src: nrpe.tar.gz
dest: /opt/nrpe.tar.gz
when: nrpe_installed.changed
– name: untar nrpe.tar.gz
become: yes
command: tar nrpe.tar.gz
args:
chdir: ‚/opt/‘
when: nrpe_installed.changed

Mit einem vergleichbaren Trick wird auch Naemon kompiliert: Zuerst muss das Archiv von GitHub in der gewünschten Version bezogen und entpackt werden. Im Anschluss werden die Befehle „configure“, „make“ und „make install“ ausgeführt:

– name: download naemon
become: yes
get_url:
url: ‚https://github.com/naemon/naemon-core/archive/v{{ naemon.version }}.tar.gz‘
dest: /root/naemon-core-{{ naemon.version }}.tar.gz
mode: 0664
when: naemon_installed.stat.exists == False
– name: unzip naemon-core
become: yes
command: tar xfv naemon-core-{{ naemon.version }}.tar.gz
args:
chdir: ‚/root/‘
when: naemon_installed.stat.exists == False
– name: run naemon configure
become: yes
command: ./autogen.sh –prefix=/opt/openitc/nagios …
args:
chdir: ‚/root/naemon-core-{{ naemon.version }}‘
when: naemon_installed.stat.exists == False

Jeder, der schon einmal den MySQL-Server oder phpMyAdmin über „apt-get“ installiert hat, weiß, dass bei der Installation einige Dialoge erscheinen, die beantwortet werden müssen. Für „apt“ können sie automatisiert via „debconf“ beantwortet werden. Diese Möglichkeit ist glücklicherweise auch in Ansible vorhanden, wie das folgende Beispiel zeigt:

– name: debconf for pma
debconf:
name: phpmyadmin
question: ‚phpmyadmin/dbconfig-install‘
value: ‚true‘
vtype: ‚boolean‘
– name: debconf for pma
debconf:
name: phpmyadmin
question: ‚phpmyadmin/mysql/admin-pass‘
value: ‚{{ mysql.root_password }}‘
vtype: ‚password‘

Fazit
Ab einem gewissen Grad an Automatisierung gehen individuelle Einstellungen verloren. Diesen Kompromiss muss man zwangsweise eingehen. Mit Ansible lassen wir jedoch dem Entwickler seine Freiheit, da er entscheiden kann, welche Software in welcher Version wann installiert werden soll.
Dennoch bleiben alle Entwicklungsumgebungen auf einem einheitlichen Stand, können flexibel neu gebaut und auch für automatisierte Tests von CI-Systemen genutzt werden. Das Erstellen des Ansible Playbooks mit seinen einzelnen Rollen ging nach etwas Übung sehr leicht von der Hand. Rollen, die nicht durch vorhandene Ansible-Module installiert oder konfiguriert werden konnten, können durch kleine Workarounds und simple Bash-Skripte trotzdem problemlos angesprochen werden.

Diese Artikel könnten Sie auch interessieren:

Tags: , , ,

Daniel Ziegler - Softwareentwickler Als Senior Developer im Nagios-Projekt openITCOCKPIT ist Daniel spezialisiert auf alle Spielarten von Systemmonitoring mit Open Source.
Webprofile von Daniel: XING, Blog

Ein Gedanke zu „Entwicklungsumgebungen automatisiert erstellen mit Ansible

  1. Pingback: Konfigurationsmanagement im integrierten IT-Service Management

Kommentar schreiben

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.