Разберём запуск Redis/Valkey в Kubernetes от простого к сложному: одиночный под, StatefulSet для репликации и HA-кластер через Sentinel.
Одиночный Redis
Самый простой способ — Deployment:
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: valkey/valkey:8.0
ports:
- containerPort: 6379
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "512Mi"
---
apiVersion: v1
kind: Service
metadata:
name: redis
spec:
selector:
app: redis
ports:
- port: 6379Недостаток: нет persistence. После перезапуска пода данные теряются.
StatefulSet с Persistence
Для производственной среды нужен StatefulSet с PVC:
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis
spec:
serviceName: redis
replicas: 1
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: valkey/valkey:8.0
args: ["--save", "60", "1000", "--appendonly", "yes"]
ports:
- containerPort: 6379
volumeMounts:
- name: data
mountPath: /data
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 10GiКлючевые параметры:
--save 60 1000— снапшот каждые 60 секунд при ≥1000 изменениях ключей.--appendonly yes— AOF-журнал для защиты от потери данных.volumeClaimTemplates— автоматическое создание PVC на каждый под.
Репликация: Master-Replica
Добавим реплику. Конфигурация через ConfigMap:
apiVersion: v1
kind: ConfigMap
metadata:
name: redis-config
data:
redis.conf: |
save 60 1000
appendonly yes
replica-read-only yes
replica-serve-stale-data yes
min-replicas-to-write 1
min-replicas-max-lag 10
replica.conf: |
replicaof redis-0.redis 6379StatefulSet с двумя подами и initContainer для определения роли:
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis
spec:
serviceName: redis
replicas: 2
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
initContainers:
- name: config
image: busybox
command:
- sh
- -c
- |
if [ "$(hostname)" = "redis-0" ]; then
cp /mnt/redis.conf /data/redis.conf
else
cp /mnt/replica.conf /data/redis.conf
fi
volumeMounts:
- name: config
mountPath: /mnt
- name: data
mountPath: /data
containers:
- name: redis
image: valkey/valkey:8.0
command: ["redis-server", "/data/redis.conf"]
ports:
- containerPort: 6379
volumeMounts:
- name: data
mountPath: /data
volumes:
- name: config
configMap:
name: redis-config
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 10GiHeadless Service для прямого доступа к подам:
apiVersion: v1
kind: Service
metadata:
name: redis
spec:
clusterIP: None
selector:
app: redis
ports:
- port: 6379Высокая доступность: Sentinel
Sentinel мониторит Redis-узлы и выполняет автоматический failover. Три инстанса для кворума.
apiVersion: v1
kind: ConfigMap
metadata:
name: sentinel-config
data:
sentinel.conf: |
port 26379
sentinel monitor mymaster redis-0.redis 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
sentinel parallel-syncs mymaster 1Ключевые параметры Sentinel:
sentinel monitor— имя мастера, хост, порт, кворум.down-after-milliseconds— задержка объявления мастера мёртвым (5 сек).failover-timeout— таймаут фейловера (60 сек).- Кворум 2 из 3 значит — нужно минимум 2 сентинела для инициирования фейловера.
Развернём Sentinel как отдельный StatefulSet:
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: sentinel
spec:
serviceName: sentinel
replicas: 3
selector:
matchLabels:
app: sentinel
template:
metadata:
labels:
app: sentinel
spec:
containers:
- name: sentinel
image: valkey/valkey:8.0
command: ["redis-sentinel", "/etc/redis/sentinel.conf"]
ports:
- containerPort: 26379
volumeMounts:
- name: config
mountPath: /etc/redis
volumes:
- name: config
configMap:
name: sentinel-configService для Sentinel:
apiVersion: v1
kind: Service
metadata:
name: sentinel
spec:
selector:
app: sentinel
ports:
- port: 26379Проверка фейловера
Симулируем отказ мастера:
kubectl delete pod redis-0Sentinel обнаружит отказ в течение 5 секунд (down-after-milliseconds), выберет новый мастер среди реплик и обновит конфигурацию. Redis-клиенты должны использовать Sentinel API для обнаружения нового мастера:
from redis import Sentinel
sentinel = Sentinel([('sentinel', 26379)], socket_timeout=0.1)
master = sentinel.master_for('mymaster')
master.set('key', 'value')Использование операторов
Вручную настраивать Sentinel и репликацию — трудоёмко. Существуют операторы, автоматизирующие процесс:
| Оператор | Репозиторий | Особенности |
|---|---|---|
| OT-CONTAINER-KIT | github.com/OT-CONTAINER-KIT/redis-operator | Самый популярный, поддерживает Redis-Cluster и Sentinel, богатая конфигурация |
| Spotahome | github.com/spotahome/redis-operator | Лёгкий, только Sentinel, хорош для начала |
| Opstree | github.com/ot-container-kit/redis-operator | Развивается OT-CONTAINER-KIT, поддержка Valkey |
Пример установки OT-CONTAINER-KIT оператора:
helm repo add ot-helm https://ot-container-kit.github.io/helm-charts/
helm install redis-operator ot-helm/redis-operatorСоздание HA-кластера через оператор:
apiVersion: redis.redis.opstreelabs.in/v1beta2
kind: Redis
metadata:
name: redis-standalone
spec:
kubernetesConfig:
image: quay.io/opstree/redis:v8.0
storage:
volumeClaimTemplate:
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 1Gi
---
apiVersion: redis.redis.opstreelabs.in/v1beta2
kind: RedisSentinel
metadata:
name: redis-sentinel
spec:
replicas: 3
redisSentinelConfig:
redisReplicationName: redis-standalone
quorum: 2Ключевые выводы
- Valkey — полная замена Redis для Kubernetes. Меняется только образ контейнера.
- StatefulSet + PVC — минимальная продакшн-конфигурация с persistence.
- Sentinel даёт автоматический failover, но усложняет конфигурацию.
- Операторы (OT-CONTAINER-KIT) автоматизируют весь жизненный цикл Redis-кластера.
- Redis Cluster для шардирования данных — отдельная тема, будет в следующих статьях.