{"id":8798,"date":"2022-05-22T17:12:22","date_gmt":"2022-05-22T15:12:22","guid":{"rendered":"https:\/\/u-labs.de\/portal\/?p=8798"},"modified":"2022-12-12T16:38:19","modified_gmt":"2022-12-12T14:38:19","slug":"eigener-server-cluster-diese-grundlagen-zum-aufbau-solltest-du-ueber-das-clustering-wissen-mit-und-ohne-kubernetes","status":"publish","type":"post","link":"https:\/\/u-labs.de\/portal\/eigener-server-cluster-diese-grundlagen-zum-aufbau-solltest-du-ueber-das-clustering-wissen-mit-und-ohne-kubernetes\/","title":{"rendered":"Eigener Server-Cluster: Diese Grundlagen zum Aufbau solltest du \u00fcber das Clustering wissen (mit und ohne Kubernetes)"},"content":{"rendered":"<p>Im ersten Beitrag haben wir einen sogenannten &#8222;Single-Node&#8220; Kubernetes-Cluster eingerichtet. Er bietet keine Lastverteilung oder gar Ausfallsicherheit und ist daher streng genommen gar kein Cluster. F\u00fcr Test- und Entwicklungszwecke reicht das oft. Wer aber produktiv mit einem echten Cluster arbeiten m\u00f6chte, braucht zwangsl\u00e4ufig mehrere Ger\u00e4te. Auch das l\u00e4sst sich mit Raspberry Pis umsetzen. Wobei das nur eine M\u00f6glichkeit ist. Wer X86 Systeme hat, kann die nat\u00fcrlich ebenfalls verwenden. Der Pi ist hier eine preiswerte und kompakte Alternative. Ein <strong>Knoten<\/strong> ist im folgenden ein Kubernetes-Server, also ein Raspberry Pi oder eine andere Maschine.<\/p>\n<p>In diesem ersten Teil soll es um die Planung und den hardwareseitigen Aufbau des Clusters gehen. Sp\u00e4ter schauen wir uns die Softwareseite an, wie man mit K3s einen Kubernetes-Cluster aufbauen kann. Eventuell alternativ auch den manuellen Weg ohne Kubernetes.<\/p>\n<h2 class=\"wp-block-heading\">Was ist ein Cluster und welche Vorteile\/Nachteile bietet er?<\/h2>\n<p>Ein Cluster ist eine Verbund von mehreren Systemen (meist <em>Knoten<\/em> genannt), die zu einer Gruppe verkn\u00fcpft werden und sich i.d.R gegenseitig \u00fcberwachen. Das k\u00f6nnen Raspberry Pis sein, aber eben so jegliche andere physische oder virtuelle Server. Innerhalb dieses Clusters betreibt man die gew\u00fcnschten Anwendungen. Das k\u00f6nnen z.B. Datenbanken oder Webanwendungen sein, aber auch andere Aufgaben wie Berechnungen, Crawler und so weiter.<\/p>\n<p>Die Vorteile liegen in der Leistung und Skalierbarkeit, da man die Last auf mehrere Systeme aufteilen und bei Bedarf um weitere Knoten erweitern kann. Durch einen Cluster kann man auch Hochverf\u00fcgbarkeit erreichen. F\u00e4llt ein Knoten aus oder ist wegen Wartungsarbeiten (z.B. Aktualisierungen) nicht verf\u00fcgbar, k\u00f6nnen die restlichen Knoten \u00fcbernehmen, sodass es f\u00fcr den Benutzer zu keinem Ausfall der Anwendung kommt.<\/p>\n<p>Je nach den gew\u00fcnschten Aufgaben kann man den Schwerpunkt auf Lastverteilung oder Redundanz setzen. Vor allem bei der Ausfallsicherheit wird man den Cluster etwas \u00fcberdimensionieren, damit Ausf\u00e4lle kompensiert werden k\u00f6nnen. Produktiv w\u00fcrde man au\u00dferdem die verschiedenen Knoten trennen. Mindestens auf unterschiedliche physische Maschinen, am besten aber auch geografisch.<\/p>\n<p>Damit werden auch bereits die Nachteile deutlich: Man ben\u00f6tigt mehrere Systeme, die Installation wird komplexer und damit auch aufw\u00e4ndiger in der Wartung. Produktiv werden Cluster daher eher f\u00fcr gro\u00dfe und\/oder wichtige Systeme aufgesetzt. Privat ist das meist \u00fcberdimensioniert. Aber eine Testumgebung kann nat\u00fcrlich dennoch sehr interessant sein, um sich in die Thematik einzuarbeiten und Praxiserfahrung zu sammeln.<\/p>\n<p>In einem eigenen Beitrag werden wir einen Kubernetes-Cluster aufsetzen. Obwohl der Schwerpunkt darauf liegt, gilt vieles generell f\u00fcr Cluster. <\/p>\n<h2 class=\"wp-block-heading\">Wo liegen die Daten?<\/h2>\n<p>Nahezu jede Anwendung arbeitet mit Daten. In einem Cluster muss man daher ber\u00fccksichtigen, welche Daten es gibt und wo diese liegen. Vor allem f\u00fcr Hochverf\u00fcgbarkeit ist das sehr wichtig. Ein einfaches Beispiel: Ein Webserver liefert statische Daten aus. Diese Dateien k\u00f6nnen auf einem Knoten liegen und z.B. per SSHFS von den anderen Servern gemoutet werden. Aber: Das System ist dann der einzelne Ausfallpunkt (Single Point of Failture). Ist dieser Knoten nicht verf\u00fcgbar, kann auch der andere Server nichts ausliefern, obwohl er funktioniert &#8211; weil ihm ja die Daten fehlen.<\/p>\n<p>Ein Cluster-Dateisystem oder zumindest Netzwerk-Dateisystem k\u00f6nnen daher sinnvoll oder gar notwendig sein. Vor allem bei Kubernetes ist diese Frage essenziell, da Kubernetes die Anwendungen eigenst\u00e4ndig verteilt. Eine Anwendung fest an einen Knoten zu binden, ist eher die Ausnahme und schr\u00e4nkt die Flexibilit\u00e4t ein. Schlie\u00dflich kann das Programm dann ja eben nicht woanders gestartet werden, obwohl genug andere Knoten verf\u00fcgbar w\u00e4ren.<\/p>\n<p>Wer hier nicht aufpasst, hat schnell einen versteckten einzelnen Ausfallpunkt als Abh\u00e4ngigkeit seines Clusters. Das kann z.B. auch ein einzelner NFS-Server sein, auf dem s\u00e4mtliche Knoten ihre Daten ablegen. Wobei das nat\u00fcrlich nur dann ein Problem ist, wenn man Ausfallsicherheit erreichen m\u00f6chte. Falls es lediglich darum geht Last zu verteilen, kann das &#8211; vor allem privat oder zu Testzwecken &#8211; v\u00f6llig ausreichen.<\/p>\n<h2 class=\"wp-block-heading\">Wie kommt man auf die Dienste der Cluster-Knoten?<\/h2>\n<p>Diese Frage ist vor allem dann interessant, wenn man einen Dienst anbietet, auf den von au\u00dferhalb des Clusters zugegriffen werden soll &#8211; wie z.B. Webserver oder Datenbanken. Teilweise kann man in der Anwendung mehrere Hostnamen oder IPs angeben und es wird automatisch anhand verschiedener Bedingungen gewechselt. Oft ist das aber nicht der Fall und wir brauchen eine zentrale Instanz, welche die &#8222;Weichen&#8220; stellt. Im Falle einer Lastverteilung etwa soll diese Instanz die Anfragen gleichm\u00e4\u00dfig auf die Knoten aufteilen. Sinnvoll ist auch zu pr\u00fcfen, ob die Knoten funktionieren und keine Anfragen an Knoten zu \u00fcbergeben, die wir als fehlerhaft oder offline identifiziert haben.<\/p>\n<p>Eine solche Instanz hei\u00dft <em>Load Balancer<\/em>. Er muss auch redundant sein, wenn wir Hochverf\u00fcgbarkeit m\u00f6chten &#8211; ansonsten ist der Lastverteiler unser einzelner Ausfallpunkt. Hier wird es dann wieder komplexer: Man braucht eine <em>Floating IP<\/em>. Diese IP ist nicht fix einem Server zugeordnet, wie es ansonsten \u00fcblich ist. Sondern sie kann &#8222;gleitet&#8220; im Fehlerfall zu einem anderen System. Etwa zu einem zweiten Lastverteiler, wenn der erste Ausf\u00e4llt. F\u00fcr den Nutzer \u00e4ndert sich dadurch nichts, da die IP-Adresse gleich bleibt. Es kommt somit zu keinen Verz\u00f6gerungen und Caching-Problemen, wie es etwa bei DNS-\u00c4nderungen der Fall w\u00e4re.<\/p>\n<p>Auch hier sollte man zuerst \u00fcberlegen, was man wirklich braucht. Wenn es nicht gerade darum geht Floating IPs auszuprobieren, reicht privat und f\u00fcr Testzwecke eine einzelne Instanz aus.<\/p>\n<h2 class=\"wp-block-heading\">Planung: Lastverteilung oder Hochverf\u00fcgbarkeit &#8211; Wie viele Raspberry Pis brauche ich?<\/h2>\n<p>Man sollte sich zun\u00e4chst Gedanken machen, was man mit dem Cluster in erster Linie erreichen m\u00f6chte. Wenn man nur die Last aufteilen m\u00f6chte, reicht im einfachsten Falle bereits ein zweiter Pi. F\u00fcr eine zustandslose HTML-Seite w\u00fcrde das ausreichen: 2 Webserver, ein Loadbalancer zur Lastverteilung, schon kann ein Server ausfallen und der andere \u00fcbernimmt.<\/p>\n<p>F\u00fcr alle zustandsorientierten Anwendungen wird es aber komplexer. Das bedeutet: Die Anwendung arbeitet mit Daten, die aus einer vorherigen Operation stammen. Ein klassisches Beispiel sind Datenbanken. Darin speichert man Informationen, die erst sp\u00e4ter wieder abgerufen werden. Nahezu jede Webanwendung ist ebenfalls zustandsorientiert, etwa durch Sitzungen. Ein deutliches Beispiel w\u00e4re hier ein Onlineshop, der einen Warenkorb speichert, um den Kauf sp\u00e4ter abzuschlie\u00dfen. <\/p>\n<p>Bei Datenbanken ist vor allem die Integrit\u00e4t von Daten wichtig. Man muss also sicherstellen, dass \u00c4nderungen an alle Instanzen verteilt werden und es nirgendwo fehlerhafte Informationen gibt. Daf\u00fcr braucht es bestimmte Regeln. Die von Kubernetes verwendete Datenbank <a href=\"https:\/\/etcd.io\/docs\/v3.5\/faq\/#what-is-failure-tolerance\" title=\"Etcd ben\u00f6tigt eine Mehrheit von Knoten\" target=\"_blank\" rel=\"nofollow\">Etcd ben\u00f6tigt eine Mehrheit von Knoten<\/a>, um sich beim replizieren auf einen Anf\u00fchrer zu einigen. Haben wir nur 2 Knoten und einer f\u00e4llt aus, gibt es keine Mehrheit mehr. \u00c4hnlich wie in einer Abstimmung kann es hier zu einem &#8222;Unentschieden&#8220; kommen. Bei 3 Knoten k\u00f6nnen 2 eine Mehrheit bilden, sodass einer ausfallen kann. Den verwendeten <a href=\"https:\/\/raft.github.io\/\" title=\"Raft-Algorithmus\" target=\"_blank\" rel=\"nofollow\">Raft-Algorithmus<\/a> kann man sich wie eine Wahl vorstellen: Alle verbleibenden Nodes w\u00e4hlen ihren neuen Anf\u00fchrer, die Mehrheit entscheidet.<\/p>\n<p>Optimal ist daher eine ungerade Anzahl an Nodes bzw. Pis: Bei 4 Knoten darf n\u00e4mlich ebenfalls nur einer ausfallen, da wir mit 2 verbleibenden Knoten keine Mehrheit mehr h\u00e4tten. Auf der anderen Seite steigt aber grunds\u00e4tzlich das Ausfallrisiko mit der Anzahl an Servern. Ein Cluster mit 3 Nodes w\u00e4re hinsichtlich Ausfallsicherheit daher besser als 4 Nodes. Oder man erweitert alternativ auf 5 Nodes, wodurch 2 davon ausfallen k\u00f6nnen. <\/p>\n<p>Wer statt Kubernetes selbst clustern m\u00f6chte, sollte sich \u00fcber die Anforderungen und Konzepte der gew\u00fcnschten Anwendung informieren. Diese muss nat\u00fcrlich in jedem Falle clusterf\u00e4hig sein, auch ohne Kubernetes. <\/p>\n<h3 class=\"wp-block-heading\">Master bzw. Control Plane und Worker Nodes<\/h3>\n<p>Als &#8222;Nodes&#8220; bezeichnet Kubernetes keinen beliebigen Server, sondern die <strong>Worker Nodes<\/strong>: Auf Ihnen laufen die Pods, welche wiederum die gew\u00fcnschten Anwendungen in Form von Containern betreiben &#8211; die sozusagen die <em>Arbeitslast<\/em>, also das was wir betreiben m\u00f6chten.<\/p>\n<p>F\u00fcr einen Cluster reicht das aber nicht, wir ben\u00f6tigen auch mindestens einen Control Plane oder fr\u00fcher auch Master genannten Node. Er koordiniert den Cluster und entscheidet beispielsweise, auf welchem Worker Node ein Pod gestartet wird. In einer Produktivumgebung aus dem Leerbuch hat man mehrere Master Nodes, sodass diese hochverf\u00fcgbar sind. Und sie sind von den Workern getrennt, d.H. insgesamt 6 Systeme (3x Master, 3x Worker).<\/p>\n<p>Nat\u00fcrlich kann man hier &#8211; zu recht &#8211; argumentieren, dass dies f\u00fcr einige Szenarien \u00fcbertrieben ist &#8211; und man derartige Hochverf\u00fcgbarkeit vielleicht gar nicht braucht. Es gibt verschiedene Alternativen und Kompromisse. Man kann etwa Worker und Control Plane Rollen auf die gleichen Systeme installieren. Das ist vor allem bei Testsystemen und in kleineren Umgebungen g\u00e4ngig. Oder man trennt Master und Worker zwar, aber nutzt nur einen Control Plane und verzichtet damit auf Hochverf\u00fcgbarkeit.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Im ersten Beitrag haben wir einen sogenannten &#8222;Single-Node&#8220; Kubernetes-Cluster eingerichtet. Er bietet keine Lastverteilung oder gar Ausfallsicherheit und ist daher streng genommen gar kein Cluster. F\u00fcr Test- und Entwicklungszwecke reicht das oft. Wer aber produktiv mit einem echten Cluster arbeiten m\u00f6chte, braucht zwangsl\u00e4ufig mehrere Ger\u00e4te. Auch das l\u00e4sst sich mit Raspberry Pis umsetzen. Wobei das &#8230;<\/p>\n","protected":false},"author":5,"featured_media":8951,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[62],"tags":[1045,719],"class_list":["post-8798","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-server","tag-cluster","tag-kubernetes"],"_links":{"self":[{"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/posts\/8798","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/comments?post=8798"}],"version-history":[{"count":9,"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/posts\/8798\/revisions"}],"predecessor-version":[{"id":9746,"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/posts\/8798\/revisions\/9746"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/media\/8951"}],"wp:attachment":[{"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/media?parent=8798"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/categories?post=8798"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/tags?post=8798"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}