Elk Deployment in Kubernetes

In diesem Beitrag wollen wir zeigen, wie einfach man einen ELK-Stack auf Kubernetes deployen kann.

Auf unserem Github Repository findet man das vorgeführte Beispiel-Deployment.

Das Beispiel enthält Yaml-Dateien die notwendig sind, einen ELK-Stack auf einem Kubernetes zu deployen, darunter Ingresses, Konfigurationen und Services.

Dieses Schema beschreibt die Basisstruktur vom ELK:


elk schema


Der Logstash-shipper pushed die Daten in den Redis-cache. Der Logstash-indexer nimmt diese dann vom Redis und pushed sie in den Elasticsearch. Zuletzt können dann die Daten vom Kibana über eine WebUI visualisiert werden.

Die Elasticsearch Nodes sind untereinander über den Port 9300 verbunden und bilden einen Cluster mit sharded Daten.

Auf dem Port 9200 kann man zusätzlich Daten von etwa fluentd oder beats pushen, zudem ist die Schnittstelle des Logstash-indexers auf Port 9600 für das interne Netzwerk geöffnet, was die Kontrolle über diese ermöglicht.

Sämtliche Daten werden auf einem NFS-Share gespeichert, in unserem Fall werden die Indexes auf dem gleichem Storage mit unterschiedlichen Ordnern angelegt.

Voraussetzungen

Voraussetzung um dieses Beispiel auszuprobieren, ist ein funktionierendes Kubernetes Setup und ein NFS-Server. Hat man kein Kubernetes-Cluster zur Hand, kann man das ganze lokal mithilfe von Minikube testen.

NFS-Server

Einen NFS-Server kann man sich mit wenig Aufwand mit Vagrant bereitstellen. Ein entsprechendes Vagrantfile könnte so aussehen:

Vagrant.configure("2") do |config|
   config.vm.define "nfs" do |server|
      server.vm.box       = "centos/7"
      server.vm.hostname  = "nfs.test.local"
      server.vm.network :private_network, ip: "192.168.99.10"
      end
   end
end

Nach einem vagrant up und vagrant ssh kann man die benötigten Ordner und Einträge /etc/exports anlegen:

# mkdir /srv/es-data
# cat /etc/exports
/srv/es-data 192.168.99.0/24(rw,sync,no_root_squash)

Unser Kubernetes-Cluster befindet sich demnach im Netzwerk 192.168.99.0/24. Fehlt nur noch, den NFS-Server Dienst neuzustarten:

# systemctl restart nfs-server

Ressourcen für das Deployment

Ein ready-to-run ELK-Beispiel findet sich hier: https://github.com/afdata/elk-deployment

Für unser Beispiel muss man folgendes anpassen:

Hier kann man die Konfiguration unserer zwei K8s Volumes finden. Hier tragen wir dann die richtige IP-Adresse unseres NFS-Servers ein:

- name: es-data
  nfs:
     server: 192.168.99.10 # IP Adresse des NFS-Share auf dem die Datenbank des Elasticsearch ist.
     path: "/srv/nfsshare/k8s-stage/elasticsearch"

Wichtiges vor dem Deployment

  • Elasticsearch Ports sind geöffnet um eine direkte Verbindung ohne redis-logstash-indexer zu ermöglichen.

    Man kann daher z.B. fluentd als leichtgewichtige Alternative zum Logstash benutzen. Alle Vorteile von fluentd findet man hier

    Viele fluentd Beispiele

    Einstellungen für den Elasticsearch Output hier

    Anzahl and Einstellungen für den Elasticserach output hier

  • Auf jeder Host-Maschine (Compute Node) muss ausgeführt werden: sysctl -w vm.max_map_count=262144

  • Abhängig von der benutzten Kubernetes Version muss man die API-Version im Yaml anpassen, bei 1.8 oder älter batch/v2alpha1 und bei neueren Versionen apiVersion: batch/v1beta1 .

    Die API Version übeprüft man mit: kubectl api-versions Falls batch/v2alpha1 API fehlt: vi /etc/kubernetes/apiserver mit dem Parameter --runtime-config=batch/v2alpha1=true ergänzen.

  • Um filebeat zu starten muss man rbac.authorization.k8s.io/v1alpha1 in KUBE_API_ARGS hinzufügen:

--authorization-mode=RBAC,ABAC

Neustarten von kube-apiserver und überprüfen der Version: kubectl api-versions

Ausrollen der Kubernetes Services & Ressourcen:

  1. Ausrollen des Namespaces:
# kubectl apply -f namespace/elasticsearch-ns.yaml

Ausrollen notwendiger Einstellungen:

# kubectl apply -f configs/.
  1. Ausrollen der Ingresses:
# kubectl apply -f ingress/.
  1. Ausrollen von Services und Pods:
# kubectl apply -f .

Folgende Topologie lässt sich damit aufbauen:

elk-Topologie

Nun können wir den Status unserer Pods auf running überprüfen:

# kubectl get pods -n elk

Das ganze sieht in etwa dann so aus:


NAME                        READY     STATUS    RESTARTS   AGE
es-node-0                   1/1       Running   0          1d  
es-node-1                   1/1       Running   0          1d  
kibana-3971276974-0dtdk     1/1       Running   0          1d  
kibana-3971276974-w7w08     1/1       Running   0          1d  
logstash-3874044503-kkltw   1/1       Running   0          1d  
logstash-3874044503-m9xfq   1/1       Running   0          1d  
redis                       1/1       Running   0          1d  

Das Kibana Web-Interface sollte auf http://kibana.test.local erreichbar sein, genauso wie Elasticsearch auf Port 9200 für externe Verbindungen und Logstash auf 9600 für die Logstash API.

Debug

Sollte es Probleme bei dem Deployment geben, kann es sein das unser NFS-Server nicht erreichbar ist. Um unseren NFS-Server zu überprüfen, geht man wie folgt vor:

# showmount -e 192.168.99.10

output:

Export list for 192.168.99.10:   
/srv/es-data  192.168.99.0/24  
# mount 192.168.99.10:/srv/es-data /media && umount /media

Sollte eine Applikation nicht erreichbar sein, weil die Node IP oder der Port unbekannt ist, können die folgenden Befehle helfen:

# kubectl get service  
# kubectl get nodes -o yaml  

Der Befehl docker ps zeigt die laufenden Container.