Upgrade für Ihr K8s-Monitoring

Kubernetes-Integration jetzt mit mehr Konfigurationsoptionen, optimierten Logs und geringerem Speicherbedarf

Veröffentlicht 8 Minuten Lesedauer

Immer umfangreichere Kubernetes-Implementierungen prägen das Bild von heute. Im Zuge der Skalierung dieser Umgebungen nimmt auch ihre Komplexität immer weiter zu – auch im Hinblick auf Performance- und Health-Monitoring. Unsere Kubernetes-Integration, die ab sofort in Version 3 verfügbar ist, trägt dem auf breiter Basis Rechnung: Ihr Bedarf an CPU- und Speicherressourcen fällt deutlich geringer aus, zudem unterstützt sie externe Kontrollebenen etwa auf Basis von Rancher und erleichtert durch Optimierungen bei Log-Nachrichten die Erkennung potenzieller Probleme. Was die Speichernutzung angeht, so sind mit der neuen Integration beispielsweise Konfigurationen mit 80 % geringeren Anforderungen und somit durchaus beachtliche Reduzierungen möglich.

Diese sowie die weiteren Vorteile ebenso wie einige der Herausforderungen, die es bei der Umsetzung dieses Updates zu meistern galt, beleuchten wir im Folgenden:

Was spricht für ein Upgrade Ihrer Kubernetes-Integration?

Ganz gleich, ob Sie eine frühere Version unserer Integration nutzen oder erst in Kubernetes-Monitoring mit New Relic einsteigen: Das Update auf v3 ist in jedem Fall mit weitreichenden Vorteilen verbunden. Dazu gehören:

  • Reduzierte Speicheranforderungen: Durch Optimierungen bei einer Scraping-Komponente für kube-state-metrics (KSM) sind hier in groß angelegten Clustern Effizienzgewinne von bis 80 % realisierbar.
  • Vereinfachte Problemdiagnose und -behebung: Logs sowie der Prozess-Cycle wurden im Sinne stärker zielorientierter Fehleranalysen und punktgenauer Fixes optimiert.
  • Mehr Konfigurationsoptionen: Es stehen drei komplett unabhängig voneinander konfigurierbare Komponenten zur Verfügung. Dabei bieten die zugehörigen Konfigurationsdateien feinstufigere Einstellungsmöglichkeiten für die einzelnen Datenquellen.
  • Scraping externer Kontrollebenen: Metrics-Scraping ist nun auch bei Komponenten außerhalb Ihrer Cluster möglich.
  • Flexiblere Scraping-Intervalle: Die Erfassung von Daten lässt sich entsprechend Ihren Anforderungen ausweiten oder verringern.

Verfahren zum Upgrade Ihrer Kubernetes-Integration

Sofern Sie derzeit mit Version 2 arbeiten, erfolgt das Upgrade einfach durch Ausführung des folgenden Befehls:

helm upgrade --install my-installation newrelic/nri-bundle

An Ihren Konfigurationen, Dashboards oder Alerts sind dabei in aller Regel keine Anpassungen vonnöten. Lesen Sie für weitere Einzelheiten hierzu unseren Migrationsleitfaden

Optimierung unserer Kubernetes-Integration: Ein Blick hinter die Kulissen

Das Update, wie es in seiner jetzigen Form vorliegt, ist das Resultat verschiedenster Faktoren, die es zu berücksichtigen und zu erfüllen galt. So bestand eine zentrale Anforderung etwa darin, Kompatibilität mit Version 2 zu gewährleisten, dabei aber zugleich Verbesserungen mit greifbarem Nutzen zu realisieren. Zudem sollte sich das Upgrade auf die neue Integration so einfach für Sie gestalten wie möglich. Nicht zuletzt auch deshalb galt es, die neue Implementierung im Zuge der mit ihr einher gehenden Änderungen der Architektur laufend zu testen.

Eine besonders tiefgreifende Neuerung liegt hier in der mit Version 3 nun vollumfänglichen Nutzung des Deployment-Modells sowie einer Reihe von Features von Kubernetes, die die Integration bislang nicht abdeckte. Um dies klarer nachvollziehbar zu machen, gilt es allerdings, etwas tiefer in die technischen Details zu gehen.

Zentral für die vollumfängliche Nutzung der Kubernetes-Features waren folgende Optimierungen:

  • Einrichtung separater Komponenten für Scraping-Operationen für intelligentere Entscheidungen beim Scheduling und Deployment und nicht erst in der Runtime-Phase
  • Konzeptionelle Anpassung im Sinne einer Sidecar-Struktur zur Abwicklung der Integrations- und Agent-Prozesse in jeweils eigenen Containern und somit gemäß Best Practices für Kubernetes
  • Scraping-Funktionalität für externe Kontrollebenen wie Rancher oder verwaltete apiServer
  • Reduzierung der Komplexität des Cache-Systems anhand von Kubernetes-Informers
  • Unterstützung komplexer Datenstrukturen in den Konfigurationen zur Integration, darunter etwa Listen und Maps
  • Eliminierung des hartcodierten Scraping-Intervalls für Kontrollebenen und somit Flexibilität zur manuellen Anpassung entsprechend den Anforderungen der jeweiligen Anwendung

In den folgenden Abschnitten gehen wir im Detail auf die einzelnen Optimierungen ein.

Voneinander entkoppelte Komponenten

Scraping-Prozesse der Komponenten für KSM und Kontrollebene aus einem DaemonSet können zur Erfassung von Daten-Dubletten führen. Um dem vorzubeugen, erfolgt die Leader-Election nun ortsgesteuert.

In Version 2 veränderte sich das Verhalten des Infrastruktur-DaemonSet abhängig davon, welche Pods innerhalb eines Nodes gemeinsam ausgeführt wurden.

Dazu ist die neue Architektur so angelegt, dass sich die verschiedenen Operationen zur Integration auf separate Komponenten verteilen. Dadurch erfolgt deren Scheduling als jeweils eigener Workload, der über eine für ihn spezifische Konfiguration rund um Ressourcen, Annotations, Logs etc. verfügt. Da es zudem keinen Einfluss mehr auf das Verhalten der Komponenten hat, welche Pods innerhalb des ihnen zugehörigen Nodes ausgeführt werden, sind intelligentere Entscheidungen möglich. Denn so kann die Integration diese bereits beim Scheduling und Deployment fällen, anstatt hierfür bis zur Runtime warten zu müssen. Im nächsten Abschnitt gehen wir darauf näher ein.

In Version 3 wird das Scraping anhand einer neuen Methodik gelöst: Für den Kubelet-Prozess erfolgt es über ein auf dem Node ausgeführtes DaemonSet, für kube-state-metrics und die Metrics und Komponenten für die Kontrollebene auf separaten Deployments. Wichtig hierbei: Die Kontrollebene lässt sich auch als DaemonSet einrichten, falls Ihre Konfiguration dies erfordern sollte.

Version 3 weist eine komplexere Architektur auf, die jedoch mit einer schlankeren Codebase auskommt und so zu einer besseren UX beiträgt.

Die auf diese Weise optimierte Architektur der Integration weist zudem eine weniger umfangreiche Codebase auf. Dies wiederum bedeutet eine bessere UX im Zusammenhang mit der Integration für Sie.

Eliminierung unnötiger Prozesse durch Sidecar-Struktur

Bei Version 2 wurden auf jedem Container diverse Prozesse angelegt: Ausgelöst durch den Agent von New Relic Infrastructure, erfolgte die Ausführung der Integration nri-kubernetes immer als jeweils eigener Prozess. Eine Folge dieser Konstellation: Es werden nur Ausfälle registriert, die den Primärprozess eines Containers betreffen. Denn nur diese haben den Neustart eines Pods zur Folge.

Nun wird die Integration bei Version 2 aber nicht als der primäre Prozess eines Containers ausgeführt. Liegt dann ein Fehler bei der Konfiguration oder Ausführung der Integration vor, wird dies nicht registriert, da kein automatischer Neustart des zugehörigen Pods erfolgt. Dies wiederum erschwert die Erkennung von Problemen. 

Version 3 löst dies durch die Implementierung einer Sidecar-Struktur: Der Scraping-Prozess für nri-kubernetes erfolgt in einem Container, der einem Agent in einem separaten Sidecar zur Seite gestellt wird. Da in jedem Container so nur jeweils ein Prozess abgewickelt wird, erhält Kubernetes Kontrolle über den Lifecycle der Integration: Fällt sie infolge eines Fehlers aus, reagiert das System mit der Ausgabe einer Benachrichtigung und einem Neustart des zugehörigen Pods.

Scraping-Funktionalität für externe Kontrollebenen

Bei Version 2 bestand keinerlei Möglichkeit zum Scraping externer Kontrollebenen – auch nicht durch explizite Angabe einer URL, für die dies durchgeführt werden sollte.

In Version 3 unserer Kubernetes-Integration können Sie hierfür einen statischen Endpunkt definieren. Um einer hieraus ggf. resultierenden Erfassung von Daten-Dubletten vorzubeugen, richten Sie die Kontrollebene einfach als Deployment anstatt als DaemonSet ein.

Hier schematisch dargestellt ist der Scraping-Vorgang, wie er in Version 3 bei der Server-Kontrollebene der AWS API erfolgt.

Ebenfalls lässt sich für die einzelnen Komponenten jeweils spezifisch das Verfahren definieren, nach dem ihre Authentifizierung erfolgen soll. So etwa via Bearer Token oder Mutual Transport Layer Security (MTLS).

Praktisch außerdem: Auto-Discovery und andere Konfigurationen sind bereits standardmäßig enthalten. Unterstützung für Kubernetes-Varianten wie Kubeadm, kind und minikube bietet die Integration so out of the box, für Varianten, die nicht von der Standardkonfiguration abgedeckt werden, sind wiederum Custom-Definitionen möglich: Von der Wahl des Selektors bis hin zur URL und dem Authentifizierungsverfahren bestehen hierbei keinerlei Einschränkungen.

Konfigurationsmethodik auf Basis von Umgebungsvariablen

Ging es darum, die Konfiguration der Integration vorzunehmen, war Version 2 auf Umgebungsvariablen und somit auf Schlüssel-Wert-Paare beschränkt. Gerade für komplexe Szenarien gestaltet sich dies jedoch recht aufwendig. So etwa im Hinblick darauf, dass bei Konfiguration in Form einer flachen Liste ergänzende Präfixe zur Unterscheidung der Gruppenzugehörigkeit der Variablen erforderlich sind. Denn zur Ergänzung jedes neuen Parameters für ineinander eingebettete Konfigurationsgruppen braucht es Umgebungsvariablen mit eindeutigen Präfixes. So kommen etwa DiscoveryCacheTTL, APIServerCacheTTL, APIServerCacheK8SVersionTTL oder APIServerCacheK8SVersionTTLJitter zustande, was sukzessive immer unübersichtlicher wird.

Die neue Version unterstützt dagegen auch komplexere Datenstrukturen auf Listen- und Map-Basis. Dies erfolgt via YAML, in der zudem auch die meisten Parameter der Integration custom angepasst werden können. Der neuen YAML-Konfiguration für das Helm-Diagramm nach erscheint ihre Struktur verglichen mit der Vorgängerversion zwar auf den ersten Blick komplexer. Dies hängt jedoch damit zusammen, dass die Datei values.yaml zusätzlich noch häufig für Helm-Diagramme verwendete Syntax umfasst.

Bei Verwendung des Helm-Diagramms als Installationsmethode erfolgt im Zuge von Konfigurationsänderungen nun zudem automatisch ein Neustart der Instanzen. So wird gewährleistet, dass direkt die Datei mit der neuen Konfiguration geladen wird.

Kein hartcodiertes Scraping-Intervall mehr

Bei Version 2 betrug das Scraping-Intervall 15 Sekunden, hartcodiert. Selbst wenn hierfür Bedarf bestanden hätte, der Wert war partout nicht zu verändern.

Das ist nun passé: Der Parameter ist zur manuellen Konfiguration verfügbar, unterstützt dabei Intervalle in einer Spanne ab 10 bis maximal 40 Sekunden. Standardmäßig sind 15 Sekunden festgelegt, bei Auswahl des lowDataMode zur Reduzierung der abgerufenen Datenmenge wird das Intervall automatisch auf 30 Sekunden erhöht.

Durchgängiges Testing auf dem Weg zur neuen Architektur

Begleitend zu Version 3 stehen Test-Kits zur Validierung der Integration zur Verfügung. Neben Verbesserungen in punkto Discovery zeichnet diese ihr modularer Aufbau aus: Zunächst werden statische Daten generiert, die dann als Referenzsatz in die einzelnen Komponenten eingespeist werden. 

Das Innovative ist dabei die zugrunde liegende Methodik, die durch Abkopplung von der eigentlichen Implementierung durchgängige End-to-End-Tests möglich macht. So wird lediglich ein Diagramm in einer Kubernetes-Umgebung installiert, das zur Verifizierung davon dient, ob gemäß den zugehörigen Konfigurationsdateien alle Entitäten eingerichtet wurden und das Reporting sämtlicher Metrics erfolgt. Dadurch sind die Tests nicht an eine bestimmte Architektur gebunden. Zudem decken sie die gesamte Pipeline ab, sind also auf jede beliebige Version oder Implementierung der Integration anwendbar. So auch im Verlauf der Entwicklung von Version 3. Höchst nützlich waren sie hier etwa dabei, in der Vorgängerversion bestehende Bugs auszumachen und im gleichen Zuge zu beheben.

End-to-End-Tests sind unabhängig von der Architektur möglich, da die gesamte Pipeline rund um sie quasi „ausgeblendet“ wird.

Minimierung upgradebedingter Ausfallrisiken

Das Upgrade auf Version 3 vereinfachen wir mit einem speziellen Layer im Helm-Diagramm, der die Werte aus der Vorgängerversion ihrem aktuell geltenden Pendant zuordnet, um die Vorteile der neuesten Version von nri-kubernetes vollumfänglich und ganz ohne Unsicherheitsfaktoren wie Ausfälle oder Probleme durch Konfigurationsänderungen nutzen zu können.

Abwärtskompatibilität mit Version 2 wird über einen eigenen Layer zur Unterstützung des früheren Werteformats gewährleistet.