ELK Stack im Cluster-Betrieb

Mit dem ELK Stack bekommt man eine abgestimmte Umgebung um Log-Einträge per Logstash abzuholen, diese in Elasticsearch vorzuhalten und dann per Kibana anzuzeigen. Das Aufsetzen des ELK Stack wird mit den Docker Images von Elastic vereinfacht. Um diese jedoch im Cluster zu nutzen müssen ein paar Anpassungen durchgeführt werden, welche hier dargestellt werden.

Einrichtung

Elastic bietet auf GitHub mehrere Docker Images an:

Mittels docker-compose kann eine Konfiguration aufgesetzt werden, um die gewünschte Cluster-Umgebung aufzusetzen. In diesem Beispiel wird vernachlässigt, dass die einzelnen Container auf unterschiedliche Hosts laufen sollten. Jedoch wird hierfür bei der Konfiguration schon entsprechend Beachtung geschenkt.

Die angestrebte Umgebung sieht wie folgt aus:

ELK Stack Cluster

Die Grundgedanken sind:

  • Ein Elasticsearch Client Node dient nur für die reine Koordination und stellt die benötigten Ports (hier: 9200 und 9300) bereit.
  • Ein paar Elasticsearch Master Nodes, welche selbst keine Daten halten.
  • Ein paar Elasticsearch Data Nodes für die reine Datenhaltung.
  • Ein direkter Zugriff ist nur über den Client Node möglich.
  • Kibana und Logstash kennen nur den Client Node und dessen Port.

Die docker-compose Konfiguration sieht wie folgt aus:

#
# docker-compose.yml
#
# Config file for running the following images
# - elasticsearch (master, loadbalancer and data node)
# - logstash
# - kibana
#
# To use elasticsearch in a cluster use the docker-compose scale logic:
# docker-compose scale elasticsearch=3
# Elasticsearch config use zen for instance discovering.
# Consider that a master and loadbalancer node is also configured. Kibana and
# Logstash instance should never act directly with a master node. For this reason
# is on the master node http.enabled deactivated.
#
#
# Hafid Haddouti <code@haddouti.com>
# 23.05.2017
# 

version: '3'

services:

  # Coordinating/Loadbalancing node
  # master, data and ingest features are deactivated
  # static port mapping for usage with external services like Kibana, Logstash
  elasticsearch-coordinating:
    build: elasticsearch/
    container_name: elasticsearch-coordinating
    volumes:
      - ./elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml
    ports:
      - "9200:9200"
      - "9300:9300"
    environment:
      - "ES_JAVA_OPTS=-Xmx256m -Xms256m"
      - "node.master=false"
      - "node.data=false"
      - "node.ingest=false"
      - "discovery.type=zen"
      - "discovery.zen.ping.unicast.hosts=elasticsearch-master"
      - "discovery.zen.minimum_master_nodes=1"
    networks:
      - elk

  # Master node
  # Without static port mapping and http transport disabled
  elasticsearch-master:
    build: elasticsearch/
#    container_name: elasticsearch-master
    volumes:
      - ./elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml
    ports:
      - "9300"
    environment:
      - "ES_JAVA_OPTS=-Xmx256m -Xms256m"
      - "node.master=true"
      - "node.data=false"
      - "node.ingest=false"
      - "http.enabled=false"
#      - "discovery.zen.minimum_master_nodes=2"
      - "discovery.zen.ping.unicast.hosts=elasticsearch-master"
    networks:
      - elk
    depends_on:
      - elasticsearch-coordinating


  # elasticsearch data service. 
  # Do not use a static container name, this will be generated during scaling
  # also do not use static port mapping, instead let elasticsearch use random ports
  elasticsearch:
    build: elasticsearch/
#    container_name: elasticsearch
    volumes:
      - ./elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml
    ports:
      - "9300"
    environment:
      - "ES_JAVA_OPTS=-Xmx256m -Xms256m"
      - "node.master=false"
      - "node.ingest=true"
      - "http.enabled=false"
      - "discovery.type=zen"
      - "discovery.zen.ping.unicast.hosts=elasticsearch-master"
#      - "discovery.zen.minimum_master_nodes=2"
    networks:
      - elk
    depends_on:
      - elasticsearch-coordinating

  logstash:
    build: logstash/
    container_name: logstash
    volumes:
      - ./logstash/config/logstash.yml:/usr/share/logstash/config/logstash.yml
      - ./logstash/pipeline:/usr/share/logstash/pipeline
    ports:
      - "5000:5000"
    environment:
      - "LS_JAVA_OPTS=-Xmx256m -Xms256m"
    networks:
      - elk
    links:
      - elasticsearch-coordinating
    depends_on:
      - elasticsearch-master
      - elasticsearch-coordinating

  kibana:
    build: kibana/
    container_name: kibana
    volumes:
      - ./kibana/config/kibana.yml:/usr/share/kibana/config/kibana.yml
    ports:
      - "5601:5601"
    networks:
      - elk
    links:
      - elasticsearch-coordinating
    depends_on:
      - elasticsearch-master
      - elasticsearch-coordinating

networks:

  elk:
    driver: bridge

Zu beachten sind folgende Punkte:

  • Elasticsearch bietet mit Zen ein Discovery Mechanismus an, um neue Nodes zu finden. Dabei müssen alle Hosts angegeben werden. Hier wurde es vereinfacht, da der Service-Name "elasticsearch-master" verwendet wurde.
  • Container welche skaliert werden sollen, dürfen keinen festen container_name verwenden; da dieser eindeutig sein muss. Beim Start wird hierfür ein Name mit einer Nummer vergeben.
  • Dabei Logstash kann mit einem Unterstrich „_“ im Hostnamen nicht umgehen (https://github.com/logstash-plugins/logstash-output-elasticsearch/pull/363)
  • In logstash.yml und logstash.conf wird der Hostname (elasticsearch-coordinating) aufgenommen.
  • Logstash darf nicht mit dem Master kommunizieren; hierfür ist auch beim Master Node explizit der HTTP Transportweg deaktiviert; andernfalls wird bei der Ermittlung der vorhandenen Nodes auch der Master Node betrachtet.
  • Zu beachten ist, dass für Elasticsearch der virtuelle Adressraum ausreichend groß gewählt wird, um ein möglichen OutOfMemory zu vermeiden: https://www.elastic.co/guide/en/elasticsearch/reference/current/vm-max-map-count.html
  • Standardmäßig wird seit Version 5 Elasticsearch mit X-Pack bereitgestellt (https://www.elastic.co/guide/en/x-pack/5.4/xpack-introduction.html). X-Pack ist eine Erweiterung um Elasticsearch, bzw. auch Kibana, um Funktionen bezüglich Security, Alerting, Monitoring und Reporting bereitzustellen. Dadurch lässt sich standardmäßig schon viele Informationen sammeln und direkt im ELK-Stack bereitstellen. In diesem Beispiel wurde Security deaktiviert; da hier für Logstash Probleme mit der benötigten Rolle auftraten und gesondert gelöst werden muss.
  • Damit die Container sich untereinander finden und Dienste/Ports aus anderen Container verwendet werden können, muss eine Verlinkung her. Der beim links angegebene Name dient als Hostname in dem entsprechenden Docker Container (hier: elasticsearch-coordinating).

Ein

docker-compse up -d > dc.log

sorgt dafür, dass die Docker Container gestartet werden - das sind neben den Client, Master und ein Data Node auch die Container für Kibana und Logstash.

http://localhost:9200/_cat/health

liefert ein gelben Status zurück, da wir nur einen Data Node verfügen.

Mittels

docker-compose scale elasticsearch-master=2

docker-compose scale elasticsearch=2

werden die Master und Data Nodes hochskaliert. Danach liefert ein Healtcheck auch den grünen Status zurück.

Fazit

Mit einfachen Mitteln lässt sich ein ELK Stack im Cluster-Betrieb aufsetzen. Die Skalierung der einzelnen Nodes - hier Master und Data - ist einfach realisierbar, wenn man die wichtigsten Punkte beachtet: Jegliche Kommunikation über einen Client Node und die Verlinkung zwischen den Container soll über symbolische Namen erfolgen.

Alle Dateien sind in Git zu finden: https://bitbucket.org/playsphere/monitoring.git

Hilfreiches

  • Aufruf URL für Kibana: http://localhost:5601/
  • Aufruf URL für Elasticsearch: http://localhost:9200/
  • Um mittels einer Shell in ein Docker Container zu gelangen: docker exec -it $ID bash wobei $ID die ID z.B. von docker ps für den relevante Container.

Offen

  • ELK-Stack mit X-Pack Security verwenden, hierfür muss das Problem mit der fehlenden Rolle/Privileg für Logstash gelöst werden.
  • Einsatz von Docker swarm um die Skalierung zu vereinfachen.
comment

Comments

arrow_back

Previous

Dokumentation einfach gemacht

Next

DevEnv: Docker und Elasticsearch
arrow_forward