In der Anfangszeit von Kubernetes haben Unternehmen häufig mit zwei Arten von Clustern operiert: einem für die Produktion und einem für nichtproduktive, vorgelagerte Tests oder die Entwicklung. Der Grund für dieses Vorgehen war die Vermeidung von Komplexität und das Bestreben, den operativen Aufwand für den Betrieb der Cluster gering zu halten. Falls doch mehrere Stages (Development, Test, Integration, Pre-Production) benötigt wurden, hat man diese Umgebungen über verschiedene Namespace-Suffixe oder -Präfixe realisiert.
Nachdem die neue Komplexität beherrschbar wurde, konnte man darüber nachdenken, ob eine Aufteilung der Cluster in Stages nicht weitere Vorteile mit sich bringen würde. Auch der Betrieb mehrerer produktiver Cluster wurde möglich. Die Abwägung der Vor- und Nachteile für diese Multi-Cluster-Umgebungen ist dabei sehr vielfältig. Mögliche Gründe dafür können unter anderem sein:
- unterschiedliche Zugriffsberechtigungen (allgemeine Security- oder regulatorische Vorgaben)
- Blast-Radius bei Systemausfällen (Vermeidung eines Single Point of Failure)
- operative Flexibilität innerhalb des Clusters und Reduzierung der Clustergröße
- Zweckbindung des Clusters für bestimmte Workloads
- Notwendigkeit der Migration/Transition des Clusters
Diese Liste kann sicherlich noch erweitert werden, aber eine tiefergehende Diskussion dieser Argumente würde den Rahmen dieses Artikels sprengen. Für den weiteren Verlauf unserer Diskussion ist es ausreichend, zu wissen, dass wir uns mit mehreren Kubernetes-Clustern beschäftigen müssen.
Multi-Cloud
Auf der anderen Seite haben Unternehmen begonnen, die Public Cloud in die eigene Infrastruktur zu integrieren. Die Infrastruktur wurde in die Cloud ausgeweitet oder man hat sich dafür entschieden, alle notwendigen Ressourcen komplett in die Cloud zu verlagern. Um bei dieser Strategie noch eine gewisse Unabhängigkeit vom Cloud-Provider zu haben, sind in Unternehmen mögliche Cloud-Migrationsszenarien ein wichtiges Thema. Sollte man sich für einen Wechsel des Cloud-Providers entscheiden, hat man zumindest einen Plan, wie dieser umgesetzt werden kann. Andere begeben sich erst gar nicht in diese Abhängigkeit, indem sie von Anfang an ihre Infrastruktur bei mehreren Cloud-Providern betreiben.
Multi-Mesh
Unternehmen, die sich für den Einsatz eines Service Mesh wie Istio entschieden haben, werden nun mit der oben beschriebenen Multi-Cluster-Strategie vor eine neue Entscheidung gestellt. Soll das Service Mesh nur innerhalb der jeweiligen Cluster operieren oder will man seine Vorzüge auch über Clustergrenzen hinweg nutzen? Dann spricht man von Multi-Mesh.
Im Fall einer Multi-Cloud-Strategie muss man sich sogar mit der Option beschäftigen, das Service-Mesh über die Grenzen der Infrastruktur hinweg zu betreiben – also ein Multi-Mesh über den Cloud-Provider und die On-Premise-Umgebung hinweg aufspannen. Sogar der Betrieb über mehrere Cloud-Provider hinweg ist denkbar.
Die erste Frage, die sich bei einem Multi-Mesh stellt, ist: Welche Vorteile bringt es? Im Grunde werden alle Vorteile, die ein Service Mesh mit sich bringt, transparent auf alle Cluster ausgeweitet. Einige der wichtigsten Pluspunkte schauen wir uns in den folgenden Abschnitten genauer an.
Ende-zu-Ende-Verschlüsselung und Berechtigungsprüfungen
Eine Ende-zu-Ende-Verschlüsselung, die mit dem Service Mesh innerhalb eines Clusters möglich war, wird nun auch über die Clustergrenzen hinweg möglich. Die mTLS-Verschlüsselung erstreckt sich ohne Unterbrechung vom Workload im aufrufenden Cluster (Downstream) bis zum Workload im aufgerufenen Cluster (Upstream). Damit kann die kryptografisch gesicherte Identität des Aufrufers im Workload des Upstream-Clusters geprüft werden.
Die Grundlage für Verschlüsselung und Berechtigungsprüfungen für den clusterübergreifenden Aufruf sind damit etabliert. Die notwendigen Regeln für die Berechtigungsprüfungen (Istio AuthorizationPolicy) sind ohne weitere Anpassungen einsetzbar.
Stay tuned
Regelmäßig News zur Konferenz und der Java-Community erhalten
Cross-Cluster-Routing
Das Routing, das von Istio gesteuert und kontrolliert wird, kann in einem Multi-Mesh für den Aufrufer völlig transparent an den entsprechenden Cluster weitergeleitet werden. Ein Upstream Workload kann also von einem Cluster in einen anderen verschoben werden, ohne dass dies Einflüsse auf den Aufrufer hätte. Es müssen hierbei keine Konfigurationen am Aufrufer geändert werden. Die Verschiebung der Upstream Workloads in einen anderen Cluster kann sogar ohne Unterbrechung (Zero Downtime) im laufenden Betrieb geschehen. Der Service-Name des Upstream Workloads, in der Regel service.namespace.svc.cluster.local muss dafür nicht geändert werden.
Werden die Upstream Workloads in mehreren Clustern deployt, so kann mit einer kleinen Anpassung der Routingregel ein sog. Locality-based Routing erreicht werden. Durch verschiedene Routingstrategien kann der jeweils nächstgelegene Upstream Workload aufgerufen werden. Ist dieser im selben Cluster verfügbar, wird der Request an diese Instanzen weitergeleitet. Andernfalls erfolgt das Routing in einem anderen Cluster. Welcher Zielcluster hierfür verwendet werden soll, kann ebenfalls mit einer passenden Routingregel festgelegt werden. So kann ein gewünschter Kompromiss zwischen Latenz, Verfügbarkeit und Clusterauslastung erreicht werden.
Für dieses Cross-Cluster-Routing können dieselben Resilienzregeln wie bei einer clusterinternen Kommunikation verwendet werden. Das Multi-Mesh kennt zu jedem Zeitpunkt den Zustand der Workloads – genau wie das Service Mesh bei einem einzigen Cluster. Damit ist es möglich, vordefinierte Resilienzpatterns wie Circuit Breaker oder Bulkhead über die Clustergrenze hinweg anzuwenden. Ausfälle einzelner Workloads in anderen Clustern oder sogar ganzer Cluster werden damit für den Aufrufer kompensiert, ohne dass er etwas davon mitbekommt.
Cross-Cluster-Observability
Durch das transparente Routing der Aufrufe über die verschiedenen Cluster hinweg, kann der Überblick zur Laufzeit sehr unübersichtlich werden. Mit Istio im Multi-Mesh-Set-up kann die Frage: „In welchem Cluster wurde der Workload aufgerufen?” sehr einfach beantwortet werden. Das sog. Tracing, das bereits im Service-Mesh vorhanden ist, wird hier auch für die clusterübergreifende Kommunikation verwendet. Es kommen dabei dieselben Trace- bzw. Observability-Header zum Einsatz.
Die Infrastruktur muss hierfür eine einzige zusätzliche Voraussetzung erfüllen. Die Tracedaten der jeweiligen Cluster müssen an ein zentrales Tracing-Backend übermittelt werden. Istio integriert hierfür den OpenTelemetry-Standard, der diese weitreichenden Funktionalitäten mitbringt.
Um ein Multi-Mesh aufzuspannen, sind ein paar Voraussetzungen zu erfüllen. Ohne zu tief in die jeweiligen Themen einzusteigen, soll die folgende Beschreibung eine erste Einschätzung im Sinne Pro und Contra Multi-Mesh bzw. von dessen Aufwand und Nutzen für die eigene Systemlandschaft ermöglichen. In der Regel ist das Upgrade von einem Service auf ein Multi-Mesh mit vertretbarem Aufwand möglich.
Gemeinsame Trust Domain
Für die mTLS-Verschlüsselung über Clustergrenzen hinweg, muss eine sog. Trust Domain etabliert werden. Im klassischen Istio-Betrieb wird jedem Workload ein Istio Proxy als Sidecar zugewiesen (Das klassische Istio verwendet Sidecars für jeden Workload. Das neue Istio Ambient verzichtet darauf. Die Funktionsumfang des Service Mesh ist dabei derselbe). Ein Kubernetes Pod besteht somit aus zwei Containern. Das Sidecar übernimmt transparent für den Workload-Container die Kommunikation und kümmert sich auch um die Verschlüsselung mittels mTLS. Dazu erhält das Sidecar ein Zertifikat, das von der sog. Control Plane von Istio (istiod) alle 24 Stunden neu ausgestellt wird. Die Service-Mesh-Kommunikation innerhalb eines Clusters wird aus Sicht des SSL-Protokolls mit zwei Zertifikaten etabliert, die alle von derselben Certificate Authority (CA) stammen.
Eine mTLS-Verschlüsselung von einem Cluster zu den anderen muss demselben SSL-Protokoll entsprechen. Die Zertifikate in den Sidecars der beiden Cluster müssen von derselben CA ausgestellt worden sein. Um diese Voraussetzung im Multi-Mesh zu erfüllen, müssen die Zertifikate in den jeweiligen Control Planes der Cluster von derselben Root CA abgleitet worden sein (Abb. 1).
Abb. 1: Gemeinsame Trust Domain [1]
Als Vorbereitung wird eine Root CA außerhalb des Clusters verwendet, um davon sog. intermediate CAs abzuleiten. Jede Control Plane erhält dabei ihr eigenes intermediate CA, mit dem sie dann wiederum die Zertifikate der Sidecars signiert. Als Ergebnis besitzt jedes Sidecar im Multi-Mesh ein Zertifikat, das über die Zertifikatskette hinweg von derselben Root CA stammt. Damit sind aus Sicht des SSL-Protokolls die Voraussetzungen geschaffen, um über die Clustergrenze hinweg eine mTLS-Verbindung zu etablieren.
Die Konfiguration dieser Trust Domain lässt sich noch vereinfachen bzw. vereinheitlichen, sofern eine externe Public Key Infrastructure (PKI) vorhanden ist. Die Service Mesh Control Plane kann angewiesen werden, das Signieren der Zertifikate der Sidecars an diese PKI zu delegieren. So können alle Cluster des Multi-Mesh mit dieser PKI verknüpft werden. Die Cloud-Provider bieten solche PKI Services als Managed Services an.
Deployment Model auswählen
Das Multi-Mesh kann in Form verschiedener Topologien eingerichtet werden. Für die Auswahl der passenden Topologie sind hierbei die Netzwerkzonen, in denen die jeweiligen Kubernetes-Cluster eingerichtet werden, und der Grad der Ausfallsicherheit der Control Planes ist ausschlaggebend. Istio unterscheidet dabei folgende Variationen für die Redundanz der Control Planes:
- Primary Remote
- Multi-Primary
Bei Primary Remote existiert nur eine Control Plane, die für alle Cluster im Multi-Mesh zuständig ist. Diese Topologie ist einfach einzurichten und zu betreiben, aber bzgl. Ausfallsicherheit nicht so hochwertig wie Multi-Primary. Hier besitzt jeder Cluster seine eigene Control Plane (Abb. 2).
Abb. 2: Multi-Primary Multi-Network [2]
Bei der Auswahl der geeigneten Topologie muss daher ein Kompromiss zwischen Ausfallsicherheit und Konfigurationsaufwand gefunden werden. Da aber eine Multi-Cluster-Umgebung ohne Automatisierung zur Erstellung der Cluster nicht ratsam ist, kann der Konfigurationsaufwand vernachlässigt werden. Es bleibt somit nur das Argument der Ausfallsicherheit und diese ist im Multi-Primary-Modus definitiv besser. Die Anzahl der im Multi-Mesh betriebenen Cluster ist eine weitere Stellgröße für die Auswahl der Topologie. Je mehr Cluster es werden, desto eher sollte man sich für Multi-Primary entscheiden.
Endpoint Discovery
Das Traffic Routing, das ebenfalls von den Sidecars ausgeführt wird, steuert die Control Plane. Diese informiert die Sidecars über alle Workloads, die sich im Cluster bzw. im Multi-Mesh befinden. Darüber hinaus wird den Sidecars noch mitgeteilt, über welche Netzwerkverbindungen sie die Workloads in den anderen Clustern im Multi-Mesh erreichen können (siehe nächster Abschnitt).
Hierfür benötigt die Control Plane aktuelle Informationen bzgl. Kubernetes Services und Kubernetes Endpoints aus der Service Registry der jeweiligen Cluster. Da diese Informationen im Kubernetes API hinterlegt sind, fragen die Control Planes sie regelmäßig dort ab. Für die Workloads eines Partnerclusters muss die Control Plane daher auf das Kubernetes API des Partnerclusters zugreifen (Abb. 3).
Abb. 3: Endpoint Discovery [3]
In der Regel sind diese externen Zugriffe auf das Kubernetes API durch Security geschützt. Folglich benötigt die Control Plane die notwendigen Tokens aller Partnercluster, um sich dort die benötigten Informationen zu holen.
Änderungen im Kubernetes API des Partnerclusters werden periodisch abgefragt und an die Sidecars des eigenen Clusters weitergeleitet. Auf diese Weise sind die Sidecars zeitnah über den Zustand der Workloads aller verknüpften Cluster informiert und können die Kommunikation zielgerichtet dorthin lenken.
East-West Gateways
In der Regel werden die Kubernetes-Cluster in eigenen Netzwerkzonen (Subnetze) installiert. Um diese Subnetze in der übergreifenden Kommunikation zu verbinden, benötigt man einen Proxy, der den Eingang in das jeweilige Subnetz ermöglicht. Das ist für Kubernetes-Cluster nichts Neues, da so in der Regel die Ingress-Kommunikation aufgebaut wird. Im Fall einer Cluster-zu-Cluster-Kommunikation muss ein solcher Proxy ebenfalls zur Verfügung stehen. Istio setzt hierbei auf dasselbe Ingress Gateway, das schon für die Ingress-Kommunikation empfohlen wird. Nur diesmal wird dieses Gateway als sog. East-West Gateway konfiguriert. Das bedeutet, dass eine eingehende Verbindung aus dem Partnercluster über einen Auto-Pass-through-Modus an den aufgerufenen Workload weitergeleitet wird (Abb. 4).
Abb. 4: East-West Gateways [4]
Die vom aufrufenden Sidecar initiierte mTLS-Verbindung wird nicht im East-West Gateway terminiert, sondern an das aufgerufene Sidecar weitergeleitet. Der mTLS Handshake findet zwischen diesen beiden Sidecars statt. Die mTLS-Verbindung erfolgt also analog zur Kommunikation im Service Mesh, die innerhalb eines Clusters stattfindet. Im Wesentlichen ist das der Grund dafür, dass für eine Multi-Mesh-Kommunikation dieselben Funktionalitäten wie bei einer Service-Mesh-Kommunikation zur Verfügung stehen.
Für die genannten Voraussetzungen (Trust Domain, Deployment Model, Endpoint Discovery und East-West Gateway) liefert Istio passende Utilities mit, die die Konfiguration der entsprechenden Cluster sehr stark vereinfachen. Es bleibt also nur noch die Aufgabe, diese Utilities oder deren Ausgaben (Kubernetes-Ressourcendateien) in die DevOps Pipeline zu integrieren.
Stay tuned
Regelmäßig News zur Konferenz und der Java-Community erhalten
Anwendungsbeispiele
Die folgenden Beispiele stellen nur ein Teil der Funktionalitäten dar, die in einem Multi-Mesh möglich sind. Vorhandene Istio-Regeln, die bereits in einem Service-Mesh zum Einsatz kommen, können ganz ohne oder mit nur geringen Anpassungen spezielle Multi-Mesh-Funktionalitäten nutzen.
Locality-based Routing
Workloads, die in verschiedenen Clustern deployt sind, können über eine definierte Aufrufverteilung angesprochen werden. Diese Cluster werden mit Hilfe von Regions und Zones gekennzeichnet, wobei eine Region in verschiedene Zones unterteilt wird. Die Aufteilung in Region/Zone ist bei den bekannten Cloud-Providern für die Deklaration ihrer Verfügbarkeitszonen üblich.
Mit der Istio DestinationRule in Listing 1 kann beim Aufruf von helloworld.sample.svc.cluster.local folgende Verteilung festgelegt werden: 70 Prozent aller Aufrufe, die innerhalb von region1/ zone1 initiiert werden, sollen in derselben Region und Zone bleiben: from: “region1/zone1/” to: “region1/zone1/”: 70
Zwanzig Prozent der Aufrufe verbleiben in derselben Region (region1), werden aber in die Zone zone2 geleitet, und die restlichen zehn Prozent werden in eine andere Region (region3) und dort in die Zone zone4 geroutet.
Listing 1
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: helloworld
spec:
host: helloworld.sample.svc.cluster.local
trafficPolicy:
loadBalancer:
localityLbSetting:
enabled: true
distribute:
- from: "region1/zone1/*"
to:
"region1/zone1/*": 70
"region1/zone2/*": 20
"region3/zone4/*": 10
Locality-based Routing mit Fail-over
Um sich vor dem Ausfall einer Region oder Zone zu schützen, können sog. Fail-over-Regeln erstellt werden. Eine Weiterleitung in eine andere Region/Zone erfolgt also nur im Fehlerfall. Diese Art der Weiterleitung verwendet ebenfalls eine Istio DestinationRule (Listing 2).
Listing 2
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: helloworld
spec:
host: helloworld.sample.svc.cluster.local
trafficPolicy:
connectionPool:
http:
maxRequestsPerConnection: 1
loadBalancer:
simple: ROUND_ROBIN
localityLbSetting:
enabled: true
failover:
- from: region1
to: region2
outlierDetection:
consecutive5xxErrors: 1
interval: 1s
baseEjectionTime: 1m
Fazit
Eine Entscheidung zugunsten Multi-Cluster wird von einem Service Mesh nicht blockiert. Das Gegenteil ist der Fall. Ein Service Mesh, das bei einer Multi-Cluster-Umgebung zu einem Multi-Mesh erweitert wird, kann diese Entscheidung sogar fördern. Ein Wechsel von Single- zu Multi-Cluster, ohne dabei das Service Mesh zu berücksichtigen, ist allerdings wenig sinnvoll. Der Nutzen eines Multi-Mesh überwiegt in der Regel den Aufwand, der für seinen Aufbau erforderlich ist. Das geht sogar so weit, dass auch eine kurzfristige Multi-Cluster-Strategie mit einem Multi-Mesh harmoniert. Eine kurzfristige Multi-Cluster-Strategie kann beispielsweise bei einer Migration von On-Premise in die Cloud (oder umgekehrt) oder bei einem Wechsel des Cloud-Providers vorliegen. Ob nach dieser Migration noch Multi-Cluster benötigt werden, kann dann wieder gesondert überlegt werden.
Links & Literatur
[1] https://istio.io/latest/docs/tasks/security/cert-management/plugin-ca-cert/
[2] https://istio.io/latest/docs/setup/install/multicluster/multi-primary_multi-network/
[4] https://istio.io/latest/docs/ops/deployment/deployment-models/#multiple-networks