Redis-Cluster on Kubernetes: Hands-on Guide ①


Manifest (YAML) overview

Redis-Cluster overview

Redis-Cluster spreads data across three Redis Pods (masters), and each master Pod has a backup (replica) Pod.   If a Redis master Pod goes down, the backup (replica) Redis is promoted to master.
Let’s build Redis-Cluster with six Pods (3 masters, 3 replicas).
🔗 See here for an overall Redis-Cluster overview.

1. Redis-Cluster manifests (YAML)

When you deploy Redis-Cluster on Kubernetes, split the work into Config, Service, and creation (StatefulSet) roles and manage them as three YAML files.

┌─────────────────────────────────────────────────────┐ │ 1. redis-cluster-config.yaml (ConfigMap) │ │ : redis.conf, users.acl │ └──────────────────┬──────────────────────────────────┘ │ [Step 1: provide Config values] ▼ ┌─────────────────────────────────────────────────────┐ │ 2. redis-cluster-service.yaml (Headless Service) │ │ : redis-cluster-service, clusterIP: None, port │ └──────────────────┬──────────────────────────────────┘ │ [Step 2: prepare the Service] ▼ ┌─────────────────────────────────────────────────────┐ │ 3. redis-cluster-statefulset.yaml (StatefulSet) │ │ : Config, Service -> redis-cluster-0~5 (6Pods) │ │ Persistent Volume Claim (PVC) │ └─────────────────────────────────────────────────────┘ [Step 3: create Redis Pods]

2. File contents by deploy order

🟢 [Step 1] Redis config: redis-cluster-config.yaml

  • kind: ConfigMap
  • name (metadata:name): redis-cluster-config
    ⚠️ Names are strictly limited to lowercase (a-z), digits (0-9), and hyphen (`-`) (uppercase is not allowed)
  • This is the ConfigMap settings file. The directives here are used to create redis.conf.
  • The redis.conf that ships with the tarball is not used.
  • If each Redis instance (Pod) needs a different value, you can set it dynamically with a command script in the StatefulSet.   Example) cluster-announce-hostname redis-cluster-0,1,2...

🧑‍💻 Key values

  • bind * -::* # IPs are assigned and change dynamically, so accept all IPs.
    KISA (Korea Internet & Security Agency) [Cloud Vulnerability Assessment Guide] insists on setting an IP on bind for security.   That is correct on VMs/bare metal, but you cannot do that in Kubernetes.
    (You will need to explain this clearly to auditors on public-sector/finance projects.)
  • protected-mode no # Because bind is '*', setting 'yes' blocks external connections.
    It may look like a security violation, but Kubernetes has its own security, so this setting is fine.
  • daemonize no # Do not set this to 'yes'.
  • requirepass password # 💥Always set a password. If the server or PC is on the internet, set a password even in a development environment. Redis is not hacked by 🕵️people (hackers) but by 💻 programs that scan 24 hours a day. Without a password, even a few minutes of a dev instance can be compromised immediately.
    See here for details. 🔗 Redis Hacking
    If you configure users.acl, you do not need to set 'requirepass'.
  • masterauth password # Always set this.
  • cluster-node-timeout 3000 # Node-down detection time (3000ms (3sec)): set to 3 seconds.
  • cluster-announce-hostname, cluster-announce-human-nodename These two items are injected dynamically at Pod creation time: the initContainer command in statefulset.yaml looks up the Pod name. So do not set them here.
    echo "cluster-announce-hostname ${POD_FQDN}" >> /data/redis.conf
    echo "cluster-announce-human-nodename ${POD_NAME}" >> /data/redis.conf
  • users.acl: lines 90–91. Password ('#0cbc...' 64 chars) must be set separately.
    See here for details. 🔗 ACL
💾 View redis-cluster-config.yaml ▼
📄 redis-cluster-config.yaml

The values shown here are redis.conf settings applied at 90%+ of the 100+ sites redisGate has installed and operated.   (Adjust maxmemory to match your data size)

💻 On bare metal/VMs, change the following values.

  • bind 114.x.y.z 127.0.0.1 -::1 -> pin an IP
  • protected-mode yes
  • port -> default 💥port 6379 is a major hacking target. Always use a different port.
  • daemonize yes
  • dir /app/redis -> also put pidfile, logfile, etc. under this dir
  • aclfile /app/redis/users.acl -> per-user permissions: recommended
  • #maxmemory <bytes> -> comment out (default)
    ① On a Redis-dedicated server, set 50%–90% of system memory
    ② If you have plenty of RAM: e.g. 16GB system memory and Redis using 1–2GB, (in practice) you may not need to set it
    ③ 💥 If Redis uses all system memory, the OS (Linux) kills the Redis process.
  • #cluster-announce-hostname "" -> comment out (default)
  • #cluster-announce-human-nodename "" -> comment out (default)

🟢 [Step 2] Service config: redis-cluster-service.yaml

  • kind: Service
  • name (metadata:name): redis-cluster-service
    ⚠️ Names are strictly limited to lowercase (a-z), digits (0-9), and hyphen (`-`) (uppercase is not allowed)
  • This is the Service settings file.   Even if Pod IPs change, it prepares a network address board so you can reach each Redis by a stable domain name (FQDN: Fully Qualified Domain Name).

🧑‍💻 Key values

  • clusterIP: None # 📍Set to 'None' (to identify each Pod DNS independently)
  • port: 18504 # Redis port
  • port: 28504 # Redis Cluster bus port
💾 View redis-cluster-service.yaml ▼
📄 redis-cluster-service.yaml

🟢 [Step 3] Redis Pod creation manifest: redis-cluster-statefulset.yaml

Manifest file that creates Redis Pods (replicas, initContainers, memory, pvc (disk volume)).

  • kind: StatefulSet
  • name (metadata:name): redis-cluster
    ⚠️ Names are limited to lowercase (a-z), digits (0-9), and hyphen (`-`) (uppercase is not allowed)
    Pod names are built from this name plus a number: redis-cluster-0,1,2.
    The Pod name and serviceName are used to build an FQDN (Fully Qualified Domain Name) as follows.
    redis-cluster-0.redis-cluster-service.default.svc.cluster.local
    Each Redis can talk to other Redis instances or to the App by its unique FQDN.
    When the IP changes, the new IP is bound to the FQDN.

🧑‍💻 Key values

  • configMap: name: redis-cluster-config (linked to Step 1 Redis config)
  • serviceName: redis-cluster-service (linked to Step 2 Service)
  • replicas: 6 # Create 6 Redis Pods. Splitting roles into Master (3) and Replica (3) is decided when Redis-Cluster is created.
  • image: redis:8.8.2 # Use version 8.8.2, released 17 Aug 2026 (Mon)
  • imagePullPolicy: IfNotPresent # Use the local image
  • command script: copy ConfigMap files from Step 1 and apply dynamic settings
  • volumeMounts: mountPath: /data: stores all files Redis uses/manages (redis.conf, users.acl, aof files, and so on).
💾 View redis-cluster-statefulset.yaml ▼
📄 redis-cluster-statefulset.yaml

🧑‍💻 initContainers: command: script notes

  • ① Copy read-only redis.conf from ConfigMap to writable /data

    Redis can rewrite the conf file with 'config rewrite', and when Master-Replica roles change the 'replicaof' directive is rewritten. So redis.conf must live in a read-write directory.

    📄 initContainers: command: cp redis.conf

  • ② Copy users.acl and set permissions

    📄 initContainers: command: cp users.acl

  • ③ Resolve Redis Cluster FQDN dynamically and inject cluster-announce-*name

    📄 initContainers: command: cluster-announce-*name

🧑‍💻 containers: command: script notes

  • ④ 🚩 Add a few handy aliases in .bashrc

    📄 containers: command: .bashrc

    With '--color=auto', filenames are colored as shown below.
    dir file: redis-sentinel-model
    exec file: cluster_create.sh
    tar file: file redis-8.8.2.tar

  • ⑤ redis.tar timestamps are UTC (UK). Switch to host OS time (Korea time here).

    📄 containers: command: localtime


➡ Prep is done. Let’s create the Pods.


<< Preparing Redis on Kubernetes ③ K8s Redis-Cluster Setup ② >>

Email 답글이 올라오면 이메일로 알려드리겠습니다.