Elastic Stack automatisch mit Ansible Playbooks aktualisieren

Veröffentlicht: 2022-03-11

Die Protokollanalyse für ein Netzwerk mit Tausenden von Geräten war früher eine komplexe, zeitaufwändige und langweilige Aufgabe, bevor ich mich für den Einsatz des Elastic Stack als zentralisierte Protokollierungslösung entschied. Es erwies sich als eine sehr weise Entscheidung. Ich habe nicht nur einen einzigen Ort, an dem ich nach all meinen Protokollen suchen kann, sondern ich erhalte fast sofort Ergebnisse bei meinen Suchen, leistungsstarke Visualisierungen, die für die Analyse und Fehlerbehebung unglaublich hilfreich sind, und schöne Dashboards, die mir einen nützlichen Überblick über das Netzwerk geben.

Der Elastic Stack veröffentlicht ständig neue und erstaunliche Funktionen, behält ein sehr aktives Entwicklungstempo bei und liefert oft jeden Monat zwei neue Versionen. Ich möchte meine Umgebung immer auf dem neuesten Stand halten, um sicherzustellen, dass ich die Vorteile der neuen Funktionen und Verbesserungen nutzen kann. Auch um es frei von Fehlern und Sicherheitsproblemen zu halten. Dies erfordert jedoch, dass ich die Umgebung ständig aktualisiere.

Obwohl die Elastic-Website eine klare und detaillierte Dokumentation enthält, einschließlich des Upgrade-Prozesses ihrer Produkte, ist ein manuelles Upgrade eine komplexe Aufgabe, insbesondere des Elasticsearch-Clusters. Es sind viele Schritte erforderlich, und es muss eine ganz bestimmte Reihenfolge eingehalten werden. Aus diesem Grund habe ich mich vor langer Zeit entschieden, den gesamten Prozess mit Ansible Playbooks zu automatisieren.

In diesem Ansible-Tutorial führe ich uns durch eine Reihe von Ansible Playbooks, die entwickelt wurden, um meine Elastic Stack-Installation automatisch zu aktualisieren.

Was ist der Elastic Stack

Der Elastic Stack, früher bekannt als ELK-Stack, besteht aus Elasticsearch, Logstash und Kibana des Open-Source-Unternehmens Elastic, die zusammen eine leistungsstarke Plattform zum Indizieren, Suchen und Analysieren Ihrer Daten bieten. Es kann für eine breite Palette von Anwendungen verwendet werden. Von der Protokollierung und Sicherheitsanalyse bis hin zum Application Performance Management und der Site-Suche.

  • Elasticsearch ist der Kern des Stacks. Es handelt sich um eine verteilte Such- und Analysemaschine, die in der Lage ist, selbst bei einer großen Menge gespeicherter Daten Suchergebnisse nahezu in Echtzeit zu liefern.

  • Logstash ist eine Verarbeitungspipeline, die Daten aus vielen verschiedenen Quellen (50 offizielle Eingabe-Plugins, während ich schreibe) abruft oder empfängt, sie analysiert, filtert und transformiert und an eine oder mehrere mögliche Ausgaben sendet. In unserem Fall interessiert uns das Output-Plugin von Elasticsearch.

  • Kibana ist Ihr Benutzer- und Betriebs-Frontend. Sie können Ihre Daten visualisieren, durchsuchen, darin navigieren und Dashboards erstellen, die Ihnen erstaunliche Einblicke darüber geben.

Was ist Ansible

Ansible ist eine IT-Automatisierungsplattform, mit der Systeme konfiguriert, Software bereitgestellt oder aktualisiert und komplexe IT-Aufgaben orchestriert werden können. Seine Hauptziele sind Einfachheit und Benutzerfreundlichkeit. Meine Lieblingsfunktion von Ansible ist, dass es agentenlos ist, was bedeutet, dass ich keine zusätzliche Software auf den Hosts und Geräten installieren und verwalten muss, die ich verwalten möchte. Wir werden die Leistungsfähigkeit der Ansible-Automatisierung nutzen, um unseren Elastic Stack automatisch zu aktualisieren.

Haftungsausschluss und ein Wort der Vorsicht

Die Playbooks, die ich hier teilen werde, basieren auf den in der offiziellen Produktdokumentation beschriebenen Schritten. Es soll nur für Upgrades derselben Hauptversion verwendet werden. Zum Beispiel: 5.x5.y oder 6.x6.y wobei x > y . Upgrades zwischen Hauptversionen erfordern oft zusätzliche Schritte und diese Playbooks funktionieren in diesen Fällen nicht.

Lesen Sie unabhängig davon immer die Versionshinweise, insbesondere den Abschnitt zu wichtigen Änderungen, bevor Sie die Playbooks zum Upgraden verwenden. Stellen Sie sicher, dass Sie die in den Playbooks ausgeführten Aufgaben verstehen, und überprüfen Sie immer die Upgrade-Anweisungen, um sicherzustellen, dass sich nichts Wichtiges ändert.

Allerdings verwende ich diese Playbooks (oder frühere Versionen) seit Version 2.2 von Elasticsearch ohne Probleme. Zu der Zeit hatte ich für jedes Produkt völlig separate Playbooks, da sie nicht die gleiche Versionsnummer hatten, wie sie sie kennen.

Allerdings bin ich in keiner Weise für Ihre Verwendung der in diesem Artikel enthaltenen Informationen verantwortlich.

Unsere fiktive Umgebung

Die Umgebung, in der unsere Playbooks ausgeführt werden, besteht aus 6 CentOS 7-Servern:

  • 1 x Logstash-Server
  • 1 x Kibana-Server
  • 4 x Elasticsearch-Knoten

Es spielt keine Rolle, ob Ihre Umgebung eine andere Anzahl von Servern hat. Sie können es einfach in der Inventardatei entsprechend widerspiegeln und die Playbooks sollten problemlos laufen. Wenn Sie jedoch keine RHEL-basierte Distribution verwenden, überlasse ich es Ihnen als Übung, die wenigen verteilungsspezifischen Aufgaben zu ändern (hauptsächlich die Paketmanager-Sachen).

Das Beispiel für einen Elastic Stack, den unsere Ansible Playbooks bereitstellen werden

Das Inventar

Ansible benötigt ein Inventar, um zu wissen, auf welchen Hosts die Playbooks ausgeführt werden sollen. In unserem imaginären Szenario verwenden wir die folgende Inventardatei:

 [logstash] server01 ansible_host=10.0.0.1 [kibana] server02 ansible_host=10.0.0.2 [elasticsearch] server03 ansible_host=10.0.0.3 server04 ansible_host=10.0.0.4 server05 ansible_host=10.0.0.5 server06 ansible_host=10.0.0.6

In einer Ansible-Inventardatei repräsentiert jeder [section] eine Gruppe von Hosts. Unser Inventar umfasst 3 Gruppen von Hosts: logstash , kibana und elasticsearch . Sie werden feststellen, dass ich in den Playbooks nur die Gruppennamen verwende. Das bedeutet, dass die Anzahl der Hosts im Inventar keine Rolle spielt, solange die Gruppen korrekt sind, wird das Playbook ausgeführt.

Der Upgrade-Prozess

Der Upgrade-Prozess besteht aus den folgenden Schritten:

1) Laden Sie die Pakete vorab herunter

2) Logstash-Upgrade

3) Laufendes Upgrade des Elasticsearch-Clusters

4) Kibana-Upgrade

Oberstes Ziel ist es, Ausfallzeiten zu minimieren. Meistens bemerkt der Benutzer dies nicht einmal. Manchmal ist Kibana für einige Sekunden nicht verfügbar. Das ist für mich akzeptabel.

Wichtigstes Ansible-Playbook

Der Upgrade-Prozess besteht aus einer Reihe verschiedener Playbooks. Ich werde die import_playbook-Funktion von Ansible verwenden, um alle Playbooks in einer Haupt-Playbook-Datei zu organisieren, die aufgerufen werden kann, um sich um den gesamten Prozess zu kümmern.

 - name: pre-download import_playbook: pre-download.yml - name: logstash-upgrade import_playbook: logstash-upgrade.yml - name: elasticsearch-rolling-upgrade import_playbook: elasticsearch-rolling-upgrade.yml - name: kibana-upgrade import_playbook: kibana-upgrade.yml

Relativ einfach. Es ist nur eine Möglichkeit, die Ausführung der Playbooks in einer bestimmten Reihenfolge zu organisieren.

Lassen Sie uns nun überlegen, wie wir das obige Ansible-Playbook-Beispiel verwenden würden. Ich werde später erklären, wie wir es implementieren, aber dies ist der Befehl, den ich ausführen würde, um auf Version 6.5.4 zu aktualisieren:

 $ ansible-playbook -i inventory -e elk_version=6.5.4 main.yml

Laden Sie die Pakete vorab herunter

Dieser erste Schritt ist eigentlich optional. Der Grund, warum ich dies verwende, ist, dass ich es für eine allgemein gute Praxis halte, einen laufenden Dienst zu stoppen, bevor er aktualisiert wird. Nun, wenn Sie eine schnelle Internetverbindung haben, kann die Zeit für Ihren Paketmanager zum Herunterladen des Pakets vernachlässigbar sein. Aber das ist nicht immer der Fall und ich möchte die Zeit minimieren, in der ein Dienst ausfällt. Auf diese Weise wird mein erstes Playbook yum verwenden, um alle Pakete vorab herunterzuladen. Auf diese Weise war der Download-Schritt in den Upgrade-Zeiten bereits erledigt.

 - hosts: logstash gather_facts: no tasks: - name: Validate logstash Version fail: msg="Invalid ELK Version" when: elk_version is undefined or not elk_version is match("\d+\.\d+\.\d+") - name: Get logstash current version command: rpm -q logstash --qf %{VERSION} args: warn: no changed_when: False register: version_found - name: Pre-download logstash install package yum: name: logstash-{{ elk_version }} download_only: yes when: version_found.stdout is version_compare(elk_version, '<')

Die erste Zeile zeigt an, dass dieses Spiel nur für die logstash -Gruppe gilt. Die zweite Zeile weist Ansible an, sich nicht die Mühe zu machen, Fakten über die Hosts zu sammeln. Dies wird das Spiel beschleunigen, aber stellen Sie sicher, dass für keine der Aufgaben im Spiel Fakten über den Gastgeber benötigt werden.

Die erste Aufgabe im Stück validiert die Variable elk_version . Diese Variable stellt die Version des Elastic Stack dar, auf die wir aktualisieren. Das wird übergeben, wenn Sie den ansible-playbook-Befehl aufrufen. Wenn die Variable nicht übergeben wird oder kein gültiges Format hat, wird das Spiel sofort abgebrochen. Diese Aufgabe wird tatsächlich die erste Aufgabe in allen Stücken sein. Der Grund dafür ist, dass die Stücke, falls gewünscht oder notwendig, isoliert ausgeführt werden können.

Die zweite Aufgabe verwendet den Befehl rpm , um die aktuelle Version von Logstash abzurufen und in der Variablen version_found zu registrieren. Diese Informationen werden in der nächsten Aufgabe verwendet. Die Zeilen args: , warn: no und changed_when: False sind da, um ansible-lint glücklich zu machen, sind aber nicht unbedingt notwendig.

Die letzte Aufgabe führt den Befehl aus, der das Paket tatsächlich vorab herunterlädt. Aber nur, wenn die installierte Version von Logstash älter ist als die Zielversion. Nicht auf Download und ältere oder gleiche Version hinweisen, wenn sie nicht verwendet wird.

Die anderen beiden Spiele sind im Wesentlichen gleich, außer dass sie anstelle von Logstash Elasticsearch und Kibana vorab herunterladen:

 - hosts: elasticsearch gather_facts: no tasks: - name: Validate elasticsearch Version fail: msg="Invalid ELK Version" when: elk_version is undefined or not elk_version is match("\d+\.\d+\.\d+") - name: Get elasticsearch current version command: rpm -q elasticsearch --qf %{VERSION} args: warn: no changed_when: False register: version_found - name: Pre-download elasticsearch install package yum: name: elasticsearch-{{ elk_version }} download_only: yes when: version_found.stdout is version_compare(elk_version, '<') - hosts: kibana gather_facts: no tasks: - name: Validate kibana Version fail: msg="Invalid ELK Version" when: elk_version is undefined or not elk_version is match("\d+\.\d+\.\d+") - name: Get kibana current version command: rpm -q kibana --qf %{VERSION} args: warn: no changed_when: False register: version_found - name: Pre-download kibana install package yum: name: kibana-{{ elk_version }} download_only: yes when: version_found.stdout is version_compare(elk_version, '<')

Logstash-Upgrade

Logstash sollte die erste Komponente sein, die aktualisiert wird. Das liegt daran, dass Logstash garantiert mit einer älteren Version von Elasticsearch funktioniert.

Die ersten Aufgaben des Spiels sind identisch mit dem Gegenstück vor dem Download:

 - name: Upgrade logstash hosts: logstash gather_facts: no tasks: - name: Validate ELK Version fail: msg="Invalid ELK Version" when: elk_version is undefined or not elk_version is match("\d+\.\d+\.\d+") - name: Get logstash current version command: rpm -q logstash --qf %{VERSION} changed_when: False register: version_found

Die beiden letzten Aufgaben sind in einem Block enthalten:

 - block: - name: Update logstash yum: name: logstash-{{ elk_version }} state: present - name: Restart logstash systemd: name: logstash state: restarted enabled: yes daemon_reload: yes when: version_found.stdout is version_compare(elk_version, '<')

Die Bedingung when garantiert, dass die Aufgaben im Block nur ausgeführt werden, wenn die Zielversion neuer ist als die aktuelle Version. Die erste Aufgabe innerhalb des Blocks führt das Logstash-Upgrade durch und die zweite Aufgabe startet den Dienst neu.

Laufendes Upgrade des Elasticsearch-Clusters

Um sicherzustellen, dass es zu keinen Ausfallzeiten des Elasticsearch-Clusters kommt, müssen wir ein rollierendes Upgrade durchführen. Das bedeutet, dass wir jeweils einen Knoten aktualisieren und das Upgrade eines beliebigen Knotens erst starten, nachdem wir sichergestellt haben, dass sich der Cluster in einem grünen Zustand (vollständig fehlerfrei) befindet.

Ab dem Beginn des Stücks werden Sie etwas anderes bemerken:

 - name: Elasticsearch rolling upgrade hosts: elasticsearch gather_facts: no serial: 1

Hier haben wir die Zeile serial: 1 . Das Standardverhalten von Ansible besteht darin, das Spiel gegen mehrere Hosts parallel auszuführen, wobei die Anzahl der gleichzeitigen Hosts in der Konfiguration definiert ist. Diese Zeile stellt sicher, dass das Spiel immer nur gegen einen Host ausgeführt wird.

Als nächstes definieren wir einige Variablen, die während des Spiels verwendet werden sollen:

 vars: es_disable_allocation: '{"transient":{"cluster.routing.allocation.enable":"none"}}' es_enable_allocation: '{"transient":{"cluster.routing.allocation.enable": "all","cluster.routing.allocation.node_concurrent_recoveries": 5,"indices.recovery.max_bytes_per_sec": "500mb"}}' es_http_port: 9200 es_transport_port: 9300

Die Bedeutung jeder Variablen wird klar sein, wenn sie im Spiel erscheinen.

Wie immer besteht die erste Aufgabe darin, die Zielversion zu validieren:

 tasks: - name: Validate ELK Version fail: msg="Invalid ELK Version" when: elk_version is undefined or not elk_version is match("\d+\.\d+\.\d+")

Viele der folgenden Aufgaben bestehen darin, REST-Aufrufe für den Elasticsearch-Cluster auszuführen. Der Aufruf kann gegen jeden der Knoten ausgeführt werden. Sie könnten es einfach für den aktuellen Host im Spiel ausführen, aber einige der Befehle werden ausgeführt, während der Elasticsearch-Dienst für den aktuellen Host ausgefallen ist. Daher stellen wir in den nächsten Aufgaben sicher, dass Sie einen anderen Host auswählen, für den die REST-Aufrufe ausgeführt werden. Dazu verwenden wir das Modul set_fact und die Variable groups aus dem Ansible-Inventar.

 - name: Set the es_host for the first host set_fact: es_host: "{{ groups.elasticsearch[1] }}" when: "inventory_hostname == groups.elasticsearch[0]" - name: Set the es_host for the remaining hosts set_fact: es_host: "{{ groups.elasticsearch[0] }}" when: "inventory_hostname != groups.elasticsearch[0]"

Als Nächstes stellen wir sicher, dass der Dienst im aktuellen Knoten aktiv ist, bevor wir fortfahren:

 - name: Ensure elasticsearch service is running systemd: name: elasticsearch enabled: yes state: started register: response - name: Wait for elasticsearch node to come back up if it was stopped wait_for: port: "{{ es_transport_port }}" delay: 45 when: response.changed == true

Wie in den vorherigen Stücken werden wir die aktuelle Version überprüfen. Abgesehen von dieser Zeit verwenden wir die Elasticsearch-REST-API, anstatt das RPM auszuführen. Wir hätten auch den rpm-Befehl verwenden können, aber ich möchte diese Alternative zeigen.

 - name: Check current version uri: url: http://localhost:{{ es_http_port }} method: GET register: version_found retries: 10 delay: 10

Die verbleibenden Aufgaben befinden sich in einem Block, der nur ausgeführt wird, wenn die aktuelle Version älter als die Zielversion ist:

 - block: - name: Enable shard allocation for the cluster uri: url: http://localhost:{{ es_http_port }}/_cluster/settings method: PUT body_format: json body: "{{ es_enable_allocation }}"

Wenn Sie nun meinem Rat gefolgt sind und die Dokumentation gelesen haben, werden Sie bemerkt haben, dass dieser Schritt das Gegenteil sein sollte: die Shard-Zuweisung zu deaktivieren. Ich stelle diese Aufgabe hier gerne zuerst, falls die Shards zuvor aus irgendeinem Grund deaktiviert wurden. Dies ist wichtig, da die nächste Aufgabe darauf wartet, dass der Cluster grün wird. Wenn die Shard-Zuweisung deaktiviert ist, bleibt der Cluster gelb und die Aufgaben bleiben hängen, bis das Zeitlimit überschritten wird.

Nachdem wir also sichergestellt haben, dass die Shard-Zuweisung aktiviert ist, stellen wir sicher, dass sich der Cluster in einem grünen Zustand befindet:

 - name: Wait for cluster health to return to green uri: url: http://localhost:{{ es_http_port }}/_cluster/health method: GET register: response until: "response.json.status == 'green'" retries: 500 delay: 15

Nach einem Neustart des Knotendienstes kann es lange dauern, bis der Cluster wieder grün wird. Das ist der Grund für die Zeilen retries: 500 und delay: 15 . Das bedeutet, dass wir 125 Minuten (500 x 15 Sekunden) warten, bis der Cluster wieder grün wird. Möglicherweise müssen Sie dies anpassen, wenn Ihre Knoten eine wirklich große Datenmenge enthalten. Für die meisten Fälle ist es mehr als genug.

Jetzt können wir die Shard-Zuweisung deaktivieren:

 - name: Disable shard allocation for the cluster uri: url: http://localhost:{{ es_http_port }}/_cluster/settings method: PUT body_format: json body: {{ es_disable_allocation }}

Und bevor wir den Dienst herunterfahren, führen wir die optionale, aber empfohlene Synchronisierungsspülung aus. Es ist nicht ungewöhnlich, einen 409-Fehler für einige der Indizes zu erhalten, wenn wir einen Sync-Flush durchführen. Da dies sicher ignoriert werden kann, habe ich 409 zur Liste der Erfolgsstatuscodes hinzugefügt.

 - name: Perform a synced flush uri: url: http://localhost:{{ es_http_port }}/_flush/synced method: POST status_code: "200, 409"

Jetzt kann dieser Knoten aktualisiert werden:

 - name: Shutdown elasticsearch node systemd: name: elasticsearch state: stopped - name: Update elasticsearch yum: name: elasticsearch-{{ elk_version }} state: present

Wenn der Dienst gestoppt ist, warten wir, bis alle Shards zugewiesen sind, bevor wir den Knoten erneut starten:

 - name: Wait for all shards to be reallocated uri: url=http://{{ es_host }}:{{ es_http_port }}/_cluster/health method=GET register: response until: "response.json.relocating_shards == 0" retries: 20 delay: 15

Nachdem die Shards neu zugewiesen wurden, starten wir den Elasticsearch-Dienst neu und warten, bis er vollständig bereit ist:

 - name: Start elasticsearch systemd: name: elasticsearch state: restarted enabled: yes daemon_reload: yes - name: Wait for elasticsearch node to come back up wait_for: port: "{{ es_transport_port }}" delay: 35 - name: Wait for elasticsearch http to come back up wait_for: port: "{{ es_http_port }}" delay: 5

Jetzt stellen wir sicher, dass der Cluster gelb oder grün ist, bevor wir die Shard-Zuweisung erneut aktivieren:

 - name: Wait for cluster health to return to yellow or green uri: url: http://localhost:{{ es_http_port }}/_cluster/health method: GET register: response until: "response.json.status == 'yellow' or response.json.status == 'green'" retries: 500 delay: 15 - name: Enable shard allocation for the cluster uri: url: http://localhost:{{ es_http_port }}/_cluster/settings method: PUT body_format: json body: "{{ es_enable_allocation }}" register: response until: "response.json.acknowledged == true" retries: 10 delay: 15

Und wir warten, bis sich der Knoten vollständig erholt hat, bevor wir den nächsten verarbeiten:

 - name: Wait for the node to recover uri: url: http://localhost:{{ es_http_port }}/_cat/health method: GET return_content: yes register: response until: "'green' in response.content" retries: 500 delay: 15

Wie ich bereits sagte, sollte dieser Block natürlich nur ausgeführt werden, wenn wir die Version wirklich aktualisieren:

 when: version_found.json.version.number is version_compare(elk_version, '<')

Kibana-Upgrade

Die letzte zu aktualisierende Komponente ist Kibana.

Wie zu erwarten, unterscheiden sich die ersten Aufgaben nicht vom Logstash-Upgrade oder den Pre-Download-Spielen. Bis auf die Definition einer Variablen:

 - name: Upgrade kibana hosts: kibana gather_facts: no vars: set_default_index: '{"changes":{"defaultIndex":"syslog"}}' tasks: - name: Validate ELK Version fail: msg="Invalid ELK Version" when: elk_version is undefined or not elk_version is match("\d+\.\d+\.\d+") - name: Get kibana current version command: rpm -q kibana --qf %{VERSION} args: warn: no changed_when: False register: version_found

Ich werde die Variable set_default_index erklären, wenn wir zu der Aufgabe kommen, die sie verwendet.

Die verbleibenden Aufgaben befinden sich in einem Block, der nur ausgeführt wird, wenn die installierte Version von Kibana älter als die Zielversion ist. Die ersten beiden Aufgaben aktualisieren und starten Kibana neu:

 - name: Update kibana yum: name: kibana-{{ elk_version }} state: present - name: Restart kibana systemd: name: kibana state: restarted enabled: yes daemon_reload: yes

Und für Kibana hätte das reichen sollen. Leider verliert Kibana aus irgendeinem Grund nach dem Upgrade seinen Verweis auf sein Standardindexmuster. Dies führt dazu, dass der erste Benutzer, der nach dem Upgrade darauf zugreift, aufgefordert wird, das Standardindexmuster zu definieren, was zu Verwirrung führen kann. Um dies zu vermeiden, stellen Sie sicher, dass Sie eine Aufgabe zum Zurücksetzen des Standardindexmusters hinzufügen. Im Beispiel unten ist es syslog , aber Sie sollten es in das ändern, was Sie verwenden. Bevor wir den Index setzen, müssen wir jedoch sicherstellen, dass Kibana aktiv und bereit ist, Anfragen zu bedienen:

 - name: Wait for kibana to start listening wait_for: port: 5601 delay: 5 - name: Wait for kibana to be ready uri: url: http://localhost:5601/api/kibana/settings method: GET register: response until: "'kbn_name' in response and response.status == 200" retries: 30 delay: 5 - name: Set Default Index uri: url: http://localhost:5601/api/kibana/settings method: POST body_format: json body: "{{ set_default_index }}" headers: "kbn-version": "{{ elk_version }}"

Fazit

Der Elastic Stack ist ein wertvolles Werkzeug und ich empfehle Ihnen auf jeden Fall, einen Blick darauf zu werfen, wenn Sie ihn noch nicht verwenden. Es ist großartig wie es ist und wird ständig verbessert, so sehr, dass es schwierig sein könnte, mit den ständigen Upgrades Schritt zu halten. Ich hoffe, dass diese Ansible Playbooks für Sie genauso nützlich sind wie für mich.

Ich habe sie auf GitHub unter https://github.com/orgito/elk-upgrade zur Verfügung gestellt. Ich empfehle, dass Sie es in einer Nicht-Produktionsumgebung testen.

Wenn Sie ein Ruby on Rails-Entwickler sind, der Elasticsearch in Ihre App integrieren möchte, sehen Sie sich Elasticsearch for Ruby on Rails: A Tutorial to the Chewy Gem von Core Toptal Software Engineer Arkadiy Zabazhanov an.