This entry is part of 11 in the series logstash

Dass Elasticsearch das “Elastic” in seinem Namen richtig ernst meint, hat jeder, der mal mit mehr als einem Knoten experimentiert hat, feststellen können. Anders als viele andere geclusterte Dienste können Knoten fast nach Belieben zu einem bestehenden Cluster hinzugefügt und wieder entfernt werden.

Wie ernst es Elastic mit der Elastizität ist, sieht man unter anderem an den folgenden Eigenschaften. (Wer sich intensiver mit Elasticsearch auseinandergesetzt hat, wird wissen, dass es sich hier um Defaulteinstellungen handelt und man in komplexeren Setups doch das eine oder andere einstellt und nicht dem Automatismus überlässt. Also bitte keine Kommentare wie “In meinem Cluster steht aber, dass gateway.expected_nodes den Wert 23 hat.”)

  • Elasticsearch Cluster haben üblicherweise nirgends vermerkt, wie viele Knoten der Cluster beinhaltet. Lastverteilung, Wahl des Masters, etc. rechnet immer mit der aktuell vorhandenen Anzahl an Knoten.
  • Es gibt keinen Weg, einen Knoten aus einem Cluster “sauber” zu entfernen oder ihn hinzuzufügen. Entfernen bedeutet Beenden des Dienstes und Hinzufügen bedeutet Starten des Dienstes mit gleicher Konfiguration wie der Rest.
  • Backups bzw. Snapshots werden von allen beteiligten Knoten auf einen Share geschrieben und von dort gelesen. Egal, wie viele Knoten zum jeweiligen Zeitpunkt aktiv sind. Ein zwei Knoten Cluster kann ohne weiteres einen Snapshot restoren, der von einem 12 Knoten Cluster gemacht wurde, solange die Ressourcen dazu ausreichen. Konfiguration braucht man dafür nicht.
  • Kommunikation mit dem Cluster geschieht üblicherweise über die REST-API eines einzelnen Knotens, der die Anfrage im Cluster weiter verteilt. Egal, ob es sich dabei um ein Query oder eine dynamische Konfigurationsänderung handelt.

Der Nachteil dieser Elastizität ist, dass der Cluster nicht wissen kann, ob ein Knoten entfernt wurde oder nur mal kurz neu gestartet wird. Das hat zur Folge dass üblicherweise sofort nach Wegummiringerlgfall eines Knotens der restliche Cluster beginnt, Shards und ihre Repliken (Daten in Elasticsearch werden in Indices aufgeteilt, die wiederum in Shards unterteilt werden, die ihrerseits in Repliken kopiert werden – so erreicht Elasticsearch mit beliebigen Daten Lastverteilung und Redundanz) umzuverteilen, um den “Verlust” des Knotens auszugleichen. Dazu werden die Daten, die auf diesem Knoten waren, sofort auf andere Knoten kopiert – das ist möglich weil Elasticsearch per default jeden Datensatz mindest zweimal vorhält. Nachdem die Redundanz wieder hergestellt ist, werden die Shards und Repliken nochmal verschoben, jedoch langsamer, um die Last im Cluster gleichmässig zu verteilen.

Was aber nun, wenn der Knoten sofort wieder dem Cluster beitritt, weil er nur, z.B. wegen eines Kernel Updates, rebooted wurde? Die Daten, die sich noch auf dem Knoten befinden, werden validiert, ob sie noch brauchbar sind oder in der Zwischenzeit verändert wurden und eventuell verschobene Daten werden vielleicht wieder zurückverschoben. Wird Elasticsearch als Teil des Elastic Stack mit Logstash und Kibana verwendet (und das wollen wir doch alle), dann werden üblicherweise nur in den Index des aktuellen Tages Daten geschrieben und die anderen bleiben unverändert. Da Elasticsearch das jedoch nicht weiss, wird der gesamte Datenbestand überprüft. Abhängig von verschiedenen Faktoren kann dieses Überprüfen wenige Minuten bis etliche Stunden dauern. Während dieses Prüfens sind üblicherweise die Daten nicht so verteilt, wie es sein soll und der Cluster bleibt im Status “Yellow”, was einige Arbeiten daran verhindert und auch bedeutet, dass kein weiterer Knoten ausfallen sollte, um Datensicherheit zu gewährleisten. Das macht den Neustart eines gesamten Clusters Knoten für Knoten im laufenden Betrieb zum Geduldsspiel.

Zum Glück gibt es einen einfachen, wenn auch nicht weithin bekannten, Weg, Elasticsearch vom Rebalancing des Clusters abzuhalten und auch die Daten bereits im Vorfeld als unveränderlich zu markieren.


curl -XPUT http://elasticsearch001:9200/_cluster/settings 
{
    "persistent": {
        "cluster.routing.allocation.enable": "none"
    }
}
curl -XPOST http://elasticsearch001:9200/_flush/synced

Mehr dazu gibt in der Elasticsearch Doku. Der erste Befehl schaltet das Umverteilen von Shards komplett ab und der zweite führt einen sogenannten “Synced Flush” aus. Dabei werden ein paar Ressourcen freigegeben und Elasticsearch erstellt etwas ähnliches wie eine Checksum für jeden Index, der sich in den letzten 5 Minuten nicht verändert hat. Diese beiden Befehle haben zur Folge, dass auch bei Wegfall (in unserem Beispiel Neustart) eines Knotens weder die Redundanz im Cluster wieder hergestellt noch die Last gleichmässig verteilt wird. Das ist in diesem Fall gut, da der Knoten ja gleich wieder da sein wird. Wenn denn der neu gestartete Knoten wieder da ist, prüft Elasticsearch nur kurz, ob die Prüfsummen noch stimmen, wovon auszugehen ist, und bringt die Shards und Repliken auf diesem Knoten sofort wieder online. Das beschleunigt einen Neustart enorm.

Wenn alle geplanten Neustarts abgeschlossen sind, muss unbedingt der folgende Befehl abgesetzt werden, um die Umverteilung wieder zu aktivieren, da Elasticsearch sonst nicht auf den echten Ausfall eines Knotens reagieren kann.


curl -XPUT http://elasticsearch022:9200/_cluster/settings
{
    "persistent": {
        "cluster.routing.allocation.enable": "all"
    }
}
Thomas Widhalm

Autor: Thomas Widhalm

Thomas war Systemadministrator an einer österreichischen Universität und da besonders für Linux und Unix zuständig. Seit 2013 möchte er aber lieber die große weite Welt sehen und hat sich deshalb dem Netways Consulting Team angeschlossen. Er möchte ausserdem möglichst weit verbreiten, wie und wie einfach man persönliche Kommunikation sicher verschlüsseln kann, damit nicht dauernd über fehlenden Datenschutz gejammert, sondern endlich was dagegen unternommen wird. Mittlerweile wird er zum logstash - Guy bei Netways und hält Schulungen und erstellt Schulungsunterlagen zu diesem faszinierenden Tool.