Zum Hauptinhalt springen

Zaris mit Helm auf Kubernetes bereitstellen: eine sichere End-to-End-Anleitung

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

Zaris auf Kubernetes mit Helm bereitstellen, durchgängig abgesichert

Einen verteilten Store auf Kubernetes zu bringen, ist einfach. Ihn dort mit aktiviertem TLS, von außerhalb des Clusters erreichbar und mit einem Client, der sich tatsächlich verbindet bereitzustellen, ist der Punkt, an dem die meisten Anleitungen stillschweigend aufhören. Zaris liefert ein Helm-Chart, und wir haben den gesamten Weg — einschließlich der abgesicherten, extern erreichbaren Konfiguration — End-to-End auf einem lokalen Cluster validiert.

Dieser Beitrag ist diese Anleitung. Wir führen sie auf kind (Kubernetes-in-Docker) aus, damit Sie jeden Schritt auf einem Laptop nachvollziehen können, und wählen bewusst den schwierigeren Weg: TLS aktiviert, Zertifikate mit den richtigen Subject Alternative Names, externer Zugriff an und ein Client, der sich über den abgesicherten Endpunkt verbindet. Wir nennen das die Model-B-Konfiguration — extern erreichbar und abgesichert, im Gegensatz zu einem rein internen Cluster.

Eine Korrektheitsregel bringt fast jedes erste Deployment ins Stolpern, und sie hat nichts mit Zertifikaten zu tun: Der Store-Name in Ihrem Connection String muss mit der clusterId des Deployments übereinstimmen. Wir zeigen genau, wo das zuschlägt. Alles andere ist auf einem Produktions-Cluster identisch — kind bietet lediglich einen sauberen Wegwerf-Ort, um es zu beweisen.

Was „sicher" hier bedeutet​

Ein Zaris-Deployment besteht aus mehreren Nodes plus einem Manager, die jeweils unter einem stabilen DNS-Namen erreichbar sind. Sicherheit zu aktivieren heißt, dass drei Dinge gleichzeitig zusammenpassen:

  1. TLS ist aktiviert an den Listenern von Node und Manager.
  2. Zertifikate tragen die richtigen SANs — jeder Name, über den ein Client einen Node erreichen könnte, muss im Zertifikat dieses Nodes stehen, sonst schlägt die TLS-Verifizierung fehl.
  3. Externer Zugriff ist konfiguriert, sodass ein Client außerhalb des Clusters die Nodes unter einem Namen erreicht, der ebenfalls im Zertifikat steht.

Die SAN-Anforderung ist der subtile Punkt. Ein verifizierender Client prüft das Zertifikat gegen den Namen, den er angewählt hat; ein Zertifikat mit einer einzigen SAN, die nur zaris-0 abdeckt, wird daher nicht validiert, wenn sich ein Client über einen externen Namen wie zaris.example.com verbindet. Deshalb verwendet der abgesicherte Weg Multi-SAN-Zertifikate — ein Zertifikat, das für den In-Cluster-Servicenamen, den Pod-Namen und den externen Namen gültig ist.

Zaris stellt Tooling zur Zertifikatserzeugung und Beispiele bereit, damit dieser Schritt reproduzierbar ist, statt ein handgestrickter openssl-Marathon zu sein. Sie können es weiterhin von Hand tun — die Form sehen Sie unten —, aber das Tooling hält die SAN-Menge jedes Mal korrekt.

Schritt 1: Ein kind-Cluster​

kind create cluster --name zaris-secure
kubectl cluster-info --context kind-zaris-secure
kubectl create namespace zaris

Das ist das gesamte Fundament. Auf einem echten Cluster würden Sie das überspringen und kubectl auf Ihre verwaltete Steuerungsebene richten; nachgelagert ändert sich nichts.

Schritt 2: Multi-SAN-Zertifikate erzeugen​

Die Zertifikate müssen jeden Namen abdecken, den ein Client oder Peer verwenden wird: den In-Cluster-Servicenamen, den stabilen Namen pro Pod und einen externen Namen, den wir bereitstellen. Das Zaris-Zertifikats-Tooling erzeugt eine CA und Node-Zertifikate mit genau dieser SAN-Menge; hier die äquivalente Form im openssl-Stil, damit Sie sehen, was verlangt wird:

# 1. A CA the client will trust
openssl req -x509 -newkey rsa:4096 -nodes -days 365 \
-keyout ca.key -out ca.crt \
-subj "/CN=Zaris Dev CA"

# 2. A node certificate whose SANs cover EVERY name used to reach it
openssl req -newkey rsa:2048 -nodes \
-keyout zaris-node.key -out zaris-node.csr \
-subj "/CN=zaris"

cat > san.cnf <<'EOF'
subjectAltName = @alt
[alt]
DNS.1 = zaris-0.zaris.svc # per-pod stable name
DNS.2 = zaris.zaris.svc # in-cluster service name
DNS.3 = zaris.example.com # external name clients dial
EOF

openssl x509 -req -in zaris-node.csr \
-CA ca.crt -CAkey ca.key -CAcreateserial \
-extfile san.cnf -days 365 -out zaris-node.crt

Laden Sie die CA und das Schlüssel-/Zertifikatspaar des Nodes als Secrets in den Namespace, die das Chart einbinden kann:

kubectl -n zaris create secret generic zaris-ca \
--from-file=ca.crt=ca.crt

kubectl -n zaris create secret tls zaris-node-tls \
--cert=zaris-node.crt --key=zaris-node.key

Die Regel, die Sie sich merken sollten: Steht ein Name nicht in subjectAltName, lehnt ein verifizierender Client, der diesen Namen anwählt, die Verbindung ab. Stimmt die SAN-Liste, funktioniert TLS einfach; stimmt sie nicht, jagen Sie einem Handshake-Fehler hinterher, der wie ein Netzwerkproblem aussieht, aber keines ist.

Schritt 3: Die Values-Datei (TLS + externer Zugriff)​

Hier eine values.yaml-Skizze für Model B — Sicherheit an, externer Zugriff an und die Zertifikats-Secrets aus Schritt 2 eingebunden:

# values.yaml — Model B: secured + externally reachable
clusterId: zaris # <-- remember this value for the connection string

replicaCount: 3

tls:
enabled: true
# CA clients must trust, and the node key/cert pair
caSecret: zaris-ca
certSecret: zaris-node-tls

external:
enabled: true
# the name clients outside the cluster will dial —
# must also be a SAN on the node certificate
advertisedHost: zaris.example.com

manager:
tls:
enabled: true
caSecret: zaris-ca
certSecret: zaris-node-tls

Zwei Felder leisten die Hauptarbeit. tls.enabled: true aktiviert die abgesicherten Listener und bindet die Zertifikate ein. external.enabled: true mit einem advertisedHost macht die Nodes von außen erreichbar — und advertisedHost ist dasselbe zaris.example.com, das wir in die Zertifikats-SANs aufgenommen haben. Beide müssen übereinstimmen. Behalten Sie auch clusterId im Auge: Es ist hier zaris, und Sie benötigen es gleich wortgleich.

Schritt 4: helm install​

helm install zaris oci://registry-1.docker.io/clustron/zaris \
--version 2.0.0 \
-n zaris \
-f values.yaml

# watch the nodes come up
kubectl -n zaris rollout status statefulset/zaris
kubectl -n zaris get pods

Sind die Pods bereit, haben Sie einen Zaris-Cluster mit drei Nodes, aktiviertem TLS und einem externen Endpunkt. Auf kind erreichen Sie ihn per Port-Forward; auf einem echten Cluster übernimmt ein LoadBalancer-Service oder ein Ingress.

kubectl -n zaris port-forward svc/zaris 7000:7000

Schritt 5: Einen Client verbinden — und die clusterId-Regel​

Jetzt der Teil, an dem erste Deployments scheitern. Ein Zaris-Connection-String benennt den Store, mit dem Sie sich verbinden, und gegenüber einem Helm-Deployment muss dieser Store-Name der clusterId des Deployments entsprechen. Wir haben clusterId: zaris in values.yaml gesetzt, also lautet der Store-Name im Connection String zaris — nicht my-store, nicht der Release-Name, nicht der Service-Name. Die clusterId.

// The store segment MUST match values.yaml clusterId ("zaris").
// zariss:// selects TLS; ?ca= points at the CA we generated.
var connectionString =
"zariss://zaris.example.com:7000/zaris?ca=file:./ca.crt";

await using var client = await ZarisClient.ConnectAsync(connectionString);
await client.PutAsync("greeting", "hello from a secured cluster");
var value = await client.GetAsync("greeting");

Weichen Store-Name und clusterId voneinander ab, schlägt die Verbindung fehl — und der Fehler kann wie ein Authentifizierungs- oder Routing-Problem klingen statt wie ein Namensproblem. Wenn ein abgesichertes Helm-Deployment die Verbindung verweigert und die Zertifikate in Ordnung sind, ist dies das Erste, was Sie prüfen sollten: Store-Name im Connection String == clusterId. Es ist der häufigste Fehler bei ersten Deployments, den wir sehen.

Beachten Sie das Schema: zariss:// (mit dem zusätzlichen s) wählt den abgesicherten Endpunkt, und ?ca=file:./ca.crt teilt dem Client mit, welcher CA er vertrauen soll — der, die wir in Schritt 2 erzeugt haben. Der Host ist der externe Name, weshalb er eine SAN sein musste.

Von kind zur Produktion​

Auf einem echten Cluster unterscheiden sich zwei Dinge: Der externe Zugriff wird zu einem LoadBalancer-Service oder einem Ingress mit echtem DNS statt eines kubectl port-forward, und die Zertifikate stammen aus Ihrer eigenen CA oder von einem Issuer wie cert-manager statt aus einer Dev-CA. Was sich nicht ändert, ist das Wesentliche — die SAN-Regel (jeder Name, den ein Client anwählt, muss im Zertifikat stehen) und die Connection-String-Regel (Store-Name entspricht clusterId). Sie tauschen einen Port-Forward gegen einen LoadBalancer und eine Dev-CA gegen eine echte, ohne das Deployment neu zu entwerfen.

Wie es weitergeht​

Das ist ein abgesicherter Zaris-Cluster von Anfang bis Ende: per Helm installiert, TLS an, Multi-SAN-Zertifikate, externer Zugriff und ein Client, der über den verschlüsselten Endpunkt verbunden ist. Um tiefer in das Trust-Modell einzusteigen — Zaris unterstützt mehrere CA-Modi, sodass Sie nicht gegen die PKI Ihrer Organisation ankämpfen müssen —, lesen Sie Pluggable TLS Trust. Die vollständige Chart-Referenz und Muster für das Produktions-Networking finden Sie im Kubernetes-Deployment-Leitfaden.