Databases 14 min read

Deploy a Redis Cluster on Kubernetes: Step‑by‑Step Guide

This article introduces Redis, explains why it is popular, describes the architecture of a Redis Cluster, and provides a complete step‑by‑step tutorial for deploying, initializing, validating, and testing a Redis Cluster on Kubernetes with sample code and a hit‑counter application.

Open Source Linux
Open Source Linux
Open Source Linux
Deploy a Redis Cluster on Kubernetes: Step‑by‑Step Guide

Redis Introduction

Redis stands for REmote DIctionary Server. It is an open‑source in‑memory data store that can be used as a database, cache, or message broker. It supports advanced data types such as lists, maps, sets and sorted sets, and stores keys in various formats, reducing client workload. Redis persists data to disk only for durability while keeping the dataset in memory. It is widely adopted by companies such as GitHub, Pinterest, Snapchat, Twitter, StackOverflow and Flickr.

Why Use Redis

Very fast performance; written in ANSI C and runs on POSIX systems like Linux, macOS and Solaris.

Often ranked as the most popular key/value and NoSQL database used with containers.

Cache layer reduces calls to backend cloud databases.

Accessible via client API libraries.

Supported by all major programming languages.

Open‑source and stable.

What Is a Redis Cluster

A Redis Cluster is a set of Redis instances that partitions data to achieve scalability and resilience. Each member (master or replica) manages a subset of hash slots. If a master fails, its replica is promoted. A minimal cluster has three master nodes, each with a replica, and hash slots are divided among the masters (e.g., 0‑5000, 5001‑10000, 10001‑16383). Nodes communicate via an internal bus.

Deploying a Redis Cluster on Kubernetes

Deploying a Redis cluster on Kubernetes is challenging because each instance needs a configuration file that tracks other nodes and their roles. This requires combining Kubernetes StatefulSets with PersistentVolumes.

Clone Deployment Files

git clone https://github.com/llmgo/redis-sts.git

Create a StatefulSet Resource

[root@node01 redis-sts]# cat redis-sts.yml
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: redis-cluster
data:
  update-node.sh: |
    #!/bin/sh
    REDIS_NODES="/data/nodes.conf"
    sed -i -e "/myself/ s/[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}/${POD_IP}/" ${REDIS_NODES}
    exec "$@"
  redis.conf: |+
    cluster-enabled yes
    cluster-require-full-coverage no
    cluster-node-timeout 15000
    cluster-config-file /data/nodes.conf
    cluster-migration-barrier 1
    appendonly yes
    protected-mode no
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: redis-cluster
spec:
  serviceName: redis-cluster
  replicas: 6
  selector:
    matchLabels:
      app: redis-cluster
  template:
    metadata:
      labels:
        app: redis-cluster
    spec:
      containers:
      - name: redis
        image: redis:5.0.5-alpine
        ports:
        - containerPort: 6379
          name: client
        - containerPort: 16379
          name: gossip
        command: ["/conf/update-node.sh","redis-server","/conf/redis.conf"]
        env:
        - name: POD_IP
          valueFrom:
            fieldRef:
              fieldPath: status.podIP
        volumeMounts:
        - name: conf
          mountPath: /conf
          readOnly: false
        - name: data
          mountPath: /data
          readOnly: false
  volumes:
  - name: conf
    configMap:
      name: redis-cluster
      defaultMode: 0755
  volumeClaimTemplates:
  - metadata:
      name: data
    spec:
      accessModes: ["ReadWriteOnce"]
      resources:
        requests:
          storage: 5Gi
      storageClassName: standard
$ kubectl apply -f redis-sts.yml
configmap/redis-cluster created
statefulset.apps/redis-cluster created
$ kubectl get pods -l app=redis-cluster
NAME               READY   STATUS    RESTARTS   AGE
redis-cluster-0    1/1     Running   0          53s
redis-cluster-1    1/1     Running   0          49s
redis-cluster-2    1/1     Running   0          46s
redis-cluster-3    1/1     Running   0          42s
redis-cluster-4    1/1     Running   0          38s
redis-cluster-5    1/1     Running   0          34s

Create Service

[root@node01 redis-sts]# cat redis-svc.yml
---
apiVersion: v1
kind: Service
metadata:
  name: redis-cluster
spec:
  type: ClusterIP
  clusterIP: 10.96.0.100
  ports:
  - port: 6379
    targetPort: 6379
    name: client
  - port: 16379
    targetPort: 16379
    name: gossip
  selector:
    app: redis-cluster
$ kubectl apply -f redis-svc.yml
service/redis-cluster created
$ kubectl get svc redis-cluster
NAME            TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)                AGE
redis-cluster   ClusterIP   10.96.0.100 <none>        6379/TCP,16379/TCP    35s

Initialize Redis Cluster

The next step is to form the Redis cluster. Run the following command and type yes to accept the configuration. The first three nodes become masters and the remaining three become replicas.
$ kubectl exec -it redis-cluster-0 -- redis-cli --cluster create --cluster-replicas 1 $(kubectl get pods -l app=redis-cluster -o jsonpath='{range.items[*]}.status.podIP:6379 ')
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 10.244.2.11:6379 to 10.244.9.19:6379
Adding replica 10.244.9.20:6379 to 10.244.6.10:6379
Adding replica 10.244.8.15:6379 to 10.244.7.8:6379
M: 00721c43db194c8f2cacbafd01fd2be6a2fede28 10.244.9.19:6379
   slots:[0-5460] (5461 slots) master
M: 9c36053912dec8cb20a599bda202a654f241484f 10.244.6.10:6379
   slots:[5461-10922] (5462 slots) master
M: 2850f24ea6367de58fb50e632fc56fe4ba5ef016 10.244.7.8:6379
   slots:[10923-16383] (5461 slots) master
S: 554a58762e3dce23ca5a75886d0ccebd2d582502 10.244.8.15:6379
   replicates 2850f24ea6367de58fb50e632fc56fe4ba5ef016
S: 20028fd0b79045489824eda71fac9898f17af896 10.244.2.11:6379
   replicates 00721c43db194c8f2cacbafd01fd2be6a2fede28
S: 87e8987e314e4e5d4736e5818651abc1ed6ddcd9 10.244.9.20:6379
   replicates 9c36053912dec8cb20a599bda202a654f241484f
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
... 
>>> Performing Cluster Check (using node 10.244.9.19:6379)
M: 00721c43db194c8f2cacbafd01fd2be6a2fede28 10.244.9.19:6379
   slots:[0-5460] (5461 slots) master   1 additional replica(s)
M: 9c36053912dec8cb20a599bda202a654f241484f 10.244.6.10:6379
   slots:[5461-10922] (5462 slots) master   1 additional replica(s)
S: 87e8987e314e4e5d4736e5818651abc1ed6ddcd9 10.244.9.20:6379
   slots:(0 slots) slave   replicates 9c36053912dec8cb20a599bda202a654f241484f
S: 554a58762e3dce23ca5a75886d0ccebd2d582502 10.244.8.15:6379
   slots:(0 slots) slave   replicates 2850f24ea6367de58fb50e632fc56fe4ba5ef016
S: 20028fd0b79045489824eda71fac9898f17af896 10.244.2.11:6379
   slots:(0 slots) slave   replicates 00721c43db194c8f2cacbafd01fd2be6a2fede28
M: 2850f24ea6367de58fb50e632fc56fe4ba5ef016 10.244.7.8:6379
   slots:[10923-16383] (5461 slots) master   1 additional replica(s)
[OK] All 16384 slots covered.

Validate the Cluster

# kubectl exec -it redis-cluster-0 -- redis-cli cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:6
cluster_my_epoch:1
cluster_stats_messages_ping_sent:16
cluster_stats_messages_pong_sent:22
cluster_stats_messages_sent:38
cluster_stats_messages_ping_received:17
cluster_stats_messages_pong_received:16
cluster_stats_messages_meet_received:5
cluster_stats_messages_received:38
# for x in $(seq 0 5); do echo "redis-cluster-$x"; kubectl exec redis-cluster-$x -- redis-cli role; echo; done
redis-cluster-0
master
14
10.244.2.11
6379
14

redis-cluster-1
master
28
10.244.9.20
6379
28

redis-cluster-2
master
28
10.244.8.15
6379
28

redis-cluster-3
slave
10.244.7.8
6379
connected
28

redis-cluster-4
slave
10.244.9.19
6379
connected
14

redis-cluster-5
slave
10.244.6.10
6379
connected
28

Test the Cluster with a Hit Counter Application

A simple Python application is deployed behind a load balancer. It increments a counter stored in the Redis cluster and returns the value via HTTP. After deleting pods, the counter continues without data loss.

$ kubectl apply -f app-deployment-service.yml
service/hit-counter-lb created
deployment.apps/hit-counter-app created
$ curl $(kubectl get svc hit-counter-lb -o json|jq -r .spec.clusterIP)
I have been hit 20 times since deployment.
$ curl $(kubectl get svc hit-counter-lb -o json|jq -r .spec.clusterIP)
I have been hit 21 times since deployment.
$ curl $(kubectl get svc hit-counter-lb -o json|jq -r .spec.clusterIP)
I have been hit 22 times since deployment.
$ kubectl delete pods redis-cluster-0
pod "redis-cluster-0" deleted
$ kubectl delete pods redis-cluster-1
pod "redis-cluster-1" deleted
$ curl $(kubectl get svc hit-counter-lb -o json|jq -r .spec.clusterIP)
I have been hit 23 times since deployment.

References

http://llmgo.cn/post/redis-003/

http://www.yunweipai.com/36338.html

https://blog.csdn.net/shuyun123456789/article/details/60868718

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

KubernetesredisDevOpsClusterStatefulSet
Open Source Linux
Written by

Open Source Linux

Focused on sharing Linux/Unix content, covering fundamentals, system development, network programming, automation/operations, cloud computing, and related professional knowledge.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.