redis cluster 高可用集群的标准部署方案是“3主3从”共6个节点,最少需要3个主节点才能形成法定多数投票机制,每个主节点至少配1个从节点用于故障自动切换,这样能容忍1个主节点及其对应从节点同时故障。
一、方案概述
1.1 目标
在已有的 k8s 高可用集群上,部署一套 redis cluster(集群模式),具备:
- 高可用:3 主 3 从,容忍 1 个主节点故障
- 数据分片:16384 个 hash slot 平均分配到 3 个主节点
- 自动故障转移:主节点故障时,从节点自动提升为主
- 持久化:每个节点独立 pvc,数据落盘
1.2 技术选型
| 组件 | 用途 |
|---|---|
| bitnami redis cluster helm chart | 部署 redis cluster |
| statefulset | 管理 6 个 redis pod |
| persistentvolumeclaim | 每个节点的持久化存储 |
| redis cluster | 数据分片和自动故障转移 |
1.3 架构
应用 ↓ service: production-redis-redis-cluster:6379 ↓ redis cluster (3 主 3 从) ├── master-0 (slot 0-5460) ← slave-0 ├── master-1 (slot 5461-10922) ← slave-1 └── master-2 (slot 10923-16383) ← slave-2 ↓ persistentvolume (local-path)
二、前置条件
2.1 k8s 集群状态
- 至少 3 个可调度节点
- 集群
kubectl get nodes全部ready - cni 已部署(flannel 或 calico)
2.2 存储要求
redis 的 statefulset 需要动态存储。必须提前配好 storageclass。
检查:
kubectl get storageclass
预期:至少有一个 storageclass,且设为 default。
如果没有,先装 local path provisioner:
kubectl apply -f https://raw.githubusercontent.com/rancher/local-path-provisioner/v0.0.28/deploy/local-path-storage.
kubectl patch storageclass local-path -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'解析:
kubectl apply -f:部署 provisioner。kubectl patch:设为默认 storageclass。
2.3 镜像网络要求
这是最容易踩坑的地方。 redis cluster 需要以下镜像:
| 镜像 | 仓库 |
|---|---|
| bitnami/redis-cluster | docker hub |
| bitnami/redis-exporter | docker hub(可选,监控用) |
bitnami 从 2025 年 8 月 28 日起,把免费镜像从 docker hub 公共目录移除了。 直接拉 bitnami/redis-cluster 会返回 403 forbidden。
解决方案:从 bitnamilegacy 仓库拉旧版镜像,然后打标签。
# 从 daocloud 代理拉 bitnamilegacy 镜像 crictl pull docker.m.daocloud.io/bitnamilegacy/redis-cluster:8.2.1-debian-12-r0 # 打标签,让 containerd 认为本地有 bitnami/redis-cluster ctr -n k8s.io images tag docker.m.daocloud.io/bitnamilegacy/redis-cluster:8.2.1-debian-12-r0 docker.io/bitnami/redis-cluster:8.2.1-debian-12-r0
解析:
crictl pull:用 containerd 拉镜像。docker.m.daocloud.io/bitnamilegacy/:daocloud 代理的 bitnami legacy 仓库,免认证。ctr -n k8s.io images tag:在 k8s 命名空间里给镜像打新标签。docker.io/bitnami/redis-cluster:helm chart 里 pod 引用的镜像名。
2.4 配置 containerd 镜像加速
在每台节点上配置,解决所有 docker hub 镜像拉取问题。
编辑 /etc/containerd/config.,找到:
[plugins."io.containerd.grpc.v1.cri".registry.mirrors]
在它下面加:
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
endpoint = [
"https://docker.m.daocloud.io",
"https://docker.mirrors.ustc.edu.cn"
]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."ghcr.io"]
endpoint = [
"https://ghcr.nju.edu.cn"
]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"]
endpoint = [
"https://quay.mirrors.ustc.edu.cn"
]解析:
endpoint是数组,containerd 会按顺序尝试,第一个失败试第二个。- 多个源提高容错性。
重启:
systemctl restart containerd systemctl status containerd --no-pager | head -5
用 ansible 批量推:
---
- name: 配置 containerd 多镜像源
hosts: k8s_cluster
gather_facts: no
become: no
tasks:
- name: 备份
copy:
src: /etc/containerd/config.
dest: /etc/containerd/config..bak
remote_src: yes
force: no
- name: 插入 docker.io 镜像加速
blockinfile:
path: /etc/containerd/config.
marker: "# {mark} ansible managed mirrors"
insertbefore: '\[plugins\."io\.containerd\.grpc\.v1\.cri"\.x509_key_pair_streaming\]'
block: |
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
endpoint = [
"https://docker.m.daocloud.io",
"https://docker.mirrors.ustc.edu.cn"
]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."ghcr.io"]
endpoint = [
"https://ghcr.nju.edu.cn"
]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"]
endpoint = [
"https://quay.mirrors.ustc.edu.cn"
]
- name: 重启 containerd
systemd:
name: containerd
state: restarted
enabled: yes
- name: 验证状态
command: systemctl is-active containerd
register: status
changed_when: false
- name: 输出
debug:
msg: "{{ inventory_hostname }}: containerd {{ status.stdout }}"执行:
ansible-playbook -i inventory.ini containerd-mirror-multi.yml
三、安装 helm
3.1 确认 helm 可用
helm version
如果没有:
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | hash -r helm version
解析
curl ... |:下载官方安装脚本并执行。hash -r:让 shell 重新扫描 path。
四、下载 redis cluster chart
4.1 从 daocloud 代理拉取
不能用 helm repo add bitnami,因为 bitnami 的 chart 走 docker hub oci,国内不通。
直接用 daocloud 代理:
helm pull oci://docker.m.daocloud.io/bitnamicharts/redis-cluster --version 13.0.4
解析:
helm pull:只下载 chart,不安装。oci://docker.m.daocloud.io/bitnamicharts/redis-cluster:daocloud 代理的 oci 地址。--version 13.0.4:指定版本,避免查最新版超时。
预期输出:
pulled: docker.m.daocloud.io/bitnamicharts/redis-cluster:13.0.4 digest: sha256:45229772bdde004303e5eaf12c1fff839811ba7f17d63e9fc6cbd8923d0531c2
下载后本地会有:redis-cluster-13.0.4.tgz
4.2 常见问题
问题:华为云源返回 401
error: installation failed: get "...swr.cn-north-4.myhuaweicloud.com...": response status code 401: denied: you may not login yet
原因:华为云的 docker hub 代理需要登录认证。
解决方案:用 daocloud,它免认证。
五、部署 redis cluster
5.1 创建命名空间
kubectl create namespace redis
解析:
kubectl create namespace:创建redis命名空间。- helm 的
--namespace参数不会自动创建命名空间,需要提前建好。
5.2 安装 chart
helm install production-redis ./redis-cluster-13.0.4.tgz \ --namespace redis \ --set password=l48pw3luqopbkjyayffj \ --set cluster.nodes=6 \ --set cluster.replicas=1
逐项解析:
| 参数 | 含义 |
|---|---|
production-redis | release 名 |
./redis-cluster-13.0.4.tgz | 本地 chart 包 |
--namespace redis | 装到 redis 命名空间 |
--set password=... | 设置 redis 密码 |
--set cluster.nodes=6 | 总共 6 个节点(3 主 3 从) |
--set cluster.replicas=1 | 每个主节点 1 个从节点 |
预期输出:
name: production-redis last deployed: ... namespace: redis status: deployed revision: 1
5.3 观察 pod 启动
kubectl get pods -n redis -w
按 ctrl+c 退出。
预期:6 个 pod 逐渐启动。
name ready status restarts age production-redis-redis-cluster-0 1/1 running 0 ... production-redis-redis-cluster-1 1/1 running 0 ... production-redis-redis-cluster-2 1/1 running 0 ... production-redis-redis-cluster-3 1/1 running 0 ... production-redis-redis-cluster-4 1/1 running 0 ... production-redis-redis-cluster-5 1/1 running 0 ...
5.4 常见问题
问题一:pod 卡在 imagepullbackoff,拉 bitnami/redis-cluster 失败
原因:bitnami 从 2025 年 8 月 28 日起移除了 docker hub 公共目录的免费镜像,返回 403 forbidden。
排查:
kubectl describe pod -n redis production-redis-redis-cluster-0 | grep -a10 "events:"
解决方案:从 bitnamilegacy 拉镜像,打标签。
# 每台节点执行 crictl pull docker.m.daocloud.io/bitnamilegacy/redis-cluster:8.2.1-debian-12-r0 ctr -n k8s.io images tag docker.m.daocloud.io/bitnamilegacy/redis-cluster:8.2.1-debian-12-r0 docker.io/bitnami/redis-cluster:8.2.1-debian-12-r0
用 ansible 批量:
ansible k8s_cluster -i inventory.ini -m shell -a " crictl pull docker.m.daocloud.io/bitnamilegacy/redis-cluster:8.2.1-debian-12-r0 ctr -n k8s.io images tag docker.m.daocloud.io/bitnamilegacy/redis-cluster:8.2.1-debian-12-r0 docker.io/bitnami/redis-cluster:8.2.1-debian-12-r0 " -b
然后删除卡住的 pod:
kubectl delete pod -n redis --all
问题二:pod 卡在 pending,报 failedscheduling
原因:pvc 绑不上,或节点不够。
排查:
kubectl get pvc -n redis kubectl describe pod -n redis production-redis-redis-cluster-0 | tail -30
如果 pvc 是 pending,检查 provisioner:
kubectl get pods -n local-path-storage kubectl logs -n local-path-storage -l app=local-path-provisioner --tail=50
问题三:pod 卡在 containercreating,报挂载失败
原因:pv 绑定失败。
排查:
kubectl describe pod -n redis production-redis-redis-cluster-0 | grep -a5 "volumes" kubectl get pv | grep redis
六、验证集群
6.1 查看 pod 状态
kubectl get pods -n redis -o wide
预期:6 个 pod 全部 running 1/1。
6.2 取密码
export redis_password=$(kubectl get secret --namespace redis production-redis-redis-cluster -o jsonpath="{.data.redis-password}" | base64 -d)
echo $redis_password解析:
kubectl get secret:取 bitnami 自动创建的 secret。-o jsonpath="{.data.redis-password}":提取密码字段。| base64 -d:解码。export:存到环境变量。
保存这个密码。
6.3 查看集群节点
kubectl exec -it -n redis production-redis-redis-cluster-0 -- redis-cli -a $redis_password cluster nodes
解析:
kubectl exec -it:进入 pod 执行命令。-n redis:命名空间。production-redis-redis-cluster-0:pod 名。redis-cli cluster nodes:查看集群拓扑。-a:密码。
预期输出:
<id1> 10.244.5.21:6379@16379 myself,master - 0 0 1 connected 0-5460 <id2> 10.244.0.7:6379@16379 master - 0 ... 2 connected 5461-10922 <id3> 10.244.6.17:6379@16379 master - 0 ... 3 connected 10923-16383 <id4> 10.244.5.20:6379@16379 slave <id1> ... <id5> 10.244.1.7:6379@16379 slave <id2> ... <id6> 10.244.4.7:6379@16379 slave <id3> ...
关注:
- 3 个
master,各自负责一段 slot。 - 3 个
slave,分别跟随对应的 master。 - 所有节点
connected。 - slot 覆盖 0-16383 全部 16384 个,没有遗漏。
6.4 查看集群信息
kubectl exec -it -n redis production-redis-redis-cluster-0 -- redis-cli -a $redis_password cluster info
预期关键字段:
| 字段 | 值 | 含义 |
|---|---|---|
cluster_state | ok | 集群正常 |
cluster_slots_assigned | 16384 | 所有 slot 都分配了 |
cluster_known_nodes | 6 | 6 个节点都认识 |
cluster_size | 3 | 3 个分片 |
6.5 验证读写
kubectl exec -it -n redis production-redis-redis-cluster-0 -- redis-cli -c -a $redis_password set test-key "hello" kubectl exec -it -n redis production-redis-redis-cluster-0 -- redis-cli -c -a $redis_password get test-key
解析:
-c:集群模式,自动跟随重定向。set/get:写入和读取。
预期:
set返回ok。get返回"hello"。
6.6 高可用验证
测试:删掉一个 master,看自动故障转移
第一步:找到 master 对应的 pod
kubectl exec -it -n redis production-redis-redis-cluster-0 -- redis-cli -a $redis_password cluster nodes | grep myself
出里 myself,master 那一行就是当前 pod 的角色。记下它的 ip。
第二步:找到 ip 对应的 pod 名
kubectl get pods -n redis -o wide
第三步:删掉那个 pod
kubectl delete pod -n redis <master-pod-name>
第四步:观察
kubectl get pods -n redis -w
预期:
- 被删的 master 短暂下线。
- 它的 slave 被提升为新 master。
- 原 master 重建后,以 slave 身份重新加入。
- 集群自动恢复,slot 不丢。
第五步:验证恢复
kubectl exec -it -n redis production-redis-redis-cluster-1 -- redis-cli -a $redis_password cluster nodes
预期:6 个节点重新在线,角色可能互换,但 slot 分配仍然完整。
七、应用接入
7.1 连接信息
在集群内部:
| 用途 | 地址 |
|---|---|
| redis cluster | production-redis-redis-cluster.redis.svc.cluster.local:6379 |
简写(同命名空间):
production-redis-redis-cluster:6379
跨命名空间:
production-redis-redis-cluster.redis.svc.cluster.local:6379
密码:从 secret 取。
7.2 应用配置示例
python (redis-py):
from redis.cluster import rediscluster
client = rediscluster(
host='production-redis-redis-cluster.redis',
port=6379,
password='<密码>',
decode_responses=true
)node.js (ioredis):
const redis = require('ioredis');
const cluster = new redis.cluster([
{ host: 'production-redis-redis-cluster.redis', port: 6379 }
], {
redisoptions: {
password: '<密码>'
}
});java (lettuce):
redisclusterclient client = redisclusterclient.create(
"redis://:<密码>@production-redis-redis-cluster.redis:6379"
);go (go-redis):
import "github.com/redis/go-redis/v9"
rdb := redis.newclusterclient(&redis.clusteroptions{
addrs: []string{"production-redis-redis-cluster.redis:6379"},
password: "<密码>",
})7.3 部署后端服务到 k8s
apiversion: apps/v1
kind: deployment
metadata:
name: my-backend
namespace: default
spec:
replicas: 2
selector:
matchlabels:
app: my-backend
template:
metadata:
labels:
app: my-backend
spec:
containers:
- name: my-backend
image: my-backend:latest
ports:
- containerport: 8080
env:
- name: redis_host
value: "production-redis-redis-cluster.redis"
- name: redis_port
value: "6379"
- name: redis_password
valuefrom:
secretkeyref:
name: production-redis-redis-cluster
key: redis-password解析:
env:把连接信息通过环境变量传给应用。valuefrom.secretkeyref:从 secret 取密码,不写在 里。
7.4 验证连通性
进后端 pod:
kubectl exec -it <backend-pod> -- sh
测试端口:
nc -zv production-redis-redis-cluster.redis 6379
解析:
nc -zv:测试端口连通性。- 返回
succeeded说明网络通。
八、常用操作
8.1 查看集群状态
kubectl get pods -n redis kubectl get pvc -n redis kubectl get svc -n redis
8.2 查看日志
kubectl logs -n redis production-redis-redis-cluster-0 --tail=100
8.3 连接 redis
kubectl exec -it -n redis production-redis-redis-cluster-0 -- redis-cli -c -a $redis_password
8.4 扩容集群
增加节点:
helm upgrade production-redis ./redis-cluster-13.0.4.tgz \ --namespace redis \ --set password=l48pw3luqopbkjyayffj \ --set cluster.nodes=8 \ --set cluster.replicas=1
解析:
cluster.nodes=8:从 6 个增加到 8 个(4 主 4 从)。- helm 会滚动更新 statefulset。
8.5 删除集群
helm uninstall production-redis -n redis kubectl delete pvc -n redis -l app.kubernetes.io/instance=production-redis kubectl delete namespace redis
警告:删除 pvc 会删除所有数据,操作前先备份。
九、架构总结
9.1 组件清单
| 组件 | 数量 | 作用 |
|---|---|---|
| redis pod | 6 | 3 主 3 从 |
| statefulset | 1 | 管理 redis pod |
| pvc | 6 | 每个 pod 一块存储 |
| service | 2 | 集群内部通信和客户端入口 |
| secret | 1 | redis 密码 |
9.2 端口速查
| 端口 | 用途 |
|---|---|
| 6379 | redis 客户端连接 |
| 16379 | redis cluster 总线(集群内部通信) |
9.3 高可用机制
| 故障场景 | 影响 | 恢复方式 |
|---|---|---|
| 从节点故障 | 无影响 | 主节点继续服务,从节点重建后重新同步 |
| 主节点故障 | 该分片短暂不可用 | 从节点自动提升为主,slot 自动接管 |
| 多个主节点故障 | 部分 slot 不可用 | 如果超过半数主节点故障,集群停止服务 |
9.4 已知隐患
| 隐患 | 影响 | 解决方案 |
|---|---|---|
| 节点集中在 q5、q6 | 节点故障影响多个 pod | 加工作节点,或允许调度到控制平面 |
| local path 存储 | pod 漂移数据丢失 | 换 nfs / ceph / longhorn |
| bitnami 免费镜像移除 | 无法拉取最新镜像 | 用 bitnamilegacy 旧版镜像 |
| 未配备份 | 数据无法恢复 | 用 redis-cli --rdb 或 redis 持久化 |
十、总结
这套 redis cluster 基于 bitnami helm chart,提供了:
- 高可用:3 主 3 从,容忍 1 个主节点故障
- 数据分片:16384 个 slot 平均分配到 3 个主节点
- 自动故障转移:主节点故障时,从节点自动提升
- 持久化:每个节点独立 pvc
- 声明式管理:helm chart 一条命令部署
部署中最容易踩的坑:
- bitnami 免费镜像移除:必须用
bitnamilegacy旧版镜像,并打标签。 - docker hub 访问超时:必须配 containerd 镜像加速。
- helm chart 拉取超时:用 daocloud 的 oci 代理。
到此这篇关于redis cluster 高可用集群部署方案详解的文章就介绍到这了,更多相关redis cluster 集群部署内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论