Elasticsearch

Eine Liste der Begriffe und Konzepte einer Lucene-basierten Suchmaschine ist unter OpenSearch zu finden.

Installation

Mit unserer linuxfabrik.lfops.elasticsearch Ansible-Rolle kann Elasticsearch installiert sowie ein Clusters konfiguriert werden.

API-Calls

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

# only output certain headers
curl --cacert "$elastic_cacert" \
    --user "elastic:${ELASTIC_PASSWORD}" \
    --request GET "https://$elastic_host:9200/_cat/shards?h=index,node" \
    --header "Content-Type: application/json"

# list available headers and get info about them
curl --cacert "$elastic_cacert" \
    --user "elastic:${ELASTIC_PASSWORD}" \
    --request GET "https://$elastic_host:9200/_cat/shards?help" \
    --header "Content-Type: application/json"

# manually move a shard to a different node. note that the automatic allocation might move the shard back
curl --cacert "$elastic_cacert" \
    --user "elastic:${ELASTIC_PASSWORD}" \
    --request GET "https://$elastic_host:9200/_cat/shards?help" \
    --header "Content-Type: application/json" --data '
    {
      "commands": [
        {
          "move": {
            "index": "lfops-default_900",
            "shard": 3,
            "from_node": "node1",
            "to_node": "node3"
          }
        }
      ]
    }'

Neustart vom Cluster

Das Vorgehen ist bei einem Rolling Restart und bei einem ganzen Cluster-Restart das gleiche.

  1. Replica shard allocation deaktivieren:

curl --cacert "$elastic_cacert" \
    --user "elastic:${ELASTIC_PASSWORD}" \
    --request GET "https://$elastic_host:9200/_cluster/settings?include_defaults=true&filter_path=**.routing.allocation.enable" \
    --header "Content-Type: application/json"

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"
       }
    }'
  1. (Rolling) Restart durchführen. In der Zeit ist es normal, dass der Cluster Health gelb ist

  2. Warten, bis alle Nodes wieder verfügbar sind

  3. Replica shard allocation 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
       }
    }'

curl --cacert "$elastic_cacert" \
    --user "elastic:${ELASTIC_PASSWORD}" \
    --request GET "https://$elastic_host:9200/_cluster/settings?include_defaults=true&filter_path=**.routing.allocation.enable" \
    --header "Content-Type: application/json"

Elastic Agent und Fleet

Elastic Agent erfasst Logs, Metriken und weitere Datenpunkte auf dem Host-System und leitet diese an Elasticsearch/Logstash weiter. Elastic Agents werden in der Regel von einen Fleet Server verwaltet. Jeder Fleet Agent / Elastic Agent läuft mit einer Agent Policy, d. h. Richtlinien, die festlegen, welche Metriken erfasst werden und wohin diese gesendet werden. Jede Policy kann mehrere Integrations enthalten. Eine Elastic integration legt fest, wie Logfiles sowie Programme wie Elasticsearch oder Logstash von den Agents überwacht werden sollen.

Mit Fleet lassen sich Policies für Elastic Agent und Fleet Server via Kibana verwalten (https://kibana.example.com/app/fleet/agents). Vorgenommene Änderungen werden anschliessend automatisch an die Hosts propagiert.

Default Policies:

  • Fleet Server Policy 1 (id: fleet-server-policy)

Neue Agent Policy erstellen und ausrollen

  • 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“

Initiales Setup

Voraussetzungen: Elastic Repo, Elasticsearch und Kibana sind eingerichtet

Zunächst wird der Fleet Server eingerichtet, anschliessend die Elastic Agents.

Schritte:

  1. Fleet Server Host Unter https://kibana.example.com/app/fleet/settings > „Fleet server hosts“: Authentication > Fleet Server > Elastic Agents certificate authorities: ASCII-armored CA-Zertifikat einfügen

  2. Outputs Unter https://kibana.example.com/app/fleet/settings > „Outputs“: Als default Output alle Elasticsearch Hosts eintragen Bei Server SSL certificate authorities: ASCII-armored CA-Zertifikat einfügen

  3. Server-Zertifikat generieren. Erzeugt ein ZIP-Archiv mit fleet-server-01.{crt,key}. Diese werden vor Installation des Fleet-Servers auf den Host kopiert.

    /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
    
  4. Fleet Server enrollen Unter https://kibana.example.com/app/fleet/agents > „Add Fleet Server“

    • Advanced

    • Fleet Policy: „Fleet Server Policy 1“ („Create new agent policy“, falls noch nicht existiert)

    • Deployment mode for security: „Production“

    • Fleet Server Host: Hostname und Port des Fleet Servers (der neu enrolled wird)

    • Service Token generieren

    • Fleet Server auf Host installieren

      ELASTIC_AGENT_FLAVOR=servers dnf -y install elastic-agent
      systemctl enable elastic-agent
      systemctl start 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
      
    • Warten bis „Confirm connection“ erfolgreich ist. Falls das nicht funktioniert, kann mman den Status auf dem Host abfragen:

      elastic-agent status --output=full
      
  5. Elastic Agent enrollen Unter https://kibana.example.com/app/fleet/agents > „Add agent“

    • Agent Policy: „Agent Policy 1“ („Create new agent policy“, falls noch nicht existiert)

    • Enroll in fleet

      dnf -y install elastic-agent
      systemctl enable elastic-agent
      systemctl start elastic-agent
      elastic-agent enroll \
        --url=https://fleet-server-01.example.com:8220 \
        --enrollment-token='<SERVICE_TOKEN>' \
        --certificate-authorities=/path/to/fleet-ca.crt
      
  6. Zustand der Fleet überprüfen Unter https://kibana.example.com/app/fleet/agents

    • Status: „Healthy“

    • Auf Host klicken > „Agent Details“ > „Integrations“: Zustand der einzelnen Integrationen prüfen

Troubleshooting

Herausfinden, warum Shards „unassigned“ sind
elastic_host=localhost
elastic_cacert=/etc/elasticsearch/certs/http_ca.crt

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_replicas bei einem Managed Index Template anpassen

Das Template sollte nicht direkt angepasst werden, da dieses z.B. vom Fleet Manager administriert wird. Um trotzdem Modifikationen vornehmen zu können, gibt es normalerweise ein <index name>@custom Component Template, z.B. kibana_sample_data_logs@custom. Falls es dieses nicht gibt kann ein leeres Component Template erstellt werden und im Index Template importiert werden (Achtung: die Reihenfolge spielt der Component Templates spielt eine Rolle).

Bemerkung

Man könnte ein neues Index Template mit einer höheren Priority anlegen, allerdings wird dann gesamte Template überschrieben - nicht nur eine bestimmte Einstellung.

Anschliessend im Component Template die number_of_replicas (oder eine andere Einstellung) setzen:

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 kann die Erstellung eines neuen Indexes simuliert und die vererbten Einstellungen geprüft werden:

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

Ausserdem sollte geprüft werden, ob eine Index Lifecycle Management („ILM“) Policy die number_of_replicas anpasst. Ist dies der Fall, kann man die ILM Policy kopieren und in dem <index name>@custom Component Template auf die Kopie verweisen, beispielsweise:

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": {
        "lifecycle": {
          "name": "logs-1-replica"
        },
        "number_of_replicas": "3"
      }
    }
  }
}
EOF
Elastic-Agent wird als unhealthy angezeigt

Der Zustand des Elastic-Agents kann auf dem betroffenen Agent mittels elastic-agent status abgefragt werden.

elastic-agent status
elastic-agent status --output=full
elastic-agent status --output=yaml
elastic-agent status --output=json