Infrastructure as Code(1): Wie, was?

Kaum etwas bewegt die Leute, die für die Server-Infrastruktur in Unternehmen zuständig sind, derzeit so wie zentrales Konfigurationsmanagement. Unter dem Schlagwort “Infrastructure as Code”, oft zusammen mit dem Herald “DevOps”, ist das Thema derzeit aus der Szene nicht mehr wegzudenken. Dieser Artikel soll der Auftakt zu einer kurzen Reihe von Postings sein, in denen ich mich mit dem Thema auseinander setzen will.

Um den ersten Aspekt zu Verstehen, warum es sich bei diesem Konzept um einen tiefgreifenden Paradigmenwechsel handelt, muß man sich als erstes mit dem Unterschied zwischen deklarativer und imperativer Programmierung auseinandersetzen. Als Beispiel für den Unterschied soll uns zunächst ein Toastbrot mit Frischkäse und Salami dienen:

imperative Programmierung: Lege eine Scheibe Toastbrot in den Toaster. Schalte den Toaster an und warte, bis das Toastbrot fertig ist. Nimm Frischkäse und streiche ihn auf den Toast. Nimm Salami und belege das Toastbrot damit.

deklarative Programmierung:Das Endprodukt ist eine Scheibe fertig getoastetes, mit Frischkäse bestrichenes und mit Salami belegtes Toastbrot.

Vergleicht man die beiden Beispiele, werden einem recht schnell zwei Dinge auffallen:

  • die deklarative Variante beschreibt sehr übersichtlich die Qualitäten, die das fertige Ergebnis aufweisen soll.
  • die deklarative Variante trifft keinerlei Aussage darüber, wie das Ergebnis im Einzelnen erreicht werden soll.

Für das Beispiel “Toastbrot” funktionieren beide Varianten recht gut - das Problem ist hochgradig trivial, es ist nicht schwer, eine Handlungsanweisung zur Bedienung eines Toasters zu erstellen. Das ändert sich jedoch recht schnell, wenn es um komplizierte Dinge geht. Eine MySQL-Datenbank z.B. ist schon deutlich komplexer, hier müsste man, imperativ, die einzelnen Kommandos beschreiben, wie das Paket installiert wird, wie man es konfiguriert, startet, stoppt etc. Konzentrieren wir uns hier auf den Aspekt, das Paket zu installieren. Wenn wir das imperativ Beschreiben wollen, so könnten wir das auf einem Debian-System folgendermaßen tun:

apt-get install mysql-server

Geben wir diese Anweisung nun jemandem, der mit CentOS-Systemen arbeitet, so ist das für ihn völlig wertlos. Wir müssten die Anweisungen also erweitern und auch

yum install mysql-server

aufnehmen. Hier wird der größte Nachteil imperativer Programmierung ersichtlich: Durch die Konzentration auf einzelne Schritte kommt es sehr schnell zu großen, unnötig aufgeblähten Programmen. Durch die Konzentration auf das Ziel kann man das stark vereinfachen: Es soll das Paket mysql-server installiert sein. In Puppet würde man den Code einfach so schreiben:

package{'mysql-server':
  ensure => present,
}

Erreicht wird die geringere Komplexität durch die Verwendung einer Zwischenschicht, die uns die Arbeit abnimmt, aus der deklarativen Beschreibung eines SOLL-Zustandes die nötigen Schritte abzuleiten, die notwendig sind, um ein gegebenes System vom IST-Zustand zum Ziel zu überführen. Ein anderes Beispiel, daß die meisten wohl schon erlebt haben, sind Dokumentationen von Kollegen/Kolleginnen: Es gibt Dokumentationen, die beschreiben haarklein, wie ein neues Logical Volume angelegt und formatiert wird. Und dann gibt es Dokumentationen, die erwähnen nur in einem Nebensatz, daß das Filesystem auf einem eigenen LV leben und eine bestimmte Größe haben muß.

Wir halten drei Dinge fest:

  1. Ein Aspekt von “Infrastructure as Code” ist es, sich auf das zu erzielende Ergebnis zu konzentrieren: Die qualitative Beschreibung geht vor.
  2. Um dies zu erreichen wird mit Zwischenschichten wie Chef, Puppet oder anderer geeigneter Software gearbeitet.
  3. Da nur ein Ergebnis beschrieben wird, besteht nicht die Gefahr, daß einzelne Zwischenschritte vergessen werden können.

Der zweite wichtige Aspekt ist die Art und Weise, wie die Infrastruktur betrachtet wird. Ein naiver Ansatz würde den Einsatz eines Tools wie Puppet isoliert betrachten und nicht versuchen, ihn in eine größere Architektur einzubauen. Im Gegensatz dazu würde ein Configuration Management (CM)-Tool wie Puppet innerhalb der Infrastructure as Code-Philosophie lediglich als ein Service unter mehreren wahrgenommen werden: Eben als Configuration Service. Das Schlagwort Service zeigt dabei schon, wohin die Reise geht: Die Rede ist von Service-oriented architecture. Während diese Sicht bei der Entwicklung und Kombination von Anwendungen bereits weit verbreitet ist, so ist die Idee, die einzelnen Infrastrukturkomponenten relativ neu und hat sich erst mit der Verfügbarkeit von Cloud-basierten Diensten wie Amazon AWS oder der breiten Verfügbarkeit von Virtualisierung herausgebildet. Ein besonders wichtiger Punkt ist, daß man bei dieser Betrachtungsweise relativ einfach drei Merkmale definieren kann, die jeder Infrastruktur-Dienst erfüllen sollte:

  1. Er sollte modular sein: Kein angebotener Service sollte Dutzende von Abhängigkeiten haben. Die UNIX-Philosophie “one job, one tool” ist hier ein mögliches Vorbild.
  2. Er sollte kooperativ sein: Es darf nicht schwer sein, einen angebotenen Infrastruktur-Service in Anspruch zu nehmen.
  3. Er sollte zusammensetzbar sein: Die verschiedenen Infrastruktur-Services sollten sich kombinieren lassen.

Auf der einfachsten Ebene benötige ich also drei Dienste, um meine Infrastruktur aufzubauen. Dies sind:

  1. Der bootstrap service: Dieser Service ist dafür zuständig, eine Plattform das erste Mal in Betrieb zu nehmen und ein Basis-Betriebssystem zu installieren. Dabei sollte es egal sein, ob hier echte Hardware oder eine virtuelle Maschine bereitgestellt wird. Ein Beispiel für ein solches Tool ist z.B. Foreman. Der Zustand, in dem sich die Plattform nach dem initialen Provisioning befindet, sollte so sein, daß andere Infrastruktur-Dienste mit dem neu installierten Server arbeiten können.
  2. Der configuration service: Wie oben bereits erwähnt ist es Aufgabe dieser Software, das System in einen gewünschten Zustand zu versetzen - und dabei mit dem bootstrap service zu kooperieren. In der Konfiguration Foreman und Puppet lässt sich dies z.B. über den Mechanismus des External Node Classifier erreichen.
  3. Der integration service: Aufgabe dieses Services ist es, die einzelnen Teile zusammenzufügen. So kommt es z.B. so gut wie nie vor, daß nach der Installation und Konfiguration einer neuen virtuellen Maschine keine weiteren Arbeiten notwendig sind: Die neue VM muß z.B. in das System-Monitoring und das Backup aufgenommen werden. Stellt die VM die gleichen Dienste wie bereits vorhandene Server bereit, so kann es z.B. notwendig sein, vorhandene Loadbalancer neu zu konfigurieren, in Datenbanken neue Reche zu vergeben oder auch bereits bestehende Applikationen neu zu konfigurieren. Ein möglicher Weg, das zu erreichen, sind die Puppet die Exported Resources, die es ermöglichen, die Konfiguration eines Systems auch anderen Systemen zur Verfügung zu stellen.

Das erklärte Ziel dieser Bemühungen ist, entweder nach Stephen Nelson-Smith:

Enable the reconstruction of the business from nothing but a source code repository, an application data backup, and bare metal resources.

…oder nach Adam Jacob in Web Operations:

Provision a new server from bare metal to running application in less time than it takes to restore the application data.

Wir halten fest: Der zweite, wichtigere Aspekt von Infrastructure as Code ist eine systemische Sicht auf die Infrastruktur-Komponenten. Und dieser Aspekt ist es auch, der das Anforderungs- und Job-Profil unserer Branche neu definiert: An die Stelle von Administratoren, die sich sehr gut mit Betriebssystemen auskennen, treten zunehmend Architekten oder Ingenieure, deren Fokus auf der gesamten Umgebung und deren Zusammenspiel liegt. Tiefgreifende Kenntnisse der eingesetzen Techniken sind nicht länger hinreichend, um einen fähigen IT-Mitarbeiter zu beschreiben, sondern nur noch notwendig - sie sind, sozusagen, das “Handwerkszeug”. Darüber hinaus müssen Mitarbeiter in der heutigen Zeit lernen, ihre Umgebung als System, ja, als System von Systemen zu verstehen.

Ist das eine große Herausforderung? Zweifellos. Lohnt es sich: Meiner Meinung nach auf jeden Fall.

Ich höre mir jetzt von Scarlatti die Sonate in B-Moll, K87, an. Mit Horrowitz am Klavier. Tiefenentspannung pur!