您的位置:首页 > 手游攻略 > Redis Cluster 高可用集群部署方案完整指南

Redis Cluster 高可用集群部署方案完整指南

作者:互联网  时间: 2026-09-30 09:20:02  

平时做技术实践时,很多问题不是概念不会,而是细节没串起来。拿“Redis Cluster 高可用集群部署方案”来说,它看着像小点,放到项目里常会牵出环境、配置、兼容性和维护成本。下面按实际采用顺序,把思路、关键写法和容易踩坑的地方讲清楚,便于大家直接对照操作。

Redis Cluster 高可用集群的 标准部署方案是“3主3从”共6个节点理解这一步时,,最少需3个主节点才能形成法定多数投票机制,每个主节点至少配1个从节点用来故障自动切换,这样能容忍1个主节点及其对应从节点同时故障。

一、方案概述

1.1 目标

结合项目来看,在已有的 K8s 高可用集群上,部署一套 Redis Cluster(集群模式),具备:

  • 高可用:3 主 3 从,容忍 1 个主节点故障
  • 数据分片:16384 个 hash 平均分配到 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 ( 0-5460) ← slave-0
  ├── master-1 ( 5461-10922) ← slave-1
  └── master-2 ( 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,各自负责一段 。
  • 3 个 slave,分别跟随对应的 master。
  • 所有节点 connected。
  • 覆盖 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_s_assigned16384所有 都分配了
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 身份重新加入。
  • 集群自动恢复, 不丢。

第五步:验证恢复

kubectl exec -it -n redis production-redis-redis-cluster-1 -- redis-cli -a $REDIS_PASSWORD cluster nodes

预期:6 个节点重新在线,角色可能互换,但 分配仍然完整。

七、应用接入

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 高可用机制

故障场景影响恢复方式
从节点故障无影响主节点继续服务,从节点重建后重新同步
主节点故障该分片短暂不可用从节点自动提升为主, 自动接管
多个主节点故障部分 不可用若超过半数主节点故障,集群停止服务

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 个 平均分配到 3 个主节点
  • 自动故障转移:主节点故障时,从节点自动提升
  • 持久化:每个节点独立 PVC
  • 声明式管理:Helm chart 一条命令部署

部署中最容易踩的坑:

  1. Bitnami 免费镜像移除:必须用 bitnamilegacy 旧版镜像,同时打标签。
  2. Docker Hub 访问超时:必须配 containerd 镜像加速。
  3. Helm chart 拉取超时:用 DaoCloud 的 OCI 代理。

结合项目来看,总的来说,Redis Cluster 集群部署适合结合实际项目边做边理解。先抓住核心思路,再逐步补上细节和边界处理,最后效果会更稳定,也更容易复用。

最新游戏

更多

Copyright©2010-2019. All rights reserved | 波波三国游戏官网|[email protected]

备案编号:湘ICP备2022015115号-4