Monitoring und Tracing für Akka Anwendungen unter Kubernetes
Einleitung
Um eine hohe Verfügbarkeit von Anwendungen zu garantieren, müssen diese mittels Monitoring und Tracing überwacht werden. Aus diesem Grund haben wir verschiedene Monitoring- und Tracingprodukte für Akka Anwendungen betrachtet. Um die Produkte zu testen, wurden diese in unsere Akka Demo-Applikation eingebunden. Die Akka Demo-Applikation wurde auch schon in früheren Beiträgen erwähnt (https://innfactory.de/softwareentwicklung/scala-akka-play-co/akka-service-deployment-on-kubernetes/). Für die spätere Konzepterstellung wird jeweils ein Monitoring- und Tracingprodukt ausgewählt.
Monitoring
Einleitung
Für das Monitoring von Applikationen gibt es keine pauschale Lösung, da jede Applikation anders aufgebaut ist. Es gibt jedoch einige Regeln, an die man sich halten sollte:
Checkbox Monitoring vermeiden
Bei dieser Methode wird versucht möglichst viele Metriken einer Anwendung zu überwachen. Dies wird aus Angst gemacht, es könnte eine Metrik nicht überwacht werden, die später einmal benötigt wird. Meist führt dies aber dazu, dass zu viele Metriken gesammelt werden und wichtige Informationen durch das Überangebot an Metriken verloren gehen. Daher sollte lieber mit einer kleineren Anzahl an Metriken begonnen werden.
Monitoring ist ein stetiger Prozess
Ein weiterer wichtiger Punkt ist, dass Monitoring ein Prozess ist, der stetig angepasst und verändert werden muss. Dies liegt an der Weiterentwicklung der Anwendung und dem hinzugewinnen von neuen Erkenntnissen beim Überwachen der Anwendung.
Tool Besessenheit vermeiden
Hierbei wird versucht die Applikation mit einer möglichst großen Anzahl an verschiedenen Tools allumfassend zu überwachen. Diese Versuche scheitern oft, da die große Anzahl der Tools nicht richtig gepflegt wird und sich niemand mehr in diesem Tool „Dschungel“ zurechtfindet.
Richtiges konfigurieren von Schwellwerten
Schwellwerte für überwachte Metriken müssen richtig konfiguriert werden. Ein zu früher Alarm führt oft dazu, dass dieser nach kurzer Zeit nicht mehr beachtet wird, da er zu oft auslöst und keiner Handlung bedarf. Das Konfigurieren der Schwellwerte ist ein stetiger Prozess und wir vor allem am Anfang Zeit in Anspruch nehmen.
Auch können beim Monitoring verschiedene Schwerpunkte gelegt werden. In diesem Artikel liegt der Schwerpunkt auf dem Monitoring der Applikationsperformance. Deswegen muss die Monitoring Software eine Möglichkeit bieten, Metriken von Akka, Scala und der JVM (Java Virtual Machine) zu erfassen. Dazu wurden verschiedene Produkte betrachtet, die im folgenden Abschnitt vorgestellt werden.
Lightbend Monitoring
Lightbend Monitoring ist Teil der Lightbend Enterprise Tools und besteht aus den beiden Produkten Lightbend Monitoring und Lightbend Console. Das Produkt wird von der Firma Lightbend Inc. entwickelt, welche auch Scala und Akka mitentwickelt. Lightbend Monitoring wurde von Lightbend Inc. speziell für das Monitoring von Akka, Play und Lagom Anwendungen entwickelt.
Die Abbildung 1 gibt einen Überblick über die Struktur von Lightbend Monitoring, wenn dies unter Kubernetes betrieben wird. Dargestellt sind die einzelnen Pods, der verschiedenen Bausteine von Lightbend Monitoring. Um Telemetriedaten aus der Akka Anwendung zu bekommen, wird in die Akka Anwendung die Cinnamon Erweiterung eingebunden. Das Cinnamon Plugin besteht aus einen Java Agent, welcher Telemetrie Daten zu Akka und der JVM sammelt und einen Webserver öffnet über den die Telemetrie Daten abgegriffen werden können. Prometheus sammelt diese bereitgestellten Daten ein und speichert diese. Grafana und Lightbend Console dienen zur Visualisierung der gesammelten Telemetrie Daten.
In Abbildung 2 ist die Lightbend Console zu sehen. Der obere Abschnitt zeigt die verschiedenen Deployments, jeder Punkt stellt hier einen Pod dar. Über die verschiedenen Farben wird dargestellt, ob das Deployment bzw. der Pod ordnungsgemäß läuft. Im unteren Abschnitt sind weitere Informationen zu den Deployments, wie die Anzahl der Nodes, Pods und Container, sowie der Gesundheitszustand der Deployments über einen längeren Zeitraum zu sehen.
Kamon
Ein weiteres Produkt auf dem Markt ist Kamon. Kamon ist eine unter Apache 2 lizenzierte Software. Kamon wirkt auf den ersten Blick wie eine kostengünstigere Version von Lightbend Monitoring.
Die Abbildung 3 gibt einen Überblick über die Struktur von Kamon. Diese ist ähnlich zur Struktur von Lightbend Monitoring. In der Akka Anwendung ist die Kanela Erweiterung zu finden, welche einen Java Agent beinhaltet. Durch das Einbinden der Kamon Prometheus Erweiterung können die gesammelten Telemetriedaten von einem Prometheus Server abgegriffen werden. In verschiedenen Grafana Dashboards werden die gesammelten Daten visualisiert. Kamon ist neben Akka auch zum Play Framework kompatibel.
In der Abbildung 3 ist in Orange noch Kamon APM (Application Performance Management) zu sehen. Kamon APM ist eine kostenpflichtige Lösung. Bei dieser Lösung werden die gesammelten Metriken an Kamon gesendet, welches die Speicherung und Visualisierung über vorgefertigte Dashboards übernimmt. Um Kamon APM nutzen zu können, muss die Erweiterung Kamon APM Reporter eingebunden werden.
Istio
Da die Istio Webseite auch für den Bereich Monitoring wirbt, wurde es auch betrachtet. Istio ist ein kostenloses unter Apache Lizenz 2 lizenziertes Service Mesh. Das sammeln von Metriken für Akka, Scala, JVM wird nicht unterstützt. Somit wurde es für den Bereich Monitoring verworfen.
Tracing
Einleitung
Für die Fehlersuche und Optimierung von Applikationen ist Tracing ein nützliches Instrument. Mit der Einführung von verteilten Systemen, wurde das Tracing immer komplexer.
In der Abbildung 4 ist die Demo-Applikation zu sehen. Ziel des Tracings ist es, die Anfrage ab dem Eintreffen am Service zwei aufzuzeichnen und durch das gesamte System zu verfolgen. Die kleinste Einheit, die beim Aufzeichnen einer Anfrage an die Applikation entsteht, ist ein Span. In Abbildung 5 ist ein Trace der Demo-Applikation zu sehen. Auf der linken Seite, sind die verschiedenen Spans zu sehen, die einen Trace ergeben. Der oberste und somit Initiale Span wurde maximiert, damit die Details sichtbar werden. Dies ist der Punkt, an dem die Anfrage des Clients auf den Webservice trifft. Die hier sichtbaren Spans, sind alle im Service zwei der Demo-Applikation entstanden. Ein Trace kann somit Spans von einem oder mehreren Microservices enthalten.
Für das Tracing wurden die Produkte Zipkin und Jaeger betrachtet.
Jaeger
Jaeger wird zum Tracing von verteilten Systemen benutzt und ist unter Apache 2 lizenziert. Ursprünglich wurde es von Uber Technologies entwickelt. Mittlerweile ist es ein Projekt der Cloud Native Computing Foundation.
In Abbildung 6 ist die Architektur von Jaeger dargestellt. Der Jaeger Client besteht aus der Tracing Bibliothek, die in der zu überwachenden Anwendung läuft. Diese Bibliothek sammelt Spans und sendet diese weiter an den Jaeger Agent. Die Übertragung der Daten zum Jaeger Agent findet via User Datagram Protocol (UDP) statt. Auch hat der Jaeger Client die Möglichkeit, den Jaeger Agent zu überspringen und die Daten sofort an den Jaeger Collector zu senden. Je nach Komplexität und Größe der zu überwachenden Anwendung, kann das direkte Senden zum Jaeger Collector oder der Weg über den Jaeger Agent von Vorteil sein. Über den control flow in der Grafik, besteht die Möglichkeit dem Jaeger Client und Agent Konfigurationsänderungen mitzuteilen.
Der Jaeger Agent läuft als Side-car in den Pods, der zu überwachenden Anwendung und sendet die Daten weiter an den Jaeger Collector. Der Jaeger Collector empfängt die Spans der Jaeger Agents im Zipkin oder Jaeger Format über die Protokolle HTTP, GRPC oder TChannel. Die empfangenen Daten können in JavaScript Object Notation (JSON), Thrift oder Protocol Buffers (Protobuf) enkodiert sein. Nach dem Empfang der Daten werden diese in ein internes Datenmodell konvertiert und in der Datenbank gespeichert. Als Datenbank kann Kafka, Cassandra oder Elasticsearch verwendet werden. Wenn Jaeger nur zum Testen installiert wird, besteht auch die Möglichkeit, den lokalen Festplattenspeicher der Jaeger Instanz zum Speichern der Daten zu verwenden. Die Komponente Jaeger Query wird von der Benutzeroberfläche zum Abfragen der gespeicherten Daten genutzt.
Die data mining Jobs sind optional und können zum weiteren Auswerten der gesammelten Tracingdaten verwendet werden. Über diese können zum Beispiel Graphen aufgebaut werden, in denen man die Abhängigkeiten eines Dienstes zu anderen Diensten sieht.
Zipkin
Zipkin ist wie Jaeger auch zum Tracing von verteilten Systemen geeignet und auch unter Apache 2 lizenziert. Zipkin wurde ursprünglich von Twitter entwickelt und existiert schon länger als Jaeger.
Wie in Abbildung 7 zu sehen ist, ist der Aufbau der Zipkin Architektur ähnlich zur Jaeger Architektur. Hier muss ein sogenannter Reporter in der Applikation laufen, der die Daten für das Tracing sammelt und sie zum Collector sendet. Als Protokoll zur Datenübertragung kann unter anderem HTTP, GRPC oder Advanced Message Queuing Protocol (AMQP) genutzt werden. Der Collector validiert und indexiert die Daten und sendet sie weiter zur permanenten Speicherung. Zum Speichern der Tracingdaten kann Cassandra, ElasticSearch oder MySQL verwendet werden. Weitere Systeme können über Drittanbieter Erweiterungen angebunden werden. Damit die Daten einfach abgerufen werden können, stellt Zipkin eine HTTP Schnittstelle zur Verfügung, über die die Daten im JSON Format zur Verfügung gestellt werden. Zur Darstellung der Daten, stellt Zipkin eine eigene Weboberfläche bereit.
Konzept für Monitoring und Tracing
Für die Konzepterstellung wurde für das Monitoring Kamon ausgewählt. Dies liegt daran, dass die Lizenzkosten für Lightbend Monitoring sehr hoch sind. Auch ist der Funktionsumfang von Kamon fast mit dem von Lightbend Monitoring identisch. Istio wird nicht weiter betrachtet, da es den benötigten Funktionsumfang nicht erfüllt.
Im Bereich Tracing wurde Jaeger ausgewählt. Zipkin und Jaeger sind vom Funktionsumfang fast identisch. Jedoch bietet Jaeger die bessere Akka Unterstützung und unterstützt den Standard Opentracing. Opentracing ist ein herstellerunabhängiges und standardisiertes Framework für Tracing.
Unter Abbildung 8 ist ein Konzept zu sehen welches für Laura AI erstellt wurde.
Monitoring
Oben rechts in der Abbildung 8 sind die beiden Pods Prometheus und Grafana zu finden, welche das Monitoring beinhalten. In Grafana können Dashboards angelegt werden, um die Daten zu visualisieren. Dazu holt sich Grafana die Daten von Prometheus und InfluxDB. Auch übernimmt Grafana die Alarmierung über verschiedene Kanäle. Prometheus übernimmt das Sammeln und Speichern der Daten. Lauracrawler und lauradialogflow enthalten die Kamon Prometheus Erweiterung, damit Prometheus eine Schnittstelle zum Sammeln der Daten zur Verfügung steht. Der Pod links oben mit InfluxDB ist optional, dies ist durch die gestrichelte Linie gekennzeichnet. Falls dieser vorhanden ist, schreibt Prometheus die gesammelten Metriken zusätzlich nach InfluxDB. Dieser wird nur benötigt, wenn die Monitoringdaten über längere Zeit aufbewahrt werden sollen und der Festplattenspeicher unter Prometheus dazu nicht ausreicht.
Tracing
In der Abbildung 8 sind die beiden unteren Pods für das Tracing zuständig. In lauracrawler und lauradialogflow ist der Kamon Reporter für Jaeger integriert. Dieser ist so konfiguriert, dass er die Daten an den Jaeger Agent weitersendet. Der Jaeger Agent gibt diese Daten dann an den Jaeger Collector weiter. Es gibt auch die Möglichkeit den Jaeger Agent zu überspringen und die Daten direkt an den Jaeger Collector zu senden. Ob dieser übersprungen werden kann, hängt von der Menge der Daten ab, die übertragen werden. Um eine bessere Skalierbarkeit zu erreichen, wird die Verwendung des Jaeger Agent empfohlen. Der Jaeger Collector sendet die Daten zum Speichern an Elasticsearch. Elasticsearch ist hier zu empfehlen, da es um einen kompletten Elasticsearch, Logstash, Kibana (ELK) Stack erweitert werden kann, falls dies zu einem späteren Zeitpunkt benötigt wird. Falls die Umgebung sehr groß ist, können auch mehrere Jaeger Collectoren eingesetzt werden. Jaeger UI dient lediglich dazu die Daten zu visualisieren. Die Pfeile zwischen Jaeger Collector, Jaeger Agent und lauracrawler bzw. lauradialogflow gehen in beide Richtungen, weil die Tracingdaten von der Akka Anwendung Richtung dem Jaeger Collector gesendet werden und Konfigurationsdaten vom Jaeger Collector in Richtung der Akka Anwendung gesendet werden.
Praxistest
Damit die verschiedenen Softwarelösungen mit wenig Aufwand getestet werden können, gibt es dazu verschiedene Branches im GitHub Repository der Demo-Anwendung:
- Kamon und Jaeger: https://github.com/innFactory/akka-microservice-example/tree/kamon_jaeger
- Lightbend Monitoring: https://github.com/innFactory/akka-microservice-example/tree/lightbend_monitoring
- Istio: https://github.com/innFactory/akka-microservice-example/tree/istio
Der Branch kamon_jaeger testet das in Abbildung 8 beschriebene Konzept. In den jeweiligen Branches ist unter den Verzeichnissen monitoring-and-tracing, lightbend_monitoring oder istio eine Markdowndatei enthalten die das Setup beschreibt.