Im letzten Artikel der Serie “Microservice-Deployment ganz einfach ” erkläre ich, dass Docker nicht zwingend notwendig ist, um Microservice-Anwendungen auszuliefern. Wie der Artikel zeigt, kann man die Linux-Paketverwaltung benutzen, um Microservice-Anwendungen schnell und komfortabel auszuliefern. Leider muss man sich bei diesem Ansatz um die Auslastung seiner Rechner und die Verteilung der einzelnen Microservices auf die unterschiedlichen Rechner selbst kümmern. Es ist aus meiner Sicht aber wünschenswert, dass man einem Rechner-Cluster einfach Arbeit in Form eines Microservice gibt und sich das Cluster eigenständig darum kümmert, die Microservices entsprechend zu verteilen und auszuführen. In der Praxis interessiert mich eigentlich nicht wo ein Microservice läuft, sondern nur das ein bestimmter Microservice läuft. Mit Kubernetes stelle ich im Artikel “Microservice-Deployment ganz einfach mit Kubernetes” ein Werkzeug vor, dass mich bei der Verteilung der Container in einem Rechner-Cluster unterstützt und mir zusätzlich auch noch dabei hilft, dass sich die Container auf unterschiedlichen Rechnern gegenseitig finden. Mein Kollege Christian Zunker beschreibt die Service-Discovery-Thematik, die durch die Verteilung von Docker-Containern auf unterschiedlichen Rechnern entsteht, ausführlich in seinem Artikel “Variation des Ambassador Pattern von CoreOS ”.
Microservice-Deployments mit Kubernetes
Kubernetes benutzt Pods, Replication Controller und Services, um Docker-Container in einem Rechner-Cluster zu verteilen und auszuführen. Weiterhin verfügt Kubernetes über ein sehr nützliches Feature, das so genannte Rolling-Update. Mit ihm kann man beliebige Docker-Container über mehre Knoten hinweg zeitverzögert ausliefern. Damit hat man die Möglichkeit einen Microservice auszurollen und mit realem Traffic entsprechende Daten über den Erfolg eines Deployments zu sammeln, bevor ein Microservice im kompletten Cluster ausgeliefert ist. Geht etwas schief, hat man immer noch die Möglichkeit das Deployment abzubrechen. Damit minimiert man die Gefahr, dass grobe Softwarefehler im kompletten Cluster in Produktion landen. Allerdings gilt das nur für Softwarefehler, wenn unsere Fachabteilungen bei der Produktentwicklung Änderungen machen, die die Benutzer nicht gut finden, dann stellt man das erst am geringeren Umsatz nach dem Deployment fest. Es ist aber aus meiner Sicht wünschenswert, dass man im Produkt-Entwicklungsprozess Kundenfeedback nach Fertigstellung einer neuen Funktionalität einholen kann, um eine Produktidee zu verbessern.
Dazu wäre es gut, wenn man einen Router hätte, der die Verteilung der Benutzer entsprechend bestimmter Regeln auf unterschiedliche Docker-Container organisiert, um das Benutzerverhalten mit einem Teil seiner Kunden messen und analysieren zu können. Einen solchen Router besitzt Kubernetes allerdings nicht. Die Verteilung der Benutzer ist abhängig von der Anzahl der Knoten im Kubernetes-Cluster, auf die die neue Version der Software ausgeliefert ist. Daher bietet Kubernetes out-of-the-box keine Möglichkeit, ein so genanntes Canary-Release abzubilden.
Canary-Release
Ein Canary-Release verwendet man, um das Risiko bei der Einführung einer neuen Software-Version zu vermindern. Man stellt Änderungen erst mal nur einem Teil seiner Benutzer zu Verfügung und misst wie dieser Teil auf die Änderungen reagiert, bevor man die neue Software auf der kompletten Infrastruktur ausrollt. Durch dieses Vorgehen hat man die Möglichkeit die Software schrittweise zu verbessern.
Ein Canary-Release ähnelt in der Ausführung einem Blue-Green-Deployment , das aber das Ziel verfolgt, die Downtime einer Applikation zu minimieren. Dazu hält man zwei Infrastruktur-Stränge für zwei unterschiedliche Softwareversionen vor und leitet die Benutzer über einen Router auf die entsprechende Version um. Bei einem Blue-Green-Deployment macht man einen harten Wechsel auf die neue Version der Software. Beim Canary-Release leitet man dagegen z.B. nur 5 Prozent des Traffic auf die neue Version um. Mit einem Canary-Release möchte man also vielmehr herrausfinden, ob eine neue Funktionalität wirklich eine signifikante Veränderungen im Verhalten der Benutzer auslöst. Diese Releases können auch benutzt werden, um A/B-Testing zu implementieren.
Microservice-Deployments mit Vamp
Vamp oder Very Awesome Microservices Platform vereinfacht das Durchführen von Canary-Releases. Vamp unterstützt im Moment Mesos und Marathon , später soll aber auch Kubernetes als Container-Manager hinzukommen. Die Plattform wird von der niederländischen Firma magnetic.io entwickelt. Ähnlich wie Kubernetes ist Mesos ein Dienst zum Starten von Docker-Containern in einem verteilten Rechner-Cluster. Mesos ist zuständig für Ressourcenverwaltung im Cluster und kann mit Marathon das Deployment von Microservice-Anwendungen durchführen. Marathon übernimmt dabei die Aufgabe eines Schedulers, der die Verteilung und Ausführung von Docker-Containern steuert. Viele große Firmen setzen ähnliche Technologie-Stacks schon erfolgreich in Produktion ein, darunter sind z.B, Apple , Holidaycheck und Otto.
Vamp ist ein Dienst, der sich überhalb eines Container-Manager ansiedelt und aus mehren Bestandteilen besteht. Vamp-Core bietet eine Plattform-agnostische DSL und ein REST-API. Die DSL kann ähnlich wie Giant Swarm und Docker-Compose benutzt werden, um eine Microservice-Anwendung mit ihren Abhängigkeiten zu beschreiben. Diese Beschreibung benutzt die REST-Schnittstelle von Vamp-Core, um mit Marathon die Microservices im Mesos-Cluster zu deployen. Darüberhin beinhaltet die DSL auch Elemente zum Beschreiben von A/B Tests und Canary-Releases sowie zum Beschreiben von SLAs. Diese SLAs sorgen dafür, dass wenn bestimmte Antwortzeiten unterschritten werden und noch Ressourcen im Cluster verfügbar sind, automatische neue Docker-Container im Cluster gestartet werden. Zum Sammeln der Metriken, die für die SLAs und A/B Tests benötigt werden, gibt es den Metriken- und Event-Store Vamp-Pulse, in dem Daten von Core und Router in Elasticsearch gespeichert werden. Der Vamp Router ist eine Komponente die einen HAProxy steuert, der die Verbindung zwischen den laufenden Docker-Containern und den eigentlichen Benutzern realisiert.
Wie in den vorgangegangen Artikeln der Serie “Microservice-Deployment ganz einfach ” benutze ich einen Online-Shop als Beispiel, um die Funktionionsweise vom Vamp zu zeigen. Diesen Online-Shop findet man in meinem Github-Repository . Die genaue Fachlichkeitsbeschreibung, die hinter diesem Beispiel steckt, erkläre in meinem Artikel “Microservices und die Jagd nach mehr Konversion” . Um Vamp für das Deployment unserer Microservice-Anwendung zu benutzen, müssen wir erst einmal einen so genannten Blueprint anlegen. Ein Blueprint ist eine Art Ausführungsplan für unsere Microservice-Anwendung, der in einer Datei gespeichert wird. Ein Blueprint beschreibt die abstrakte Topologie der Anwendung im Cluster. In einem Blueprint wird unter anderem beschrieben
- welche Ports von außen erreichbar sind,
- welche Abhängigkeiten zwischen den unterschiedlichen Microservices bestehen,
- welche Microservices im Cluster für A/B Tests benutzt werden,
- welche Routing-Regeln für A/B Tests bestehen,
- wie viele Ressourcen (CPU, Speicher, Skalierung) reserviert werden müssen und
- welche SLAs es geben soll.
Das folgende Listing zeigt einen Ausschnitt eines Blueprints des obengenanntem Online-Shops. Der vollständige Blueprint befindet sich auf Github.
1--- 2name: shop:1.0 3 4endpoints: 5 catalog.port: 9050 6 7clusters: 8 9 catalog: 10 services: 11 - 12 breed: 13 name: catalog 14 deployable: zutherb/catalog-frontend:latest 15 ports: 16 port: 80/http 17 environment_variables: 18 CHECKOUT_DESIGN: standard 19 SHOP_PORT_8080_TCP_ADDR: $checkout.host 20 SHOP_PORT_8080_TCP_PORT: $checkout.ports.port 21 PRODUCT_PORT_18080_TCP_ADDR: $product.host 22 PRODUCT_PORT_18080_TCP_PORT: $product.ports.port 23 NAVIGATION_PORT_18090_TCP_ADDR: $navigation.host 24 NAVIGATION_PORT_18090_TCP_PORT: $navigation.ports.port 25 CART_PORT_18100_TCP_ADDR: $cart.host 26 CART_PORT_18100_TCP_PORT: $cart.ports.port 27 dependencies: 28 product: product 29 navigation: navigation 30 cart: cart 31 checkout: checkout 32 scale: 33 instances: 1 34 cpu: 0.1 35 memory: 128 36 routing: 37 weight: 100 38 - 39 breed: 40 name: catalogWithAlternativeCheckoutDesign 41 deployable: zutherb/catalog-frontend:latest-b 42 ports: 43 port: 80/http 44 environment_variables: 45 SHOP_PORT_8080_TCP_ADDR: $checkout.host 46 SHOP_PORT_8080_TCP_PORT: $checkout.ports.port 47 PRODUCT_PORT_18080_TCP_ADDR: $product.host 48 PRODUCT_PORT_18080_TCP_PORT: $product.ports.port 49 NAVIGATION_PORT_18090_TCP_ADDR: $navigation.host 50 NAVIGATION_PORT_18090_TCP_PORT: $navigation.ports.port 51 CART_PORT_18100_TCP_ADDR: $cart.host 52 CART_PORT_18100_TCP_PORT: $cart.ports.port 53 dependencies: 54 product: product 55 navigation: navigation 56 cart: cart 57 checkout: checkout 58 scale: 59 instances: 1 60 cpu: 0.1 61 memory: 128 62 routing: 63 weight: 0 64 filters: 65 - condition: User-Agent = Chrome 66 67 checkout: 68 services: 69 breed: 70 name: checkout 71 deployable: zutherb/monolithic-shop:latest 72 ports: 73 port: 8080/http 74 environment_variables: 75 CART_PORT_18100_TCP_ADDR: $cart.host 76 CART_PORT_18100_TCP_PORT: $cart.ports.port 77 MONGODB_PORT_27017_TCP_ADDR: $mongodb.host 78 MONGODB_PORT_27017_TCP_PORT: $mongodb.ports.port 79 dependencies: 80 mongodb: mongodb 81 cart: cart 82 scale: 83 instances: 2 84 cpu: 0.5 85 memory: 512
Diesen Blueprint schickt man einfach an das REST-API von Vamp-Core und dann wird die Anwendung im Cluster deployt. Wie die Orchestierung in einem 5 Node Cluster aufsieht, kann man in folgenden Video sehen. Außerdem ist zu sehen, wie A/B Tests ins laufende Cluster ohne Downtime deployt werden.
Mit dem Laden des Videos akzeptieren Sie die Datenschutzerklärung von YouTube.
Mehr erfahren
YouTube immer entsperren
Fazit
Zusammenfassend kann man sagen, dass Vamp über eine Plattform-agnostische DSL die Möglichkeit bietet Microservice-Anwendung zu beschreiben und in einem Mesos-Cluster auszuführen. Vamp nimmt die Arbeit ab, dass man sich darum kümmern muss, wo ein Microservice läuft. Mesos findet freie Ressourcen im Cluster und startet dort Docker-Container. Vamp sorgt dafür, dass die entsprechenden Endpunkte der Services den entsprechenden Docker-Container mitgeteilt werden, die andere Microservices darstellen. Dies passiert über Umgebungsvariablen und einem HAProxy als Ambassador.
Mit dieser Plattform bekommt man völlig neue Möglichkeiten Microservice-Anwendungen auszuliefern. Man kann sehr einfach A/B Tests formulieren, mit denen man komplette Prozesse verändern und testen kann. Zur Auswertung der A/B Test muss man im Moment aber leider noch auf ein Web-Tracking wie Google Analytics zurückgreifen. Außerdem wird die Ausführung von Zero-Downtime-Deployments und Skalierungsszenarien stark vereinfacht. Wenn mehr Hardware gebraucht wird, fügt man einfach neue Maschinen in das Cluster und Vamp sorgt dafür, dass bei einer Verlangsamung von Antwort-Zeiten automatisch neue Docker-Container gestartet werden.
Für alle, die das Thema mehr interessiert und die auch auf der kommenden W-JAX in München sein werden. Ich halte dort am 3. November den Vortrag “Von Null auf Hundert mit Microservices” , wo ich dieses Thema ausführlicher beleuchte.
Weitere Beiträge
von Bernd Zuther
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
Bernd Zuther
Du hast noch Fragen zu diesem Thema? Dann sprich mich einfach an.
Du hast noch Fragen zu diesem Thema? Dann sprich mich einfach an.