Canary-Release mit der Very Awesome Microservices Platform (Vamp)

Keine Kommentare

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.

Canary Release

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 ArchitekturVamp 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.

---
name: shop:1.0

endpoints:
 catalog.port: 9050

clusters:

 catalog:
   services:
     -
       breed:
         name: catalog
         deployable: zutherb/catalog-frontend:latest
         ports:
           port: 80/http
         environment_variables:
           CHECKOUT_DESIGN: standard
           SHOP_PORT_8080_TCP_ADDR: $checkout.host
           SHOP_PORT_8080_TCP_PORT: $checkout.ports.port
           PRODUCT_PORT_18080_TCP_ADDR: $product.host
           PRODUCT_PORT_18080_TCP_PORT: $product.ports.port
           NAVIGATION_PORT_18090_TCP_ADDR: $navigation.host
           NAVIGATION_PORT_18090_TCP_PORT: $navigation.ports.port
           CART_PORT_18100_TCP_ADDR: $cart.host
           CART_PORT_18100_TCP_PORT: $cart.ports.port
         dependencies:
           product: product
           navigation: navigation
           cart: cart
           checkout: checkout
       scale:
         instances: 1
         cpu: 0.1
         memory: 128
       routing:
         weight: 100
     -
       breed:
         name: catalogWithAlternativeCheckoutDesign
         deployable: zutherb/catalog-frontend:latest-b
         ports:
           port: 80/http
         environment_variables:
           SHOP_PORT_8080_TCP_ADDR: $checkout.host
           SHOP_PORT_8080_TCP_PORT: $checkout.ports.port
           PRODUCT_PORT_18080_TCP_ADDR: $product.host
           PRODUCT_PORT_18080_TCP_PORT: $product.ports.port
           NAVIGATION_PORT_18090_TCP_ADDR: $navigation.host
           NAVIGATION_PORT_18090_TCP_PORT: $navigation.ports.port
           CART_PORT_18100_TCP_ADDR: $cart.host
           CART_PORT_18100_TCP_PORT: $cart.ports.port
         dependencies:
           product: product
           navigation: navigation
           cart: cart
           checkout: checkout
       scale:
         instances: 1
         cpu: 0.1
         memory: 128
       routing:
         weight: 0
         filters:
         - condition: User-Agent = Chrome

 checkout:
   services:
     breed:
       name: checkout
       deployable: zutherb/monolithic-shop:latest
       ports:
         port: 8080/http
       environment_variables:
         CART_PORT_18100_TCP_ADDR: $cart.host
         CART_PORT_18100_TCP_PORT: $cart.ports.port
         MONGODB_PORT_27017_TCP_ADDR: $mongodb.host
         MONGODB_PORT_27017_TCP_PORT: $mongodb.ports.port
       dependencies:
         mongodb: mongodb
         cart: cart
     scale:
       instances: 2
       cpu: 0.5
       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.

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.

 

Bernd Zuther

Kampferprobter Projektveteran, der immer fokussiert auf die Lieferung von funktionierender Software in der vorgegebenen Zeit ist. Zu seinen stärksten Waffen gehören ein sicherer Umgang mit agilen Methoden wie Scrum und sein breit gestreutes IT-Wissen, das er gezielt dazu einsetzt, auch die schwierigsten Problemstellungen pragmatisch und einfach zu lösen.

Share on FacebookGoogle+Share on LinkedInTweet about this on TwitterShare on RedditDigg thisShare on StumbleUpon

Kommentieren

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