Shownotes & Links
- Podcast - Service Meshes - Teil 1
- Microservices & Istio Beispielanwendung von Eberhard Wolff
- Bookinfo Beispielanwendung von Istio
- Bookinfo Tasks von Istio
- Self-Contained Systems
Transkript
Jörg Müller: Hallo und herzlich Willkommen zum INNOQ-Podcast. Diesmal mit dem zweiten Teil zum Thema Service Meshes. Ich habe wieder eingeladen: Hanna –
Hanna Prinz: Hallo Jörg!
Jörg Müller: Und Eberhard!
Eberhard Wolff: Guten Tag!
Jörg Müller: Wir haben uns ja im letzten Teil sehr intensiv damit auseinandergesetzt, was so ein Service Mesh eigentlich ist und wie so ein Service Mesh funktioniert. Diesmal wollen wir uns ein wenig damit beschäftigen: Warum benutze ich eigentlich so ein Service Mesh und was sind vielleicht auch die Alternativen oder Nachteile des Ganzen? Fangen wir doch direkt mal mit dieser Frage an. Beim letzten Mal klang das Ganze so, als wäre ein Service Mesh wirklich der goldene Wasserhahn schlechthin, den wir benutzen wollen. Was sind denn eigentlich die Dinge, auf die ich achten muss, und was sind potentielle Nachteile von dem Ganzen?
Hanna Prinz: Man kann generell sagen: So etwas kommt nie umsonst. Magic always comes with a price. Bei einem Service Mesh gibt es ein paar Sachen, über die man mehr oder weniger besorgt sein kann, aber als Erstes ist da immer die Frage nach der Latenz. Ich habe schon gesagt: Im Fall von Istio gibt es schon Sachen, die bei jedem Request passieren. Also immer wenn dieses Sidecar, also der Proxy, eine Anfrage bekommt, gibt es etwas, das er tun muss. Und es gibt sogar einen Aufruf an einen anderen Dienst, der jedes Mal gemacht werden muss und da ist die Frage nach der Latenz natürlich auch nicht unbegründet. Tatsächlich gibt es auch Angaben von Istio, die sagen, dass jede Anfrage mit zehn Millisekunden mehr Latenz hat. Es gibt auch Anwendungen, bei denen das gemessen wird und da ist es sogar noch ein bisschen mehr und es hängt natürlich auch von der Konfiguration und davon ab, wie oft man die Konfiguration ändert, aber sicherlich muss man mit Latenzeinbußen rechnen. Von der Größenordnung muss aber auch mal dazu sagen: Diese Beispiele, die man da macht, diese Load-Tests, sind natürlich mit einer anderen Anwendung, die aber auch nicht die Features hat, die ein Service Mesh hat. Man vergleicht da auf jeden Fall Äpfel mit Birnen und muss dann auch sagen, dass andere Vorteile von dem Service Mesh die eventuellen Latenzen vielleicht auch aufheben können, individuell.
Jörg Müller: Wir reden ja auch nochmal darüber, was Alternativen dazu sein können.
Eberhard Wolff: Man könnte jetzt hinzufügen, dass ich mich an der Stelle, an der ich ein Microservice-System gebaut habe, eh damit beschäftigen muss, dass die Microservices untereinander bei den Aufrufen höhere Latenzzeiten haben, insbesondere im Vergleich zu lokalen Methodenaufrufen. Und wenn ich jetzt sozusagen über die Klippe falle, weil die Latenz eben ein bisschen höher ist, fände ich das komisch. Ich würde argumentieren, dass an der Stelle, an der die Latenzzeiten ein Problem sind, ich sowieso mit der Microservice-Architektur an sich ein Problem habe. Aber sei’s drum, ist halt so.
Jörg Müller: Neben der Latenz, was sind andere Aspekte, auf die man noch so achten sollte?
Hanna Prinz: Man braucht ein bisschen Know-How. Das muss jetzt auch nicht unbedingt ein Nachteil sein, aber man muss sich auch darum kümmern, dass jemand das Ding administriert. Man muss vielleicht auch damit rechnen, dass sich an APIs von solchen neuen Technologien Details ändern. Das wäre für mich persönlich kein Grund, es nicht zu tun, aber man sollte sich bewusst sein, dass man in einem sehr jungen Bereich unterwegs ist, was ja bei DevOps eigentlich auch der Status Quo ist. Für mich wäre es aber auch deshalb kein Problem, weil ich schon der Meinung bin, dass gerade auch Istio auf vielen anderen Komponenten basiert, die für sich auch erprobt sind. Natürlich kann es auch Probleme geben, es wird sicherlich noch irgendwelche schwerwiegenden Probleme geben in bestimmten Konfigurationen, dafür ist es halt einfach noch zu jung.
Jörg Müller: Da machst du mir jetzt aber schon ein bisschen Angst.
Hanna Prinz: Naja, man muss sich halt einfach bewusst sein, dass es eine junge Technologie ist und dass man das vielleicht auch erst einmal auf einem Testfeld ausprobiert.
Eberhard Wolff: Wobei da aus meiner Sicht der Hinweis wichtig ist, dass eben die Bestandteile reif sind. Den Envoy-Proxy gibt es ja schon sehr lange, so etwas wie Prometheus oder Grafana gibt es auch schon sehr lange. Viele Microservice-Systeme benutzen das, sodass die Frage ist, ob man die Integration, die man da drumherum baut, ob man die selbst bauen will oder ob man sich die sozusagen fertig kaufen wollen würde, was dann eben eher der Istio-Ansatz wäre. Der andere Punkt ist dabei: Für den Fall, dass Istio irgendetwas ändert, hat das ja keinen Impact auf meinen Code, das ist ja genau ein Feature. Das Feature ist ja gerade, dass diese Belange aus dem Code heraus sind. Das heißt also, es kann sich vielleicht etwas ändern, aber wenn es sich ändert, wird es sich üblicherweise außerhalb des Codes ändern und das empfinde ich immer als eine relativ gute Position, in der man dann ist. Grundsätzlich meine ich. Wenn ich es schaffe, im Wesentlichen Geschäftslogik zu implementieren und den technischen Kram herauszuhalten, dann ist das toll in Bezug auf langfristig einsetzbare Systeme.
Jörg Müller: Jetzt haben wir diese Probleme, die Service Meshes lösen, ja früher auch schon gehabt. Die kommen ja nicht plötzlich aus dem Nichts. Was wären denn Alternativen, wenn ich kein Service Mesh nutze oder mit was kann man Service Meshes am besten vergleichen? Welche Ansätze gibt es da?
Eberhard Wolff: Ich glaube, das ist eine wichtige Frage. Denn wenn man jetzt aufgrund der Herausforderungen entscheidet, dass Service Meshes keine gute Lösung sind, muss man etwas anderes machen. Das Erste, das mir einfallen würde, ist auch etwas Klassisches. Ich habe ein Buch geschrieben, in dem es sehr viel um Technologien für die Kommunikation von Microservices geht. Da gibt es unterschiedliche Varianten von irgendwelchen Frameworks, letztendlich. So ein bisschen prototypisch ist da der Netflix-Stack, gerade in der Java-Community. Und highlevel, würde ich sagen, löst es ähnliche Probleme. Es hat das Problem, dass es Libraries sind, was bedeutet, dass bestimmte Programmiersprachen bevorzugt werden und im Netflix-Universum ist es halt insbesondere Java und das ist erstmal ein Nachteil. Die Frage ist, ob dem irgendwelche Vorteile gegenüber stehen. Das würde ich jetzt erst einmal in Abrede stellen. Ich sehe nicht den großen Vorteil von so etwas wie dem Netflix-Stack. Und wenn wir nun als Beispiel für die Libraries bei dem Netflix-Stack bleiben, der hat eben tatsächlich auch das Problem, dass so etwas wie Hystrix mittlerweile nicht weiterentwickelt wird, sodass man dort im Code eine Abhängigkeit auf eine Library hat, die man eigentlich nicht mehr benutzen möchte. Das ist sehr deutlich suboptimal. Deswegen würde ich in diese Richtung nicht gehen. Man kann das ein bisschen abschwächen: Viele von den Features sind ja vielleicht schon in Kubernetes selbst drin. Man kann versuchen, ein paar Sachen hinein zu bauen in Service Discovery. Aber gerade solche Sachen wie Resilience oder so etwas, da kann ich diese Features eigentlich nur mit einem Proxy oder so implementieren, wenn ich eben nicht den Weg der Library gehen möchte. Und der Weg der Library hat für mich zu viele Nachteile und zu wenig Vorteile, sodass ich das eigentlich nicht tun wollen würde.
Hanna Prinz: Was man sich auch immer klar machen muss, ist: Wenn man so eine Library hat, dann beschäftigt man sein Entwicklerteam damit, diese Libraries zu instrumentalisieren; ergo bleibt weniger Zeit, um echte Features zu entwickeln. Wenn man das Team entlasten kann, dann ist das auch ein gutes Argument, denke ich.
Jörg Müller: Ja und gerade bei Microservice-Architekturen hat man ja in letzter Zeit oft beobachtet, dass die Teams sich fast nur noch mit der Infrastruktur beschäftigt haben. Zumindest ist das ein Risiko.
Eberhard Wolff: Wobei ich mir da nicht so sicher bin. Am Ende ist es so, dass ich Funktionalitäten habe. Wenn wir bei dem Beispiel von Resilience bleiben, das sind halt Funktionalitäten, die muss ich irgendwie machen und es ist nur anders, wie ich es mache. Ich weiß nicht, ob sozusagen der mentale Overhead, den eine Library da generiert, größer ist als der, den ein Istio generiert. Er fällt vielleicht woanders an. Istio ist eben etwas, was vielleicht eher Infrastruktur ist, aber es ist ja eh so, dass im Microservices-Universum Entwickler sich zunehmend mit Infrastruktur auseinandersetzen. Ich bin mir nicht sicher, ob das Eine einfacher ist als das Andere.
Jörg Müller: Was ist denn mit anderen Infrastruktur-Ansätzen, die da in der Vergangenheit zu dem Thema existiert haben, wie zum Beispiel Enterprise-Service-Busses, welche ja durchaus auch versucht haben, viele dieser Probleme in irgendeiner Form zu lösen. Wie stellen die sich im Verhältnis zu Service Meshes dar?
Hanna Prinz: Enterprise-Service-Busses spielen in der Cloud-Umgebung aktuell eine untergeordnete Rolle, wenn überhaupt. Leute, die vielleicht mal mit einem ESB gearbeitet haben, können vielleicht gemeinsame Ziele entdecken, allerdings hat der Enterprise-Service-Bus aus meiner Sicht das Problem, dass er sowohl Netzwerkangelegenheiten, als auch fachliche Angelegenheiten versucht zu vereinen. Der Enterprise-Service-Bus weiß sehr viel über die Anwendung. Der weiß, dass wenn der eine Service das und das machen will, dann muss er jetzt diesen aufrufen. Das ist etwas, das man bei einem Service Mesh versucht zu trennen. Man versucht Fachlichkeit in einem Service Mesh nicht in der Art unterzubringen wie in einem Enterprise-Service-Bus.
Eberhard Wolff: Genau. Will heißen, ein Enterprise-Service-Bus kann Sachen irgendwo hin routen und hat da gewisse zusätzliche Funktionalitäten, auch zum Beispiel die Konvertierung von irgendwelchen Daten in verschiedene Formate. Das ist eigentlich etwas, das eine Microservice-Architektur, wenn man es so einsetzt, fundamental versucht zu vermeiden, dort würde man diese Sachen eher in die Microservice-Architektur selbst hineinziehen. Und ich glaube auch aus gutem Grund, weil man dadurch am Ende eine stärkere Entkopplung erreicht. Man kann die Microservices untereinander reden lassen und hat nicht eine zentrale Instanz, die man außerdem noch ändern müsste, in der noch andere Funktionalitäten sind, sondern die sind in den Microservices rein modularisiert. Von daher würde ich tatsächlich erst einmal sagen, dass ein Enterprise-Service-Bus in einer Microservice-Architektur grundsätzlich fragwürdig ist. Die andere Sache ist, dass ein Enterprise-Service-Bus häufig auch für asynchrone Kommunikation steht. Daran finde ich gar nichts Schlechtes, im Gegenteil, eigentlich bin ich der Meinung, dass asynchrone Microservices eine super Idee sind. Das finde ich auch unproblematisch. Wir müssen, glaube ich, an einer anderen Stelle noch einmal darüber diskutieren, ob asynchrone Microservices und Service Meshes zusammen irgendwie hilfreich sind, aber in dem Kontext ist es jetzt erst einmal nicht offensichtlich unsinnig, über solch ein System zu reden und auf ein ESB zu setzen. Da müssen wir dann eben noch einmal drüber reden, wie das mit einem Service Mesh zusammen funktioniert.
Jörg Müller: Was ist mit der anderen relativ typischen Komponente, die man dort einführt, nämlich den API-Gateways? Wie verhalten sich API-Gateways und Service Meshes zueinander?
Hanna Prinz: Es gibt verschiedene Arten, wie man ein API-Gateway nutzt. Wenn man es als Einstiegspunkt oder auch als Schnittstelle betrachtet, wenn man zum Beispiel eine öffentliche API hat und dafür ein API-Gateway, dann schließen sich ein Service Mesh und ein API-Gateway nicht aus. Sondern es kann sein, dass man bestimmte Funktionen von dem API-Gateway in das Service Mesh hineinziehen kann, ergo darüber lösen kann. Was mit einem Service Mesh dem allerdings entgegen laufen würde, wäre, wenn man ein API-Gateway hat, das zwischen allen Microservices aufgerufen wird. Das ist genau das, was man bei einem Service Mesh anders löst. Aber generell kann man schon sagen: Ein API-Gateway für eine bestimmte Funktion kann ein Service Mesh ergänzen.
Eberhard Wolff: Wir sollten vielleicht noch kurz darüber reden, dass ein API-Gateway, wie der Name schon sagt, typischerweise etwas ist, das genutzt wird, um eine API insbesondere nach draußen anzubieten. Und man baut da Features ein wie zum Beispiel Routing, dass Requests an die richtigen Systeme weiter geroutet werden. Aber auch weitere Themen, wie zum Beispiel, dass ich API-Keys habe, so eine Authentifizierung, nicht nur aufgrund von API-Keys, sondern eine weitergehende Authentifizierung. Dass ich die Möglichkeit habe, Rate-Limits festzulegen und all solche Geschichten. Das sind natürlich Features, die in einem Service Mesh drin sind, aber mit einem anderen Fokus und ich würde jetzt auch argumentieren, dass ein API-Gateway eigentlich erst einmal für die Kommunikation nach draußen notwendig ist. Aber das ist natürlich auch anders möglich.
Jörg Müller: Das heißt wir kennen jetzt ein bisschen die Alternativen, wir haben uns auch über Nachteile von Service Meshes unterhalten, vielleicht sollten wir jetzt tatsächlich einmal genauer in bestimmte Architektur-Formen hineinschauen. Es gibt ja nun verschiedene Arten und Weisen, solche verteilten Services aufzubauen, Microservices aufzubauen etc. Das Erste und Typische, das einem immer gerne einfällt, ist die sogenannte Netflix-Architektur, bei der man sehr viel mit synchronen Aufrufen etc. arbeitet. Vielleicht: Wie passen Service Meshes da hinein, in die jeweiligen Architekturen? Vielleicht können wir auch noch einmal kurz etwas dazu sagen, wie die eigentlich funktionieren.
Eberhard Wolff: Unter synchronen Aufrufen verstehe ich im Allgemeinen, dass ich den Aufruf mache und dann auf mein Ergebnis warte und an dem Ergebnis weiterarbeite. Das würde bedeuten, dass ich also als Microservice da stehe, ich akzeptiere einen Aufruf, ich mache irgendetwas, ich kann mir währenddessen auch noch andere Informationen von weiteren Microservices holen, schnüre das Ganze zusammen und schicke es dann zurück. Ich soll eine Rechnung anzeigen, ich gehe zu irgendeinem Service und sage dem: Gib mir mal die Kundeninformation. Der gibt mir die Kundeninformation, ein anderer Service gibt mir die Wareninformation und dann habe ich eben diese beiden Sachen zusammen gesammelt und generiere daraus eine Rechnung, die ich zurückgebe. Grundsätzlich an dieser Stelle: Das bedeutet, dass ich fundamentale Probleme habe. Ein Problem ist, dass sich die Latenzzeit dieser Services aufaddiert, ich muss auf diese beiden Services warten, bis ich selbst antworten kann. Ich habe ein Resilience-Problem, wenn die beiden Services ausfallen, was mache ich dann? Wenn ich die Kundendaten nicht bekommen kann, dann kann ich eigentlich nur sagen: Schwamm drüber, geht halt nicht. Und das führt für mich eigentlich dazu, dass ich erst einmal grundsätzlich argumentieren würde, dass so etwas keine tolle Idee ist. Und ich würde sogar argumentieren, dass eigentlich der Schnitt der Services komisch ist. Wenn ich sage, dass ein Modul, das Rechnungen darstellt, für Basisfunktionalitäten andere Module ansprechen muss, dann ist die Modularisierung vielleicht nicht so gut. Eigentlich sollte ein Modul eine Funktionalität erbringen. Und das führt für mich dazu, dass ich es schade finde, dass es diese sehr stark synchronen Architekturen gibt und sie auch so im Fokus stehen, weil ich argumentieren würde, dass sie an der Stelle sehr viele Nachteile haben. Das führt noch zu der Frage: Warum würde ich das tun wollen? Ich glaube, weil es halt einfacher verstehbar und so ein bisschen der Default ist, aber eigentlich würde ich davor warnen.
Hanna Prinz: Synchrone Microservice-Architekturen sind genau ein sehr geeigneter Anwendungsfall für Service Meshes. Denn genau dort hat man das Problem, dass man einen schlechten Einblick hat, welcher Service welchen aufruft, wo die große Latenz herkommt und man auch sehr viel Kommunikation zwischen den Microservices hat. Genau das ist es ja, wobei uns ein Service Mesh sehr hilft, wenn die Services viel miteinander kommunizieren. Das ist ja auch ein sehr großer Teil von Microservices, die genauso funktionieren und ich denke, dass es deshalb auch Istio gibt und es deshalb so beliebt ist, weil es viele von den Problemen in Angriff nimmt. Natürlich kann man mit einem Service Mesh nichts dagegen tun, dass die Services voneinander abhängen und dass es am Ende eine höhere Latenz bedeutet. Wer sich mal anschauen möchte, wie man ein Service Mesh in so einer Umgebung anwenden kann: Es gibt von Istio auf deren Webseite eine Anwendung, die heißt Bookinfo, da sind ein paar Microservices auch in den verschiedenen Versionen, da kann man mal so ein paar Szenarien durchspielen. Das ist natürlich für Istio eine ideale Umgebung, man muss immer im Hinterkopf haben, dass eine reale Anwendung ein bisschen anders aussieht, aber das ist auf jeden Fall eine gute Art, das mal auszuprobieren.
Eberhard Wolff: Genau. Damit wir das erwähnt haben, weil ich finde, dass das total wichtig ist: Es gibt diese Istio-Tasks, die in der Dokumentation drin sind, wo man auch einfach mal ein Beispiel durchspielen kann für bestimmte Features. Das ist, glaube ich, extrem hilfreich, wenn man sich einmal selbst damit beschäftigen will. Es sind zehn oder fünfzehn und das ist eine gute Sache, um mal ein bisschen hands-on damit Erfahrung zu bekommen, also jenseits dieser konkreten Beispielanwendung. Ich glaube, den Link werden wir auch in die Shownotes tun.
Jörg Müller: Eberhard, du hast ja gerade schon angesprochen, dass diese Art der synchronen Verknüpfung der Microservices nicht immer die ideale Vorgehensweise ist. Was ist die Alternative, Asynchronität, wie sieht das aus?
Eberhard Wolff: Ja genau, ich würde tatsächlich sagen: Asynchron. Das würde jetzt bedeuten, dass ein Microservice mit einem anderen Microservice kommuniziert, aber eben nicht unbedingt jetzt sofort das Ergebnis benötigt und damit weiter arbeitet. Dafür gibt es für mich zwei Szenarien: Wenn ich nun gerade einen Request bearbeite, kann ich zwar selbst etwas herausschicken, aber ich warte nicht auf ein Ergebnis. Ich bekomme eine Bestellung, die Bestellung soll ausgeführt werden, ich schicke irgendetwas weiter und sage: Sorge bitte dafür, dass das bezahlt wird. Und das tue ich im Rahmen meiner Bearbeitung des Requests bei der Bestellung. Aber ich warte nicht auf das Ergebnis, sondern gehe davon aus, dass die Bezahlung einfach funktioniert. Oder ich mache irgendwann spontan irgendwelche Requests und sage: Gib mir bitte neue Informationen über Kunden oder was auch immer und speichere das dann bei mir. In beiden Fällen ist es so, dass zur Erfüllung des Requests, den ich gerade bearbeite, nichts von anderen Microservices notwendig ist. Entweder ich kommuniziere spontan mit anderen Microservices, dann bin ich nicht darauf angewiesen, dass die antworten, um selbst einen Request zu bearbeiten, denn ich bearbeite eben gerade keinen Request. Oder ich warte eben nicht auf Ergebnisse, sodass ich auch dort bei der Bearbeitung meines Requests entkoppelt bin von dem, was die anderen gerade tun. Das kann man jetzt unterschiedlich implementieren. Eine Möglichkeit, so etwas zu implementieren, ist, dass ich eine asynchrone Kommunikations-Infrastruktur einziehe, also ein Kafka oder etwas anderes in der Richtung, so ein Messaging-System gibt es ja schon länger. Ich kann das auch mit REST machen. Wenn ich es mit REST mache, würde ich es typischerweise so machen, dass jemand zum Beispiel alle Informationen zu allen Bestellungen anbietet und die anderen können dann GET-Requests machen und sich die abholen. Dadurch sorge ich dafür, dass die anderen Systeme diese Informationen pollen und ich diese Information einfach nur anbiete, sodass zum Beispiel an der Stelle, an der die anderen ausfallen, erst einmal nichts passiert. Wenn sie hochkommen, holen sie sich halt die neuen Informationen über die Bestellung und alles ist gut.
Jörg Müller: Aber das klingt ja fast so, als würde ich so etwas wie Service Meshes gar nicht brauchen, was ist denn der Mehrwert von Service Meshes in so einer Situation?
Eberhard Wolff: Ich glaube, das hängt davon ab. Für die REST-basierte Kommunikation habe ich immer noch Unterstützung im Service Mesh, das heißt ich bekomme die ganzen Informationen daraus durch die Proxies, ich könnte also immer noch die Informationen über die Latenzzeiten herausbekommen, ich kann Fault-Injection machen, um herausfinden, ob mein System tatsächlich weiterhin funktioniert. Und ich kann an der Stelle auch so etwas wie Tracing machen, obwohl das jetzt nicht so super sinnvoll ist, weil typischerweise ein Aufruf nicht andere Aufrufe zur Folge haben sollte, denn dann wäre ich in diesem synchronen Fall. Ich habe mal ein Beispiel gebaut, das genau so etwas macht, das benutzt eine REST-basierte Kommunikation und ein Polling-Konzept, das kann man mit Istio zusammen bekommen, dann bekomme ich zum Beispiel Monitoring-Informationen heraus. Oder Tracing-Informationen mit eingeschränktem Wert, aber ich kann dort auch Logging einbauen. Das heißt, es funktioniert alles. Es ist ein bisschen die Frage, wieviel ich an Wert herausbekomme an der Stelle. Und da finde ich es eigentlich nicht abwegig, so etwas einzusetzen. Wenn ich jetzt als zentrale Infrastruktur habe, so etwas wie ein Kafka, dann entziehe ich dem Service Mesh eigentlich diese zentrale Möglichkeit, sich in der Kommunikation reinzuhängen, weil die Kommunikation dann im Wesentlichen über den Kafka läuft. Das heißt ich kann da jetzt nicht mehr so super viel machen. Und dann ist es irgendwie fragwürdig, ob mir der Service Mesh noch so viel bringt. An der Stelle sollte man vielleicht auch darauf hinweisen, dass wir über synchrone und asynchrone Systeme reden, als ob sie Gegensätze wären, ich bin mir aber nicht sicher, ob das so ist. Ich kann auch bei einem perfekten Schnitt nicht immer ausschließen, dass synchrone Aufrufe nicht doch irgendwo notwendig sind. Ich würde nur kein System bauen, das von vornherein sagt: Hey, wir machen nur synchrone Kommunikation, denn das macht man halt so. Dafür sind die Nachteile zu groß. Wenn ich aber ein reales System habe, werde ich wahrscheinlich mehrere Kommunikationsmöglichkeiten haben und dadurch vielleicht, auch wenn ich primär auf asynchron setze, dennoch Benefits aus einem Service Mesh heraus generieren.
Jörg Müller: Jetzt gibt es ja noch andere Arten und Weisen, Microservices aufzubauen oder zu strukturieren, unter anderem das Stichwort der Self-Contained Systems, auch da würde mich mal interessieren, wie dort das Thema Service Mesh eigentlich hinein passt? Vielleicht kannst du auch noch einmal ein, zwei Worte dazu sagen, was ein Self-Contained-System ist, dann bekommen wir das vielleicht etwas genauer eingeordnet.
Eberhard Wolff: Zu Self-Contained Systems gibt es diese Webseite: http://scs-architecture.org/, wo das genau diskutiert ist. Im Wesentlichen bedeutet ein Self-Contained-System, dass es, so sagt es ja auch der Name, in sich abgeschlossen ist. Und das bedeutet, dass es im Wesentlichen eine Domäne implementiert und dass innerhalb dieser Domäne die gesamte Logik, auch die UI, in dem Self-Contained-System drin ist. Es ist letztendlich eine Webanwendung. Ich könnte also jetzt sagen: Ich habe eine Webanwendung, die Bestellungen entgegen nimmt und es gibt eine andere Webanwendung, die mir Bezahlinformationen darstellt, wo ich später sagen kann, ob diese Bestellung bezahlt worden ist, wo ich auch dafür sorgen kann, dass die entsprechende Logik für die Bezahlung drin ist und vielleicht ein Weiteres für die Lieferung. Das ist das, was ich auch in dieser Beispielanwendung, über die ich eben schon gesprochen habe, auch implementiert habe, da gibt es eben drei verschiedene Webanwendungen: Eine Webanwendung, bei der ich die Bestellung abgeben kann, eine Webanwendung, die mir die Bezahlinformationen anzeigt und eine andere, die mir die Lieferinformationen anzeigt. Das ist sehr trivial gebaut, aber es reicht, um den Punkt zu illustrieren. Da ist es so, dass dadurch, dass das Service Mesh sich in die Kommunikation hineinhängt, eben auch in die HTTP-Kommunikation, und dadurch, dass ich diese Verbindung nach draußen auch über Istio laufen lassen kann oder über Kubernetes – da gibt es diese Ingress, die es mir ermöglicht Kommunikation von draußen auf diese Microservices zu verteilen – dadurch habe ich einen Ansatzpunkt. Es kommt ein HTTP-Request rein, ich kann sehen, dass dieser HTTP-Request zu irgendeinem von diesen Services geht und dort bearbeitet wird, ich kann die Latenzzeiten sehen, das ganze Monitoring, benutzerbasierte Latenzzeiten, Durchsätze, solche Geschichten. Da macht so etwas schon Sinn oder ist meiner Ansicht nach sinnvoll, weil ich eh eine starke HTTP-orientierte Kommunikation habe, zumindest nach draußen. Da würde ein Service Mesh, glaube ich, Sinn ergeben.
Jörg Müller: Das wäre jetzt auch noch meine andere Frage in die Richtung: Nach draußen, also zwischen verschiedenen SCS macht ein Service Mesh Sinn, macht es vielleicht auch innerhalb eines SCS Sinn, sofern es in kleineren Einheiten strukturiert ist?
Eberhard Wolff: Das hängt wieder davon ab, ob sie synchron kommunizieren oder nicht. Insbesondere bei der synchronen Kommunikation über REST hat es eben Vorteile. Es ist eine leicht bizarre Situation, weil man argumentieren kann, dass durch asynchrone Kommunikation, die Self-Contained Systems eigentlich auch in erster Linie befürworten, dass dadurch eben einige Hauptherausforderungen von Microservices, wie zum Beispiel Resilience, sowieso schon gelöst werden, sodass eine Infrastruktur da weniger hilft. Wir hatten das ja schon am Anfang diskutiert; für mich besteht die Frage nach Alternativen. Ich würde sagen, dass ich ja eh irgendetwas bauen muss, das für HTTP-Requests Durchsätze anzeigt, Latenzzeiten, solche Geschichten. Ich werde eine Logging-Infrastruktur bauen, Tracing vielleicht nicht, aber so etwas ähnliches wie ein Service Mesh werde ich sowieso bauen und dann ist für mich die Frage: Kaufe ich es sozusagen, also nehme ich das vorhandene oder baue ich so etwas selbst? Ich glaube, man kommt auch bei einem SCS nicht darum herum, diese Frage zu beantworten.
Jörg Müller: Was in dem Zusammenhang auch ganz spannend ist, ist: Wenn man eine Infrastruktur wie ein Service Mesh hat und ich habe Entwickler, die gerade aktiv Services entwickeln, wie gehe ich damit eigentlich um? Entwickelt der Entwickler jetzt im Rahmen eines Service Meshes, entwickelt er es separat oder was wären da interessante und empfehlenswerte Vorgehensweisen?
Hanna Prinz: Das ist eine ausgezeichnete Frage! Service Meshes sind noch so jung, dass es da, glaube ich, noch kein Standard-Vorgehen gibt, aber deine Frage, das sind eigentlich zwei Fragen. Die erste Frage ist: Wer kümmert sich eigentlich um so ein Service Mesh, wer ist dafür verantwortlich? Aus meiner Sicht ist der gleiche Mensch oder das gleiche Team dafür verantwortlich, das sich um die Infrastruktur kümmert. Natürlich muss dieses Team auch mit den Leuten sprechen und fragen: Wie soll der Circuit-Breaker denn genau funktionieren, was kann passieren, was ist die Definition von „Der Service ist kaputt“? Aber an sich ist es eine Infrastruktur-Angelegenheit. Das bedeutet auch, dass ich, solange ich lokal an meiner Anwendung entwickle und mich nicht um diese Infrastruktur-Themen kümmere – also nicht aktiv daran entwickle, auch kein Service Mesh brauche. Ein Service Mesh fügt mir halt Features hinzu, aber wenn ich die Features alle wegnehme, sollte die Anwendung genauso gut funktionieren.
Jörg Müller: Das heißt, im Idealfall entwickle ich dann, ohne dass ich ein Service Mesh überhaupt berücksichtige.
Hanna Prinz: Ich empfehle definitiv, das gleiche Service Mesh mit den gleichen Konfigurationen auf dem Staging-System zu haben, definitiv. Aber lokal auf meinem Rechner, macht es mir das einfacher, wenn ich auch kein Service Mesh habe. Wenn ich schon ein lokales Kubernetes-Cluster habe, dann ist das für meinen Rechner mit bestimmten Anwendungen genug Aufgabe, da braucht man das Service Mesh, aus meiner Sicht, für normale Anwendungsentwicklung nicht unbedingt.
Jörg Müller: Okay, cool. Jetzt haben wir uns ganz viel zu den Vor- und Nachteilen angehört, wissen jetzt, wie ein Service Mesh funktioniert, was es da für Alternativen zu gibt. Wenn wir die zwei Teile, die wir zu dem Thema geredet haben, jetzt mal zusammenfassen wollten, was wäre dann euer persönliches Fazit zu dem Thema?
Eberhard Wolff: Für mich gibt es eigentlich zwei Punkte, die wichtig sind. Auf der einen Seite ist es so, dass ich ein großer Verfechter der Meinung bin, dass Architektur- und Technologieentscheidungen Dinge sind, die jeder für sich treffen und auch begründen muss und es ist durchaus valide zu sagen: Ich baue ein System und ich baue es nicht als Microservices, ich kann es als Deployment-Monolith bauen. Dafür gibt es gute Gründe, zum Beispiel auch weniger technischen Overhead. Analoges würde ich jetzt für ein Service Mesh in Anspruch nehmen. Es gibt sicher Gründe oder Szenarien, in denen ein Service Mesh nicht sinnvoll ist und man sollte begründen können, warum man etwas benutzt oder eben auch nicht. Auf der anderen Seite ist es für mich so, dass sich für mich bei diesem Thema mit den Infrastrukturen für Microservices klare Favoriten herausbilden. Für mich sind das auf der einen Seite Kubernetes als Infrastruktur, in der ich Docker-Container betreiben kann, was auch viele andere Probleme löst, also beispielsweise Service-Discovery, Load-Balancing oder solche Geschichten. Und Istio sehe ich da als eine Ergänzung, die Monitoring, Logging, Resilience und viele andere Probleme, die ich so habe, auch löst. Und ich gehe eigentlich davon aus, dass das in Zukunft die Infrastruktur sein wird, auf der wir Microservice-Systeme betreiben werden. Das auch aus gutem Grund, weil die technischen Vorteile, wie wir diskutiert haben, dort eben überzeugend sind, wenn man mal Systeme, die sehr stark auf etwas wie Kafka setzen, ausklammert. Von daher glaube ich, dass das etwas ist, bei dem wir darüber reden können, wann es sich durchgesetzt haben wird, aber nicht ob. Ich glaube, das wird sich letztendlich durchsetzen.
Hanna Prinz: Ich sehe das ganz ähnlich, ich denke auch, dass uns das Thema noch sehr lange beschäftigen wird. Man weiß nie, was passiert, aber es macht mich – nach allem, was ich gesehen habe, womit ich mich jetzt beschäftigt habe – ein bisschen euphorisch, es ist schon sehr vielversprechend, was man damit alles machen kann, es fehlt aber definitiv noch an Produktionserfahrungen. Viele experimentieren damit und viele probieren das mit einer kleinen Beispielanwendung aus. Aber ich denke, bezüglich der Frage, wie sich so ein Service Mesh unter Realbedingungen verhält, braucht man noch ein paar experimentierfreudige Teams, die sagen: Okay, ich probiere das mal aus, ich lasse das wirklich mal in Produktion laufen. Das ist auch genau der Aufruf, den das Team von Istio herausgegeben hat. Die haben gesagt: Okay, wir haben hier die 1.0, die und die Features sind produktionsreif und jetzt sagt uns doch mal, wie das funktioniert, sagt uns doch mal, wo wir weiter entwickeln sollen. Ich glaube, wenn man möchte, dass sich so eine Architektur verbessert, dann muss man auch diese Risiken eingehen und auch mal sagen: Okay, ich probiere das jetzt aus. Und wenn da etwas kaputt geht, sich daran beteiligen und sagen: Okay, bei mir hat es nicht funktioniert. Darum werden wir nicht herum kommen, wenn wir möchten, dass das Ding wirklich resistent und so stabil ist wie zum Beispiel Kubernetes heute.
Jörg Müller: Ja, sehr schön. Ich glaube, dabei können wir es belassen. Vielen Dank für die Zeit, die ihr euch genommen habt und vielen Dank an die Hörer fürs Zuhören und bis zum nächsten Mal!
Eberhard Wolff: Danke!
Hanna Prinz: Sehr gerne.