Reaching Zaris From Outside the Cluster: External Clients Without a Native SDK
Run Zaris in Kubernetes and the happy path is easy: in-cluster clients reach the pods by their internal addresses — pod IPs and cluster-DNS names like zaris-0.zaris.svc — and everything routes cleanly. The moment a client lives outside the cluster, that breaks. An external application cannot dial zaris-0.zaris.svc or a pod IP; those names and addresses only resolve and route inside the cluster network.
This is not a Zaris quirk — it is the fundamental split between the cluster's internal network and the outside world. It bites hardest with topology-aware clients. A cluster-mode Redis client, or any client that discovers nodes and routes per-key, fetches a topology map from the server and connects to the addresses in it. If those addresses are internal, an external client gets a map full of endpoints it can never reach.
Zaris solves this with advertised addresses, handled as a per-listener "boundary view."
Why in-cluster addresses fail externally
Kubernetes gives every pod an internal identity: a pod IP on the cluster network, and stable DNS names through a headless Service, such as zaris-0.zaris.svc. Inside the cluster those route perfectly. Outside, they are meaningless — the external client's network has no route to a pod IP and no resolver for *.svc.
When Zaris answers a topology or redirect request, it hands back addresses. If it always returned its internal addresses, an external client would receive a map of nodes it cannot connect to. It would fetch the topology, dutifully try to open connections to the advertised nodes, and fail on every one — even though the cluster is perfectly healthy.
Why a single LoadBalancer endpoint isn't enough
The obvious first fix is one load balancer in front of everything, and for simple clients that works. But it does not satisfy a topology-aware client that needs per-node addressing.
A cluster-mode client's whole design is to fetch the node list and route each key directly to the node that owns it, following redirects as ownership moves. To do that it needs a distinct, reachable address for each node — not one shared endpoint that hides them all. A single virtual IP gives the client nowhere to send a per-node connection or a redirect. So each node has to be independently reachable from outside, and the addresses Zaris advertises to external clients have to be those externally reachable, per-node addresses.
Per-listener advertised addresses: the boundary view
Here is the core idea. Each node — more precisely, each listener on a node — can advertise a different address to external clients than the one it uses internally. Zaris treats each listener as a boundary between two views of the topology, and translates the addresses it hands back per listener.
Concretely: when a request arrives on the internal listener, Zaris fills the topology response (the node addresses it returns in cluster and redirect responses) with internal addresses. When a request arrives on the listener designated for external clients, it fills that same response with each node's externally advertised address instead. Every topology or redirect reply is rewritten to match the boundary the client is on — an external client is always told an address it can reach, and an in-cluster client still gets the internal address that is fastest for it.
Because this is per listener, the cluster does not have to choose between being internally addressable and externally addressable — it is both at once, and each client gets the view matching where it entered.
Live-validated: 200/200, both sides at once
This was validated with external and internal clients running simultaneously against the same cluster: 200/200 operations succeeded from both external and internal clients at the same time, with correct per-listener address translation — external clients connected to the externally advertised addresses, internal clients used the internal ones, and neither view leaked into the other. Running both concurrently is the point: the boundary has to hold in both directions at once.
The Kubernetes wiring you still own
Zaris makes the addressing correct — it hands each client an address it can reach. Making each node actually reachable from outside is Kubernetes networking, and that stays operator work. Two pieces matter.
Per-pod Services. Because topology-aware external clients need each node independently reachable, you expose nodes individually — a Service per pod, each giving one node its own externally reachable address, which is exactly the address that node advertises on its external listener.
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
Each node is then told its externally advertised address:
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. When TLS is enabled, a client validates the certificate against the name it connected to. Since external clients connect to the externally advertised names, those names must appear in the certificate's Subject Alternative Names. If a node advertises 10.0.0.10 (or a name like redis.example.com) but its certificate only covers zaris-0.zaris.svc, the external TLS handshake fails even though the address is reachable. Managing those SANs is operator work.
The honest boundary
Zaris's contribution is precise: it makes the addressing correct across the cluster/outside-world boundary, per listener, so no client is ever handed an address it cannot use. It does not provision your load balancers or issue your certificates. Per-pod Services and TLS SAN management are yours to wire.
That is the right division of labor. The hard, easy-to-get-wrong part — translating every topology and redirect response to the correct view for the client that asked — is handled for you. Once the networking around it is in place, external and internal clients share one cluster without stepping on each other.
- Redis protocol reference: Redis protocol (RESP) compatibility
- Failover models for RESP clients: Three ways to fail over
- Install: clustron.io/install