Maintenance

Site is under maintenance — quizzes are still available.

Go to quizzes

Deploy Redis Cluster on Kubernetes

Learn to deploy a Redis cluster on Kubernetes with this hands-on tutorial. Covers core concepts, step-by-step deployment, troubleshooting, and next steps in the Redis learning path.

Focus: deploy redis cluster on kubernetes

Sponsored

Deploying a Redis cluster on Kubernetes can feel like orchestrating a symphony of stateful nodes—getting it wrong means data loss, split brains, or endless crash loops. This lesson cuts through the YAML noise to give you a battle-tested approach for running a production-grade Redis cluster inside Kubernetes, so you stop fighting infrastructure and start scaling.

The problem this lesson solves

Running a single Redis pod is easy. Running a Redis cluster—six or more nodes with automatic sharding, replication, and failover—inside Kubernetes is a different beast. The default redis-cluster setup expects static IPs and direct node-to-node communication. Kubernetes gives you ephemeral pods with dynamic IPs. Without careful orchestration, your cluster will never form, or worse, it will form and then silently lose data.

Pain point: You need a Redis cluster for high availability and horizontal scaling, but you keep seeing CLUSTERDOWN The cluster is down errors in your logs.

Core concept / mental model

Think of a Redis cluster as a team of librarians. Each librarian (node) manages a subset of the books (hash slots). Kubernetes is the library building that can reassign rooms (pods) whenever it wants. To make this work, you need three things:

  • Stable networking – Each pod must know the exact IP of every other pod before the cluster forms.
  • Headless service – A Kubernetes Service that gives each pod a predictable DNS name like redis-cluster-0.redis-cluster.default.svc.cluster.local.
  • StatefulSet – A controller that assigns stable identities and persistent storage to each pod.

Definitions

Term Meaning
StatefulSet Kubernetes controller for stateful apps with stable network IDs.
Headless Service A Service with clusterIP: None that exposes pod DNS names without load balancing.
Redis cluster bus The internal channel Redis nodes use for gossip and failover.
Hash slot A unit of data ownership—Redis cluster has 16,384 slots.

How it works step by step

  1. Provision a StatefulSet with 6 replicas (3 masters, 3 replicas) using a headless Service.
  2. Mount a PersistentVolumeClaim for each pod to store appendonly.aof and dump.rdb.
  3. Configure each pod via a ConfigMap. Enable cluster mode: cluster-enabled yes and cluster-require-full-coverage no for resiliency.
  4. Wait for all pods to become Ready (their IPs are resolvable via DNS).
  5. Run redis-cli --cluster create from inside one pod, pointing to all six pod DNS names.
  6. Verify the cluster with redis-cli cluster info and try a SET/GET.

Pro tip: Always use cluster-require-full-coverage no in production. If one master goes down, the entire cluster won't stop serving reads.

Hands-on walkthrough

Prerequisites

  • A Kubernetes cluster (minikube or cloud) with kubectl configured.
  • helm installed (optional, but makes life easier).

Step 1: Create a namespace

kubectl create namespace redis

Step 2: Create the ConfigMap

apiVersion: v1
kind: ConfigMap
metadata:
  name: redis-cluster-config
  namespace: redis
data:
  redis.conf: |
    cluster-enabled yes
    cluster-require-full-coverage no
    cluster-node-timeout 5000
    appendonly yes
    protected-mode no
    bind 0.0.0.0
    port 6379

Save as redis-config.yaml and apply:

kubectl apply -f redis-config.yaml

Step 3: Deploy the headless Service and StatefulSet

---
apiVersion: v1
kind: Service
metadata:
  name: redis-cluster
  namespace: redis
  labels:
    app: redis-cluster
spec:
  clusterIP: None
  ports:
  - port: 6379
    targetPort: 6379
    name: client
  - port: 16379
    targetPort: 16379
    name: gossip
  selector:
    app: redis-cluster
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: redis-cluster
  namespace: redis
spec:
  serviceName: redis-cluster
  replicas: 6
  selector:
    matchLabels:
      app: redis-cluster
  template:
    metadata:
      labels:
        app: redis-cluster
    spec:
      containers:
      - name: redis
        image: redis:7.2
        command: ["/bin/sh", "-c"]
        args:
          - |
            IP=$(hostname -i)
            sed -i "s/^# bind 0.0.0.0/bind $IP/" /etc/redis/redis.conf
            redis-server /etc/redis/redis.conf
        ports:
        - containerPort: 6379
          name: client
        - containerPort: 16379
          name: gossip
        volumeMounts:
        - name: config
          mountPath: /etc/redis
        - name: data
          mountPath: /data
      volumes:
      - name: config
        configMap:
          name: redis-cluster-config
  volumeClaimTemplates:
  - metadata:
      name: data
    spec:
      accessModes: ["ReadWriteOnce"]
      resources:
        requests:
          storage: 1Gi

Save as redis-cluster.yaml and apply:

kubectl apply -f redis-cluster.yaml

Step 4: Wait for all pods to be Ready

kubectl get pods -n redis -w

Wait until all 6 pods show Running.

Step 5: Create the cluster

kubectl exec -it -n redis redis-cluster-0 -- redis-cli --cluster create \
  redis-cluster-0.redis-cluster.default.svc.cluster.local:6379 \
  redis-cluster-1.redis-cluster.default.svc.cluster.local:6379 \
  redis-cluster-2.redis-cluster.default.svc.cluster.local:6379 \
  redis-cluster-3.redis-cluster.default.svc.cluster.local:6379 \
  redis-cluster-4.redis-cluster.default.svc.cluster.local:6379 \
  redis-cluster-5.redis-cluster.default.svc.cluster.local:6379 \
  --cluster-replicas 1

You should see output like:

>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica redis-cluster-3 to redis-cluster-0
Adding replica redis-cluster-4 to redis-cluster-1
Adding replica redis-cluster-5 to redis-cluster-2
>>> OK

Step 6: Test the cluster

# Write a key
kubectl exec -n redis redis-cluster-0 -- redis-cli -c set mykey "hello"
# Should return -> OK

# Read from a different pod
kubectl exec -n redis redis-cluster-2 -- redis-cli -c get mykey
# Should return -> "hello"
  • Success! Your Redis cluster is now running on Kubernetes.

Compare options / when to choose what

Approach Pros Cons Best for
Manual via StatefulSet + exec Full control, no extra tooling Manual cluster creation, harder to automate Learning, small dev clusters
Helm chart (bitnami/redis-cluster) One-command install, auto-cluster formation Opacity, hard to customize Production, teams familiar with Helm
Redis Operator (e.g., OLM) Self-healing, backups built-in Operator lifecycle complexity Large-scale, multi-cluster deployments
  • Use the manual approach for labs and understanding internals.
  • Use Helm when you need a stable, configurable cluster fast.
  • Use an Operator when you want automated failover recovery without manual redis-cli commands.

Troubleshooting & edge cases

"Waiting for the cluster to join..." hangs forever

  • Cause: Pods cannot resolve each other's DNS.
  • Fix: Ensure the Headless Service has clusterIP: None and that your cluster DNS is healthy. Try: bash kubectl exec -n redis redis-cluster-0 -- nslookup redis-cluster-0.redis-cluster

"[ERR] Node is not empty" when creating cluster

  • Cause: A pod already has old AOF or RDB files from a previous cluster.
  • Fix: Delete the PVC and let it recreate: bash kubectl delete pvc data-redis-cluster-0 -n redis Then re-run redis-cli --cluster create.

One master goes down and cluster stops serving writes

  • Cause: cluster-require-full-coverage yes (default).
  • Fix: Set it to no in the ConfigMap. The cluster will serve writes on remaining masters.

Pod IP changes after restart and cluster breaks

  • Cause: The cluster was created using pod IPs instead of DNS names.
  • Fix: Always use the full service DNS name (<pod>.<service>.<namespace>.svc.cluster.local) during --cluster create.

Pro tip: When using StatefulSets, the pod hostname is guaranteed to be <name>-<ordinal>, but the DNS resolution depends on the headless service.

What you learned & what's next

You now know how to deploy a Redis cluster on Kubernetes from scratch. You understand:

  • The core components: StatefulSet, Headless Service, and ConfigMap.
  • The difference between static IPs and DNS-based node discovery.
  • How to create the cluster with redis-cli --cluster create.
  • How to troubleshoot common failures like DNS issues or unclean node state.

This skill is critical because it lets you run Redis at scale without locking yourself to a specific cloud provider. Next up in your Redis learning path, you'll explore scaling the cluster dynamically—adding and removing nodes without downtime—and setting up automated failover with Redis Sentinel on Kubernetes.

Remember: a Redis cluster on Kubernetes is production-ready only when you have persistent storage, proper DNS, and a failover strategy. Now go make your data resilient.

Practice recap

Try scaling your cluster to 9 pods (6 masters, 3 replicas) using the same StatefulSet approach. Then, manually fail over a master by killing one pod with kubectl delete pod redis-cluster-0 -n redis and verify the cluster heals using redis-cli cluster nodes.

Common mistakes

  • Forgetting to set the hostname -i bind address inside the container, causing the cluster to form on 127.0.0.1 and then refuse external connections.
  • Running redis-cli --cluster create with pod IPs instead of the headless service DNS names—when pods restart, the cluster fails to rejoin.
  • Setting cluster-require-full-coverage yes (default) and then losing one master—this takes the entire cluster offline for writes.
  • Not using a PersistentVolumeClaim—when a pod dies, all data is lost, forcing a full cluster rebuild.

Variations

  1. Use Helm stable/redis-cluster chart for an automated one-command deployment that handles cluster formation.
  2. Deploy using the Redis Operator (from OLM) which offers automated failover, upgrades, and backup integrations.
  3. Run the cluster on a DaemonSet with hostNetwork: true for bare-metal-like performance (not recommended for multi-tenant clusters).

Real-world use cases

  • E-commerce session store: A Redis cluster shards user sessions across nodes, ensuring no single point of failure during Black Friday traffic spikes.
  • Real-time leaderboard: Gaming companies use a 6-node Redis cluster on Kubernetes to keep leaderboards sorted and replicated with minimal read latency.
  • Message queue for microservices: Redis streams backed by a cluster allow multiple producers and consumers with automatic failover, even when pods reschedule.

Key takeaways

  • Headless Services + StatefulSets give Redis pods stable DNS names required for cluster discovery.
  • Always bind to the pod's own IP, not 0.0.0.0, to avoid loopback issues in Redis cluster mode.
  • Use cluster-require-full-coverage no to avoid total outage when a master fails.
  • The redis-cli --cluster create command must use full DNS names (e.g., pod.service.namespace.svc.cluster.local) for resilience.
  • PersistentVolumeClaims are mandatory—without them, a pod restart wipes all cluster data.

Sponsored

Sponsored

Discussion

Questions, corrections, and tips help everyone reading this page.

0 comments

Add a comment

Shown publicly with your comment.

Be constructive · max 4,000 characters

No comments yet — start the thread.

Related tutorials, quizzes, and articles for this topic.