Im ersten Blog Post in der Serie über Immutable Infrastructure & Micro Services mit CoreOs, Docker und Dropwizard möchte ich den Micro Service und Immutable Infrastructure Architekturansatz vorstellen. Dazu werden wir uns anschauen, warum Micro Services im Umfeld von hochverfügbaren Infrastruktur-Lösungen ein nicht nur interessanter, sondern auch gangbarer Weg ist seine Software zu bauen.
Wir werden uns dazu Vor- bzw. Nachteile von Micro Services und im Bereich der Infrastruktur das Immutable Server Pattern anschauen. Am Ende des ersten Posts werden wir einen ersten Blick auf einige Tools werfen, mit denen Micro Services und Immutable Server umgesetzt werden können. Im zweiten Teil der Serie werde ich dann zeigen, wie Immutable Infrastructure & Micro Services mit CoreOs, Docker und Dropwizard umgesetzt werden können.
Das Ablösen von Altanwendungen hat in den letzten 10 Jahren auf Grund der Komplexität der vorhandenen Anwendungen viel Geld gekostet. Hinzu kommt, dass viele Firmen sich bis heute, aufgrund unüberschaubarer Risiken, nicht trauen alte Anwendungen abzulösen. Dies wiederum führt zur künstlichen Verlängerung des Software-Lebenszyklus, obwohl die Systeme längst veraltet und buchhalterisch abgeschrieben sind.
Ein aktueller Ansatz um in Zukunft vergleichbare Probleme zu vermeiden ist die Zerteilung von Anwendungen in viele Micro Services die unabhängig voneinander weiterentwickelt werden können. Da jeder einzelne Service klein ist, sind die Risiken bei der Weiterentwicklung in diesem Paradigma überschaubar [1][4].
Micro Service haben eine Reihe von Eigenschaften. Diese sind:
- Werden nach dem “rewrite first” Paradigma geschrieben. (Neu schreiben statt anpassen).
- Übernehmen genau eine Aufgabe (Ähnlich einem Linux Service).
- Sind klein (Klein genug für einen Sprint).
- Bringen alles mit um eigenständig lauffähig zu sein.
- Bringen eigene Oberflächenelemente mit. Ein Beispiel hierfür wäre eine Tabelle welche alle Kunden innerhalb einer Kundenverwaltung ausgeben oder ein Formular mit dem ein Kunde angelegt werden kann. Diese Oberflächenelemente können dann innerhalb von Client Anwendungen per Web Service Aufruf eingebunden werden.
- Haben ein eigenes Datenmanagement.
- Sind individuell skalierbar, werden mit einer hohen Testabdeckung entwickelt und sind individuell deploybar.
Hinzu kommt, dass es egal ist, in welcher Sprache die Micro Services geschrieben werden, da sie mit dem Uniform Interface Ansatz (REST) entwickelt werden [7]. Der Uniform Interface Ansatz besteht aus vier Prinzipien, diese sind:
- Identifizieren von Ressourcen – Individuelle Ressourcen werden durch eindeutige bspw. Uniform Resource Identifier (URI) repräsentiert. Die Server Interne Ressource wird bspw. durch HTML, XML oder JSON repräsentiert.
- Manipulation der Ressourcen – Geschieht über die gesendeten HTLM, XML oder JSON Ressourcen
- Selbstbeschreibende Nachrichten – Eine gesendete Ressource beinhaltet genügend Information um sowohl vom Server als auch vom Client weiter verarbeitet zu werden. Nachrichten sind also Zustandslos.
- Hypermedia as the engine of application state (A.K.A. HATEOAS) – Ein Client navigiert über Hypermedia auf zuvor vom Server dynamisch bereitgestellten Schnittstellen. HATEOAS soll lose Bindungen gewährleisten und es so ermöglichen Schnittstellen zu ändern.
Dies ermöglicht es, verschiedenste Micro Service mit verschiedensten Technologien zu entwickeln. Da jedes Team in unterschiedlichsten Technologien verschiedene Fähigkeiten aufweißt, kann somit der volle Umfang der teaminternen Fähigkeiten ausgeschöpft werden. Dabei wird auf HTTP request-response mit Resourcen API’s (REST) und leichtgewichtigem Messaging gesetzt und nicht auf komplexe Protokolle wie WS-Choreography, BPEL oder sonst einer Orchestrierung durch ein zentrales Tool.
Ein Nachteil der Micro Service Architektur ist sicherlich die verhältnismäßig große Verteilung verschiedenster Anwendungen. Dies führt dazu, dass immer davon ausgegangen werden muss, dass ein anderer Micro Service keine Antwort liefert oder aktuell nicht vorhanden ist. Es entsteht also eine zusätzliche Komplexität: Das Erstellen einer Anwendung in einer verteilten Umgebung. Es müssen hierfür Strategien entwickelt werden, wie die einzelnen Micro Services untereinander kommunizieren, was bei einer ausbleibenden Antwort geschieht und wie mit verteilten Transaktionen umgegangen wird. Für die IT-Betriebsmannschaft kommt hinzu, dass Sie plötzlich anstatt ein paar Anwendungen eine ganze Armada von Anwendungen zu starten, überwachen und warten haben. Dies ist nur mit einer hohen Automatisierung in diesem Bereich möglich. Ein Grund mehr warum wir uns Immutable Infrastruktur mit CoreOs und Docker genauer anschauen werden.
Einigen der beschriebenen Probleme wird durch ein ausgeprägtes Real-Time Monitoring der einzelnen Micro Service begegnet. Solch ein Monitoring könnte bspw. folgende Auswertungen liefern:
- Service Monitoring: Ist der Service generell erreichbar
- Architektur Monitoring: Wie viele Anfragen pro Sekunde gehen auf die Datenbank
- Business Monitoring: Wie viele Bestellungen werden pro Minute verarbeitet
- Semantic Monitoring: Verhaltens Monitoring um Fehler schon im Voraus zu erkennen
Fassen wir Micro Service zusammen: Micro Services sind leichtgewichtig (im Sinne der Entwicklungszeit und der eingesetzten Tools), eigenständig (Auf allen Ebenen) und ermöglichen individuelles Tooling für jedes Team, egal über welche technologischen Fähigkeiten das Team verfügt.
Um die Betriebsmannschaft zu unterstützen schauen wir uns jetzt ein unterstützendes Muster an um die höhere Komplexität der Infrastruktur, die bei vielen Micro Services anfällt, in den Griff zu bekommen. Martin Fowler hat neben dem Micro Service auch den so genannten Phoenix Server beschrieben [2]. Ein Phoenix Server zeichnet sich dadurch aus, dass er bei jeder Änderung komplett zerstört und neu aufgebaut wird – wie ein Phönix aus der Asche. Um einen solchen Phoenix Server bspw. innerhalb einer Continuous Deployment (CD) Pipeline einzusetzen, kommt das Immutable Server Pattern zum Einsatz [3]. Betrachten wir die CD-Pipeline in Abb. 1, so sehen wir, dass im Schritt “Konfiguriere Infrastruktur” ein bereits installierter und konfigurierter Server erneut konfiguriert wird. Führt man das Immutable Server Pattern ein, so wird (wie in Abb. 2 gezeigt) in diesem Schritt der Server vollständig neu provisioniert. Dies führt dazu, dass auch kleinste Änderungen sowohl an der Infrastruktur als auch am Code der Anwendung zu einer neuen Provisionierung des Servers führen. Server sind also unveränderlich und bleiben damit über alle Umgebungen gleich. Dies hat zum Vorteil, dass ein Auseinanderdriften der Konfiguration (engl. Configuration Drifts [1]), also bspw. dem Entstehen von Unterschieden zwischen der Infrastruktur in Entwicklung, Test und Produktion verhindert wird.
Abb. 1: Die herkömmliche CD-Pipeline bietet viele Gefahren für Configuration Drifts.
Abb. 2: Die überarbeitete CD-Pipeline provisioniert den Server immer neu.
Um Micro Services zu erstellen und Server ohne viel Aufwand immer wieder aus der Asche heben zu können, benötigen wir verschiedene Werkzeuge. Dazu werde ich im nächsten Blog Post CoreOs, Docker und Dropwizard nutzen. In diesem Post möchte ich die Werkzeuge kurz vorstellen.
Docker hat zum Ziel, das Deployment von Anwendungen in Container zu automatisieren. Dazu nutzt Docker Container Virtualisierung. Container Virtualisierung wiederum baut auf den vorhandenen Linux Kernel auf und wird deshalb oft auch System-Level-Virtualisierung genannt (siehe Abb. 3). Docker schafft es so, sehr schnell und leichtgewichtig Anwendungen zu bauen, zu transportieren und auszuführen. Für einen sehr guten Einstieg in Docker empfehle ich die folgenden Blog Post [8][9][10][11][12]. In unserem Fall, der Immutable Infrastruktur, bildet der Docker Container den Server ab, der bei jeder Änderung immer neu zu provisionieren ist.
Abb. 3: Aufbau von Containern (Quelle: http://xebia.github.io/docker-introduction/slides/img/docker-filesystems-busyboxrw.png)
CoreOS ist eine leichtgewichtige Linux-Distribution zum schnellen aufsetzen von Clustern und darauf spezialisiert, Docker Container zu verwalten (siehe Abb. 4). Unter CoreOs kann sich Docker wie ein Paketmanager vorgestellt werden.
Abb. 4: Docker Container innerhalb eines CoreOS Host
Dazu werden verschiedenste Docker Container, welche über ein Repository bereit gestellt werden können, über systemd beschrieben und mit fleet auf dem Cluster verteilt. Systemd ist ein Daemon, welcher das Starten, Stoppen und Überwachen weitere Prozesse kontrolliert. Innerhalb von CoreOs werden sogenannte Unit Files (siehe Listing 1) für die einzelnen Docker Container bereitgestellt. Fleet agiert für systemd als Cluster Manager und erlaubt so das verteilen eines Containers innerhalb des Clusters [5]. Zu guter letzt nutzt CoreOS etcd als verteilten Schlüssel-Wert Speicher. Etcd ermöglicht das nutzen von einer gemeinsamen Konfiguration und das Erkennen von Services innerhalb des Clusters. Etcd läuft dazu auf jedem Knoten im Cluster und hilft zudem bei der Auswahl des Master bei der Netzwerkpartitionierung und wenn der aktuelle Master ausfällt (siehe Abb. 5).
Abb 5. Der Master und seine Follower innerhalb eines CoreOs Clusters.
Wir werden uns die genannten Tools innerhalb von CoreOs im Zuge des nächsten Blog-Posts noch im Detail anschauen.
Listing 1:
1[Unit] 2Description=MyApp 3After=docker.service 4Requires=docker.service 5 6[Service] 7TimeoutStartSec=0 8ExecStartPre=-/usr/bin/docker kill busybox1 9ExecStartPre=-/usr/bin/docker rm busybox1 10ExecStartPre=/usr/bin/docker pull busybox 11ExecStart=/usr/bin/docker run --name busybox1 busybox /bin/sh -c "while true; do echo Hello World; sleep 1; done" 12ExecStop=/usr/bin/docker stop busybox1
Dropwizard ist wie bspw. auch Spring Boot ein Framework, mit dem sich Micro Service erstellen lassen [6]. Dropwizard packt dazu verschiedenste bewährte und produktionsreife Bibliotheken aus der Java Welt zusammen und bietet zusätzlich einige selbstentwickelte Einstiegspunkte für die Entwicklung von Micro Services.
Grundsätlzich werden in Dropwizard folgenden Bibliotheken genutzt:
- Jetty als HTTP-Server.
- Jersey ist die JAX-RS Referenz-Implementierung um REST Anwendungen zu schreiben.
- Jackson um mit JSON zu arbeiten.
- Metrics zum erstellen von Metriken.
- Guava stellt viele Klassen bereit, welche das schreiben von Code beschleunigen.
- Logback and slf4j für das Logging innerhalb der Anwendung .
- Hibernate Validator zum Validieren von Benutzereingaben.
- Der Apache HttpClient und die Jersey Client Bibliothek erlauben die Interaktion mit Web Servicen.
- JDBI erleichtert den Zugriff auf relationale Datenbanken in Java.
- Liquibase ermöglicht das Beschreiben von Datenbankschemata.
- Mit Freemarker und Mustache können Templates für die Oberflächengestaltung erstellt werden.
- Joda Time, eine ausgereifte Bibliothek rund um das Thema Datum und Zeit.
Ich hoffe ihr konntet einen guten Eindruck gewinnen wieso Micro Services und Immutable Infrastruktur hilfreich sein können und was die grundsätzlichen Ideen dahinter sind. Für alle Freunde des praktischen Einstiegs kann ich getrost sagen, dass wir uns im nächsten Blog Post genug austoben werden. Ich hoffe die Erklärungen und die Zusammenstellung der Tools hat euch gefallen und ihr beschäftigt euch schon ein bisschen mit den genannten Tools bevor wir im nächsten Post an die Umsetzung gehen. Ich freue mich natürlich auch über jedes Feedback.
Weiter unten habe ich noch ein Reihe von Tools gelistet die ebenfalls beachtenswert sind.
[1] http://martinfowler.com/articles/microservices.html
[2] http://martinfowler.com/bliki/ImmutableServer.html
[3] http://martinfowler.com/bliki/PhoenixServer.html
[4] http://martinfowler.com/articles/microservices.html#AreMicroservicesTheFuture
[5] https://coreos.com/docs/launching-containers/launching/launching-containers-fleet/
[6] https://dropwizard.github.io/dropwizard/
[7] http://en.wikipedia.org/wiki/Representational_state_transfer#Uniform_interface
[9] https://blog.codecentric.de/2014/07/vier-wege-in-den-docker-container/
[10] https://blog.codecentric.de/en/2014/01/docker-networking-made-simple-3-ways-connect-lxc-containers/
[11] https://blog.codecentric.de/en/2014/08/docker-dock-development-environment/
[12] https://blog.codecentric.de/en/2014/02/docker-registry-run-private-docker-image-repository/
Weitere Links zu stöbern:
http://martinfowler.com/bliki/MicroservicePrerequisites.html
http://martinfowler.com/bliki/SnowflakeServer.html
http://kief.com/configuration-drift.html
http://martinfowler.com/articles/enterpriseREST.html#versioning
http://netflix.github.io/#repo
Weitere Tools zum stöbern:
Vagrant
Terraform
Packer
Packer vs Vagrant
https://groups.google.com/forum/#!msg/packer-tool/4lB4OqhILF8/NPoMYeew0sEJ
Docker with Puppet
http://puppetlabs.com/blog/building-puppet-based-applications-inside-docker
Packer and Docker
http://www.packer.io/docs/builders/docker.html
Packer builds Docker containers without the use of Dockerfiles. By not using Dockerfiles, Packer is able to provision containers with portable scripts or configuration management systems that are not tied to Docker in any way. It also has a simpler mental model: you provision containers much the same way you provision a normal virtualized or dedicated server. For more information, read the section on Dockerfiles.
Boxen
Immutable Server Pattern auf die Spitze Treiben siehe Netflix Chaos Monkey
http://techblog.netflix.com/2011/07/netflix-simian-army.html
Weitere Beiträge
von Felix Massem
Dein Job bei codecentric?
Jobs
Agile Developer und Consultant (w/d/m)
Alle Standorte
Weitere Artikel in diesem Themenbereich
Entdecke spannende weiterführende Themen und lass dich von der codecentric Welt inspirieren.
Gemeinsam bessere Projekte umsetzen.
Wir helfen deinem Unternehmen.
Du stehst vor einer großen IT-Herausforderung? Wir sorgen für eine maßgeschneiderte Unterstützung. Informiere dich jetzt.
Hilf uns, noch besser zu werden.
Wir sind immer auf der Suche nach neuen Talenten. Auch für dich ist die passende Stelle dabei.
Blog-Autor*in
Felix Massem
Du hast noch Fragen zu diesem Thema? Dann sprich mich einfach an.
Du hast noch Fragen zu diesem Thema? Dann sprich mich einfach an.