Redis on Kubernetes 运维面试题
10 道题- 分类
- Kubernetes
- 子分类
- middleware-ops
- 题目数
- 10 道
1 Redis 在 Kubernetes 上有哪些部署模式?各自适用场景是什么?
答案:
Redis 在 Kubernetes 上的部署模式分为三种:Standalone、Sentinel 和 Cluster。
| 部署模式 | 架构特征 | 高可用 | 数据分片 | 适用场景 |
|---|---|---|---|---|
| Standalone | 单实例 Deployment 或 StatefulSet | 无 | 无 | 开发测试、缓存场景(数据可丢失) |
| Sentinel | 一主多从 + Sentinel 哨兵集群 | 自动故障转移 | 无 | 读多写少、数据量在单机内存范围内 |
| Cluster | 多主多从、分片架构 | 自动故障转移 + 分片冗余 | 16384 个 Slot | 数据量超过单机内存、高吞吐写入 |
Standalone 以 Deployment 部署 Redis 单实例,无持久化,数据丢失可接受时最简单。
Sentinel 架构在 K8s 上通常以三个独立 Deployment 部署 Sentinel 进程,Redis 主从以 StatefulSet 部署,通过 Headless Service 实现 Pod 间互相发现。
Cluster 模式需为每个节点配置 cluster-announce-ip,依赖 StatefulSet + Headless Service 提供稳定网络标识,扩容时需手动执行 Slot 迁移命令。
2 Redis Sentinel 在 Kubernetes 上如何部署?自动故障转移流程是怎样的?
答案:
Sentinel 在 K8s 上的经典部署架构:
# Sentinel Deployment(3 副本)
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis-sentinel
spec:
replicas: 3
selector:
matchLabels:
app: redis-sentinel
template:
spec:
containers:
- name: sentinel
image: redis:7.2
command: ["redis-sentinel"]
args: ["/etc/redis/sentinel.conf"]
ports:
- containerPort: 26379
Redis 主从以 StatefulSet 部署:
# Redis StatefulSet(3 副本:1 主 2 从)
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis
spec:
serviceName: redis-headless
replicas: 3
selector:
matchLabels:
app: redis
template:
spec:
containers:
- name: redis
image: redis:7.2
command: ["redis-server"]
args: ["/etc/redis/redis.conf"]
ports:
- containerPort: 6379
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 50Gi
故障转移流程:
- Sentinel 通过 Headless Service(
redis-headless)发现所有 Redis Pod,持续PING检测 - 主观下线(SDOWN):单个 Sentinel 判定主节点不可达(
down-after-milliseconds超时) - 客观下线(ODOWN):超过
quorum数量的 Sentinel 确认主节点下线 - Sentinel Leader 选举:通过 Raft 协议选出执行故障转移的 Sentinel
- 从节点选举:按
slave-priority、复制偏移量、Run ID 排序选出新主 - 故障转移执行:新主执行
SLAVEOF NO ONE,其余从节点重定向到新主 - ConfigMap 更新:K8s 场景下 Sentinel 通过 ConfigMap 或 Operator 更新客户端连接信息
关键配置:
| 参数 | 说明 |
|---|---|
sentinel monitor mymaster <ip> <port> <quorum> | 监控主节点,quorum 设为 2 |
sentinel down-after-milliseconds mymaster 5000 | 主观下线判定超时 5 秒 |
sentinel failover-timeout mymaster 60000 | 故障转移超时 60 秒 |
sentinel parallel-syncs mymaster 1 | 故障转移后并行同步的从节点数 |
6 Redis Cluster 在 Kubernetes 上部署的核心挑战是什么?
答案:
| 挑战 | 说明 | 解决方案 |
|---|---|---|
| Pod IP 变化 | Pod 重启后 IP 变更,nodes.conf 中的节点地址失效 | 使用 StatefulSet + Headless Service 提供稳定 DNS 名;配置 cluster-announce-ip 为 Pod 域名 |
| Cluster Bus 通信 | Cluster Bus 端口固定 16379(6379 + 10000)需路由可达 | Service 暴露 Cluster Bus 端口;NetworkPolicy 放行 TCP/16379 |
| 配置持久化 | nodes.conf 记录集群拓扑,Pod 重启后不能丢失 | 挂载 PVC 存储 nodes.conf;或使用 ConfigMap + Operator 管理 |
| Slot 迁移与 Pod 生命周期 | 直接 kubectl delete pod 会导致 Slot 丢失 | 缩容前先执行手动 Slot 迁移;使用 PDB 防止意外驱逐 |
| 客户端重定向 | Redis Cluster 返回 MOVED / ASK 错误,需客户端支持 | 客户端使用支持集群模式的驱动(JedisCluster、go-redis cluster) |
| 跨可用区延迟 | 跨区 Gossip 通信延迟可能触发误判 PFAIL | 增大 cluster-node-timeout;配置 cluster-require-full-coverage no |
配置示例:
# redis.conf
cluster-enabled yes
cluster-config-file /data/nodes.conf
cluster-node-timeout 15000
cluster-require-full-coverage no
cluster-announce-hostname $(hostname).redis-cluster-headless.redis.svc.cluster.local
# cluster-announce-ip $(POD_IP) # Pod IP 在重启后会变,**推荐用 cluster-announce-hostname + DNS**
cluster-announce-port 6379
cluster-announce-bus-port 16379
7 Redis Operator 生态有哪些选择?各自优劣是什么?
答案:
| Operator | 维护方 | 功能特点 | 适用场景 |
|---|---|---|---|
| Redis Enterprise Operator | Redis Inc. | 商业版,支持 Active-Active、集群自动管理、GUI 运维 | 企业级生产环境,需要商业支持 |
| Spotahome Redis Operator | Spotahome | 开源,支持 Sentinel 和 Cluster 模式,自动故障转移 | 社区主流选择,中小规模集群 |
| Ot Redis Operator | OT-CONTAINER-KIT | 开源,支持 Cluster 和 Sentinel,Leader/Follower 模式 | 轻量级场景,K8s 原生集成 |
对比详情:
| 能力 | Redis Enterprise | Spotahome | Ot Operator |
|---|---|---|---|
| Sentinel 模式 | ✅ | ✅ | ✅ |
| Cluster 模式 | ✅ | ✅ | ✅ |
| 自动扩缩容 | ✅ | 手动 | 手动 |
| Active-Active 地理分布 | ✅ | ❌ | ❌ |
| 备份恢复 | ✅(内置 S3) | 手动 | 手动 |
| Prometheus 监控集成 | ✅ | ✅ | ✅ |
| 许可证 | 商业 | Apache 2.0 | Apache 2.0 |
| K8s CRD 管理 | 丰富 | 基础 | 基础 |
Spotahome 示例 CR:
apiVersion: databases.spotahome.com/v1
kind: RedisFailover
metadata:
name: redisfailover
spec:
sentinel:
replicas: 3
redis:
replicas: 3
storage:
persistentVolumeClaim:
metadata:
name: redis-data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 50Gi
8 Redis 持久化在 Kubernetes 上如何实现?
答案:
Redis 提供三种持久化策略,在 K8s 上均依赖 PVC 存储。
| 策略 | 机制 | 数据安全性 | 性能影响 | K8s 实现要点 |
|---|---|---|---|---|
| RDB | 定期全量内存快照 | 可能丢失最近几分钟数据 | 低(fork 子进程写入) | PVC 存储 /data/dump.rdb,save 参数控制触发频率 |
| AOF | 追加写日志 | 最多丢 1 秒数据(everysec) | 中(持续 IO 写入) | PVC 存储 /data/appendonly.aof,配合 aof-rewrite 控制文件增长 |
| RDB + AOF | 两者同时开启 | 高(AOF 优先于 RDB 加载) | 较高 | PVC 同时存储两种文件,恢复时优先使用 AOF |
| No Persistence | 纯内存 | 数据可丢失 | 最优 | 适用于纯缓存场景 |
RDB 配置:
save 900 1 # 900 秒内至少 1 个键变更
save 300 10 # 300 秒内至少 10 个键变更
save 60 10000 # 60 秒内至少 10000 个键变更
dbfilename dump.rdb
dir /data
AOF 配置:
appendonly yes
appendfsync everysec # 每秒同步一次(推荐)
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
K8s StatefulSet 持久化配置:
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: "ssd-storage"
resources:
requests:
storage: 100Gi
性能考量:RDB fork 采用 Copy-on-Write(COW) 机制,fork 后父子进程共享内存页,仅在写入时才复制新页(高写入场景下内存可能接近翻倍)。K8s 建议 memory limit >= maxmemory * 1.5(保守)或 * 2(高写入场景),并使用 redis-check-rdb 定期校验备份文件。AOF 写入需确保底层存储 IOPS 满足 appendfsync everysec 的延迟要求。
9 Redis 使用 StatefulSet 与 PVC 存储如何配置?
答案:
StatefulSet 为 Redis 提供稳定的网络标识和持久化存储,是生产部署的基础。
核心设计要点:
- ServiceName:绑定 Headless Service,生成稳定的 Pod DNS 名(
<pod-name>.<service-name>.<namespace>.svc.cluster.local) - volumeClaimTemplates:每个 Pod 自动创建独立 PVC,保证存储隔离
- Pod 顺序管理:
podManagementPolicy设为Parallel可并行启动(Sentinel/Cluster 场景) - 存储类选择:使用 SSD/high-IOPS StorageClass
完整配置:
# Headless Service
apiVersion: v1
kind: Service
metadata:
name: redis-headless
spec:
clusterIP: None
selector:
app: redis
ports:
- name: redis
port: 6379
- name: cluster-bus
port: 16379
# StatefulSet
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis
spec:
serviceName: redis-headless
replicas: 6
podManagementPolicy: Parallel
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values: ["redis"]
topologyKey: kubernetes.io/hostname
containers:
- name: redis
image: redis:7.2
command: ["redis-server"]
args: ["/etc/redis/redis.conf"]
ports:
- containerPort: 6379
name: redis
- containerPort: 16379
name: cluster-bus
resources:
requests:
cpu: "2"
memory: 4Gi
limits:
cpu: "4"
memory: 8Gi
volumeMounts:
- name: data
mountPath: /data
- name: config
mountPath: /etc/redis
readinessProbe:
exec:
command: ["redis-cli", "ping"]
initialDelaySeconds: 10
periodSeconds: 5
livenessProbe:
exec:
command: ["redis-cli", "ping"]
initialDelaySeconds: 30
periodSeconds: 10
volumes:
- name: config
configMap:
name: redis-config
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: "ssd-storage"
resources:
requests:
storage: 100Gi
10 Redis 备份与恢复在 Kubernetes 上如何实现?
答案:
备份策略:
| 方案 | 类型 | RPO | 实现方式 |
|---|---|---|---|
| RDB 快照 + S3 | 全量 | 分钟级 | CronJob 定时执行 BGSAVE,上传 dump.rdb 至 S3/MinIO |
| AOF 连续备份 | 增量 | 秒级 | sidecar 容器持续同步 /data/appendonly.aof 至对象存储 |
| 混合(RDB + AOF) | 全量 + 增量 | 秒级 | RDB 为基准备份,AOF 为增量补充 |
| Volume Snapshot | 存储层 | 取决于 CSI | 利用 CSI Snapshot 创建 PVC 快照 |
CronJob 备份示例:
apiVersion: batch/v1
kind: CronJob
metadata:
name: redis-backup
spec:
schedule: "0 */4 * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: backup
image: redis:7.2
env:
- name: S3_BUCKET
value: "redis-backups"
command:
- /bin/sh
- -c
- |
redis-cli -h redis-0.redis-headless BGSAVE
# 等待 BGSAVE 完成
while [ $(redis-cli -h redis-0.redis-headless INFO persistence | grep rdb_bgsave_in_progress | cut -d: -f2) -eq 1 ]; do
sleep 5
done
aws s3 cp /data/dump.rdb s3://$S3_BUCKET/redis-backup-$(date +%Y%m%d-%H%M).rdb
volumeMounts:
- name: data
mountPath: /data
volumes:
- name: data
persistentVolumeClaim:
claimName: data-redis-0
restartPolicy: OnFailure
恢复流程:
- 从 S3 下载最新 RDB 文件至 PVC
- 恢复 AOF 文件(如有)至
/data/appendonly.aof - 启动 Redis,自动加载持久化文件
- 验证数据一致性:
redis-cli INFO keyspace - 切换流量至恢复后的实例
27 Redis 跨集群复制与灾备如何实现?
答案:
| 方案 | 同步方式 | RPO | RTO | 适用场景 |
|---|---|---|---|---|
| 异地从节点 | 异步复制(REPLICAOF) | 秒级 | 分钟级 | 同地域跨可用区 |
| 双写 | 应用层同时写两个集群 | 取决于应用实现 | 秒级 | 最终一致性容忍场景 |
| Redis-Shake 持续同步 | RDB + AOF 解析同步 | 秒级 | 分钟级 | 跨云迁移、异地灾备 |
| Redis Enterprise Active-Active | CRDT 冲突解决 | 毫秒级 | 秒级 | 全球分布式,需要商业许可 |
| RDB 定时备份 + 异地恢复 | 全量备份 + S3 同步 | 小时级 | 30 分钟+ | 低成本灾备 |
异地从节点配置:
# 灾备集群从节点
REPLICAOF <primary-cluster-master-ip> 6379
Redis-Shake 灾备同步(持续模式):
[sync_reader]
address = "primary-cluster-redis:6379"
[redis_writer]
address = "dr-cluster-redis:6379"
[advanced]
dir = /data
ncpu = 4
灾备演练流程:
- 停止源集群写入
- 确认灾备集群数据同步完成(对比
master_repl_offset) - 灾备集群从节点执行
REPLICAOF NO ONE提升为主 - DNS/Service 切换流量至灾备集群
- 验证业务功能完整性
- 数据反向同步:灾备 → 原集群恢复后回流
29 Redis on Kubernetes 常见故障排查
答案:
| 故障现象 | 可能原因 | 排查步骤 | 解决方案 |
|---|---|---|---|
| OOM Kill | 内存超出 Limit | kubectl describe pod 查看 OOMKilled;检查 maxmemory 配置 | 增加 resources.limits.memory;降低 maxmemory;启用逐出策略 |
| CPU Throttling | CPU Limit 过低 | 检查 container_cpu_cfs_throttled 指标 | 提高 CPU Limit 或使用 Guaranteed QoS |
| 启动失败 | RDB/AOF 损坏 | redis-check-rdb /data/dump.rdb;redis-check-aof /data/appendonly.aof | 修复或删除损坏文件重新启动 |
| 复制延迟 | 网络带宽不足、主写入量大 | INFO replication 查看 master_repl_offset - slave_repl_offset | 增大网络带宽;使用 repl-diskless-sync |
| 脑裂 | Sentinel quorum 不满足;网络分区 | 检查 Sentinel 日志;SENTINEL MASTER mymaster | 调整 quorum 为 N/2+1;配置 min-slaves-to-write |
| 集群状态 fail | 主节点宕机且无从节点接管 Slot | CLUSTER INFO 查看 cluster_state | 修复故障节点;CLUSTER FAILOVER 手动切换 |
| 磁盘空间满 | RDB/AOF 文件增长过大 | df -h /data | 调整 auto-aof-rewrite-min-size;扩展 PVC |
| 客户端连接泄漏 | 未正确关闭连接 | CLIENT LIST 查看连接数增长 | 应用端 Connection Pool 设置 MaxLifetime |
| Pod 无法调度 | PDB + Anti-Affinity 冲突 | kubectl describe pod 查看 Events | 调整 PDB minAvailable;增加节点 |
| 慢查询阻塞 | KEYS *、O(N) 命令 | SLOWLOG GET 10 | 替换为 SCAN;RENAME 禁用危险命令 |
排查常用命令:
# K8s 侧
kubectl describe pod redis-0
kubectl logs redis-0 -c redis --tail=200
kubectl exec -it redis-0 -- redis-cli INFO
kubectl exec -it redis-0 -- redis-cli CLUSTER INFO
kubectl get events --field-selector involvedObject.name=redis-0
# Redis 侧
redis-cli INFO all
redis-cli CLUSTER NODES
redis-cli SLOWLOG GET 20
redis-cli CLIENT LIST
redis-cli MEMORY STATS
redis-cli --latency -h <host>
30 Redis on Kubernetes 生产环境最佳实践总结
答案:
部署架构:
- 使用 StatefulSet 而非 Deployment,保障稳定的网络标识和持久化存储
- 配置 Headless Service(
clusterIP: None),为每个 Pod 提供独立 DNS 记录 - 设置 Pod Anti-Affinity 确保 Redis 实例分散在不同节点 / 可用区
- 使用 Operator(Spotahome / Ot Operator)管理 Sentinel 或 Cluster 拓扑,减少运维复杂度
- 配置 PodDisruptionBudget 防止节点维护时批量驱逐
资源配置:
resources.limits.memory >= maxmemory * 1.5,为 RDB fork 和系统开销留余量resources.requests.memory = resources.limits.memory(Guaranteed QoS),避免被 OOM Killresources.requests.cpu >= 2,生产环境不共享 CPU- 使用 SSD / NVMe StorageClass 且 IOPS >= 3000
- PVC 大小按
maxmemory * 1.5(RDB)或maxmemory * 3(AOF)预估
高可用与可靠性:
- Sentinel 部署 3 个或 5 个(奇数),quorum = N/2 + 1
- 配置
min-replicas-to-write 1和min-replicas-max-lag 10,防止主节点脑裂后写入丢失 - Cluster 模式每个主节点至少配 1 个从节点,跨可用区分布
- 配置
cluster-require-full-coverage no,允许部分 Slot 不可用时集群继续服务 - 定期执行备份演练和故障转移演练
持久化与备份:
- 生产环境开启 AOF(
everysec)+ RDB 混合持久化 - 配置
auto-aof-rewrite-percentage 100和auto-aof-rewrite-min-size 64mb - 使用 CronJob 定时执行 RDB 备份并上传至对象存储(S3/MinIO)
- 定期执行
redis-check-rdb和redis-check-aof验证备份文件完整性 - 备份数据跨区域复制(S3 Cross-Region Replication)
安全:
- 为每个应用创建独立 ACL 用户,最小权限原则(
+@read -@write -@dangerous) - 启用 TLS 加密通信(
tls-port),使用 cert-manager 自动管理证书 - 重命名或禁用危险命令:
rename-command FLUSHALL ""、rename-command CONFIG "" - 配置
protected-mode yes和bind限制访问网段 - 不暴露 Redis 端口至公网,使用 NetworkPolicy 限制入站流量
监控与告警:
- 部署
redis_exporter作为 Sidecar 容器,通过 Prometheus PodMonitor 采集指标 - 配置关键告警:内存 > 80%、连接数 > 80%、命中率 < 90%、复制延迟 > 10MB
- 使用 Grafana Dashboard(如 763)集中展示 Redis 集群状态
- 集成日志采集(Filebeat/Fluentd → Elasticsearch/Loki),结构化解析 Redis 日志
- 设置慢查询告警:
SLOWLOG增长速率异常时触发通知