Redis is the most widely deployed in-memory data store in the world, and running it on Kubernetes is increasingly common for teams that want a unified platform for both stateless services and stateful workloads. Unlike a pure in-memory cache that accepts total data loss on restart, production Redis deployments almost always enable persistence: either the AOF log, RDB snapshots, or both together. That persistence decision transforms Redis from a network-attached hash table into a storage-sensitive workload with write patterns that interact directly with Kubernetes scheduling constraints.
Getting storage right for Redis on Kubernetes means understanding both the persistence write path and the scheduling model. These two interact in ways that create operational problems if you start with local disk and discover the constraints only when a node drains or fails unexpectedly.
Why Redis Storage Is Demanding on Kubernetes
Redis supports two persistence mechanisms, and each makes different demands on the underlying storage:
Append-Only File (AOF): Redis writes every write command to an append-only log file. The appendfsync setting controls when the kernel’s write buffer is flushed to disk:
appendfsync always: every command triggers an fsync call before Redis acknowledges the write. This is the most durable mode and the most storage-latency-sensitive, because fsync blocks until the write reaches durable media.appendfsync everysec(the default): Redis calls fsync once per second, batching commands between flushes. This mode tolerates up to one second of data loss on a crash and is less latency-sensitive, but still requires storage that can sustain continuous sequential writes.appendfsync no: the OS decides when to flush. This delivers the best throughput but offers no durability guarantees beyond what the kernel provides.
RDB snapshots: Redis periodically forks a child process to write a point-in-time snapshot of the entire dataset to a .rdb file. The fork is near-instant (copy-on-write), but the child process writes the full dataset sequentially to disk. On a large dataset (tens of gigabytes), this produces a burst of sequential write I/O that saturates storage for the duration of the snapshot. If storage delivers inconsistent throughput under burst, the snapshot write slows, the fork period extends, and the Redis process accumulates copy-on-write memory overhead during the delay.
The combined I/O profile on a production Redis node running AOF with RDB backup is:
- Continuous low-volume sequential writes from the AOF log (fsync-gated at
everysecoralways) - Periodic high-volume sequential write burst from RDB snapshot generation
- Sequential reads during restart and replica sync for AOF replay or RDB load
On Kubernetes, these storage requirements combine with a scheduling problem. Redis runs as a Kubernetes StatefulSet with persistent storage attached to each pod. If that storage is local NVMe (hostPath or local PersistentVolumes), the pod becomes pinned to the node where the disk lives. When the node drains for maintenance or fails unexpectedly, the pod cannot reschedule until the node returns or the data is manually migrated.
Persistent Volume Architecture for Redis StatefulSets
Redis on Kubernetes requires one persistent volume claim per replica at minimum, and ideally two per replica: one for the data directory (AOF log and RDB snapshot) and one for the AOF rewrite buffer if you want to isolate the rewrite burst from the live log I/O. For most teams, a single PVC per replica is the practical starting point, with the data directory containing both the .aof and .rdb files.
The StatefulSet pattern uses volumeClaimTemplates to provision a PVC per replica automatically. Each Redis pod gets its own volume, independent of other replicas. Redis does not support shared data access between replicas (primary and replica maintain independent datasets that are synchronized at the command level), so ReadWriteOnce access mode is correct.
| Storage Attribute | Recommended Value | Reason |
|---|---|---|
| Volume mode | Filesystem | Redis manages its own file layout; raw block mode offers no benefit |
| Access mode | ReadWriteOnce | One pod per volume; Redis does not support shared data access |
| Volume binding | WaitForFirstConsumer | Ensures the volume is provisioned in the scheduler’s chosen zone |
| Reclaim policy | Retain | Prevents accidental data loss when a pod or StatefulSet is deleted |
| Allow expansion | true | Online capacity growth without pod restart (requires CSI driver support) |
| IOPS provision | 3,000–15,000 IOPS | everysec mode can run on 3k IOPS; always mode needs 10k or more |
Table 1: Persistent volume configuration recommendations for Redis StatefulSets on Kubernetes.
A minimal StorageClass for Redis on Kubernetes using a CSI driver looks like this:
apiVersion: storage.k8s.io/v1kind: StorageClassmetadata: name: redis-nvmeprovisioner: csi.simplyblock.ioparameters: replication: "2" compression: "false"reclaimPolicy: RetainvolumeBindingMode: WaitForFirstConsumerallowVolumeExpansion: trueThe volumeClaimTemplates section of the StatefulSet references this StorageClass:
volumeClaimTemplates: - metadata: name: redis-data spec: accessModes: ["ReadWriteOnce"] storageClassName: redis-nvme resources: requests: storage: 50GiThe volumeBindingMode: WaitForFirstConsumer is critical: without it, the PVC binds in a random zone before the pod is scheduled, often ending in a zone mismatch that prevents the pod from starting.
Running Redis on Kubernetes and hitting AOF write latency or snapshot slowdowns? simplyblock’s disaggregated NVMe/TCP storage delivers consistent sub-millisecond fsync latency without credit-burst limits, and lets Redis pods reschedule freely across nodes. Talk to a storage architect
AOF and RDB: Persistence Modes and Their Storage Impact
Choosing between AOF and RDB (or combining them) is the most consequential Redis configuration decision for persistent storage sizing and StorageClass selection. The right choice depends on your recovery point objective, your dataset size, and the write rate of your application.
| Persistence Mode | Write Pattern | IOPS Requirement | Data Loss Risk | Recovery Time |
|---|---|---|---|---|
AOF always | Every command: synchronous fsync | Very high (10k+ for busy workloads) | Zero (each command durable) | Fast (replay log from last fsync) |
AOF everysec (default) | Continuous sequential, 1 fsync/sec | Moderate (3k–8k) | Up to 1 second | Fast (replay from last second) |
| RDB only | Burst sequential on snapshot schedule | Low baseline, high burst | Minutes to hours (since last snapshot) | Moderate (load full .rdb file) |
| AOF + RDB | Both patterns combined | Highest overall | Near-zero (AOF), plus periodic checkpoint | Fastest (use RDB as base, replay AOF delta) |
Table 2: Redis persistence mode comparison for Kubernetes storage planning.
For teams running Redis as a cache where data loss is acceptable, disabling both AOF and RDB is valid: the pod consumes no storage at all and can be scheduled anywhere. But for Redis used as a primary data store (session state, rate limiter, leaderboard, queue), AOF is mandatory, and the storage must handle the fsync rate of your application’s write throughput.
The AOF rewrite process (triggered automatically when the AOF file grows beyond a configured size) creates a temporary rewrite file and then atomically renames it over the existing AOF. During the rewrite, Redis buffers new write commands in memory and flushes them to the new file before the rename. This process is CPU-bound and I/O-bound simultaneously. On a node with local NVMe, the rewrite competes with foreground AOF writes for disk bandwidth. With disaggregated storage, the rewrite I/O goes to the same network-attached pool, where throughput is shared across all volumes but not artificially capped.
High Availability: Redis Sentinel and Redis Cluster
Redis supports two distinct high availability topologies, and each has different persistent storage requirements on Kubernetes.
Redis Sentinel is the standard HA approach for a single Redis keyspace. A Sentinel deployment consists of one Redis primary, one or more Redis replicas, and three or more Sentinel processes (which are stateless monitors and do not need persistent volumes). The Sentinels agree on a quorum when the primary is unreachable and promote the most up-to-date replica to primary. Each replica pod needs its own PVC because it maintains an independent copy of the dataset.
Redis Cluster shards the keyspace across multiple primary nodes (six nodes minimum: three primaries and one replica per primary). Each primary owns a subset of the 16,384 hash slots and has its own dataset. Each Cluster member (primary and replica) needs its own PVC. Clients route commands to the correct shard using the CLUSTER REDIRECT protocol or a client-side routing library.
| HA Model | Node Failure Recovery | Storage Requirement | Scheduling Flexibility |
|---|---|---|---|
| Local NVMe + Sentinel failover | Pod waits for node return or manual re-sync | Low per-node cost, high over-provision ratio | Pod pinned to node with data |
| Cloud block storage (gp3, Premium SSD) | Pod reschedules; volume reattaches (slow in multi-AZ) | Per-GB and per-IOPS pricing, burst limits apply | Zone-bound; multi-AZ attach adds latency |
| Disaggregated NVMe/TCP (simplyblock) | Pod reschedules; volume reattaches in seconds | Flat pool pricing, no per-volume IOPS caps | Any node in the cluster |
Table 3: High availability model comparison for Redis on Kubernetes.
With local storage, a Redis primary failure in a Sentinel deployment triggers a failover to a replica, but the failed primary’s pod cannot reschedule until the node returns. The old primary’s PVC is stuck on the failed node. In a Redis Cluster, the situation is the same: a shard primary that was on a failed node cannot restart until the node recovers, and the cluster operates in degraded mode (reads can be served by the replica that was promoted, but the failed primary’s slot assignments are unavailable until failover completes and the old primary slot range is transferred).
Disaggregated storage removes this constraint entirely. When a node drains or fails, the Redis pod reschedules on any available node. The CSI driver re-attaches the same PVC to the new node. Redis performs AOF replay or loads the RDB snapshot and resumes operation. For a Sentinel primary, this means the node failure duration is the time it takes Kubernetes to detect the failure (typically 40 to 60 seconds with default kubelet settings) plus the AOF replay time, not the time to repair or replace hardware.
For Redis Cluster, each shard member uses the same StatefulSet and volumeClaimTemplates pattern. The operator (Spotahome Redis Operator, Bitnami Helm chart, or Redis Operator by OT-Container-Kit) manages cluster membership and slot rebalancing at the database layer. The storage layer handles durability and replication independently.
Snapshot-based point-in-time recovery is a further advantage of the storage layer approach. simplyblock’s CSI external snapshotter integration allows you to take a consistent storage snapshot of a Redis data volume in seconds, without pausing AOF writes. Restoring from snapshot brings the dataset back to a known-good state significantly faster than replaying a full AOF log from an old backup.
Questions and Answers
What persistent storage settings work best for Redis on Kubernetes?
Use volumeBindingMode: WaitForFirstConsumer to prevent zone mismatches, reclaimPolicy: Retain to prevent accidental data loss on PVC deletion, and allowVolumeExpansion: true for online capacity growth. For IOPS, the requirement depends on the AOF fsync mode: appendfsync everysec (the default) needs 3,000 to 8,000 IOPS per node for most workloads; appendfsync always needs 10,000 or more. RDB-only mode needs burst IOPS headroom on the snapshot schedule but modest sustained IOPS otherwise.
How does AOF appendfsync always affect storage latency on Kubernetes?
With appendfsync always, Redis calls fsync after every write command before acknowledging the client. If the storage volume introduces tail latency on fsync (common with cloud block storage that has burst IOPS credit limits), each Redis write stalls until the fsync completes, and application latency grows. The solution is storage that delivers consistent, low-latency fsync without burst credit models: NVMe/TCP disaggregated storage removes the burst model and delivers fsync latency in the sub-millisecond range on a well-tuned 25 GbE link.
Can Redis pods reschedule freely with NVMe/TCP persistent storage?
Yes. NVMe/TCP volumes are network-attached and not bound to any physical node. When a Redis pod reschedules (node drain, node failure, or normal pod eviction), the CSI driver re-attaches the persistent volume to the new node. Redis replays the AOF log (or loads the RDB snapshot) and resumes operation. For appendfsync everysec, AOF replay of up to one second of commands completes in well under one second. For RDB-only mode, startup time depends on dataset size but not on data migration across the network.
How does simplyblock compare to local NVMe for Redis on Kubernetes?
Local NVMe delivers the lowest absolute latency but pins the Redis pod to a specific node, complicates Sentinel failover after node failure, and requires node-level RAID for durability. simplyblock’s disaggregated NVMe/TCP storage delivers latency in the 100 to 400 microsecond range on 25 GbE, which is within the acceptable range for appendfsync everysec and even appendfsync always on moderate write rates. The scheduling flexibility and storage-layer replication reduce the operational burden significantly for teams running Redis Sentinel or Cluster.
Does this architecture work for Redis Cluster deployments?
Yes. A Redis Cluster is composed of multiple shard primaries, each with one or more replicas. Each member uses the same StatefulSet and volumeClaimTemplates pattern: every pod gets its own PVC provisioned from the shared NVMe pool. Cluster membership, hash slot assignment, and failover are managed by Redis Cluster itself or by a Kubernetes operator. The storage layer handles durability and replication at the volume level, independently of Redis Cluster’s replication. Adding a new shard to the cluster requires adding pods and their PVCs, without adding Kubernetes nodes or storage hardware.