Seite wählen

NETWAYS Blog

Kubernetes 101: Wie sichere ich Kubernetes ab?

This entry is part 6 of 6 in the series Alles rund um Kubernetes

In meinen bisherigen Blogposts habe ich dir bereits einige wichtige Aspekte von Kubernetes näher gebracht. Von „Was ist Kubernetes“ über „Wie richte ich Kubernetes auf Linux ein“ zu „Wie installiere ich eine Anwendung in Kubernetes“. Im besten Fall hast du nun bereits Erfahrung in einer laufenden Umgebung sammeln können und bist bei der sogenannten „Day 2 Operation“, also dem alltäglichen, laufenden Betrieb angekommen. Eine Sache, die ich bisher allerdings ein wenig vernachlässigt habe, ist die Absicherung eines Kubernetes Clusters und der darin befindlichen Workloads.
In diesem Punkt ist Kubernetes‚ offener Standard Fluch und Segen gleichzeitig: Während die einfach erweiterbare Funktionalität ein großes Plus von Kubernetes ist, ist das Fehlen (fast) jeglicher Konfiguration von Security und Policing „out of the box“ definitiv ein großes Minus.
Deswegen zeige ich dir in diesem Beitrag, wie du in diesem Bereich nachbesserst!

Wie ist Kubernetes aufgebaut?

Wenn du meine bisherigen Blogposts verfolgt hast (oder bereits Erfahrung mit Kubernetes gesammelt hast) weißt du: Kubernetes ist ein verteiltes System.
Auf mehreren Nodes werden containerisierte Workloads geplant, die dann die eigentlichen Anwendungen ausführen. Hinzu kommen je nach Kubernetes-Distribution mehrere lokal auf dem jeweiligen Node laufende Services (bspw. Kubelet, kube-apiservercontainerd, etc.) sowie Container, die aufgrund ihrer Aufgaben manchmal erweiterte Privilegien auf den Nodes genießen. Etwa um den clusterinternen Netzwerkverkehr zu regeln oder im Cluster verteilten Speicher bereitstellen zu können.
Es gibt also eine einigermaßen klare Trennung zwischen Clusterinfrastruktur und Workloads, die in einer idealen Welt auch nur wenig miteinander zu tun haben (sollten). Eine Anwendung sollte schließlich in der Lage sein, ordnungsgemäß laufen zu können, ohne dass sie Kenntnisse über ihre Laufzeitumgebung (in diesem Fall Kubernetes) besitzt.
Wie klar diese Trennung in der Realität auch ausfallen mag, im Folgenden werde ich die zwei Welten und mögliche Ansatzpunkte für mehr Sicherheit getrennt voneinander betrachten.

Clustersicherheit bei Kubernetes

Wie bereits eingangs erwähnt, ist ein Kubernetes Cluster nach seiner Installation nicht unbedingt umfassend abgesichert – das beginnt bereits beim Zugriff auf das Kubernetes Cluster. Die kubeconfig, mit der du als Admin normalerweise arbeitest, ist mit maximalen Privilegien ausgestattet und sollte unter keinen Umständen verteilt oder von anderen Nutzern verwendet werden.
Deshalb solltest du weiteren User:innen einen alternativen Clusterzugriff (und damit verknüpfte Regeln) einrichten.

Zugriff und Zugriffskontrolle einrichten

Von Haus aus besitzt Kubernetes ein feingranular einstellbares RBAC-System (Role-based Access Control), mit dem sich grundsätzlich gut arbeiten lässt: Mittels (Cluster-)Roles, (Cluster-)RoleBindings und Usern bzw. ServiceAccounts lassen sich Verknüpfungen zwischen beliebigen Sets an Privilegien und einzelnen, im Cluster agierenden, Identitäten herstellen.
Für jede Gruppe an existierenden API-Objekten können durch Verbs die Privilegien entweder auf Namespace– oder auf Cluster-Ebene eingestellt werden. Die verfügbaren Verbs sind getlistcreateupdatepatchwatchdelete, und deletecollection und implizieren verschiedene Privilegien für die verknüpften API-Objekte.

Möchtest du eine hierarchische Struktur mehrerer Rollen erreichen, kannst du mehrere Clusterrollen zu einer übergeordneten Clusterrolle aggregieren. Auf diese Weise behältst du den Überblick, auch wenn die Anzahl an verfügbaren Rollen mit der Zeit wachsen sollte.
Überblick ist zudem ein gutes Stichwort, denn ab einer gewissen Anzahl an Rollen, Nutzern und Verknüpfungen zwischen den beiden Konzepten leidet unweigerlich die Übersichtlichkeit des Berechtigungskonstrukts. Zwar liefert Kubernetes‘ CLI kubectl mit dem Cmdlet auth can-i eine Möglichkeit des Auditings mit (siehe Auflistung aller Berechtigungen des Standard-Adminusers für den Namespace default unten), das Gelbe vom Ei ist dieser Ansatz der Nutzerverwaltung ab einer gewissen Clustergröße nicht mehr.

Oder möchtest du regelmäßig für alle User deines Clusters manuell die Berechtigungen prüfen?

kubectl auth can-i --list --namespace=default
Resources                                       Non-Resource URLs   Resource Names   Verbs
*.*                                             []                  []               [*]
                                                [*]                 []               [*]
selfsubjectaccessreviews.authorization.k8s.io   []                  []               [create]
selfsubjectrulesreviews.authorization.k8s.io    []                  []               [create]
                                                [/api/*]            []               [get]
                                                [/api]              []               [get]
                                                [/apis/*]           []               [get]
                                                [/apis]             []               [get]
                                                [/healthz]          []               [get]
                                                [/healthz]          []               [get]
                                                [/livez]            []               [get]
                                                [/livez]            []               [get]
                                                [/openapi/*]        []               [get]
                                                [/openapi]          []               [get]
                                                [/readyz]           []               [get]
                                                [/readyz]           []               [get]
                                                [/version/]         []               [get]
                                                [/version/]         []               [get]
                                                [/version]          []               [get]
                                                [/version]          []               [get]

 

Eine bessere Verwaltungsmöglichkeit für unsere Kubernetes Cluster User ist also dringend angeraten, sowohl aus Gründen der Übersichtlichkeit als auch der Sicherheit. Bei immer mehr Nutzern und komplexeren Berechtigungsstrukturen ist es sonst nur eine Frage der Zeit, bis bei einem Nutzer die falschen Berechtigungen gesetzt werden. Schaut man sich das Angebot an verfügbaren Lösungen für Zugriffskontrolle auf Kubernetes an, stechen ein paar Projekte heraus:

Als SUSE Partner setzen wir bei mehreren Kunden erfolgreich Rancher ein, ein Open-Source Tool zur ganzheitlichen Verwaltung von Clustern in der Cloud und on premise. Rancher setzt mit seinem Berechtigungskonzept direkt auf Kubernetes‘ RBAC-Modell auf und erweitert es um Projekte, die eine Abstrahierung um einen oder mehrere Namespaces bilden.
Das Web-Frontend bietet die Möglichkeit, (Cluster-)Rollen mit einzelnen Usern oder Usergruppen aus der in Rancher integrierten Benutzerverwaltung zu verknüpfen, zu auditieren und sich einen schnellen Überblick darüber zu verschaffen, welcher User in welchem Cluster welche Berechtigungen hat.

Grundlage für das Berechtigungskonzept sowohl in Rancher’s WebUI als auch in den verwalteten Clustern bieten die vielen verschiedenen Authentifizierungsplugins: Rancher unterstützt LDAP (z.B. Active Directory, OpenLDAP, AzureAD), OAuth (z.B. Google, GitHub), OIDC (z.B. Keycloak) und SAML (z.B. Okta, Shibboleth, ADFS).

Ein weiteres bewährtes Tool zur Zugriffskontrolle für u.A. Kubernetes ist Teleport, das ebenfalls eine Open-Source Software ist und kostenlos genutzt werden kann. Teleport fungiert als vorgelagerter Proxy, der die Anfragen an das Cluster terminiert, den Nutzer authentifiziert und authorisiert und diese Anfragen dann weitergibt. Stärken von Teleport sind zum Beispiel Policy-as-Code, umfangreiche Auditierbarkeit aller Zugriffe und vergangenen Sitzungen sowie die Kompatibilität nicht nur mit Kubernetes, sondern auch anderen gemanagten oder selbst betriebenen Services und Cloudressourcen.

Netzwerkabsicherung bei Kubernetes

Die Zugriffskontrolle für Endnutzer und Serviceaccounts, also handelnde Identitäten, haben wir nun abgearbeitet. Doch wie steht es mit Zugriffsversuchen, die von Services inner- und außerhalb des Clusters stammen und anderweitig beschränkt werden müssen? Schließlich besteht je nach Architektur und genutzten Dritt-Tools selbst ein „leeres“ Cluster aus (bis zu) mehreren hundert Containern, die untereinander kommunizieren (wollen), sich Updates aus dem Internet ziehen oder andere Services innerhalb der Infrastruktur deines Unternehmens (z.B. AD-Server) erreichen müssen.

Per Default können all diese Container das auch erst einmal ungestört. Kubernetes besitzt out-of-the-box kein Konzept einer „Firewall“ oder ähnlicher Maßnahmen, die den Netzwerkverkehr einschränken könnte. Weder in Ost-West, noch in Nord-Süd-Richtung, übrigens. Hierfür bedarf es eines Container Network Interfaces (CNI), das in der Lage ist, NetworkPolicies zu interpretieren und umzusetzen.
NetworkPolicies sind ein natives Konzept der Kubernetes-API, deren Umsetzung aber an externe CNIs übergeben wird. Ohne passendes CNI also keine Einschränkung des Netzwerkverkehrs.

Das Angebot an verfügbaren CNIs ist recht groß, beliebte Lösungen mit Support für NetworkPolicies auf Namespaceebene und teilweise einer ganzen Bandbreite weiterer Features (BGP-Routing, Nodefirewall, Networkpolicies auf Clusterebene) sind bspw. Cilium bzw. Calico.

„Best Practices“ für das Einrichten von Networkpolicies in Kubernetes gibt es wie Sand am Meer. Welche Blaupause für dein Unternehmen sinnvoll und geeignet sein könnte, ist meist eine Einzelfallentscheidung. Ein oft gesehenes Muster ist eine „globale“ NetworkPolicy über alle Namespaces hinweg (das CNI muss dieses Feature mitbringen!), die keinerlei Ingress bzw. Egress bis auf Anfragen an den clusterinternen DNS-Service erlaubt.
Auf diese Weise sperrst du sämtlichen Netzwerkverkehr, der nicht innerhalb eines einzigen Namespaces stattfindet und etablierst ein „Opt-in“-Modell, bei dem die Operatoren der Anwendungen bei Deployment die benötigten Networkpolicies mitdeployen müssen. Einziges Caveat hierbei ist, dass eventuell bereits vorhandene Infrastruktur im Cluster natürlich ebenfalls von den Regelungen betroffen ist.  Es ist deshalb ratsam, dass also ein etwas genauerer Namespace-Filter als „alle Namespaces“ zum Einsatz kommt.

Ressourcenverwaltung in Kubernetes

Ein weiterer wichtiger Punkt neben Zugriffskontrolle und Netzwerkpolicies ist das Verwalten der im Cluster vorhandenen Ressourcen. Der Grund hierfür ist einfach – hat ein Pod die Möglichkeit, alle Ressourcen eines Nodes für sich zu beanspruchen, nimmt er allen anderen Workloads auf diesem Clusternode buchstäblich die Luft zum Atmen. Doch nicht nur „herkömmliche“ Ressourcen wie Arbeitsspeicher und CPUs sollten reguliert sein – auch abstraktere Dinge wie PIDs oder Sockets können zum Problem werden – die in Pods laufenden Container befinden sich schließlich nach wie vor in Namespaces des jeweiligen Nodes. Spielt ein Container verrückt, kann das unangenehme Nachwirkungen für den gesamten Node nach sich ziehen. So kann beispielsweise mit einer Fork Bomb ein Denial of Service (DoS) erreicht werden.

Fälle wie oben beschrieben gilt es natürlich zu unterbinden – für Arbeitsspeicher und CPUs lässt sich das entweder auf Container– oder Namespaceebene umsetzen: Für Container innerhalb eines Pods können unterhalb des Felds resources sowohl requests als auch limits gesetzt werden. Was hier konkret eingetragen werden sollte, um einen möglichst reibungslosen Betrieb bei möglichst kompletter Auslastung eines Nodes durch die dort geschedulten Workloads herzustellen, ist eine seit Jahren diskutierte Frage. Die inzwischen häufigste Antwort lautet:

Für CPUs sollten Requests, aber keine Limits gesetzt werden. Für Arbeitsspeicher sollten Requests==Limits gesetzt werden.

Die Gründe für diese Richtlinie mögen etwas unklar sein, ohne tiefer darauf einzugehen, deswegen verlinke ich an dieser Stelle zwei Blogposts – einen zum Thema CPU-Limits und einen zu Memory-Limits, inklusive lustiger Vergleiche 😉.

An dieser Stelle neben den gängigsten Verwaltungseinstellungen für CPUs und Arbeitsspeicher auf all die anderen zu berücksichtigenden Stellschrauben für sichere Workloads in Kubernetes einzugehen, würde den Rahmen dieses als Überblick gedachten Posts sprengen – deswegen hier nur eine kurze Auflistung einiger Dinge, die man im Hinterkopf behalten sollte:

  • PID Limits für Pods, Nodes und PID-based eviction
  • (un)privilegierte Container
  • Sicherheitskontexte für Container
  • zusätzliche Policies (bspw. Nutzung von ausschließlich signierten Images)
  • Handhabe von Secrets (bspw. Verschlüsselung at rest)

Nodesicherheit sicherstellen

Neben den einzelnen Workloads und Netzwerkverkehr im Cluster muss man natürlich auch die Nodes, aus denen das Cluster besteht, ordentlich absichern. Insbesondere gilt es, die Nodes des Controlplanes, auf denen typischerweise auch etcd mitläuft, abzusichern – Zugriff auf etcd ist gleichzusetzen mit unbegrenztem schreibenden Zugriff auf das Cluster selbst.

Für die Absicherung von Nodes können klassische Technologien wie lokale Firewalls, SELinux oder AppArmor und beliebige weitere Härtungsmaßnahmen zum Einsatz kommen. Doch auch hier gibt es einige Cloud-Native-Technologien, die helfen können:
So unterstützen einige CNIs das Einrichten von Networkpolicies auf Node-Level. Mit nur einem Tool kann also nicht nur Netzwerkverkehr im Cluster reguliert werden, sondern in erweitertem Rahmen auch schon auf den vorgelagerten Nodes selbst.

Darüber hinaus gibt es einige Tools, die in der Lage sind, die komplexen Abläufe, die im Kontext von Kubernetes im Kubelet, den Pods und der Containerlaufzeitumgebung vor sich gehen, zu durchleuchten und ungewünschtes Verhalten zu unterbinden. Oftmals kommt hierbei eBPF zum Einsatz, eine Technologie, die die modulare Erweiterung des Betriebssystemkernels mit kleinen Programmen ermöglicht.

Anwendungssicherheit erhöhen

Ist das Cluster erst einmal abgesichert, kann man sich den darauf betriebenen Anwendungen widmen – auch wenn einige Mechanismen aus dem vorherigen Abschnitt bereits greifen sollten, beispielsweise Netzwerkpolicies und Ressourcenverwaltung.
Damit ist es jedoch in vielen Organisationen nicht getan – vielleicht gibt es Richtlinien, welche Images genutzt werden dürfen, aus welchen Registries sie bezogen werden sollen, ob gewisse Scans laufen müssen oder ob gewisse Signaturen erforderlich sind. Und übrigens dürfen auch anfangs grob geschätzte Ressourcenlimits anhand der tatsächlichen Leistungsdaten angepasst werden 😉.

Für viele dieser Zwecke gibt es Werkzeuge, die das Einrichten individueller Policies im Cluster ermöglichen. Die am weitesten verbreiteten sind zum Einen der Open Policy Agent und zum Anderen Kubewarden. Mit solchen Tools lassen sich verschiedenste Policies entsprechend den Vorgaben eurer Organisationen und Prozesse definieren die -as-Code vorliegen, versioniert und deployed werden können.

Für das Scannen von Workloads und deren Konfiguration gibt es ebenfalls etablierte Lösungen zum Beispiel Trivy oder Kubescape.
Beide Lösungen ermöglichen die Integration von CI/CD-Pipelines, um Sicherheitsrisiken und Misskonfigurationen noch vor Deployment zu bemerken und darauf reagieren zu können.
Trivy bietet darüber hinaus einen Operator, der in regelmäßigen Abständen aus dem Cluster herausselbstständig nach Sicherheitslücken suchen kann.

Für das Finetuning von Ressourcenrequests oder -limits benötigst du hingegen in erster Linie Metriken. Diese können aus verschiedenen Quellen stammen, die sich unter dem Begriff Observability zusammenfassen lassen. Mit Hilfe von Prometheus können so zum Beispiel Performancedaten wie genutzter Arbeitsspeicher, CPU-Last, Netzwerkverkehr auf Anwendungsebene nachvollzogen werden, sofern die Anwendung entsprechend instrumentalisiert wurde.
Mithilfe dieser Daten lassen sich dann Rückschlüsse ziehen ob wir mit unseren initial gewählten Ressourcerequests/limits zu großzügig oder doch eher zu optimistisch umgegangen sind und nun nachbessern.

Ein weiteres Tool zur Erkennung von zu lockeren oder fehlenden Ressourcerequests/limits ist KRR (Kubernetes Resource Recommender), das ebenfalls anhand von Prometheus-Daten die bestehenden Konfigurationen für Pods analysiert und Verbesserungen vorschlägt.

Zu voll umfänglicher Anwendungssicherheit gehört jedoch auch die Absicherung und Überwachung der CI/CD-Pipeline mit der die Anwendung erstellt bzw. ausgeliefert wird. Hier empfiehlt sich die Orientierung an Frameworks wie SLSA (Supplychain Levels for Software Artifacts), eine von Google veröffentlichte Sammlung an Empfehlungen für Software-Entwickler, wie und wo sie ihre Anwendungen härten sollten.
Zusätzlich lassen sich Anwendungen auch im Betrieb in Kubernetes (automatisiert) überwachen. So erlauben Tools wie NeuVector, in Containern ausgeführte Prozesse und versuchte/erfolgte Netzwerkaufrufe zu protokollieren, gewünschtes Verhalten zu „erlernen“ und nicht vorgesehene Aufrufe in Echtzeit zu unterbinden.

Fazit

Am Ende eines weiteren Blogposts in unserer „Kubernetes 101“ Reihe angekommen stellen wir einmal mehr fest: Kubernetes ist komplex.

Eine Vielzahl an Tools können in Sachen Security in Betracht gezogen haben und welcher „Stack“ letzten Endes für eure Anforderungen ausreichend und passend ist muss sich oft erst einmal herausstellen. Nicht zur Diskussion steht, dass eben aufgrund dieser Komplexität eine voll umfängliche Absicherung des Clusters als Plattform und der darin laufenden Anwendungen (ab dem Moment ihrer Entwicklung) oberste Priorität haben sollte. Denn ist erst einmal „der Wurm drin“ kann es ansonsten schwierig werden, Sicherheitslücken klar zu benennen, „den Schuldigen“ zu finden und das Ausmaß der Kompromittierung einzuschätzen.

Sollte dir dieser Blogpost gefallen haben, schau doch gerne noch die anderen in dieser Serie erschienenen Artikel an.
Und solltest du auf den Geschmack gekommen sein, aber an manchen Stellen noch Hilfe in Sachen Kubernetes brauchen, schau entweder einmal bei unseren Trainings zum Einstieg in Kubernetes vorbei oder buche direkt Consulting zu (fast) Allem rund um Kubernetes bei mir oder meinen Kolleg:innen.

Daniel Bodky
Daniel Bodky
Consultant

Daniel kam nach Abschluss seines Studiums im Oktober 2021 zu NETWAYS und berät nun Kunden zu den Themen Icinga2 und Kubernetes. Nebenher schreibt er in seiner Freizeit kleinere Tools für verschiedenste Einsatzgebiete, nimmt öfters mal ein Buch in die Hand oder widmet sich seinem viel zu großen Berg Lego. In der wärmeren Jahreszeit findet man ihn außerdem oft auf dem Fahrrad oder beim Wandern.

NETWAYS stellt sich vor – Daniel Bodky

This entry is part 54 of 58 in the series NETWAYS stellt sich vor

 

Name: Daniel Bodky

Alter: 25

Studium: B.A. Linguistische Informatik

Position bei NETWAYS: Consultant

Bei NETWAYS seit: Oktober 2021

 

 

Wie bist Du zu NETWAYS gekommen und was genau gehört zu Deinem Aufgabenbereich?

Zu NETWAYS gekommen bin ich in erster Linie, weil ich nach meinem Abschluss keine Lust auf einen weiteren Abschluss unter ungewissen (und teils einfach schlechten) Umständen aufgrund der Pandemie mehr hatte. Da ich während meines Studiums bereits als Werkstudent bei einem großen Medizintechnikunternehmen eine Icinga-Umgebung betreut hatte, war es ein naheliegender Schritt, mich bei dem Icinga-Experten, noch dazu in der Region, zu bewerben – und das hat super geklappt.
Dementsprechend startete ich auch mit einem Aufgabenbereich, der sich größtenteils auf Icinga2 konzentrierte, mit gelegentlichen Abstechern zu GitLab. Nach und nach hat sich das aber etwas verschoben, weg von Icinga2 und hin zu Docker, Kubernetes und DevOps im Allgemeinen. Gelegentliche Ausflüge zurück zu Icinga2 sind allerdings trotzdem noch möglich und machen mir nach wie vor Spaß.

Ganz egal um welches Themengebiet es geht, bin ich als Consultant natürlich in erster Linie für die Beratung von Kunden und ihren Projekten zuständig. Das kann von Reviews vorhandener Umgebungen und Projekte über die Erarbeitung von Plattformarchitekturen bis hin zu einer gemeinsamen Umsetzung erst einmal alles bedeuten. Am meisten Spaß macht es mir, wenn Theorie und Praxis Hand in Hand gehen, und ich weder ausschließlich über die Schulter des Kunden auf seinen Bildschirm schaue, noch alles alleine machen muss. So lernen meist beide Seiten etwas Neues, vorhandenes Wissen kann sich weiter „festklopfen“, und man kennt sich auch beim nächsten „Besuch“ noch aus.

 

Welche größeren, besonders interessanten Projekte stehen künftig an?

Puh, schwierige Frage. Grundsätzlich ist es gerade rund um das Thema Kubernetes so, dass viele Unternehmen gerade erst das Potenzial dieser Technologie und die damit einhergehenden Implikationen für sich entdecken – und teilweise möglichst schnell „umsteigen“ möchten. Hier gilt es dann, eine gesunde Strategie zu finden, nicht überhastet zu reagieren und die richtigen Lösungen für die gestellten Anforderungen zu finden. Das klingt erstmal nach einer Menge Stress, kann aber auch sehr lehrreich sein und wenn das Resultat passt, ist man enorm happy.
Darüber hinaus bin ich als Trainer für unsere Kubernetes- und GitLab-Trainings auch in die Weiterentwicklung der Trainings involviert, was deren Inhalt, Didaktik und Aufmachung angeht. Gemeinsam mit den anderen Trainern mache ich mir also von Zeit zu Zeit Gedanken, was man besser, interessanter, oder interaktiver gestalten könnte, und wenn das Feedback nach dem nächsten Training wieder etwas besser wurde, ist auch das immer ein interessantes und schönes Projekt.

 

Wie gefällt es Dir bisher bei NETWAYS?

Ich bin ja nun bereits etwas länger bei NETWAYS, und muss sagen – Vieles! Egal, ob gemeinsame Konferenzbesuche mit Kolleg:innen aus verschiedenen Abteilungen, die gelegentlich stattfindenden, mehr oder weniger geplante Bürofeiern, das Teamwochenende, oder unsere Amsterdamfahrt im vergangenen Sommer, bei uns gibt’s immer was zu feiern oder zumindest Gelegenheit und Mitstreiter, um einfach so eine gute Zeit zu haben, auch während der Arbeitszeit. Gerade arbeite ich z.B. mit meinem Kollegen Alex gemeinsam an einem größeren Kundenprojekt, unsere Trainings halten wir fast immer zu zweit, die Azubis kommen ungezwungen auf einen zu und man kommt ins Gespräch – es geht hier einfach sehr freundschaftlich zu.

 

Was machst Du, wenn Du mal nicht bei NETWAYS bist?

Was ich mache, wenn ich nicht bei NETWAYS bin, hängt auch etwas am Wetter bzw. den Jahreszeiten – seit einigen Wochen fahre ich wieder viel Fahrrad und gehe hin und wieder wandern Im Winter verlagern sich meine Hobbies eher nach innen, zum gelegentlichen Bouldern mit Freunden oder zu meiner Legosammlung. Eine Konstante, die sich fast allabendlich durchs Jahr zieht, sind zum einen Computerspiele mit Freunden aus Nah und Fern und zum anderen mehrere Programmierprojekte, die ich in meiner Freizeit verfolge (und die meistens im Sand verlaufen 😉). Seit ich bei NETWAYS mit dem Thema Kubernetes in Kontakt gekommen bin, probiere ich auch in meiner Freizeit öfters neue Technologien rund um das Thema aus, einfach, weil es mir Spaß macht und ich es auch nach Feierabend noch interessant finde.

 

Wie geht es in Zukunft bei Dir weiter?

Das kann man natürlich nie so ganz genau wissen, deshalb ist es ja schließlich die Zukunft – aber Vorstellungen, Wünsche und Ziele habe ich natürlich! Zum Einen habe ich schon während dem Studium gerne vor Publikum gesprochen und konnte das fast nahtlos bei NETWAYS weiterführen, in diesem Jahr bereits mit Talks in Tampa, Berlin, und im Juni in Amsterdam. Hier möchte ich dranbleiben, und die Qualität meiner Talks in 2024 nach und nach verbessern – denn da ist auf jeden Fall noch Luft nach oben. Für unser noch sehr kleines Team an „Kubernetes-Consultants“ würde ich mir noch etwas Zuwachs wünschen, um auch umfangreichere Projekte angehen zu können und von der jeweiligen Expertise profitieren zu können, aber das ist sicherlich nur eine Frage der Zeit. Ansonsten möchte ich einfach weiterhin einen guten Job machen, mich in meinem Feld weiterentwickeln und spannende Projekte umsetzen – mal schauen, was sich ergibt!

Daniel Bodky
Daniel Bodky
Consultant

Daniel kam nach Abschluss seines Studiums im Oktober 2021 zu NETWAYS und berät nun Kunden zu den Themen Icinga2 und Kubernetes. Nebenher schreibt er in seiner Freizeit kleinere Tools für verschiedenste Einsatzgebiete, nimmt öfters mal ein Buch in die Hand oder widmet sich seinem viel zu großen Berg Lego. In der wärmeren Jahreszeit findet man ihn außerdem oft auf dem Fahrrad oder beim Wandern.

Kubernetes 101: Anwendungen in Kubernetes skalieren

This entry is part 5 of 6 in the series Alles rund um Kubernetes

Für viele Anwender ist die einfache Skalierbarkeit und Flexibilität von Anwendungen im Cluster der Hauptgrund für einen Umstieg auf Kubernetes. Doch auch hier geschieht nichts (oder nur sehr wenig) „magisch“ und von allein. Anwendungen müssen bereits zum Zeitpunkt der Entwicklung in Hinblick auf diese gewünschte Flexibilität gebaut und die Deployments entsprechend konfiguriert werden. Natürlich spielt die Infrastruktur, auf der K8s selbst läuft, ebenfalls eine wichtige Rolle. Aber bevor wir direkt zu tief einsteigen, fangen wir doch erstmal mit den Basics an und klären zunächst ein paar Begrifflichkeiten.

Bei Deployments handelt es sich um eine von Kubernetes definierte Abstraktion von zu betreibenden Anwendungen. Anstelle einer konkreten Konfiguration für genau einen Pod wird ein sogenanntes Template definiert, quasi eine Vorlage für eine beliebige Anzahl an zu betreibenden Pods. Durch diese Abstraktion können mehrere Pods des gleichen Deployments gebündelt betrachtet und verwaltet werden, was mehrere Vorteile mit sich bringt – unter anderem eine einfachere Skalierung.

Willst du deine Anwendungen nun skalieren, ist es wichtig den Unterschied zwischen horizontaler Skalierung und vertikaler Skalierung (Scaling out vs. Scaling up) zu verstehen.
Horizontale Skalierung beschreibt das Hinzufügen neuer Pods (oder Nodes, auf Clusterlevel) zum Cluster, um beispielsweise Anfragespitzen eines Webshops o.Ä. zu bewältigen. Vertikale Skalierung hingegen bezeichnet das Hinzufügen von mehr Ressourcen zu bestehenden Pods oder Nodes, beispielsweise in Form von mehr vCPUs oder Arbeitsspeicher.

Nachdem wir jetzt die wichtigsten Begriffe geklärt haben und (hoffentlich) auf dem gleichen Wissensstand sind, steigen wir ordentlich in das Thema Skalierung auf K8s ein!

Skalierung von Deployments

Wenn du und dein Team den Plan verfolgen Anwendungen auf Kubernetes skalieren, hast du dafür mehrere Möglichkeiten. Zum einen die grundlegende Unterscheidung zwischen horizontalem und vertikalem Scaling, zum anderen die Frage, ob und wie diese Skalierung automatisiert werden kann. Für Workload-Skalierung wird meistens horizontales Scaling genutzt. Wie du bereits weißt, ist das gleichbedeutend mit dem Hinzufügen neuer Pods zu dem bestehenden Deployment. Das kannst du theoretisch manuell umsetzen, bspw. mittels eines kubectl Befehls:

kubectl scale --replicas=5 deployment/application-a

In diesem Beispiel weist man Kubernetes‘ API an, das Deployment application-a auf 5 Pods zu skalieren. K8s kümmert sich dann automatisch um den Rest. Optional können bei Verwendung von kubectl auch Voraussetzungen mitgegeben werden, die für eine Skalierung notwendig sind, etwa die Anzahl momentan laufender Pods oder eine erwartete Versionsnummer. Treffen die Voraussetzungen nicht zu, wird auch keine Skalierung vorgenommen.

Du merkst, der manuelle Ansatz funktioniert relativ simpel. Er bringt aber auch einige Schwierigkeiten mit sich! So müssen bestehende Deployments kontinuierlich auf die Anzahl ihrer Repliken geprüft werden. Denn nach einer Skalierung der Deployments auf mehr Repliken z. B. aufgrund von hoher Last auf der Anwendung, kann diese nicht automatisch wieder herunterskaliert werden. Hier lassen sich also sehr einfach Geld und Clusterressourcen verschwenden.
Des Weiteren muss jede Skalierung, egal in welche Richtung, von einem Clusternutzer mit entsprechenden Rechten vorgenommen werden. Und ab einer gewissen Anzahl an Skalierungsanfragen ist diese Art zu arbeiten einfach nicht mehr praktikabel. Es benötigt also eine Form der Automatisierung.

Voraussetzungen für automatisierte Skalierung

Damit du eine automatisierte Skalierung von Deployments aber überhaupt durchführen kannst, ist ein entsprechender Controller im Cluster notwendig. Dieser muss zum Einen die zu definierenden Anforderungen an die Deployments erkennen und (re-)evaluieren, und zum anderen die daraus resultierenden Skalierungen vornehmen. Das Kubernetes-Projekt bietet hier sowohl für horizontales Autoscaling als auch für vertikales Autoscaling einen entsprechenden Controller:

Egal für welche Vorgehensweise du dich entscheidest, die Controller übernehmen die gleiche Aufgabe. Sie prüfen in einem zu definierenden Intervall (standardmäßig alle 15 Sekunden), ob die festgelegten Grenzwerte für ein Auf- oder Herunterskalieren des betroffenen Deployments über- bzw. unterboten werden und passen die Anzahl an Repliken entsprechend an.
Für die Konfiguration dieser Grenzwerte gibt es eine eigene API-Ressource namens HorizontalPodAutoscaler.

Eine weitere Voraussetzung der automatisierten Skalierung ist die Installation des sogenannten Metricsservers. Er übernimmt die Aufgabe, deine Pod- und Containermetriken innerhalb des Clusters zu aggregieren und via Kubernetes-API für beliebige Drittanwendungen bereitzustellen – zum Beispiel für unsere Autoscaler.

Einrichtung automatisierter Skalierung

An diesem Punkt habe ich dir hoffentlich die Vorteile einer automatisierten Skalierung näherbringen können und du kannst es kaum abwarten, selbst damit loszulegen. Dafür kannst du dich (wie so oft) zwischen zwei Möglichkeiten entscheiden: Imperativ durch einen kubectl Befehl oder deklarativ durch ein Kubernetes-Manifest. Um dir beide Varianten besser zu veranschaulichen, habe ich Beispiele für den HorizontalPodAutoscaler eines Deployments nginx geschrieben.

Imperativ

kubectl autoscale deployment php-apache --cpu-percent=50 --min=1 --max=10

Deklarativ

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: nginx
  namespace: default
spec:
  maxReplicas: 10
  metrics:
  - resource:
      name: cpu
      target:
        averageUtilization: 50
        type: Utilization
    type: Resource
  minReplicas: 1
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: nginx

Beide Varianten erstellen ein HorizontalPodAutoscaler Objekt, dass das Deployment nginx bei durchschnittlicher Auslastung von 50% hochskaliert bzw. bei 0% in einen Bereich zwischen 1-10 Pods herunterskaliert. Auf diese Weise lassen sich Kubernetes Deployments automatisch horizontal skalieren, die Grenzwerte sind dabei seit API-Version 2 des HorizontalPodAutoscalers sehr flexibel konfigurierbar.

Anstatt lediglich auf ein von der Kubernetes-Metrics-API bereitgestelltes Attribut zu schauen (CPU-Last/Memory) können mehrere Attribute kombiniert werden oder sogar externe Messwerte verglichen werden, beispielsweise resultierend aus einer Überwachung mittels PrometheusAußerdem können statt der Metriken von Pods die einzelnen Metriken für Container als Basis des Autoscalings genutzt werden.

Und auch ansonsten bietet die API-Definition des HorizontalPodAutoScalers eine Bandbreite an konfigurierbarem Verhalten. So lässt sich mittels Scaling Policies das Skalierungsverhalten für Hoch- bzw. Herunterskalierung separat einstellen. Etwa wenn du Kubernetes Pods schnellstmöglich hochfahren lassen willst, der Abbau überflüssiger Pods aber in Erwartung weiterer Lastspitzen langsam stattfinden soll.
Ein weiteres nützliches Feature ist die Existenz der Eigenschaft StabilizationWindowSeconds, die eine Art Filter für Flappingalso stark und häufig wechselndes Verhalten der beobachteten Metriken, darstellt. Eine genauere Auseinandersetzung mit den Konfigurationsmöglichkeiten des HorizontalPodAutoscalers würde den Rahmen dieses Blogposts sprengen, stattdessen verweise ich einmal mehr auf die oben verlinkte offizielle Dokumentation.

Der VerticalPodAutoscaler ist noch in einer frühen Betaversion (momentan v0.13.0) und deswegen noch nicht in der offiziellen Kubernetes Dokumentation enthalten. Eine Auflistung seiner Fähigkeiten und Dokumentation findet sich im oben verlinkten Repository des Projekts.

Skalierung von Nodes

Hast du über einen längeren Zeitraum eine hohe Last auf deinem Cluster, und/oder wurden nach und nach immer mehr verschiedene Deployments hochskaliert, kann es passieren, dass die Nodes des Clusters selbst an die Grenzen ihrer Ressourcenkapazitäten zu gelangen. Auch hier hat man nun die Möglichkeit, horizontal oder vertikal zu skalieren, um das Cluster weiter funktionsfähig zu halten.
Für die horizontale Skalierung eines Kubernetes-Clusters stellt das Kubernetes-Projekt auf GitHub den Cluster-Scaler zur Verfügung, der in der Lage ist, dynamisch Nodes bei einer Vielzahl an Public-Cloud-Providern zu (de-)provisionieren.

Die vertikale Skalierung der Nodes eines Kubernetes-Clusters kann dir noch nicht durch einen Controller abgenommen werden – hier ist manuelle oder extern automatisierte Arbeit notwendig. Hast du also deine Kubernetes-Cluster auf VMs aufgesetzt, kannst du deren zugewiesene Ressourcen (vCPUs, Arbeitsspeicher, Festplattenspeicher) anpassen. Läuft Kubernetes als „Managed Kubernetes„, ist es oftmals möglich, die Node Pools anzupassen zu einer leistungsstärkeren Klasse an Nodes.

 

Fazit

Auf den ersten Blick erscheint die Skalierung von Workloads und des Clusters selbst, wie so viele Dinge rund um Kubernetes, als machbares Vorhaben. Dank kubectl und der von der API angebotenen Objekttypen in Kombination mit den vorhandenen Autoscalern können Workloads sowohl imperativ als auch deklarativ und horizontal sowie vertikal skaliert werden. Für Cluster in der Cloud lassen sich auch Nodes horizontal skalieren.

Geht man allerdings weiter ins Detail, findet man viele Stellschrauben, fortgeschrittene Konzepte und Designfragen, die es bei der Definition eines Autoscaler-Objekts zu beachten gilt. Hier ist die Erfahrung der zuständigen Clusteradministratoren gefragt, um die Kapazitäten des Clusters durch Autoscaling optimal zu nutzen, ohne Ressourcen unnötig zu verschwenden oder Workloads zu spät oder gar nicht zu skalieren.
Auch Monitoring der Workloads kann helfen, um nach und nach ein Gespür für zu erwartende Auslastung des Kubernetes-Clusters zu bekommen und das Autoscaling einiger oder gar aller Anwendungen im Cluster feinjustieren zu können.

Daniel Bodky
Daniel Bodky
Consultant

Daniel kam nach Abschluss seines Studiums im Oktober 2021 zu NETWAYS und berät nun Kunden zu den Themen Icinga2 und Kubernetes. Nebenher schreibt er in seiner Freizeit kleinere Tools für verschiedenste Einsatzgebiete, nimmt öfters mal ein Buch in die Hand oder widmet sich seinem viel zu großen Berg Lego. In der wärmeren Jahreszeit findet man ihn außerdem oft auf dem Fahrrad oder beim Wandern.

Das war die KubeCon 2023

Ende April stand für die Kollegen im Consulting Daniel Bodky und Markus Waldmüller eine der großen Konferenzen des Kalenderjahres an – die KubeCon+CloudNativeCon EU 2023 in Amsterdam, wohin es NETWAYS bereits letzten Sommer im Rahmen der Startup Days verschlagen hatte. Mit fachlichem Vorwissen und Ortskenntnis konnten sich die beiden also in den Konferenzalltag mit Talks, Podiumsdiskussionen und dem allseits bekannten „Hallway Track“ voller interessanter Gespräche stürzen. In diesem Blogpost blicken sie zurück: Wie war die Konferenz, was treibt Anwender und Betreiber um, und welche Trends konnten sie ausmachen?

 

So fanden wir uns also zusammen mit den über 10.000 Teilnehmern (ja, richtig gelesen!) unter dem Motto „Community in Bloom“ im Amsterdamer RAI Kongresszentrum ein. Nach den Workshops am Vortag erfolgte die Eröffnung der eigentlichen Konferenz durch Priyanka Sharma, der Geschäftsführerin (Executive Director) der Cloud Native Computing Foundation (CNCF). Sie erwähnte u.a., dass 58% der Anwesenden zum ersten Mal an einer KubeCon teilnahmen. Wie auch an den anderen Konferenztagen fanden anschließend eher sponsorenlastige Keynotes statt, bevor dann ab dem späten Vormittag die tiefergehenden Tech-Talks angesetzt waren.

Neben den zahlreichen Präsentationen zu verschiedensten Themen waren in zwei großen Hallen mit GitLab, AWS, SUSE Rancher, Google Cloud und Co. auch ca. 220 Aussteller vertreten, bei denen man sich vor, zwischen und nach den Sessions zusätzlich auf dem neusten Stand zu Kubernetes und anderen Cloud Produkten bringen konnte.

Die Auswahl an Talks war groß, die professionellen und privaten Bekanntschaften aus aller Welt allgegenwärtig, und zwischendurch lockte der ein oder andere Sticker, eine spezifische Frage zu einem Produkt oder einfach nur Neugierde in die Ausstellerhalle. An dieser Stelle auf sämtliche Eindrücke einzugehen wäre wohl etwas zu viel verlangt. Wir hoffen, dass ihr uns verzeiht und euch unsere persönlichen Highlights ausreichen.

Unsere Highlights

Einen Tag vor Beginn der eigentliche Konferenz fand u.A. die ArgoCon im Rahmen der „Co-located Conferences“ statt, die sich Daniel nicht entgehen lassen wollte. Das war wohl auch die richtige Entscheidung:

„Rückblickend würde ich fast soweit gehen, zu sagen, dass mir die ArgoCon am besten gefallen hat. Hier konnte ich mich einen Tag lang den Themen GitOps (dazu später mehr), Workflows, Deployments und Events widmen – alles Themen, die das Argo-Projekt abbilden kann. Eines meiner Highlights dieses ersten Tages war der Beitrag „Scaling GitOps using ArgoCD Application-Sets: Lessons learnt“ von Amit Dsouza, der ein eher selten genutztes Feature in ArgoCD, Application Sets, und seine möglichen Vor- und Nachteile genauer beleuchtete.“

Im Verlauf der folgenden Tage waren insbesondere die 90-minütige Frage-Antwort-Session von Kelsey Hightower zum Thema „From Community to Customers“ sowie die „Wasserstandsmeldung“ „The State of Backstage in 2023“ zum CNCF-Projekt Backstage von besonderem Interesse. Hierbei handelt es sich um  eine Internal Developer Platform (IDP, auch hierzu später mehr) entwickelt von Spotify. Natürlich gab es noch viele weitere gute Beiträge zu unterschiedlichsten Themen und Problemstellungen.

GitOps, Wasm, Service Meshes und IDPs – die Trends im Überblick

Die KubeCon EU, die von den „großen“ Konferenzen meistens am frühesten im Kalenderjahr angesetzt ist, wird gerne auch als Trendbarometer und Gradmesser für Technologien und Frameworks rund um Cloud-Native und Kubernetes wahrgenommen. Und so stellt sich natürlich auch 2023 die Frage: „Wo geht’s hin?“. Einen ersten Aufschluss darüber können oft die Co-located Conferences an „Day Zero“ der KubeCon geben – zu brandaktuellen Themen gibt es oftmals gesteigertes Interesse an Workshops, Einführungen, Fallstudien und tiefergehenden Talks. So finden sich Interessengruppen zu eigenen, kürzeren, parallel stattfindenden Konferenzen zusammen. Daniel besuchte z.B. die ArgoCon, die sich u.A. mit dem Thema GitOps befasste, also der Praxis, zu deployende Anwendungen und teilweise auch Infrastruktur in Git zu versionieren, um einen eindeutigen, nachvollziehbaren und deklarativen Stand seiner Umgebung zu forcieren.

Doch auch andere Co-located Conferences befassten sich mit momentan heiß gehandelten Themen, sei es der Cloud Native Wasm Day, Istio Day oder Linkerd Day. Wasm steht für „Web Assembly“, ein portierbares Compilationtarget für verschiedene Programmiersprachen, das bspw. im Vergleich zu Javascript mehr Performanz und Plattformunabhängigkeit für Webanwendungen verspricht. Mehr Informationen zu WebAssembly findet man unter https://webassembly.org.
Istio und Linkerd hingegen sind zwei Service Mesh Technologien, die sich um das Management und die Absicherung von Netzwerkverkehr innerhalb von Microservice-Architekturen, aber auch zwischen Endnutzer und Anwendung(en) kümmern. Dass die zwei „beliebtesten“ Service Meshes parallel eigene Konferenzen veranstalten, spricht für den Einfluss und Nachfrage der darunterliegenden Technologie. Wir sind jedenfalls gespannt, wie sich die Thematik rund um Netzwerkarchitekturen auf und um Kubernetes herum weiterentwickeln wird.

Ein drittes Thema, das auf der Kubecon großen Anklang zu finden schien, waren sogenannte Internal Developer Platforms (IDP). In einer „cloud-native“ Welt, in der sich Anwendungen aus vielen einzelnen Microservices und verschiedensten Technologien und Frameworks zusammensetzen, wird es für Entwickler zunehmend schwieriger, den Überblick zu behalten und weiterhin ungehindert gute Software zu schreiben. Das Konzept einer internen Entwicklerplattform, die eine Übersicht über im Unternehmen vorhandene Technologien, festgelegte Konventionen und Best Practices und im Bestfall sogar die Integrationen bestehender Dritttools bietet, kann den Alltag für Entwicklerteams deutlich vereinfachen.
Das wohl bekannteste Projekt in dieser Sparte ist Backstage (s.o.), ursprünglich entwickelt von Spotify und momentan ein „incubating project“ in der CNCF. Aber auch andere Produkte und Projekte existieren, so waren bspw. die beiden Anbieter „Port“ und „Mia-Platform“ Sponsoren der diesjährigen KubeCon EU.
Es wird sicherlich spannend sein zu sehen, wie sich Developer Tools und Plattformen die kommenden Monate und Jahre weiterentwickeln werden, und welche Tools sich letzten Endes durchsetzen können.

Fazit

Auch wenn die vielen Teilnehmer fast schon als Kleinstadt durchgehen würden, war die Konferenz sehr gut organisiert, sodass dem Wissenstransfer überhaupt nichts im Wege stand und wir eine unüberschaubare Anzahl an neuen Informationen und Kenntnissen mitnehmen konnten.
Bei der KubeCon EU im nächsten Frühjahr in Paris sind wir auf jeden Fall wieder vertreten und freuen uns bis dahin unser Wissen an unsere Kunden weiterzugeben bzw. dort umzusetzen.

Sei es ein Training rund um Docker und Kubernetes für Einsteiger, die Zusammenarbeit in und an euren cloud-native Projekten oder die Arbeit mit Containern im CI/CD-Bereich, z.B. auf GitLab –  für Anfragen aller Art zu Cloud Native stehen wir natürlich gerne zur Verfügung!

Daniel Bodky
Daniel Bodky
Consultant

Daniel kam nach Abschluss seines Studiums im Oktober 2021 zu NETWAYS und berät nun Kunden zu den Themen Icinga2 und Kubernetes. Nebenher schreibt er in seiner Freizeit kleinere Tools für verschiedenste Einsatzgebiete, nimmt öfters mal ein Buch in die Hand oder widmet sich seinem viel zu großen Berg Lego. In der wärmeren Jahreszeit findet man ihn außerdem oft auf dem Fahrrad oder beim Wandern.

Kubernetes 101: So installierst und verwaltest du Anwendungen

This entry is part 4 of 6 in the series Alles rund um Kubernetes

Nachdem wir uns vergangene Woche damit befasst haben, welche Mittel und Wege existieren, um sich ein Cluster für Tests oder die Produktion zu installieren, sind wir nun (hoffentlich) an dem Punkt angekommen, an dem wir erste Anwendungen auf Kubernetes portieren oder neu installieren möchten. Da sich Kubernetes als Containerorchestrator deutlich von „althergebrachten“ Betriebsumgebungen für Anwendungen unterscheidet, ist es nur logisch, dass sich auch Best Practices für die Installation und den Betrieb von Anwendungen unterscheiden. Grob lassen sich die zu beachtenden Gesichtspunkte in 5 Felder unterteilen:

  • Dateisystem vs. Container
  • Monolithen vs. Microservices
  • Stateful vs. Stateless
  • Blackbox vs. Whitebox
  • Monitoring vs. Observability

Diese Felder und ihre Implikationen bedingen einander teilweise. Fangen wir also mit dem evtl. offensichtlichsten an – der Installationsmethodik.

Dateisystem vs. Container

Der größte und für viele auch folgenschwerste Unterschied zwischen Anwendungen, die in Kubernetes laufen ,und solchen, die auf VMs oder physischen Servern installiert werden, ist Containerisierung der Workloads. Jede Anwendung muss als Containerimage definiert, gebaut, gesichert und verteilt werden – dies erfordert oftmals eine Umstellung bestehender Abläufe für Tests, Bau und Verteilung der Software, bspw. in den CI/CD-Pipelines der Entwickler- und DevOps-Teams. Des Weiteren muss oftmals neue Infrastruktur eingerichtet werden, um etwa Imagescans oder eine eigene Container- und Artefaktregistry für das Unternehmen bereitstellen zu können.

Des Weiteren gilt es natürlich, entsprechendes Know-How in den Teams aufzubauen – nicht jede/r Entwickler/in hat in der Vergangenheit mit Docker und containerisierten Anwendungen gearbeitet, geschweige denn entwickelt. Auch wenn Tools wie Docker Desktop oder Podman Desktop den Einstieg heutzutage erleichtern, müssen Mindset, Praktiken und Routinen oftmals erst aufgebaut werden. Gleiches gilt für die Handhabe der Containerimages nach dem Bau: Wie werden Sie gespeichert und für Pipelines und Cluster verfügbar gemacht? Nutzt man hierfür eine offene Plattform (GitHub Container Registry, DockerHub), eine SaaS-Lösung (Artifactory), oder baut eigene Infrastruktur auf (Harbor)?
Mit diesen möglichen Problematiken sollte man sich im Bestfall bereits im Vorfeld befassen und aufkommende Fragen initial klären, um einen möglichst reibungslosen Umstieg auf Kubernetes für alle beteiligten Teams zu gewährleisten.

Monolithen vs. Microservices

Eine direkte Folge der Containerisierung von Anwendungen ist die Transition von sog. Monolithen zu Microservices. Der Grund hierfür ist klar: In einer Umgebung, in der Softwarereleases oft mehrmals täglich stattfinden und ein Orchestrator installierte Anwendungen nach Belieben skalieren, verwerfen oder an anderer Stelle erneut initialisieren kann, sind Anwendungen mit einer Paketgröße von mehreren Gigabyte nicht praktikabel – man möchte schmale Pakete im Bereich von maximal einigen Hundert Megabyte, um flexibel und schnell in Sachen Verteilung und Installation zu sein.

Hierfür ist es gängige Praxis, bestehende Anwendungen umzustrukturieren bzw. bei der Entwicklung neuer Anwendungen bereits in der Designphase auf die spätere Installation als Microservices hinzuwirken, um Monolithen zu vermeiden. Unter einem Monolithen versteht man ein einzelnes Softwarepaket, das sich von Operatoren nur als eine Einheit installieren lässt und keinerlei Flexibilität und Unabhängigkeit seiner Komponenten bietet – alle Bestandteile sind unter der Haube fest miteinander „verdrahtet“. Hat man nun Probleme mit der Performanz eines bestimmten Features (ein sog. Bottleneck) bleibt einem keine andere Wahl, als den gesamten Monolithen zu skalieren – in den meisten Fällen Ressourcenverschwendung.

Viel sinniger wäre es doch, die einzelnen Bestandteile zu trennen – das Ergebnis sind viele verschiedene Microservices, die im Bestfall jeweils nur eine Aufgabe übernehmen. Ein solcher Ansatz ermöglicht die Skalierung einzelner Bestandteile der Anwendung, bspw. des viel frequentierten Webshops, anstatt direkt die gesamte Anwendung skalieren zu müssen. Die Kommunikation der einzelnen Microservices untereinander geschieht in solchen Szenarien über das (clusterinterne) Netzwerk bspw. via HTTP oder gRPC.

Stateful vs. Stateless

Eine direkte Folge der Umsetzung von Anwendungen als Microservices wiederum ist eine Transition von zustandsabhängigen (stateful) zu größtenteils zustandslosen (stateless) Anwendungen – während die meisten Monolithen zustandsabhängig sind (fast jede nennenswerte Anwendung muss an irgendeinem Punkt Daten persistent speichern können), müssen nur die wenigsten Microservices Daten persistent speichern. In vielen Fällen reicht ein lokaler Cache, bspw. zum Speichern von Nutzersitzungen oder dem Vorhalten von oft angefragten Daten.

Wirkliche Persistenz benötigen nur die Microservices, die sich unmittelbar mit der Verarbeitung und Speicherung von Daten befassen und hierfür bspw. mit rückgelagerten Datenbanken oder Dateisystemen kommunizieren. Mittlerweile gibt es allerdings genug Fallstudien, in denen auch Services wie Blockspeicher oder Datenbanken direkt auf Kubernetes betrieben werden.

Blackbox vs. Whitebox

Neben der Umstellung von „Stateful“ auf „Stateless“ betrifft eine weitere große Veränderung im Design von Anwendungen bestehend aus Microservices den Ansatz ihrer Überwachung: Anstatt lediglich von außen auf die Anwendung zu blicken und evtl. auftretende Symptome einer Fehlfunktion zu erkennen, bspw. durch HTTP-Anfragen an für Nutzer angebotene Webendpunkte (sog. Blackbox-Monitoring), instrumentalisiert man seine Microservices von vornherein so dass man tatsächliche Metriken aus den im Service ablaufenden Prozessen erhält (sog. Whitebox-Monitoring).

Beliebt für die Umsetzung ist hierbei Prometheus, was einen etablierten Standard für Metriken liefert, weit verbreitet ist und Funktionsbibliotheken für die Instrumentalisierung von Code in verschiedenen Programmiersprachen bietet. Prometheus sammelt die Metriken der Services über Webendpunkte ab und speichert sie in einer internen Timeseriesdatenbank (TSDB) ab. Ist Prometheus für euch ein gänzlich unbekannter Begriff, kann ich euch an dieser Stelle wärmstens unser Prometheus Fundamentals Training ans Herz legen, mit dem man in kürzester Zeit relativ vertraut mit Prometheus und seinem Funktionsumfang wird.
Verfolgt man also Whitebox- statt Blackboxmonitoring, hat man die tatsächlichen Metriken seiner Microservices zur Verfügung und kann bei aufkommenden Komplikationen Ursachen statt Symptomen bekämpfen. Des Weiteren können die Metriken zur permanenten Weiterentwicklung und Verbesserung der Serviceperformanzen genutzt werden – eine Win-Win-Situation!

Monitoring vs. Observability

Aufbauend auf dem letzten Absatz zu Blackbox- vs. Whiteboxmonitoring lässt sich die Monitoring-Philosophie im Hinblick auf K8s oder „Cloud-Native“ generell noch vertiefen und erweitern: Man spricht von den Three pillars of observability (Drei Säulen der Beobachtbarkeit/Observability) Metrics, Traces und LogsMetriken werden von Anwendungen und Services selbst bereitgestellt und bieten wie bereits erklärt einen ungetrübten Einblick in das Innenleben einzelner Services. Traces erlauben es, Prozessketten über Servicegrenzen hinweg zu verfolgen und bspw. zu ermitteln, in welchen Stadien der Verarbeitung besonders hohe Latenzen entstehen. Logs ermöglichen die Verarbeitung von Events o.Ä., die von den einzelnen Anwendungen protokolliert werden.

Aus der Fülle an verschiedenen Datentypen und den dafür benötigten Praktiken entsteht die Entwicklung von Monitoring hin zu Observability – es ist nicht mehr ausreichend, lediglich „von außen“ auf seine monolithische Anwendung zu blicken, sondern es gilt, stattdessen in den Services selbst anzusetzen und soviel Informationen wie möglich abzugreifen.
Für alle drei Arten an Beobachtungen gibt es umfangreiches Tooling in der Opensource-Gemeinschaft, das einem hilft, den Überblick über seine Cluster und die darauf betriebenen Anwendungen zu behalten, diese nach und nach zu optimieren und bei Fehlern schnell oder sogar proaktiv reagieren zu können. Auch bei der Einhaltung von Service Level Agreements (SLAs) gegenüber den Kunden oder internen Service Level Agreements (SLAs) hilft eine lückenlose Observability-Strategie.

 

Sollten diese Punkte etwas viel auf einmal gewesen sein oder du bereits absehbare Probleme bei der Umsetzung auf dich zukommen siehst, kann ich euch erneut auf unsere Services rund um Container, DevOps und Kubernetes verweisen – wir sind in vielen der genannten Bereichen bereit, dir mit Rat und Tat zur Seite zu stehen und bei der Umsetzung zu unterstützen. Ansonsten bleibt mir für heute nur, „bis zum nächsten Mal“ zu sagen, wenn wir uns genauer anschauen, wie man Anwendungen auf Kubernetes denn nun im Detail verwaltet und skaliert.

Daniel Bodky
Daniel Bodky
Consultant

Daniel kam nach Abschluss seines Studiums im Oktober 2021 zu NETWAYS und berät nun Kunden zu den Themen Icinga2 und Kubernetes. Nebenher schreibt er in seiner Freizeit kleinere Tools für verschiedenste Einsatzgebiete, nimmt öfters mal ein Buch in die Hand oder widmet sich seinem viel zu großen Berg Lego. In der wärmeren Jahreszeit findet man ihn außerdem oft auf dem Fahrrad oder beim Wandern.