Zum Hauptinhalt springen

Zaris von außerhalb des Clusters erreichen: externe Clients ohne natives SDK

· 6 Minuten Lesezeit
Clustron Team
Engineering für verteilte Systeme

Zaris von außerhalb des Clusters erreichen

Betreiben Sie Zaris in Kubernetes, ist der Normalfall einfach: In-Cluster-Clients erreichen die Pods über ihre internen Adressen — Pod-IPs und Cluster-DNS-Namen wie zaris-0.zaris.svc —, und alles wird sauber geroutet. Sobald ein Client außerhalb des Clusters läuft, bricht das zusammen. Eine externe Anwendung kann zaris-0.zaris.svc oder eine Pod-IP nicht anwählen; diese Namen und Adressen werden nur innerhalb des Cluster-Netzwerks aufgelöst und geroutet.

Das ist keine Eigenheit von Zaris, sondern die grundlegende Trennung zwischen dem internen Netzwerk des Clusters und der Außenwelt. Am stärksten trifft sie topologiebewusste Clients. Ein Redis-Client im Cluster-Modus oder jeder Client, der Nodes ermittelt und pro Key routet, lädt eine Topologie-Map vom Server und verbindet sich mit den darin enthaltenen Adressen. Sind diese Adressen intern, erhält ein externer Client eine Map voller Endpunkte, die er nie erreichen kann.

Zaris löst das mit Advertised Addresses, umgesetzt als per-Listener-„Boundary View".

Warum In-Cluster-Adressen extern scheitern​

Kubernetes gibt jedem Pod eine interne Identität: eine Pod-IP im Cluster-Netzwerk und stabile DNS-Namen über einen Headless-Service, etwa zaris-0.zaris.svc. Innerhalb des Clusters werden diese einwandfrei geroutet. Außerhalb sind sie bedeutungslos — das Netzwerk des externen Clients hat keine Route zu einer Pod-IP und keinen Resolver für *.svc.

Beantwortet Zaris eine Topologie- oder Redirect-Anfrage, liefert es Adressen zurück. Würde es stets seine internen Adressen zurückgeben, erhielte ein externer Client eine Map von Nodes, zu denen er sich nicht verbinden kann. Er würde die Topologie laden, brav versuchen, Verbindungen zu den angegebenen Nodes zu öffnen, und bei jeder einzelnen scheitern — obwohl der Cluster völlig gesund ist.

Warum ein einzelner LoadBalancer-Endpunkt nicht genügt​

Die naheliegende erste Lösung ist ein Load-Balancer vor allem, und für einfache Clients funktioniert das. Es genügt aber nicht für einen topologiebewussten Client, der Adressierung pro Node benötigt.

Das gesamte Design eines Clients im Cluster-Modus besteht darin, die Node-Liste zu laden und jeden Key direkt zu dem Node zu routen, der ihn besitzt, wobei er Redirects folgt, wenn die Zuständigkeit wechselt. Dafür braucht er für jeden Node eine eigene, erreichbare Adresse — nicht einen gemeinsamen Endpunkt, der sie alle verbirgt. Eine einzelne virtuelle IP gibt dem Client kein Ziel für eine Verbindung pro Node oder einen Redirect. Jeder Node muss also einzeln von außen erreichbar sein, und die Adressen, die Zaris externen Clients mitteilt, müssen genau diese extern erreichbaren Adressen pro Node sein.

Per-Listener-Advertised-Addresses: die Boundary View​

Das ist die Kernidee. Jeder Node — genauer: jeder Listener auf einem Node — kann externen Clients eine andere Adresse mitteilen als die, die er intern verwendet. Zaris behandelt jeden Listener als Grenze zwischen zwei Sichten auf die Topologie und übersetzt die zurückgegebenen Adressen pro Listener.

Konkret: Trifft eine Anfrage am internen Listener ein, füllt Zaris die Topologie-Antwort (die Node-Adressen in Cluster- und Redirect-Antworten) mit internen Adressen. Trifft eine Anfrage an dem für externe Clients vorgesehenen Listener ein, füllt es dieselbe Antwort stattdessen mit der extern bekanntgegebenen Adresse jedes Nodes. Jede Topologie- oder Redirect-Antwort wird passend zur Grenze umgeschrieben, an der sich der Client befindet — ein externer Client erhält stets eine Adresse, die er erreichen kann, und ein In-Cluster-Client bekommt weiterhin die interne Adresse, die für ihn am schnellsten ist.

Da dies pro Listener geschieht, muss sich der Cluster nicht entscheiden, ob er intern oder extern adressierbar ist — er ist beides gleichzeitig, und jeder Client erhält die Sicht, die zu seinem Zugangspunkt passt.

Live validiert: 200/200, beide Seiten gleichzeitig​

Dies wurde mit externen und internen Clients validiert, die gleichzeitig gegen denselben Cluster liefen: 200/200 Operationen waren erfolgreich, von externen und internen Clients zur selben Zeit, mit korrekter Adressübersetzung pro Listener — externe Clients verbanden sich mit den extern bekanntgegebenen Adressen, interne Clients nutzten die internen, und keine Sicht sickerte in die andere durch. Der gleichzeitige Betrieb ist der entscheidende Punkt: Die Grenze muss in beide Richtungen zugleich halten.

Die Kubernetes-Verdrahtung, die weiterhin bei Ihnen liegt​

Zaris macht die Adressierung korrekt — es gibt jedem Client eine Adresse, die er erreichen kann. Jeden Node tatsächlich von außen erreichbar zu machen, ist Kubernetes-Networking und bleibt Betreiberaufgabe. Zwei Teile sind wichtig.

Services pro Pod. Da topologiebewusste externe Clients jeden Node einzeln erreichen müssen, machen Sie die Nodes einzeln verfügbar — ein Service pro Pod, der jedem Node eine eigene, extern erreichbare Adresse gibt, und zwar genau die Adresse, die dieser Node an seinem externen Listener bekanntgibt.

apiVersion: v1
kind: Service
metadata:
name: zaris-0-ext
spec:
type: LoadBalancer
selector:
statefulset.kubernetes.io/pod-name: zaris-0
ports:
- name: resp
port: 6379
targetPort: 6379

Anschließend wird jedem Node seine extern bekanntgegebene Adresse mitgeteilt:

kubectl set env statefulset/zaris \
ZARIS_ADVERTISED_ADDRESS_EXTERNAL="10.0.0.10:6379"

# Confirm an external client is handed reachable, per-node addresses.
redis-cli -h 10.0.0.10 -p 6379 CLUSTER SLOTS

TLS-SANs. Ist TLS aktiviert, validiert ein Client das Zertifikat gegen den Namen, mit dem er sich verbunden hat. Da externe Clients sich mit den extern bekanntgegebenen Namen verbinden, müssen diese Namen in den Subject Alternative Names des Zertifikats stehen. Gibt ein Node 10.0.0.10 (oder einen Namen wie redis.example.com) bekannt, sein Zertifikat deckt aber nur zaris-0.zaris.svc ab, schlägt der externe TLS-Handshake fehl, obwohl die Adresse erreichbar ist. Die Pflege dieser SANs ist Betreiberaufgabe.

Die ehrliche Grenze​

Der Beitrag von Zaris ist präzise: Es macht die Adressierung über die Grenze zwischen Cluster und Außenwelt hinweg korrekt, pro Listener, sodass kein Client je eine Adresse erhält, die er nicht nutzen kann. Es stellt weder Ihre Load-Balancer bereit noch Ihre Zertifikate aus. Services pro Pod und die Verwaltung der TLS-SANs liegen bei Ihnen.

Das ist die richtige Arbeitsteilung. Der schwierige, fehleranfällige Teil — jede Topologie- und Redirect-Antwort in die passende Sicht für den anfragenden Client zu übersetzen — wird Ihnen abgenommen. Sobald das Networking darum herum steht, teilen sich externe und interne Clients einen Cluster, ohne sich gegenseitig in die Quere zu kommen.