IT

Insider-Leitfaden zu Splunk für Container und Kubernetes

Unsere Container-Images Splunk Enterprise und Universal Forwarder werden bei DockerHub jeden Monat millionen­fach herunter­geladen. Weil wir das zu schätzen wissen, haben wir bereits vor einiger Zeit damit begonnen, Einzel­instanz-Implementierungen von Splunk in Containern zu unterstützen. Seitdem haben viele Kunden den Wunsch geäußert, mehr über unsere Ideen und Pläne mit Containern zu erfahren, insbesondere zum Betrieb von Splunk auf Kubernetes.

Wir haben uns also zusammengetan und aus unserer gemeinsamen Erfahrung eine Reihe zusätzlicher Details und Komplexitäten zusammen­getragen, auf die ihr stoßt, wenn ihr Splunk auf Kubernetes laufen lasst: Sicherheit, nicht­flüchtiger Speicher, Hoch­verfügbarkeit und Performance. Diese Punkte haben hohe Priorität bei allen unseren Überlegungen zur künftigen Ausrichtung, und Kunden, die ihre eigenen Implementierungen entwickeln, sollten sie ebenso sorgfältig berücksichtigen.

Container-Sicherheit

Für uns als Software­anbieter sind Container mit einigen ganz speziellen Heraus­forderungen verbunden. Eine davon ist die zusätzliche Verantwortung für Sicherheit. Bisher war es so, dass es bei den von uns gelieferten Teilen Schnitt­stellen zu vielen anderen Teilen gab, die von Betriebssystem­anbietern bereitgestellt wurden. Es gab damit eine klare Trenn­linie zwischen der Angriffs­fläche, für deren Schutz wir zuständig waren (unser eigener Code und die darin eingebetteten Bibliotheken), und dem, wofür die Betriebssystem­hersteller verantwortlich waren (alles andere). Jetzt, da Container die Anwendungs- und Betriebssystem­teile bündeln, beginnt sich diese Linie zu verschieben. Zum ersten Mal müssen wir uns um Sicherheits­lücken in eher extern angesiedelten Projekten wie glibc und bash kümmern.

Es stellt sicherlich niemand die immens wichtige Rolle infrage, die Sicherheit heute spielt. Aber dass sich die Trenn­linie derart verschieben würde – darauf waren wir ehrlich gesagt nicht gefasst. Wir hatten damit begonnen, Debian für unsere Basis-Container-Images zu verwenden, und waren gewohnt, uns auf die Sicherheit „unserer“ Teile zu beschränken. Ich benutze regelmäßig eine Vielzahl von Linux-Distributionen und bin aus jeweils eigenen Gründen von allen begeistert, doch Red Hat liegt in Sachen Sicherheit eindeutig vorn.

Das zeigte sich besonders deutlich, als wir unsere Container-CI/CD-Pipelines um Sicherheits­scans erweitert hatten und mit verschiedenen Basis-Images experimentierten. Unsere Container, die auf den neuesten und besten Debian-Images aufsetzten, wurden andauernd wegen nicht gepatchter Sicherheits­lücken markiert, während bei Containern, die auf CentOS aufsetzen (einem beliebten Red-Hat-Derivat), die Überprüfung fast immer keine Fehler ergab. Das dürfte eigentlich keine große Überraschung sein: Mit der Abonnement­gebühr für Red Hat Enterprise Linux (RHEL) bekommt ihr (neben vielem anderen) eine schnelle CVE-Bearbeitung (Common Vulnerabilities and Exposures). Dies zeigen auch die Ergebnisse der letzten Scans unserer Splunk-Enterprise-7.2.6-Images:

  • Debian 9 (stretch-slim), Fehler mit Schweregrad: 12 hoch, 33 mittel, 19 niedrig, 46 vernachlässig­bar, 2 unbekannt.
  • Debian 10 (buster-slim), Fehler mit Schwere­grad: 1 hoch, 8 mittel, 4 niedrig, 36 vernachlässig­bar, 1 unbekannt.
  • Red Hat 8 (ubi-minimal): 0, null, nix!

Das Problem, das wir in der Vergangenheit mit den Container-Images von Red Hat hatten, war, dass ihre Lizenz die Weiter­verteilung einschränkte und die Verwendung nur auf RHEL-Host-Maschinen gestattete. Es sind zwar viele Splunk-Kunden auch RHEL-Kunden, aber viele sind es eben nicht. Es blieben uns also nur zwei Möglichkeiten, die beide nicht ideal waren:

  • Auf die Red-Hat-Zertifizierung verzichten und versuchen, die Betriebssystem­schwachstellen selbst zu beheben (das ist im Grunde das, was wir standard­mäßig sowieso schon taten).
  • Zwei parallele Images veröffentlichen und unterstützen – und dabei weiterhin selbst Betriebssystem­schwachstellen beheben (das würde mehr Ressourcen erfordern, als wir hatten).

Universal Base Images von Red Hat

Seit ich in den 90er-Jahren mit den Vorabversionen von Red Hat gearbeitet habe, bin ich treuer Benutzer und Fan von Red Hat (und verschiedenen RPM-Ablegern). Und gestern, auf dem Red Hat Summit in Boston, haben meine Freunde mit dem roten Hut mit ihrer Einführung von Universal Base Images (UBIs) das Container-Sicherheits­problem für uns gelöst. Die UBIs enthalten die neuesten Sicherheits­patches, wie wir es von Red Hat gewohnt sind, und werden unter einer weniger restriktiven Lizenz veröffentlicht, die es erlaubt, sie auf jedem Host-Betriebs­system auszuführen (allerdings empfehlen wir immer noch, RHEL zu verwenden).

Ich kann daher jetzt voller Stolz die Beta-Versionen der neuen Splunk-Enterprise- und Universal-Forwarder-Container-Images ankündigen, die auf Red Hat aufsetzen. Ihr könnt sie euch jetzt von DockerHub herunterladen, indem ihr „-redhat“ an unsere Image-Tags anhängt. Zum Beispiel so:

docker pull splunk/splunk:redhat
docker pull splunk/splunk:7.2.6-redhat
docker pull splunk/universalforwarder:redhat
docker pull splunk/universalforwarder:7.2.6-redhat


Wir haben vor, unsere Debian-Images zu ersetzen und künftig Red Hat zum Standard zu machen. Wir gehen davon aus, dass unsere Kunden diesen Wechsel einsehen. Außerdem arbeiten wir mit Red Hat zusammen, um diese Images zu zertifizieren, und hoffen, dass wir sie bald im Red-Hat-Container-Katalog veröffentlichen können.

Splunk und Kubernetes

Ich finde es sehr spannend, dass eine wachsende Zahl unserer Kunden Splunk auf Kubernetes laufen lassen möchte. Wir glauben, dass Kubernetes ein unglaubliches Potenzial hat und enorm wichtig ist – wir stellen uns eine Zukunft vor, in der Kubernetes die Bereit­stellung, das Monitoring und die Verwaltung von Splunk sehr viel einfacher macht.

Derzeit unterstützen wir nur Einzel­instanz-Installationen von Splunk auf Kubernetes. Einige Profis haben zwar auch schon recht erfolgreich Cluster-Implementierungen realisiert, doch es gibt dabei viele Hürden, die so etwas zu einer echten Heraus­forderung machen. Splunk ist von Haus aus sehr zustands­orientiert (stateful), Kubernetes wurde dagegen ursprünglich für zustands­lose (stateless) Microservices entwickelt. Kubernetes ähnelt zudem eher einem Toolkit für die Cloud-Entwicklung: Es bietet immense Flexibilität sowie jede Menge Ausstattung und Funktionen, die allerdings auch jede Menge Fallstricke bergen.

Wir haben bereits eine Sammlung von YAML-Vorlagen veröffentlicht, mit denen sich sowohl Einzelinstanz- als auch Cluster-Installationen von Splunk auf Kubernetes bereitstellen lassen. Außerdem haben wir intern mit ein paar Projekten experimentiert, die eines Tages dazu beitragen könnten, dass Splunk und Kubernetes gute Freunde werden. Als kleinen Vorgeschmack stelle ich euch diese Projekte im Folgenden vor – beachtet aber bitte, dass wir sie möglicher­weise nie bis zur Marktreife führen werden.

Kubernetes-Operatoren

YAML-Vorlagen werden schnell sehr komplex, wenn es sich nicht gerade um eine ganz einfache Anwendung handelt. Sie sind prima für einfache Microservices, aber weniger gut für komplexe Anwendungen wie Splunk. Mit der Einführung von benutzer­definierten Ressourcen (Custom Resources) hat sich bei Kubernetes eine ganz neue Welt aufgetan, weil die Entwicklungs­teams jetzt über die integrierten Objekttypen hinausgehen und eigene Typen erstellen können. Ein häufiger Use Case für benutzer­definierte Ressourcen sind über­geordnete Konzepte, die verschiedene Dinge kombinieren und die zugrunde liegende Komplexität durch Abstraktion auflösen. Wer damit programmiert, kann sich das Ganze wie ein Objekt vorstellen, das eine einfachere Schnittstelle bietet, indem es viele andere Objekte in sich vereint. Ein Operator geht noch einen Schritt weiter: Er ist ein persistenter Service, der innerhalb von Kubernetes ausgeführt wird und auf Änderungen bei einer Reihe von benutzerdefinierten Ressourcen wartet.

Stellt euch vor, eine Splunk-Implementierung könnte als einzelnes SplunkEnterprise-Objekt ausgedrückt werden. Stellt euch außerdem vor, dass alles, was ein Kunde konfigurieren möchte, in der Spezifikation dieses Objekts (oder einer zugehörigen ConfigMap) deklariert werden könnte. Kunden müssten sich dann nicht um Dinge wie Pods, StatefulSets, PersistentVolumes etc. kümmern, denn all dies würde der Operator für sie erledigen.

Operatoren unterscheiden sich besonders von anderen Application-Packaging-Ansätzen wie Service­paketen und Helm-Diagrammen, die für die Folge­aufgaben nach der Produkt­übergabe (Day 2 Operations) zum Zuge kommen. Mithilfe von Operatoren könnt ihr Daten­mengen nahtlos verwalten, Upgrades durchführen, hoch- und herunter­skalieren, allgemeine Wartungs­aufgaben durchführen usw. Bei zustands­orientierten Anwendungen wie Splunk müssen viele Prozesse in einer ganz bestimmten Reihenfolge ausgeführt werden. Als Software­anbieter können wir Operatoren verwenden und alle Best Practices zum Management unserer Produkte mit Code automatisieren, sodass Mitarbeiterinnen und Mitarbeiter keine Playbooks mehr von Hand abarbeiten müssen. Meiner Meinung nach werden damit die Bereit­stellung, das Monitoring und das Management von Splunk für unsere Kunden deutlich einfacher werden.

Der Splunk-Operator

Um eine einzelne Splunk-Instanz bereitzustellen, müsst ihr nur den einfachen Befehl kubectl apply in einer Vorlage ausführen, die wie folgt aussieht:

apiVersion: enterprise.splunk.com/v1alpha1
kind: Splunk Enterprise
metadata:
  name: single
spec:
  config:
    splunkPassword: helloworld456
    splunkStartArgs: --accept-license
  topology:
    standalones: 1


Diese Vorlage erstellt automatisch PersistentVolumeClaims (PVCs) und ordnet sie /splunk/etc und /splunk/var zu. Dies stellt sicher, dass sämtliche Daten mit dem Pod verschoben werden, wenn sich der Server verabschiedet und Kubernetes den Pod verschiebt.

$ kubectl apply -f singleinstance.yml
splunkenterprise.enterprise.splunk.com/single created
$ kubectl get pods
NAME                                        READY STATUS RESTARTS AGE
splunk-operator-79cfbd8746-bgv7f            1/1 Running 0 5d1h
splunk-standalone-single-5f865d6646-h2mpz   1/1 Running 0 44s




$ kubectl get pvc
NAME                               STATUS VOLUME                 CAPACITY ACCESS MODES STORAGECLASS AGE
pvc-etc-splunk-standalone-single   Bound pvc-cfdbeac0-6f9d-11e9-92ac-0acd14da47d0   1Gi RWO gp2 53s
pvc-var-splunk-standalone-single   Bound pvc-cfdce5eb-6f9d-11e9-92ac-0acd14da47d0   50Gi RWO gp2 53


Cool, oder? Wie wäre es mit einem Cluster?

apiVersion: enterprise.splunk.com/v1alpha1
kind: Splunk Enterprise
metadata:
  name: example
spec:
  config:
    splunkPassword: helloworld456
    splunkStartArgs: --accept-license
  topology:
    indexers: 3
    searchHeads: 3


Ihr könnt einen Cluster in wenigen Minuten erstellen, indem ihr einfach die Topologie­parameter ändert. All die manuellen Schritte, die normaler­weise erforderlich sind, um Search-Head-Cluster und Indexer-Cluster einzurichten, alles miteinander zu verbinden usw., besorgt der Operator.

$ kubectl apply -f cluster.yml
splunkenterprise.enterprise.splunk.com/example created
$ kubectl get pods
NAME                                             READY STATUS RESTARTS AGE
splunk-cluster-master-example-59666cd544-6dpfc   1/1 Running 0 4m24s
splunk-deployer-example-69bf676c7d-pgxp9         1/1 Running 0 4m24s
splunk-indexer-example-0                         1/1 Running 0 4m24s
splunk-indexer-example-1                         1/1 Running 0 3m46s
splunk-indexer-example-2                         1/1 Running 0 2m13s
splunk-license-master-example-59db6c48ff-2vqrf   1/1 Running 0 4m24s
splunk-operator-79cfbd8746-bgv7f                 1/1 Running 0 5d1h
splunk-search-head-example-0                     1/1 Running 0 4m24s
splunk-search-head-example-1                     1/1 Running 0 3m45s
splunk-search-head-example-2                     1/1 Running 0 2m9s


Standardmäßig wird hier unser Image splunk/splunk:latest verwendet. Ihr könnt stattdessen aber auch unsere neuen Red-Hat-UBI-Images verwenden, indem ihr einfach einen splunkImage-Parameter zur Spezifikation hinzufügt. Was aber passiert, wenn ihr hier splunk/splunk:7.2.6-redhat festlegt und nach Erscheinen der neuen Version ein Upgrade auf 7.3.0 durchführen möchtet? In diesem Fall ändert ihr splunkImage einfach in splunk/splunk:7.3.0-redhat und führt den Befehl kubectl apply erneut aus. Damit ist das Upgrade erledigt, selbst wenn eure Topologie Hunderte oder gar Tausende von Servern umfasst.

Über Remote-Volumes hinaus

Vielleicht fragt ihr euch ja, wo diese PersistentVolumes herkommen, die wie von Zauber­hand auftauchen. Normaler­weise müsstet ihr über einen Kubernetes-Cluster verfügen, der mit einem standard­mäßigen StorageClass-Setup konfiguriert ist und Remote-Volumes über euer Netzwerk einbindet (EBS-Volumes, NFS-Mounts etc.). Wenn ihr einen solchen Cluster habt, funktioniert das Ganze hervorragend, sofern ihr genügend Kapazität in eurer Speicher­ebene frei habt, um den Bedarf von Splunk abzudecken. Aber Splunk wird in der Regel für Big Data verwendet, und „Big“ bedeutet hier wirklich sehr große Daten­mengen und sehr hohe Geschwindigkeiten. Unsere größten Kunden generieren jeden Tag Petabytes an Daten, die sie mit Splunk managen. Bei solchen Big-Data-Maßstäben kann eure Speicher­ebene schnell zum Leistungs­engpass werden.

Mit dem letzten Kubernetes-Release 1.14 wurden persistente lokale Volumes als allgemein verfügbare Funktion eingeführt. Damit könnt ihr lokale Festplatten, die an eure Server angeschlossen sind, zum Speichern von Splunk-Daten verwenden. Die Geschwindigkeit ist dabei extrem hoch, vielleicht sogar genauso hoch wie bei der Ausführung von Splunk auf einem Bare-Metal-Server. Es ist also alles in Butter – bis sich einer eurer Server verabschiedet. Denn persistente lokale Volumes sind an einen bestimmten Server gebunden. Das heißt: Wenn ihr den Server verliert, verliert ihr auch alle darauf gespeicherten Daten. Die gute Nachricht ist, dass ihr die Replikations­funktion von Splunk nutzen könnt, um euch vor Daten­verlusten zu schützen – das Endergebnis ist also zumindest nicht schlechter als das, was ihre heute ohne Kubernetes erreicht.

Speicherung der nächsten Generation

Es gibt mittlerweile verschiedene Möglichkeiten der persistenten Speicherung in Kubernetes. Bei manchen werden die lokalen Festplatten, die an eure Kubernetes-Server angeschlossen sind, zu einem virtuellen Speichernetz (Storage Mesh) zusammengefasst. Dieses wird als StorageClass verfügbar gemacht, die eure PersistentVolumes unterstützt. Eines der viel­versprechendsten Speicher­produkte, mit denen wir in letzter Zeit gearbeitet haben, ist Robin Storage.

Mit Robin Storage erstellte PersistentVolumes replizieren automatisch Blöcke über mehrere Festplatten in eurem Cluster hinweg. Wenn ein Server ausfällt, startet Kubernetes eure Pods automatisch an einem anderen Ort neu, und alle von den Pods verwendeten Volumes werden ohne Datenverlust mit ihnen verschoben. Im Gegensatz zu Remote-Volumes und Objekt­speichern bleiben eure Daten innerhalb eures Clusters und damit so nah wie möglich am Computing. Dies kann Leistungs­engpässe vermeiden, da der Weg durch das Netzwerk kürzer ist. Außerdem seid ihr damit nicht von externen Speicher­services abhängig, was besonders für lokale Implementierungen von Splunk reizvoll sein kann.

Robin Storage kann eure Volumes verschlüsseln und komprimieren, Zero-Copy-Snapshots und Klone erstellen sowie den Zustand ganzer Cluster sichern und wiederherstellen. Es verlagert eure Daten in die Nähe der Pods, die häufig darauf zugreifen, was zu erheblichen Leistungs­vorteilen führen kann. Die Macher von Robin behaupten, dass die Leistung im Normalfall bis auf 5 bis 10 % an die lokaler Bare-Metal-Festplatten herankommt.

Die Bereitstellung von Robin Storage ist einfach, da es als Operator gepackt ist: Ihr führt einfach den Befehl kubectl apply aus und seid so gut wie fertig. Ihr müsst natürlich noch Roh­datenträger bereitstellen, die Robin Storage verwenden kann, und es gibt auch eine ganze Reihe von Parametern zur Fein­abstimmung. Im Splunk-Operator aus unserer Machbarkeits­studie könnt ihr die zu verwendende StorageClass über einen Parameter namens StorageClassName auswählen. Wir haben es innerhalb weniger Minuten geschafft, einen Splunk-Cluster unter Verwendung von Robin Storage auf Red Hat OpenShift zum Laufen zu bringen, indem wir unsere obigen YAML-Beispiele einfach um die folgenden Codezeilen ergänzt haben.

$ kubectl get pvc
NAME                                    STATUS VOLUME            CAPACITY ACCESS MODES STORAGECLASS AGE
pvc-etc-splunk-cluster-master-example   Bound pvc-51d9dbba-6f9e-11e9-92ac-0acd14da47d0   1Gi RWO robin 4m41s
pvc-etc-splunk-deployer-example         Bound pvc-51e12b99-6f9e-11e9-92ac-0acd14da47d0   1Gi RWO robin 4m41s
pvc-etc-splunk-indexer-example-0        Bound pvc-51eae60e-6f9e-11e9-913c-026cfa37367a   1Gi RWO robin 4m41s
pvc-etc-splunk-indexer-example-1        Bound pvc-69048c78-6f9e-11e9-913c-026cfa37367a   1Gi RWO robin 4m3s
pvc-etc-splunk-indexer-example-2        Bound pvc-a04342fa-6f9e-11e9-913c-026cfa37367a   1Gi RWO robin 2m30s
pvc-etc-splunk-license-master-example   Bound pvc-51d39a4b-6f9e-11e9-92ac-0acd14da47d0   1Gi RWO robin 4m42s
pvc-etc-splunk-search-head-example-0    Bound pvc-51f1f858-6f9e-11e9-913c-026cfa37367a   1Gi RWO robin 4m41s
pvc-etc-splunk-search-head-example-1    Bound pvc-69937886-6f9e-11e9-913c-026cfa37367a   1Gi RWO robin 4m2s
pvc-etc-splunk-search-head-example-2    Bound pvc-a2b86a7a-6f9e-11e9-913c-026cfa37367a   1Gi RWO robin 2m26s
pvc-var-splunk-cluster-master-example   Bound pvc-51db8a61-6f9e-11e9-92ac-0acd14da47d0   50Gi RWO robin 4m41s
pvc-var-splunk-deployer-example         Bound pvc-51e33300-6f9e-11e9-92ac-0acd14da47d0   50Gi RWO robin 4m41s
pvc-var-splunk-indexer-example-0        Bound pvc-51e909ae-6f9e-11e9-913c-026cfa37367a   200Gi RWO robin 4m41s
pvc-var-splunk-indexer-example-1        Bound pvc-6905b8a3-6f9e-11e9-913c-026cfa37367a   200Gi RWO robin 4m3s
pvc-var-splunk-indexer-example-2        Bound pvc-a0445066-6f9e-11e9-913c-026cfa37367a   200Gi RWO robin 2m30s
pvc-var-splunk-license-master-example   Bound pvc-51d47106-6f9e-11e9-92ac-0acd14da47d0   50Gi RWO robin 4m42s
pvc-var-splunk-search-head-example-0    Bound pvc-51f0df75-6f9e-11e9-913c-026cfa37367a   50Gi RWO robin 4m41s
pvc-var-splunk-search-head-example-1    Bound pvc-699475b7-6f9e-11e9-913c-026cfa37367a   50Gi RWO robin 4m2s
pvc-var-splunk-search-head-example-2    Bound pvc-a2b99b41-6f9e-11e9-913c-026cfa37367a   50Gi RWO robin 2m26s


Ausblick

Wir konzentrieren uns auf unternehmens­taugliche Lösungen und arbeiten eng mit dem Splunk-Ökosystem zusammen, um mit technologischen Innovationen für Agilität und Kosteneins­parungen in Multi-Cloud-Umgebungen zu sorgen. Wir arbeiten hart daran, dass unser Splunk-Operator vom Machbarkeits­nachweis zu einem marktreifen Produkt wird, und experimentieren noch mit verschiedenen Möglichkeiten, um die best­mögliche Lösung zu finden. Wenn ihr uns bei dieser Entwicklung begleiten oder unterstützen möchtet, schickt mir bitte eine Nachricht über Twitter oder LinkedIn. Wir freuen uns immer über Anregungen von Kunden und über eine Möglichkeit, Neues unter Real­bedingungen auszuprobieren. Eines scheint sicher: Kubernetes ist keine Eintags­fliege, und die Zukunft hält viele aufregende neue Entwicklungen für uns bereit.

----------------------------------------------------
Vielen Dank!
Mike Dickey


*Dieser Artikel wurde aus dem Englischen übersetzt und editiert. Der Originalblogpost wurde bereits 2019 veröffentlicht, daher sind einige der hier aufgeführten Inhalte möglicherweise nicht mehr aktuell.