当前位置: 代码网 > it编程>数据库>Redis > Redis Cluster 高可用集群部署方案详解

Redis Cluster 高可用集群部署方案详解

2026年09月29日 • Redis •我要评论
redis cluster 高可用集群的‌标准部署方案是“3主3从”共6个节点‌,最少需要3个主节点才能形成法定多数投票机制,每个主节点至少配1个从节点用于

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-clusterdocker hub
bitnami/redis-exporterdocker 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-redisrelease 名
./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_stateok集群正常
cluster_slots_assigned16384所有 slot 都分配了
cluster_known_nodes66 个节点都认识
cluster_size33 个分片

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 clusterproduction-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 pod63 主 3 从
statefulset1管理 redis pod
pvc6每个 pod 一块存储
service2集群内部通信和客户端入口
secret1redis 密码

9.2 端口速查

端口用途
6379redis 客户端连接
16379redis 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 一条命令部署

部署中最容易踩的坑:

  1. bitnami 免费镜像移除:必须用 bitnamilegacy 旧版镜像,并打标签。
  2. docker hub 访问超时:必须配 containerd 镜像加速。
  3. helm chart 拉取超时:用 daocloud 的 oci 代理。

到此这篇关于redis cluster 高可用集群部署方案详解的文章就介绍到这了,更多相关redis cluster 集群部署内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

赞 (0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com