Running Redis on Kubernetes#
Redis on Kubernetes ranges from dead simple (single pod for caching) to operationally complex (Redis Cluster with persistence). The right choice depends on whether you need data durability, high availability, or just a fast throwaway cache.
Single-Instance Redis with Persistence#
For development or small workloads, a single Redis Deployment with a PVC is enough:
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis
spec:
replicas: 1
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis:7-alpine
command: ["redis-server", "--appendonly", "yes", "--maxmemory", "256mb", "--maxmemory-policy", "allkeys-lru"]
ports:
- containerPort: 6379
volumeMounts:
- name: redis-data
mountPath: /data
resources:
requests:
cpu: 100m
memory: 300Mi
limits:
cpu: 500m
memory: 350Mi
volumes:
- name: redis-data
persistentVolumeClaim:
claimName: redis-data
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: redis-data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 5Gi
---
apiVersion: v1
kind: Service
metadata:
name: redis
spec:
selector:
app: redis
ports:
- port: 6379
targetPort: 6379Set the memory limit in Redis (--maxmemory) lower than the container memory limit. If Redis uses 350Mi and the container limit is 350Mi, the kernel OOM-kills the process during background save operations when Redis forks and temporarily doubles its memory usage. A safe ratio: set maxmemory to 60-75% of the container memory limit.
Bitnami Redis Helm Chart#
The Bitnami chart handles most operational concerns out of the box. Three architecture modes are available.
Standalone:
helm repo add bitnami https://charts.bitnami.com/bitnami
helm install redis bitnami/redis --set architecture=standalone --set auth.password=your-secure-passwordReplication (master + read replicas):
# redis-values.yaml
architecture: replication
auth:
password: "your-secure-password"
master:
persistence:
size: 10Gi
resources:
requests:
memory: 256Mi
cpu: 100m
limits:
memory: 512Mi
replica:
replicaCount: 2
persistence:
size: 10Gi
resources:
requests:
memory: 256Mi
cpu: 100m
limits:
memory: 512Mihelm install redis bitnami/redis -f redis-values.yamlThis creates redis-master and redis-replicas Services. Your application writes to redis-master:6379 and reads from redis-replicas:6379.
Sentinel (automatic failover):
architecture: replication
sentinel:
enabled: true
masterSet: mymaster
quorum: 2
resources:
requests:
memory: 64Mi
cpu: 50mWith Sentinel, clients connect to port 26379 to discover the current master. Most Redis client libraries support Sentinel natively with the master set name mymaster.
Memory and Eviction Configuration#
The two most important Redis settings for Kubernetes:
maxmemory: The maximum bytes Redis will use before evicting keys. Without this, Redis grows unbounded until the OOM killer strikes.
maxmemory-policy: What happens when maxmemory is reached:
| Policy | Behavior |
|---|---|
noeviction |
Returns errors on writes when full. Good for data you cannot lose. |
allkeys-lru |
Evicts least recently used keys. Best for general caching. |
volatile-lru |
Evicts LRU keys that have a TTL set. Keys without TTL are never evicted. |
allkeys-random |
Random eviction. Slightly faster than LRU. |
volatile-ttl |
Evicts keys with the shortest TTL first. |
For caching, use allkeys-lru. For session storage where some keys are permanent, use volatile-lru. For queues or data stores, use noeviction and monitor memory closely.
Set these via Helm values:
master:
configuration: |
maxmemory 256mb
maxmemory-policy allkeys-lru
save 900 1
save 300 10
appendonly yes
appendfsync everysecPersistent Storage Considerations#
Redis has two persistence mechanisms: RDB snapshots (save directives) and AOF (appendonly yes). RDB is fast to recover but loses data since the last snapshot. AOF logs every write – with appendfsync everysec you lose at most one second. Enable both for production and ensure the data directory is on the PVC mount (/data). Use SSD-backed StorageClasses – AOF write performance depends directly on disk latency.
Monitoring with redis-cli#
kubectl exec -it deploy/redis -- redis-cli -a your-password
INFO memory # used_memory_human, maxmemory_human, mem_fragmentation_ratio
INFO persistence # rdb_last_bgsave_status, aof_last_bgrewrite_status
INFO stats # instantaneous_ops_per_sec
SLOWLOG GET 10 # slow commands
INFO keyspace # key countsA mem_fragmentation_ratio above 1.5 means Redis is wasting memory, often from many small key deletions. A restart or MEMORY PURGE can help.
Common Issues#
OOM Killed. Pod killed with exit code 137. Causes: maxmemory not set, set too close to the container limit, or a background save fork doubling memory. Fix: set maxmemory to 60-75% of the container memory limit.
AOF rewrite blocking. Large AOF rewrites can block the main process on slow disks. Symptoms: latency spikes, client timeouts. Mitigate with SSD StorageClasses and tuning auto-aof-rewrite-percentage.
Slow commands. Redis is single-threaded. A KEYS * on a large database blocks everything. Use SCAN instead and consider rename-command KEYS "" in production.
Replica sync failures after restart. When a replica reconnects and the replication backlog has been overwritten, it falls back to a full sync, dumping the entire dataset. Increase repl-backlog-size if replicas frequently disconnect.
CrashLoopBackOff from data corruption. If the AOF file is corrupted, Redis refuses to start. Fix with redis-check-aof --fix /data/appendonlydir/appendonly.aof.1.incr.aof from a debug container.