Ist es eine gute Idee, Elasticsearch in OpenShift laufen zu lassen?

Suny Kim Agil / Agile, Automation, Compliance, Docker, Kubernetes Leave a Comment

Falls Sie sich das fragen, ist vielleicht dieser Erfahrungsbericht interessant. Er stammt aus einem Projekt, in dem wir Elastic Stacks in OpenShift haben laufen lassen.

Was ist OpenShift?

OpenShift ist eine Plattform für Containermanagement. Es ist eine Version von Kubernetes, die von Red Hat entwickelt und supportet wird, und bietet einige zusätzliche Komponenten wie Software-Defined Networks. Dieser Artikel gilt sowohl für OpenShift als auch für Kubernetes. Genau genommen verwaltet OpenShift nicht Container, sondern Pods, das sind Gruppen von Containern. Zum Verständnis dieses Artikels reicht es, sich OpenShift vorzustellen als eine Plattform, die physikalische Server in einen Pool von Resourcen verwandelt. In diesem Pool können man nun Hunderte oder Tausende von Pods entstehen und vergehen lassen, mit ein paar Befehlen. Die Anwendungen, die darin laufen, betrachten die Pods als ihre Server.

Was ist der Elastic Stack?

Der Elastic Stack besteht aus einem Event-Forwarder, Logstash, der die Daten in einen Datastore transportiert: Elasticsearch. Auf den Daten setzt ein Web-Frontend auf, Kibana, um sie zu durchsuchen und analysieren. Eine angenehme Eigenschaft des Elastic Stack ist, dass man sich um die Menge der Daten keine Sorgen machen muss. Wenn das Datenvolumen wächst, wächst der Stack problemlos mit, bis hin zu Terabytes. Der Elastic Stack ist eine beliebte Lösung für Log-Management, und in den Unternehmen, die wir sehen, melden viele Teams Bedarf daran an.

Wäre es nicht ideal, wenn wir OpenShift dazu benutzen könnten, Elastic Stacks mit einem Mausklick zu erzeugen?

Mit Kibana und Logstash klappt das alles sehr gut, sie verhalten sich so, wie OpenShift es erwartet (außer beim Einsatz von Logstash persistent queues – dann muss man sich Sorgen um die Daten machen). In diesem Artikel konzentrieren wir uns auf Elasticsearch. (Hier passt doch etwas nicht. Eben wurde Elasticsearch noch dafür gelobt, so wunderbar zu skalieren, und jetzt skalieren nur noch die anderen beiden Komponenten? Es ist beides richtig – Elasticsearch skaliert auf seine Art, und Logstash und Kibana skalieren so, wie OpenShift das vorsieht. Mehr dazu unten.)

Was sind die Vorteile von OpenShift?

(A) OpenShift versteckt die physischen Server unter einer Abstraktionsschicht – man braucht sich nicht mehr darum zu kümmern.

(B) Die Applikationen lassen sich leicht skalieren.

(C) Man kann einfach neue physische Server hinzufügen.

(D) Wenn Pods abstürzen, startet OpenShift sie neu.

(E) OpenShift verwaltet die Zuordnung von Pods zu Diensten. Wenn man eine readiness probe definiert, erkennt es daran, ob ein Pod in einen Dienst aufgenommen werden kann.

(F) Alles ist Code und Konfiguration.

(G) Es ist cool!

Was sind die Nachteile?

(W) OpenShift ist nicht einfach. Es ist eine weitere Schicht, die verstanden und betrieben werden muss.

(X) Lizenzkosten

(Y) Wie verhält sich das Konstrukt unter Last?

(Z) Augenblick mal. Funktioniert das überhaupt?

Ja, das funktioniert schon. Die Frage ist, ob es den Aufwand wert ist. Damit ist (Z) beantwortet, und wir können uns die restlichen Punkte genauer anschauen.

Die Vorteile unter der Lupe

Bevor wir uns in die Details stürzen, möchte ich anmerken, dass dies Erfahrungen vom Frühjahr 2018 sind, mit OpenShift Version 3.7 (und Elastic Stack 6.2).

Schauen wir uns den ersten Punkt an:

(A) OpenShift versteckt die physischen Server unter einer Abstraktionsschicht – man braucht sich nicht mehr darum zu kümmern.

Leider kann uns das nicht ganz egal sein, falls uns die Daten wichtig sind.

Der Elasticsearch Pod braucht Speicherplatz. Die Daten müssen vor einem Ausfall des darunterliegenden Servers geschützt sein. Dafür braucht man ein verteiltes Datensystem (glusterfs bei OpenShift) – und das ist keine einfache Sache. Oder man stellt OpenShift lokalen Speicherplatz zur Verfügung – diese Lösung haben wir gewählt. Dann muss man aber dafür sorgen, dass der Pod immer denselben Speicher bekommt und auf demselben physischen Server läuft.

An dieser Stelle lohnt es sich, das Skalieren von Elasticsearch genauer anzuschauen. Es läuft am schönsten auf folgendem Setup: Eine Menge gleichartiger, dedizierter, unabhängiger, mittelstarker Server – beispielsweise mit 64 GB RAM und 1 Terabyte SSD-Platten. Man definiert eine vernünftige Anzahl Replikas (Datenkopien) – nicht zu viele, um Plattenplatz zu sparen, aber genug, um vor Ausfällen der Server geschützt zu sein (der Lesedurchsatz profitiert auch von einer höherer Anzahl Replikas, ist aber für unsere Überlegungen nicht wichtig). Dann übernimmt Elasticsearch die Verteilung der Daten über die Server. Wenn ein Knoten das Cluster verlässt, verteilt es sie neu auf den verbliebenen Servern. Wenn Knoten hinzukommen, sorgt Elasticsearch dafür, dass sie ins Cluster eingebunden werden und ihren Teil übernehmen, ohne die laufenden Suchen oder die Datenaufnahme zu beeinträchtigen.

Wenn die Server nicht wirklich unabhängig sind, sondern beispielsweise manche in demselben Rack stehen, verliert man schon etwas von dieser Eleganz. Dann muss shard allocation awareness konfiguriert werden, um Elasticsearch davon zu informieren, dass nicht alle Replikas in demselben Rack gespeichert werden dürfen. In dem Fall von OpenShift mit lokalem Plattenplatz braucht man diese Konfiguration, sobald man mehr Elasticsearch-Knoten als physische Server hat.

Mit anderen Worten, Elasticsearch würde die Datenverwaltung auf den physischen Servern wunderbar managen – wenn OpenShift es ließe, aber es versteckt die Server vor ihm.

Das ist schade um die Schönheit von Elasticsearch, aber OpenShift geht es auch nicht besser. Es hat einen Pool von Resourcen geschaffen, in dem es seine Pods gerne frei schwimmen lassen würde, wie Enten in einem Teich, die hier abtauchen und dort wieder auftauchen – aber nun haben wir sie an die physischen Server gebunden, an die Ebene, die wir eigentlich vergessen wollten.

Das ist die Situation, die unser Zeichner in der Illustration festhält: Wir sind die Königin, die zwei Diener losgeschickt hat, um ihr Leben zu vereinfachen – und feststellen muss, dass sich die beiden Lösungen beißen, so dass sie nun vermitteln muss.


Konfiguration von Elasticsearch in OpenShift

Wenn Elasticsearch auf OpenShift betrieben wird, sind folgende Einstellungen wichtig:

  • Elasticsearch kommt mit Swapping nicht zurecht – OpenShift auch nicht, das sollte ausgeschaltet sein (OpenShift Ansible macht das beispielsweise).
  • File descriptors, max_map_count, number of threads: Die von Elasticsearch empfohlenen Einstellungen gehen davon aus, dass eine Instanz auf einem Server läuft. Was sind die richtigen Werte bei Hunderten von Instanzen pro Server? Ich weiß es nicht. Man könnte eine Formel entwickeln, die die Wahrscheinlichkeit einbezieht, dass soundso viele Instanzen zugleich einen soundso hohen Verbrauch haben – aber ich halte es für sinnvoller, diese Resourcen zu überwachen.
  • JVM DNS cache settings – Java behält positive Hostnamenauflösung per Default ewig im Cache, aber das ist bei OpenShift nicht das Richtige.
  • Prüfen Sie, ob Elasticsearch die richtige Vorstellung hat von den Resourcen, die ihm zur Verfügung stehen: Plattenplatz, Memory und CPU (nachzuschauen über die _nodes/stats API). Falls es sich darin täuscht, versorgen Sie es mit den korrekten Informationen, beispielsweise durch Setzen der Disk Watermarks, oder number of processors. Wenn Elasticsearch einen weiteren Core anfordert, den aber aufgrund der OpenShift-Konfiguration nie erhält, kann sich der Prozess aufhängen.
  • Bedenken Sie die Möglichkeit des Datenverlusts auf jeder Ebene – nur nicht beim RAID, auf Plattenebene ist RAID0 das Richtige, weil Elasticsearch die Daten dupliziert. Wie in der Diskussion von (A) erwähnt muss eventuell shard allocation awareness konfiguriert werden.

 

Der nächste Punkt ist:

(B) Die Applikationen lassen sich leicht skalieren.

Von Autoscaling ist bei Elasticsearch abzuraten. Dazu gibt es einen wirklich guten Beitrag auf Stack Overflow (In der Frage ging es um Amazon-EC2-Autoscaling, nicht um OpenShift-Autoscaling. Beide sind aber ähnlich: Wenn die Last für die bestehenden Knoten zu hoch wird, werden automatisch neue hochgefahren und dem Dienst hinzugefügt.)

Autoscaling ergibt wenig Sinn mit Elasticsearch.

Das Verlagern von Shards (Shard = physische Dateneinheit in Elasticsearch, Anm. der Übersetzerin) ist keine leichte Aufgabe. Es belastet IO und Netzwerk, und kann die Performance von Elasticsearch stark beeinträchtigen. (Falls Sie das begrenzen wollen, können Sie die Clusterwiederherstellung drosseln durch Einstellungen wie cluster.routing.allocation.cluster_concurrent_rebalance, indices.recovery.concurrent_streams, indices.recovery.max_size_per_sec. Das wird den Effekt begrenzen, aber auch die Austarierung und Wiederherstellung verlangsamen).

Also bleibt kontrolliertes Erweitern des Clusters. In diesem Fall gelten die Überlegungen zur Persistenz in (A).

(C) Man kann einfach neue physische Server hinzufügen.

Da bin ich nicht sicher, ob das stimmt. In unserem OpenShift Cluster war es nicht einfach. Vielleicht lag das an der Automatisierung (dazu mehr in Punkt (F)). Falls Sie damit andere Erfahrungen gemacht haben, wäre es großartig, wenn Sie davon berichten.

(D) Wenn Pods abstürzen, startet OpenShift sie neu.

Wenn nachts ein Server abstürzt, sind wir alle dankbar, wenn wir nicht aufstehen müssen, weil ein Automatismus das übernimmt. Solche Abstürze müssen im Fall von Elasticsearch aber auf jeden Fall untersucht werden. Wenn sie häufig vorkomen, ist es nicht gut für Datensysteme. Sie wollen kontrolliert herunterfahren. Und sie mögen es nicht, wenn ihr Cache geleert wird. Für andere Applikationen mögen Restarts in Ordnung sein – auch wenn „Reboot tut gut“ mich arg an Windows in alten Zeiten erinnert.

(E) OpenShift verwaltet die Zuordnung von Pods zu Diensten. Wenn man eine readiness probe definiert, erkennt es daran, ob ein Pod in einen Dienst aufgenommen werden kann.

Hier wird es wieder interessant. Wann ist eine Applikation bereit? Für einen einfachen Webserver reicht es, mit „200“ zu antworten. Für Elasticsearch nicht. Wenn ein Elasticsearch-Knoten mit „200“ zurückkommt, heißt das: „Ich bin bereit, im Cluster mitzumachen.“ Es bedeutet nicht, dass er Daten ausliefern kann. Das wird besonders deutlich, wenn ein Knoten startet. Wenn es bereits einen funktionierenden Cluster gibt, kommt der neue Knoten einfach hinzu. Wenn die Readiness-Probe nur diesen Fall abdeckt, funktioniert sie dafür gut. Aber wenn der ganze Cluster startet, oder ein neuer Cluster angelegt wird, dann wartet jede Node auf den Cluster – bis in alle Ewigkeit. Die Readiness-Probe muss so umgeschrieben werden, dass die ersten Knoten, die hochkommen, den Service bilden, dem sich der Rest anschließen kann. Woher weiß ein Knoten, ob er zu den ersten gehört? Weil es noch keinen Service gibt – das funktioniert, ist aber ziemlich verdreht.

Und wieder, wie bei der Datenverteilung, lösen wir ein Problem doppelt: Elasticsearch kümmert sich schon um Knoten, die zum Cluster hinzukommen oder es verlassen.

Ich habe versucht, komplexere Logik abzubilden wie: „Kibana und Logstash warten, bis Elasticsearch grün ist“. Das habe ich in OpenShift nicht hinbekommen.

Eine schöne Möglichkeit für Webfarmen in OpenShift sind Upgrades ohne Downtime. Ein Pod wird herausgenommen, mit der neuen Version betankt, wieder hereingenommen, und dann ist der nächste dran. Für Elasticsearch gibt es auch Rolling upgrades, aber sie sind komplexer. Vorher wird die Shard Allocation gestoppt, dann werden alle Änderungen auf Platte geschrieben, ein Knoten startet neu, anschließend wird die Shard Allocation wieder gestartet, und man wartet, bis sich der Cluster erholt hat. Auch dafür habe ich in OpenShift keine Lösung gefunden.

Die Readiness-Probes sind nicht zu verwechseln mit Liveness-Probes: Sie informieren OpenShift, wann eine Applikation nicht mehr antwortet und der Pod neu gestartet werden soll. Das ist nicht hilfreich für Elasticsearch, hier sind wir wieder bei der Diskussion von (D).

(F) Alles ist Code und Konfiguration.

Ja, das ist wirklich eine gute Sache, es gibt keine Brüche bespielsweise vom Aufsetzen eines Service zur Konfiguration eines Load Balancer. Von unserer Automatisierung war ich weniger begeistert, wir haben OpenShift Ansible benutzt. Es wurde kürzlich komplett neu geschrieben. Andere Teams benutzen Helm, vielleicht geht das besser.

(G) Es ist cool!

Stimmt. Man kann sogar Blogbeiträge darüber schreiben.


Ist es eine gute Idee, Elasticsearch in Docker laufen zu lassen?

Man kann sich auch fragen, ob Elasticsearch in Dockercontainern eine gute Idee ist. Ich mag Docker, weil es die Installation vereinfacht, indem es die Abhängigkeiten mitverpackt. Beispielsweise eine Rubyapplikation: Software und Systemeinstellungen passend hinzubekommen, kann auch für eine erfahrene Administratorin zur Mühsal werden. Wenn endlich alles stimmt, packt sie alles in einen Docker Container und ist dankbar, das nie wieder machen zu müssen.

Nun läuft Elasticsearch in einer JVM. Da gab es nie viele Abhängigkeiten. Man muss Java 8 installieren. Die anderen Systemvoraussetzungen sind:

  • Kein Swapping / Lock Memory
  • Dateideskriptoren erhöhen
  • Ausreichend virtuellen Speicher gewährleisten
  • Ausreichend Threads gewährleisten
  • Die JVM DNS Cache Einstellungen anpassen

Bis auf den letzten Punkt muss alles auf dem Host außerhalb des Containers umgesetzt werden. Hier ist Docker keine Hilfe. Dasselbe gilt für Diskoptimierungen (richtiger SSD-Scheduler, noatime).

Also, man kann Elasticsearch dockerisieren, oder es bleiben lassen. Es macht keinen großen Unterschied.


Die Nachteile unter der Lupe

Schauen wir uns an, was gegen OpenShift spricht.

(W) OpenShift ist nicht einfach. Es ist eine weitere Schicht, die verstanden und betrieben werden muss.

Ja, das stimmt. Wenn es Ihr erstes OpenShift-Cluster ist, müssen diverse Themen neu gedacht werden: Patch Management, Härtung, Monitoring und der Umgang mit Logs.

(X) Lizenzkosten

Das hängt von davon ab, OpenShift Origin ist frei. Wenn Sie Support haben möchten, kostet das etwas. Dann würde ich dafür plädieren, ihn ausgiebig zu nutzen. Es spart offenbar LIzenzen, wenn man einen Teil des Elastic Stack außerhalb des OpenShift Clusters betreibt.

(Y) Wie verhält sich das Konstrukt unter Last?

Dazu, wie sich das Konstrukt unter Last verhält, kann ich leider nichts sagen, weil ich nicht lange genug im Projekt war. Es interessiert mich brennend – haben Sie Erfahrungen, die Sie teilen können? Beispielsweise das Software-Defined Network: Trägt es den Traffic innerhalb des Elasticsearch Clusters? Und falls es an Grenzen stößt, woran erkennt man das?

 


You Must be This Tall to Use OpenShift

Dieser Titel ist eine Hommage an Martin Fowler’s zeitlosen Beitrag „You Must be this Tall to Use Microservices„.

Wenn die Arbeit mit OpenShift eine Freude werden soll, ist es vorteilhaft, folgendes im Griff zu haben:

  • Repositories (zuverlässiger Zugriff auf Pakete und Images – hier ist OpenShift besser geworden)
  • Beantragung von Zertifikaten / PKI (falls Sie TLS einsetzen wollen)
  • Korrekte Zeit auf den physischen Servern – wenn sie auseinanderlaufen, kommt der OpenShift Cluster durcheinander
  • Provisionierung neuer Server, Platten und anderer Resourcen
  • Konfiguration und Patch Management der physischen Server. Beispielsweise versucht OpenShift Ansible, das Betriebssystem so zu konfigurieren, wie OpenShift erwartet. Das kann zu Konflikten mit der bestehenden automatischen Konfiguration führen.

 

Fazit

Viele der Vorteile von OpenShift kommen nicht zum Tragen, wenn man Elasticsearch darauf laufen lässt. Die Plattform entwickelt sich rasant weiter, aber beim heutigen Stand würde ich Elasticsearch außerhalb betreiben, auf mittelgroßen, unabhängigen Servern. Es lohnt sich, die Mechanismen im Detail zu betrachten, bevor man zwei Systeme einsetzt, die sich im Ansatz beißen – und man am Ende mit mehr statt weniger Arbeit dasteht, wie unsere Königin.

Schreibe einen Kommentar

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