最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
如何在Kubernetes上部署高可用的Redis集群?
时间:2026-08-17 20:16:49 编辑:袖梨 来源:一聚教程网
结论是:StatefulSet + Headless Service + PersistentVolumeClaim 是唯一能稳定运行 Redis Cluster 的组合,因为 Deployment 无法提供固定 hostname、可解析 DNS 和专属持久化存储,导致 Pod 重启后 IP 和节点信息失效,引发脑裂或 CLUSTERDOWN 错误。
直接说结论:用 StatefulSet + Headless Service + PersistentVolumeClaim 是唯一能稳定跑通 Redis Cluster 的组合,其他方式(比如 Deployment)在节点重建或 IP 变更后必然导致集群脑裂或 CLUSTERDOWN 错误。
为什么不能用 Deployment 部署 Redis Cluster
Redis Cluster 节点间靠 gossip 协议通信,每个节点必须有固定身份(hostname)、可解析的 DNS 名和稳定的存储路径。而 Deployment 生成的 Pod 每次重启都会换 IP、换 hostname,且无法绑定专属 PVC —— 导致 nodes.conf 里记录的老地址失效,新节点无法加入集群,redis-cli --cluster check 会持续报 Node XXX is not connected 或 ERR Node XXX is not in cluster。
-
StatefulSet提供稳定的pod-name-0、pod-name-1等序号命名,配合Headless Service可解析为redis-cluster-0.redis-cluster.default.svc.cluster.local - 每个 Pod 必须挂载独立 PVC,否则多个实例共用同一份
nodes.conf会相互覆盖,引发槽位元数据冲突 - 镜像启动命令必须带
--cluster-enabled yes,且不能依赖默认配置;最新redis:6.2+镜像默认关闭集群模式
StatefulSet 中必须设置的关键字段
漏掉任意一项,集群初始化就会卡在 “Waiting for cluster to join” 或反复触发 MOVED 重定向失败。
-
serviceName必须指向一个Headless Service(clusterIP: None),否则 DNS 解析不到 Pod 的 A 记录 -
volumeClaimTemplates里accessModes必须是["ReadWriteOnce"],NFS 或 Longhorn 等支持该模式的存储类才可用;ReadWriteMany在多数场景下会导致nodes.conf写入竞争 - 容器
env中需显式注入POD_IP,用于动态替换nodes.conf中的旧 IP(很多教程用update-node.sh脚本做这事) - 启动命令要绕过默认配置,例如:
command: ["/bin/sh", "-c", "sed -i 's/.*bind.*/bind 0.0.0.0/g' /etc/redis/redis.conf && exec redis-server /etc/redis/redis.conf"]
集群初始化必须在所有 Pod Ready 后手动执行
Kubernetes 不会自动帮你运行 redis-cli --cluster create,StatefulSet 创建完 6 个 Pod 后,它们只是“活着”,不是“组成了集群”。常见错误是等 Ready 状态一出现就以为完事了,结果连 CLUSTER INFO 都返回 cluster_state:fail。
- 用
kubectl exec -it redis-cluster-0 -- redis-cli -p 6379 CLUSTER NODES查看,若只有一行且connected为0,说明还没初始化 - 必须进任意一个 Pod 手动执行:
redis-cli --cluster create $(seq 0 5 | xargs -I{} echo "redis-cluster-{}.redis-cluster.default.svc.cluster.local:6379") --cluster-replicas 1 - 如果提示
Sorry, Redis Cluster only supports the default port (6379),说明某个 Pod 的containerPort没写对,或 Service 的targetPort指向了错端口 - 初始化成功后,每个 Pod 的
/data/nodes.conf会被重写,且内容各不相同 —— 这是验证是否真正组网成功的最可靠依据
扩容时槽位迁移必须人工介入
加节点不是改 replicas 就完事。StatefulSet 扩容后新 Pod 会起,但 Redis Cluster 不会自动把槽位分给它,反而可能因 cluster_require_full_coverage no 设置不当导致整个集群拒绝写入。
- 先用
redis-cli --cluster add-node 新节点地址 任一老节点地址加入集群 - 再用
redis-cli --cluster reshard手动迁移槽位,指定迁移数量、目标节点 ID 和来源节点 ID - 最后用
redis-cli --cluster rebalance均衡分布(慎用,可能引发大量数据迁移) - 务必确认新节点已变成
master且CLUSTER NODES中状态为connected,再更新应用连接字符串
最容易被忽略的是:所有节点的 cluster-node-timeout 必须一致,且不能低于网络 P99 延迟的 3 倍;K8s 节点间跨 AZ 或跨节点通信稍慢,设成 15000 是底线,设太小会导致频繁误判节点失联并触发无谓的主从切换。