Elasticsearch¶
Siehe auch
- Verwandte Artikel
- Offizielle Dokumentation
- Linuxfabrik
Elasticsearch ist eine Such- und Analyse-Engine auf Basis von Apache Lucene. Sie speichert Daten als JSON-Dokumente, verteilt sie über ein Cluster und stellt eine REST-Schnittstelle für Indizierung und Suche bereit. Elasticsearch ist der Kern des Elastic Stack (zusammen mit Kibana, Logstash und Elastic Agent). OpenSearch ist 2021 als Fork daraus entstanden; Aufbau und API sind weitgehend deckungsgleich (siehe Vergleich zwischen OpenSearch und Elasticsearch).
Begriffe¶
Index: Sammlung an „Dokumenten“, wobei ein Dokument ein JSON-Objekt ist. Analogie zu Datenbanken: alle Studenten aus einer Tabelle. Zusätzlich definiert ein Index über das Mapping, wie Felder analysiert und gespeichert werden.
Shard: Ein Index wird in Häppchen (Shards) aufgeteilt und gleichmässig im Cluster verteilt. Shards dienen der Lastverteilung und ermöglichen die Parallelarbeit an Such- und Schreiboperationen. Ein Shard ist ein vollständiger Lucene-Index und belegt CPU- und RAM-Ressourcen. In der Regel sollte Elasticsearch jedem Node die „Anzahl Shards im Index“ geteilt durch „Anzahl Nodes“ zuweisen. Shards sollten in der Praxis zwischen 10 und maximal 40 GB gross werden und nicht mehr als 200 Millionen Dokumente enthalten.
Shard Replica: Backup-Kopie für den Ausfall eines Nodes, dient zusätzlich dem Lastbalancing bei Suchanfragen.
Sharding / Shard Allocation:
Elasticsearch platziert Replica Shards nach Möglichkeit auf andere Nodes als die zugehörigen Primary Shards. Sind alle Primaries zugewiesen, aber nicht alle Replicas, wird der Clusterstatus gelb.
Dokumente werden anhand eines Routing-Algorithmus auf die Shards verteilt:
shard_number = hash(id) % number_of_shards. So landen identische Routing-Werte immer im selben Primary Shard.Die Anzahl der Primary Shards (
index.number_of_shards) wird bei der Indexerstellung festgelegt und kann später nicht geändert werden, da die Dokumente sonst im falschen Shard gesucht bzw. abgelegt würden. Anpassungen erfordern einen neuen Index (z.B. per Reindex).Die Anzahl der Replica (
index.number_of_replicas) lässt sich dagegen zur Laufzeit pro Index ändern.Falls mehrere Nodes gleichzeitig ausfallen könnten (z.B. weil sie auf dem gleichen Hypervisor oder im gleichen Rechenzentrum laufen), sollten sie in Zonen gruppiert werden. Diese werden dann bei der Shard Allocation berücksichtigt.
Berechnung des Speichervolumens:
Diskgrösse im Cluster ist ungefähr
Tagesvolumen_GB × Retention_Tage × Replikationsfaktor × OverheadBeispiel mit 50 GB/Tag, 90 Tage Retention Time,
number_of_replicas: 1und 3 Nodes:Rohdaten: 50 GB/Tag × 90 Tage = 4500 GB
Replikationsfaktor bei
number_of_replicas: 1ist ungefähr 2.0 (Primary + Replica)Overhead (Index-Struktur, Segment-Metadaten, Lösch-Markierungen, ILM usw.) ist ungefähr 1.1 bis 1.3
Ergibt ca. 10 TB Daten für den gesamten Cluster
Verteilt auf 3 Nodes: ungefähr je 3.3 TB Netto-Daten pro Node
Da Platten typischerweise nicht über 70 bis 75 % vollgeschrieben werden sollten, ergeben sich in der Praxis 4 bis 6 TB nutzbare Disk pro Node.
Vergleich zwischen OpenSearch und Elasticsearch¶
OpenSearch erschien 2021 unter der Apache License 2.0 als Fork von Elasticsearch 7.10.2. Die Entwicklung wird von Amazon AWS angeführt. OpenSearch und Elasticsearch entwickeln sich seit dem Fork auseinander. Software-Produkte wie Graylog unterstützen oft beide, verweisen dann aber auf explizit einzusetzende Versionen, um eine gewisse Kompatibilität sicherzustellen.
EOL-Dates:
Elasticsearch: https://endoflife.date/elasticsearch
OpenSearch: https://endoflife.date/opensearch
Features:
Da beide auf Lucene basieren, wird alles von der Indizierung und Zusammenführung von Dokumenten bis hin zu Ähnlichkeiten und Filter-Caches unterstützt. Aktualisieren beide auf neuere Lucene-Versionen, übernehmen beide dieselben Verbesserungen und Bugfixes. Neben Lucene gibt es gemeinsame Funktionen aus Elasticsearch 7.10.2, auf dem OpenSearch ursprünglich basiert. Da sich beide getrennt weiterentwickeln, wird immer mehr dieses Codes durch neue Entwicklungen ersetzt.
Funktionen wie Authentifizierung, Autorisierung, Indexverwaltung und Alarmierung waren in Elasticsearch proprietär, weshalb OpenSearch Open-Source-Alternativen implementiert hat. Während Elasticsearch über Index Lifecycle Management verfügt, bietet OpenSearch Index State Management. Im Grossen tun sie das Gleiche, der Unterschied liegt in den (sich häufiger ändernden) Details. Nicht alle Funktionen in Elasticsearch sind frei: Index Lifecycle Management ist kostenlos, Cross-Cluster Replication oder LDAP/OpenID/SAML-Authentication nicht (siehe Subscriptions Page). Funktionen, die in OpenSearch kostenlos enthalten sind, in Elasticsearch aber nicht: IP-Filtering, konfigurierbare Retention, Anomaly Detection, Tableau Connector, JDBC- und ODBC-Treiber sowie Machine-Learning-Features.
Beide bieten inzwischen unterschiedliche Funktionen. Elasticsearch hat Zeitreihendatenströme, OpenSearch hat die Segmentreplikation wieder eingeführt.
„Searchable Snapshots“ sind in Elasticsearch länger und in OpenSearch seit 2.7 produktiv: eine „Offline“-Suchfunktion, die die Hardware für ältere, selten abgerufene Daten erheblich reduziert. In Elasticsearch kostet das Feature, in OpenSearch ist es kostenlos.
Aktuelle Elastic-Komponenten wie Logstash, Beats und Client-Bibliotheken prüfen, ob das Ziel ein Elasticsearch ist, und verweigern die Zusammenarbeit mit OpenSearch. OpenSearch stellt sich dem mit dem Projekt Data Prepper entgegen.
Security:
OpenSearch bietet die gleichen Security-Features wie das Premium-Level von Elasticsearch, aber komplett frei. Das Security-Modul von OpenSearch wird vollständig offen entwickelt und beherrscht Active Directory und LDAP, SAML, OpenID, Zugriffskontrolle inklusive Maskierung und Sicherheit auf Feldebene, Audit-Protokolle und Verschlüsselung. Dazu kommt das Security Analytics Plugin, eine SIEM-Lösung speziell für OpenSearch.
Lizenz:
Die Elastic License ist nicht von der Open Source Initiative (OSI) zertifiziert und untersagt unter anderem den Einsatz als as-a-Service.
OpenSearch steht unter der Apache-Lizenz, dem kommerziellen Einsatz steht damit nichts im Weg.
Installation¶
Elasticsearch-Repo einrichten und installieren:
rpm --import https://artifacts.elastic.co/GPG-KEY-elasticsearch
[elasticsearch]
name=Elasticsearch repository for 9.x packages
baseurl=https://artifacts.elastic.co/packages/9.x/yum
gpgcheck=1
gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
enabled=1
dnf --assumeyes install elasticsearch
Beim ersten Installieren konfiguriert Elasticsearch die Security automatisch: es generiert TLS-Zertifikate unter /etc/elasticsearch/certs/ (darunter http_ca.crt) und gibt einmalig das Passwort des Superusers elastic sowie einen Kibana-Enrollment-Token aus. Das Passwort lässt sich jederzeit neu setzen:
/usr/share/elasticsearch/bin/elasticsearch-reset-password --username elastic
Bemerkung
Eine separate Java-Runtime ist nicht nötig, Elasticsearch bringt sein JDK mit, siehe /usr/share/elasticsearch/jdk/bin/java -version.
Konfiguration¶
Mindestens die JVM-Options an die RAM-Grösse der Maschine anpassen (Faustregel: halber Arbeitsspeicher, maximal etwa 31 GB):
# update the Xms and Xmx settings with half of the installed system memory
-Xms3g
-Xmx3g
Cluster-Name anpassen, er muss unternehmensweit eindeutig sein:
cluster.name: graylog-linuxfabrik
Optional Bind-Adresse und Port anpassen. Achtung: Wird eine externe IP-Adresse angegeben, sind weitere Security-Konfigurationen nötig, sonst schlagen die „bootstrap checks“ beim Start mit einer node validation exception fehl.
# bind Elasticsearch to a specific interface; use 0.0.0.0 for all interfaces
network.host: 0.0.0.0
Bei einem Single-Node-Setup:
# avoids the bootstrap checks failing on a single node
discovery.type: single-node
Kernel-Parameter setzen:
# this is already the default, just to be sure:
sysctl --write vm.max_map_count=262144
echo 'vm.max_map_count=262144' > /etc/sysctl.d/elasticsearch.conf
Elasticsearch starten:
systemctl daemon-reload
systemctl enable --now elasticsearch.service
Test (HTTPS mit dem generierten CA-Zertifikat):
curl --cacert /etc/elasticsearch/certs/http_ca.crt \
--user "elastic:${ELASTIC_PASSWORD}" \
https://localhost:9200
Elastic Agent und Fleet¶
Elastic Agent ist ein einzelnes Programm, das auf jedem überwachten Host läuft. Es sammelt Logs, Metriken und weitere Daten und schickt sie an Elasticsearch oder Logstash. Ein Elastic Agent bündelt das, was früher mehrere einzelne Beats (Filebeat, Metricbeat und so weiter) erledigt haben.
Fleet ist die zentrale Verwaltung dieser Agents, umgesetzt als Oberfläche in Kibana (https://kibana.example.com/app/fleet). Statt jeden Host einzeln zu konfigurieren, definiert man in Fleet Agent Policies und weist sie den Agents zu. Fleet verteilt Änderungen an alle eingebundenen (enrolled) Agents. Ein Agent kann auch ohne Fleet laufen (Standalone-Modus mit lokaler Konfigurationsdatei), der Normalfall ist aber die zentrale Verwaltung über Fleet.
Fleet Server ist das Bindeglied zwischen Fleet und den Agents. Er ist selbst ein Elastic Agent, der die Integration fleet-server ausführt. Die übrigen Agents verbinden sich mit ihm: Sie holen dort ihre Policy ab und melden ihren Status. Diesen Zustand legt der Fleet Server in Elasticsearch ab. So braucht Kibana keine direkte Verbindung zu jedem einzelnen Host.
- Begriffe
Agent Policy: Satz von Regeln für einen Agent: welche Daten gesammelt werden und wohin sie gehen. Eine Policy enthält eine oder mehrere Integrations und kann mehreren Agents zugewiesen sein.
Integration: legt fest, wie eine bestimmte Quelle überwacht wird, etwa eine Logdatei oder ein Programm wie Elasticsearch oder Logstash. Mehrere Integrations bilden zusammen eine Agent Policy.
Zwei Verbindungswege sind zu trennen. Über die Steuerung verteilt der Fleet Server die Policies und sammelt den Status ein, die eigentlichen Logs und Metriken schickt jeder Agent dagegen direkt an Elasticsearch (oder Logstash), nicht über den Fleet Server.
Steuerung (Policies, Status):
Admin --> Kibana/Fleet --> Fleet Server <--> Elastic Agent (pro Host)
|
v
Elasticsearch (Policies und Status)
Daten (Logs, Metriken):
Elastic Agent --> Elasticsearch (oder Logstash)
Initiales Setup¶
Voraussetzung: Elastic-Repo, Elasticsearch und Kibana sind eingerichtet. Zuerst wird der Fleet Server eingerichtet, danach die Elastic Agents. Fleet bringt dafür die vordefinierte Policy „Fleet Server Policy 1“ (id fleet-server-policy) mit.
Fleet Server Host. Unter
https://kibana.example.com/app/fleet/settings> „Fleet server hosts“: bei Authentication > Fleet Server > Elastic Agents certificate authorities das ASCII-armored CA-Zertifikat einfügen.Outputs. Unter
https://kibana.example.com/app/fleet/settings> „Outputs“: alsdefaultOutput alle Elasticsearch-Hosts eintragen. Bei Server SSL certificate authorities das ASCII-armored CA-Zertifikat einfügen.Server-Zertifikat generieren. Das erzeugt ein ZIP-Archiv mit
fleet-server-01.{crt,key}. Diese vor der Installation des Fleet Servers auf den Host kopieren./usr/share/elasticsearch/bin/elasticsearch-certutil cert \ --name fleet-server-01 \ --ca-cert /etc/elasticsearch/ca/ca.crt \ --ca-key /etc/elasticsearch/ca/ca.key \ --dns localhost,fleet-server-01,fleet-server-01.example.com \ --ip 127.0.0.1,192.0.2.10 \ --days 3600 \ --pem \ --out /tmp/fleet-server-01.zip
Fleet Server enrollen. Unter
https://kibana.example.com/app/fleet/agents> „Add Fleet Server“:Advanced
Fleet Policy: „Fleet Server Policy 1“ (bei Bedarf „Create new agent policy“)
Deployment mode for security: „Production“
Fleet Server Host: Hostname und Port des Fleet Servers, der neu enrolled wird
Service Token generieren
Fleet Server auf dem Host installieren. Der
servers-Flavor zieht diefleet-server-Komponente mit, die seit Elastic Agent 9.0 nicht mehr im Standard-Paket enthalten ist.# 'servers' flavor includes fleet-server (required since Elastic Agent 9.0) ELASTIC_AGENT_FLAVOR=servers dnf --assumeyes install elastic-agent elastic-agent enroll \ --url='https://fleet-server-01.example.com:8220' \ --certificate-authorities=/path/to/elasticsearch-ca.crt \ --fleet-server-es-ca=/path/to/elasticsearch-ca.crt \ --fleet-server-es='https://elastic-node-01.example.com:9200' \ --fleet-server-service-token='<SERVICE_TOKEN>' \ --fleet-server-policy='fleet-server-policy' \ --fleet-server-port=8220 \ --fleet-server-cert=/path/to/fleet-server-01.crt \ --fleet-server-cert-key=/path/to/fleet-server-01.key systemctl enable --now elastic-agent
Warten, bis „Confirm connection“ erfolgreich ist. Klappt das nicht, lässt sich der Status auf dem Host abfragen:
elastic-agent status --output=full
Elastic Agent enrollen. Unter
https://kibana.example.com/app/fleet/agents> „Add agent“:Agent Policy: „Agent Policy 1“ (bei Bedarf „Create new agent policy“)
Enroll in fleet. Ein normaler Agent braucht den
servers-Flavor nicht und verwendet einen Enrollment Token (nicht den Service Token des Fleet Servers).dnf --assumeyes install elastic-agent elastic-agent enroll \ --url='https://fleet-server-01.example.com:8220' \ --enrollment-token='<ENROLLMENT_TOKEN>' \ --certificate-authorities=/path/to/fleet-ca.crt systemctl enable --now elastic-agent
Zustand der Agents in Fleet prüfen. Unter
https://kibana.example.com/app/fleet/agents: Status „Healthy“, dann auf den Host klicken > „Agent Details“ > „Integrations“.
Agent Policy erstellen und ausrollen¶
Mit Fleet werden die Policies für Elastic Agent und Fleet Server über Kibana verwaltet. Änderungen propagiert Fleet automatisch an die Hosts.
https://kibana.example.com/app/fleet/policies> „Create agent policy“Gewünschte Integrations hinzufügen
https://kibana.example.com/app/fleet/agents: „Elastic Agent Host“ > „Actions“ > „Assign to new Policy“
Kibana¶
Kibana ist die Weboberfläche von Elasticsearch zum Visualisieren, Durchsuchen und Verwalten der Daten. Kibana hostet ausserdem die Fleet-Oberfläche zur Verwaltung der Elastic Agents und ist standardmässig auf Port 5601 erreichbar.
API-Calls¶
Referenz: https://www.elastic.co/docs/api/doc/elasticsearch/
Allgemeine Optionen: https://www.elastic.co/docs/reference/elasticsearch/rest-apis/common-options#common-options-response-filtering
elastic_host=localhost
elastic_cacert=/etc/elasticsearch/certs/http_ca.crt
# list all nodes and their roles
curl --cacert "$elastic_cacert" \
--user "elastic:${ELASTIC_PASSWORD}" \
--request GET "https://$elastic_host:9200/_cat/nodes?v&h=name,ip,node.role" \
--header "Content-Type: application/json"
# disk size used by *just* the primaries
curl --cacert "$elastic_cacert" \
--user "elastic:${ELASTIC_PASSWORD}" \
--request GET "https://$elastic_host:9200/_stats/store?filter_path=indices.*.primaries.store.size_in_bytes" \
--header "Content-Type: application/json" \
| jq '[.indices[].primaries.store.size_in_bytes] | add'
# list all shards on node1
curl --cacert "$elastic_cacert" \
--user "elastic:${ELASTIC_PASSWORD}" \
--request GET "https://$elastic_host:9200/_cat/shards" \
--header "Content-Type: application/json" | grep node1 | cut -d' ' -f1
# manually move a shard to a different node (the automatic allocation might move it back)
curl --cacert "$elastic_cacert" \
--user "elastic:${ELASTIC_PASSWORD}" \
--request POST "https://$elastic_host:9200/_cluster/reroute" \
--header "Content-Type: application/json" --data '
{
"commands": [
{
"move": {
"index": "lfops-default_900",
"shard": 3,
"from_node": "node1",
"to_node": "node3"
}
}
]
}'
# obtain cluster uuid
curl --cacert "$elastic_cacert" \
--user "elastic:${ELASTIC_PASSWORD}" \
--request GET "https://$elastic_host:9200/" \
--header "Content-Type: application/json" | jq --raw-output '.cluster_uuid'
Cluster-Neustart¶
Das Vorgehen ist bei einem Rolling Restart und bei einem kompletten Cluster-Restart das gleiche.
Replica Shard Allocation deaktivieren:
curl --cacert "$elastic_cacert" \ --user "elastic:${ELASTIC_PASSWORD}" \ --request PUT "https://$elastic_host:9200/_cluster/settings" \ --header "Content-Type: application/json" \ --data ' { "persistent": { "cluster.routing.allocation.enable": "primaries" } }'
Falls das Cluster
mlNodes enthält:Bemerkung
Eine der möglichen Optionen auswählen und bei 6. gleich verfahren.
Existieren mehrere
mlNodes mit ausreichend Ressourcen, kann dieser Schritt sowie 6. übersprungen werden. Die Anomaly Detection Jobs werden dann auf verbleibendeml-Nodes verschoben.Beim Upgrade Mode werden die Anomaly Detection Jobs abgebrochen und nach Beendigung vom letzten Checkpoint wiederhergestellt. Das dauert weniger lange, als die Jobs von Hand zu schliessen und wieder zu öffnen.
Upgrade Mode aktivieren, dann gestartete Datafeeds stoppen und offene Anomaly Detection Jobs schliessen:
curl --cacert "$elastic_cacert" \ --user "elastic:${ELASTIC_PASSWORD}" \ --request POST "https://$elastic_host:9200/_ml/set_upgrade_mode?enabled=true" \ --header "Content-Type: application/json" # stop all datafeeds curl --cacert "$elastic_cacert" \ --user "elastic:${ELASTIC_PASSWORD}" \ --request POST "https://$elastic_host:9200/_ml/datafeeds/_all/_stop" \ --header "Content-Type: application/json" # close all anomaly detection jobs curl --cacert "$elastic_cacert" \ --user "elastic:${ELASTIC_PASSWORD}" \ --request POST "https://$elastic_host:9200/_ml/anomaly_detectors/_all/_close" \ --header "Content-Type: application/json"
(Rolling) Restart durchführen. In der Zeit ist es normal, dass der Cluster Health gelb ist.
Warten, bis alle Nodes wieder verfügbar sind.
Replica Shard Allocation wieder aktivieren:
curl --cacert "$elastic_cacert" \ --user "elastic:${ELASTIC_PASSWORD}" \ --request PUT "https://$elastic_host:9200/_cluster/settings" \ --header "Content-Type: application/json" \ --data ' { "persistent": { "cluster.routing.allocation.enable": null } }'
Falls das Cluster
mlNodes enthält (dieselbe Option wie bei 2.): Upgrade Mode deaktivieren, danach die Anomaly Detection Jobs öffnen und Datafeeds starten.curl --cacert "$elastic_cacert" \ --user "elastic:${ELASTIC_PASSWORD}" \ --request POST "https://$elastic_host:9200/_ml/set_upgrade_mode?enabled=false" \ --header "Content-Type: application/json"
Troubleshooting¶
- Herausfinden, warum Shards „unassigned“ sind
curl --cacert "$elastic_cacert" \ --user "elastic:${ELASTIC_PASSWORD}" \ --request GET "https://$elastic_host:9200/_cluster/allocation/explain?pretty=true" \ --header "Content-Type: application/json"
number_of_replicasbei einem Managed Index Template anpassenDas Template sollte nicht direkt angepasst werden, da es z.B. vom Fleet Manager administriert wird. Stattdessen gibt es normalerweise ein
<index name>@customComponent Template, z.B.kibana_sample_data_logs@custom. Fehlt es, kann ein leeres Component Template erstellt und im Index Template importiert werden (Achtung: die Reihenfolge der Component Templates spielt eine Rolle).index_name='kibana_sample_data_logs' curl --cacert "$elastic_cacert" \ --user "elastic:${ELASTIC_PASSWORD}" \ --request PUT "https://$elastic_host:9200/_component_template/$index_name%40custom?pretty=true" \ --header "Content-Type: application/json" \ --data @- << 'EOF' { "template": { "settings": { "index": { "number_of_replicas": "3" } } } } EOF
Mit folgendem API-Call lässt sich die Erstellung eines neuen Indexes simulieren und die vererbten Einstellungen prüfen:
index_name='kibana_sample_data_logs' curl --cacert "$elastic_cacert" \ --user "elastic:${ELASTIC_PASSWORD}" \ --request POST "https://$elastic_host:9200/_index_template/_simulate_index/$index_name" \ --header "Content-Type: application/json" | jq | grep number_of_replicas
- Elastic Agent wird als
unhealthyangezeigt Den Zustand auf dem betroffenen Agent abfragen.
--outputakzeptierthuman(Standard),full,jsonundyaml:elastic-agent status elastic-agent status --output=full