Ein kleines Beispiel: Das Unternehmen XYZ hat die Vorteile um Microservices, automatisierten Tests, Containern und CI/CD verstanden und hat es eingeführt. sie haben sich entschieden ihren software Monolithen in Modul A und Modul B zu zerteilen, die als eigenständige Services laufen. Ferner ein Modul C mit einigen neuen und unabhängigen Funktionen. Diese Module wurden in Container gepackt und unter Kubernetes deployed. Als sie anfingen diese Module in Produktion zu deployen stellten sie erste Probleme fest:
- Manchmal waren einige Services sehr inkonsistent in ihrem Antwortverhalten und haben sehr lange zum Abarbeiten der requests gebraucht.
- Manche Services haben unter Last gar nicht mehr geantwortet
- Wenn Service B keine Anfragen beantworten konnte dann antwortete Service A auch nicht, aber nur manchmal und für bestimmte Requests.
- Beim Deployment haben sich Bugs eingeschlichen, die während den automatisierten Tests nicht abgefangen wurden. Die Deployments wurden im sogenannten Blue/Green deployment durchgeführt. Hierbei wird das neue Deployment komplett in separaten Containern gestartet („green“) und wenn das Deployment durchlief und die Container gestartet wurden, dann wurde der Traffic komplett umgeschwenkt von den alten („blue“) Containern auf die Neuen. Sie hatten gehofft, dass blue-green deployments das Risiko von Deployments verringern würden, aber in der Praxis roch es wieder nach „big-bang“ Releases; was sie eigentlich verhindern wollten. Zumindest hatten die Berater das so gesagt 😉
- Die Teams von Service A und B hatten jeweils eine komplett unterschiedliche Implementierung der Security. Team A wollte sichere Verbindungen mit Zertifikaten und Private Keys. Team B hatte eine eigene Implementierung favorisiert mit Servlet Interceptors. Team C hat gar keine Security Maßnahmen ergriffen, da es sich um interne Dienste handelte hinter einer Firewall.
XYZ wurde langsam nervös und begann die Berater zu beschuldigen, die die tolle neue Welt versprochen hatten. Die Probleme sind aber nicht XYZ spezifisch, sondern inhärent in Service Orientierten Systemen:
- Verhindern, dass sich Fehler über Isolation Boundaries verbreiten
- Applikation implementieren, die mit „Veränderung“ in der Umgebung zurecht kommen
- Applikationen entwickeln, die unter teilweise ausgefallenen system noch funktionieren
- Verstehen was passiert in einem Gesamtsystem welches ständiger Veränderung unterworfen ist
- Unfähigkeit das Runtime Verhalten von Systemen zu ändern
- Starke Security implementieren in einer Umgebung wo die Attack Surface ständig wächst
- Verringern des Risikos von Änderungen am system
- Forcieren von Policies über Wer/Was/Wann die Komponenten im System nutzt
Dies sind die Haupt Probleme, um serviceorientierte Architekturen auf Cloud Infrastruktur zu bauen. In den Zeiten vor der Cloud gab es diese Herausforderungen zwar auch, aber durch die vielen beweglichen Teil von Cloud Infrastrukturen werden die Probleme verstärkt.
Cloud Infrastruktur ist nicht zuverlässig
Auch wenn wir als Nutzer der Cloud die aktuelle Hardware nicht sehen, Cloud Umgebungen bestehen aus einer riesigen Menge an beweglichen Teilen von Hardware und Software. Diese Komponenten sind virtualisierte Compute, Storage und Network Ressourcen welche wir per Self-Service API provisionieren können. Und: jede dieser Komponenten kann und wird ausfallen. In der Vergangenheit haben wir uns darauf konzentriert Infrastrukturen ausfallsicher zu machen und unsere Applikationen darauf aufzubauen mit Annahmen über Verfügbarkeit und Verlässlichkeit. In der Cloud: Pustekuchen! Geht nicht. Komponenten können und werden ausfallen; die ganze Zeit. Doch was ist die Lösung dann?
Nehmen wir an Service A ruft Service B auf und aufgrund irgend eines Problems antwortet Service B nicht. Dies kann ein Problem mit der Infrastruktur sein oder auch was völlig anderes. Service A kann nicht wissen was das Problem ist. Service A kann folgende Dinge probieren:
- Client side load balancing – der client hat mehrere Endpoints, die er aufrufen kann.
- Service Discovery – ein Mechanismus um regelmäßig funktionsfähige Endpoints zu finden
- Circuit Breaking – Request an einen Service aussetzen, wenn dieser Probleme hat
- Bulk Heading – Requests an einen Service drosseln wenn dieser Probleme hat
- Timeouts – Zeitlimitierung für connections, threads, sessions
- Retries – Ein Request wiederholen, wenn dieser nicht abgesetzt werden konnte
- Retry Budgets – Einschränkungen der Retries, z.B. 10 retries in 1 Minute
- Deadlines – Einen Kontext mitgeben der vorgibt wie lange eine Antwort noch gültig sein kann
Diese Aufzählung hat einiges gemeinsam mit den Mechanismen in einem Packt Netzwerk wie TCP/IP, nur dass die Maßnahmen auf „Message“ Ebene greifen sollen und nicht auf Packet Ebene.
Verstehen in Echtzeit
Was wir ausserdem verstehen wollen ist : Was geht vor sich in unserer Servicelandschaft, und zwar in Echtzeit. Welcher Service redet mit wem. Wie sieht ein typische, durchschnittliche Antwortzeit von Service B aus? Wir brauchen Logs, Metriken und Traces um zu verstehen wie Services miteinander interagieren.
Applikations Bibliotheken
Die ersten Unternehmen, die anfingen Ihre Applikationen in der Cloud zu betreiben waren große Internet Konzerne. Sie investierten viel Zeit und Geld um Software Bibliotheken zu bauen, die die oben genannten Anforderungen von Services in der Cloud zu gewährleisten. Z.B. baute Netflix:
- Hystrix – Circuit Breaker
- Ribbon – Client Loadbalancing
- Eureka – Service Discovery
- Zuul – Edge Proxy
Diese werden in vielen Java basierten Applikationen in der Cloud eingesetzt. Doch diese haben wiederum einige Nachteile: sie sind meist nicht sprachneutral. Die von Netflix erstellten Libraries können nur von Java Applikationen genutzt werden und sie sind nicht ganz trivial als Ganzes zu implementieren. Und das Wort sagt es schon: Implementieren, d.h. man muss die Anforderungen durch zu Hilfenahme dieser Libraries in Code gießen. Die Idee ist nun die Angelegenheit auf die Infrastruktur Ebene zu bringen. Also weg von den Entwicklern, hin zu den DevOps Kollegen, die es für die Applikationen deklarativ umsetzen. Und da sind wir bei dem Thema Service Mesh. Implementierungen hier sind Istio oder Linkerd. All die genannten Probleme lassen sich mit einem Service Mesh lösen und transparent darstellen. Der Entwickler muss sich um diese Themen nicht kümmern und kann sich auf Business Logik konzentrieren. Service Meshes verdienen sicherlich eigene Artikel. Damit ist diese Artikelreihe der Digitalen Transformation auf technischer Ebene vorbei. Wenn Sie Hilfe bei der Umsetzung oder eine Beratung über die erwähnten Technologien und Vorgehensweisen oder bei der Einführung von „DevOps“ im Unternehmen benötigen, dann kontaktieren Sie uns bitte.