Der erfolgreiche Betrieb von OpenSearch erfordert mehr als nur technisches Wissen - es braucht Erfahrung und ein tiefes Verständnis dafür, wie verschiedene Systemkomponenten zusammenwirken. In diesem Kapitel behandeln wir umfassende Best Practices, die Ihnen helfen, zuverlässige, leistungsfähige und wartbare OpenSearch-Deployments aufzubauen und zu betreiben.
Die Grundlage eines erfolgreichen OpenSearch-Deployments liegt in seiner Architektur. Denken Sie beim Design eines OpenSearch-Clusters wie bei der Stadtplanung - Sie müssen aktuelle Anforderungen berücksichtigen und gleichzeitig für zukünftiges Wachstum planen, Ressourcen effizient nutzen und Flexibilität für Veränderungen bewahren.
Beginnen wir mit einer der grundlegendsten Entscheidungen: der richtigen Dimensionierung Ihres Clusters. Hier ein Beispiel für eine gut dimensionierte Cluster-Konfiguration:
PUT _cluster/settings
{
"persistent": {
"cluster.routing.allocation.disk.threshold_enabled": true,
"cluster.routing.allocation.disk.watermark.low": "85%",
"cluster.routing.allocation.disk.watermark.high": "90%",
"cluster.routing.allocation.disk.watermark.flood_stage": "95%",
"cluster.routing.allocation.awareness.attributes": "zone",
"cluster.routing.allocation.balance.shard": 0.7,
"cluster.routing.allocation.balance.index": 0.6
}
}
Diese Einstellungen spiegeln wichtige Prinzipien wider:
Für die Berechnung der Ressourcenanforderungen können Sie folgende Formel verwenden:
def berechne_cluster_ressourcen(taegliches_datenvolumen_gb, aufbewahrungstage, replikationsfaktor):
"""
Berechnet die erforderlichen Cluster-Ressourcen basierend auf Datenvolumen und Aufbewahrung.
Parameter:
taegliches_datenvolumen_gb: Tägliche Datenaufnahme in GB
aufbewahrungstage: Anzahl der Tage zur Datenaufbewahrung
replikationsfaktor: Anzahl der Replikate + 1
Rückgabe:
Dictionary mit Ressourcenanforderungen
"""
# Berechne Gesamtspeicherbedarf
gesamtspeicher_gb = taegliches_datenvolumen_gb * aufbewahrungstage * replikationsfaktor
# 20% Puffer für Overhead und Wachstum
gesamtspeicher_mit_puffer = gesamtspeicher_gb * 1.2
# Berechne Anzahl der Shards (Ziel: ~30GB pro Shard)
empfohlene_shards = math.ceil(gesamtspeicher_gb / 30)
# Berechne Mindestanzahl an Knoten
min_knoten = math.ceil(empfohlene_shards / 25) # Max 25 Shards pro Knoten
return {
"gesamtspeicher_gb": gesamtspeicher_mit_puffer,
"empfohlene_shards": empfohlene_shards,
"mindest_knoten": min_knoten,
"empfohlene_knoten": min_knoten + 2 # Puffer für Redundanz
}Ein gutes Index-Design ist entscheidend für langfristigen Erfolg. Hier ein Beispiel für ein gut strukturiertes Index-Template:
PUT _index_template/logs_template
{
"index_patterns": ["logs-*"],
"template": {
"settings": {
"number_of_shards": "{{ knoten * 2 }}",
"number_of_replicas": 1,
"index.lifecycle.name": "logs_policy",
"index.mapping.total_fields.limit": 1000,
"index.refresh_interval": "30s",
"index.translog.durability": "async",
"index.translog.sync_interval": "5s"
},
"mappings": {
"dynamic_templates": [
{
"strings_als_keywords": {
"match_mapping_type": "string",
"mapping": {
"type": "keyword",
"ignore_above": 256
}
}
}
],
"properties": {
"@timestamp": { "type": "date" },
"nachricht": {
"type": "text",
"norms": false
},
"level": { "type": "keyword" }
}
}
}
}
Dieses Template verkörpert mehrere wichtige Prinzipien:
Eine effektive Datenverwaltung in OpenSearch erfordert sorgfältige Überlegungen zum Datenfluss, von der Aufnahme bis zur Archivierung.
Hier ein Beispiel einer optimierten Ingestion-Pipeline:
PUT _ingest/pipeline/logs_pipeline
{
"description": "Optimierte Log-Verarbeitungspipeline",
"processors": [
{
"date": {
"field": "timestamp",
"formats": ["ISO8601", "UNIX"],
"target_field": "@timestamp"
}
},
{
"script": {
"source": """
// Normalisierung der Log-Level
def level = ctx.level.toLowerCase();
if (level.contains('warn')) {
ctx.level = 'warnung';
} else if (level.contains('err')) {
ctx.level = 'fehler';
} else if (level.contains('info')) {
ctx.level = 'info';
} else {
ctx.level = 'unbekannt';
}
"""
}
},
{
"set": {
"field": "_meta.eingangszeit",
"value": "{{_ingest.timestamp}}"
}
}
]
}
Eine gut durchdachte ILM-Policy hilft bei der Verwaltung von Daten über ihren gesamten Lebenszyklus:
PUT _ilm/policy/logs_policy
{
"policy": {
"phases": {
"hot": {
"min_age": "0ms",
"actions": {
"rollover": {
"max_size": "50GB",
"max_age": "1d"
},
"set_priority": {
"priority": 100
}
}
},
"warm": {
"min_age": "2d",
"actions": {
"forcemerge": {
"max_num_segments": 1
},
"allocate": {
"require": {
"data": "warm"
}
},
"set_priority": {
"priority": 50
}
}
},
"cold": {
"min_age": "30d",
"actions": {
"allocate": {
"require": {
"data": "cold"
}
},
"set_priority": {
"priority": 0
}
}
},
"delete": {
"min_age": "90d",
"actions": {
"delete": {}
}
}
}
}
}
Performance-Optimierung in OpenSearch bedeutet, Ressourcen effektiv zu verstehen und zu verwalten.
Hier ein Beispiel optimierter JVM-Einstellungen:
# jvm.options
-Xms31g
-Xmx31g
-XX:+UseG1GC
-XX:G1ReservePercent=25
-XX:InitiatingHeapOccupancyPercent=75
-XX:+ParallelRefProcEnabled
-XX:MaxGCPauseMillis=200
-XX:+ExplicitGCInvokesConcurrent
Diese Einstellungen spiegeln wichtige Prinzipien wider:
Hier sind Beispiele für Abfrageoptimierungsmuster:
GET /logs-*/_search
{
"query": {
"bool": {
"filter": [
{
"range": {
"@timestamp": {
"gte": "now-1h"
}
}
},
{
"term": {
"level": "fehler"
}
}
],
"should": [
{
"match_phrase": {
"nachricht": {
"query": "verbindung verweigert",
"boost": 2
}
}
}
],
"minimum_should_match": 0
}
},
"_source": ["@timestamp", "nachricht", "level"],
"sort": [
{
"@timestamp": {
"order": "desc"
}
}
]
}
Diese Abfrage demonstriert mehrere Optimierungsprinzipien:
Sicherheit in OpenSearch erfordert einen umfassenden Ansatz, der alle Aspekte Ihres Deployments berücksichtigt.
Hier ein Beispiel einer gut strukturierten Rollenkonfiguration:
PUT _plugins/_security/api/roles/logs_leser
{
"cluster_permissions": [
"cluster:monitor/health"
],
"index_permissions": [
{
"index_patterns": ["logs-*"],
"allowed_actions": [
"read",
"search"
],
"field_level_security": {
"grant": ["@timestamp", "nachricht", "level", "host"],
"except": ["_source.passwort", "_source.kreditkarte"]
}
}
]
}
Implementieren Sie sichere Kommunikationseinstellungen:
# opensearch.yml
plugins.security.ssl.transport.enabled: true
plugins.security.ssl.transport.pemcert_filepath: certs/node.pem
plugins.security.ssl.transport.pemkey_filepath: certs/node-key.pem
plugins.security.ssl.transport.pemtrustedcas_filepath: certs/ca.pem
plugins.security.ssl.http.enabled: true
plugins.security.ssl.http.pemcert_filepath: certs/node.pem
plugins.security.ssl.http.pemkey_filepath: certs/node-key.pem
plugins.security.ssl.http.pemtrustedcas_filepath: certs/ca.pemEffektive Überwachung und Wartung gewährleisten die langfristige Zuverlässigkeit Ihres OpenSearch-Deployments.
Ein Beispiel für ein umfassendes Monitoring-System:
PUT _plugins/_alerting/monitors/cluster_gesundheit
{
"type": "monitor",
"name": "Cluster-Gesundheitsmonitor",
"enabled": true,
"schedule": {
"period": {
"interval": 1,
"unit": "MINUTES"
}
},
"inputs": [
{
"search": {
"indices": [".monitoring-opensearch-*"],
"query": {
"bool": {
"must": [
{
"range": {
"@timestamp": {
"gte": "now-5m"
}
}
}
]
}
}
}
}
],
"triggers": [
{
"name": "Cluster-Gesundheitsalarm",
"severity": "Hoch",
"condition": {
"script": {
"source": """
def maxHeapNutzung = 85.0;
def maxCpuNutzung = 90.0;
return ctx.results[0].hits.hits.any(hit -> {
def stats = hit._source;
return stats.jvm.mem.heap_used_percent > maxHeapNutzung ||
stats.os.cpu.percent > maxCpuNutzung;
});
"""
}
}
}
]
}