Skip to content

Redis 高可用集群部署文档

环境:RKE2 v1.35.6(6 节点)|内部 Harbor 192.168.122.156:30000|NFS 192.168.122.1:/mnt/xfs/rancher/redis 组件:Redis 8.0.2 主从(1主2从)+ Sentinel 自动故障转移 + 读写分离 Service + CronJob 每日备份 更新:2026-08-01

1. 架构

  应用 ──写──► redis-master.redis:6379   selector isMaster=true(始终指向当前主库)
       ──读──► redis-read.redis:6379     selector isMaster=false(负载到全部从库)
       └─Sentinel 感知客户端─► redis.redis:26379(masterSet: mymaster)

   redis-node-0/1/2(每 Pod 3 容器:redis + sentinel + labeler),跨 3 个节点
   主从异步复制 + Sentinel 自动故障转移(quorum=2)
   存储:NFS 192.168.122.1:/mnt/xfs/rancher/redis(StorageClass: nfs-redis)

   备份: CronJob 每天 02:00(北京) redis-cli --rdb → NFS,保留 7 天
   补偿: redis-label-sync 每 5 分钟补打丢失的 isMaster 标签

与 MySQL 方案的关键差异:Redis 用 Sentinel 实现自动故障转移(主库宕机 ~30s 自动选主), 读写分离通过 isMaster 标签驱动的两个 Service 实现,无需 ProxySQL 类代理。

2. 镜像与 Chart(全部来自内部 Harbor)

内容内部地址来源
Redis 镜像redis/redis:8.0.2-debian-12-r4daocloud bitnamilegacy/redis
Sentinel 镜像redis/redis-sentinel:8.0.2-debian-12-r2daocloud bitnamilegacy/redis-sentinel
labeler 镜像redis/kubectl:1.33.2-debian-12-r0daocloud bitnamilegacy/kubectl
Redis chartoci://…/charts/redis:21.2.6daocloud OCI bitnamicharts/redis
NFS provisionercharts/nfs-subdir-external-provisioner:4.0.18 + sig-storage/…:v4.0.2Harbor 已有

3. 前置准备

3.1 NFS 导出(192.168.122.1,已就绪)

bash
mkdir -p /mnt/xfs/rancher/redis
echo '/mnt/xfs/rancher/redis *(rw,sync,no_subtree_check,no_root_squash)' >> /etc/exports
exportfs -ra

3.2 Harbor 项目与物料同步

bash
curl -u 'admin:xxx' -X POST 'http://192.168.122.156:30000/api/v2.0/projects' \
  -H 'Content-Type: application/json' -d '{"project_name":"redis","public":true}'

export HARBOR_USER=admin HARBOR_PASS='xxx'
./deploy.sh sync    # 3 个镜像 + redis chart 一键同步

4. 一键部署

交付目录 redis/

redis/
├── deploy.sh                    # 一键部署(all|sync|check)
├── redis-values.yaml            # bitnami redis chart 参数(Sentinel、存储、RBAC)
├── nfs-provisioner-values.yaml  # 专用 StorageClass nfs-redis
├── rw-services.yaml             # redis-read 读服务 + isMaster 标签补偿 CronJob(含 RBAC)
├── backup.yaml                  # 备份 PVC + CronJob(RDB,保留 7 天)
├── .secrets.env                 # REDIS_PASSWORD(勿提交公共仓库)
└── README.md / 部署文档.md / 操作文档.md
bash
export KUBECONFIG=~/.kube/config-122.31
cd redis/
./deploy.sh

手动分步(等价命令)

bash
kubectl create ns redis

helm install redis-nfs-provisioner \
  oci://192.168.122.156:30000/charts/nfs-subdir-external-provisioner \
  --version 4.0.18 --plain-http -n redis -f nfs-provisioner-values.yaml

helm install redis oci://192.168.122.156:30000/charts/redis \
  --version 21.2.6 --plain-http -n redis -f redis-values.yaml

kubectl apply -f rw-services.yaml -f backup.yaml

# 初次部署后给两个从库补打标签(之后由 labeler + label-sync 自动维护)
kubectl -n redis label pod redis-node-<从库序> isMaster=false

5. 部署后验证

bash
# 3 个节点 3/3 Running(redis+sentinel+labeler),跨节点分布,主库带 isMaster=true
kubectl -n redis get pods -l app.kubernetes.io/instance=redis -L isMaster -o wide

# Sentinel 视角主库
kubectl -n redis exec <主库Pod> -c sentinel -- \
  redis-cli -p 26379 -a "$PW" --no-auth-warning SENTINEL get-master-addr-by-name mymaster

# 读写分离
kubectl -n redis get endpoints redis-master redis-read   # master→主库IP, read→两个从库IP
redis-cli -h redis-master -a "$PW" SET k v    # 写主库
redis-cli -h redis-read  -a "$PW" GET k       # 读从库

# 备份
kubectl -n redis create job --from=cronjob/redis-backup redis-backup-manual-$(date +%s)

# 故障转移演练:删除主库 Pod,~30s 后 Sentinel 完成选主,
# redis-master/redis-read 后端自动切换,数据不丢(异步复制无写入冲突时)
kubectl -n redis delete pod <主库Pod>

6. 关键设计决策与踩坑记录

  1. Sentinel 而非单纯主从:bitnami architecture=replication + sentinel.enabled=true, 每个节点 Pod 内 3 容器(redis / sentinel / kubectl labeler),主库宕机自动选主。
  2. replica.replicaCount 在 Sentinel 模式是节点总数:1主2从要填 3(默认 3), 填 2 只有 1主1从。这是与直觉不符的坑。
  3. 读写分离靠标签 Servicesentinel.masterService.enabled=true 生成 redis-master (selector isMaster=true),chart labeler 在选主事件时维护标签; 读服务 redis-read(selector isMaster=false)为自建,见 rw-services.yaml。 必须同时开启 rbac.create + serviceAccount.create + replica.automountServiceAccountToken, 否则 chart 校验拒绝部署。
  4. 从库 Pod 重建丢标签:labeler 只在选主事件时打标,重建的从库 Pod 没有 isMaster=false, 会掉出 redis-read 后端。由 redis-label-sync CronJob(每 5 分钟)自动补偿, 其 RBAC 独立配置(chart 自带 SA 无 pods get 权限)。
  5. 备份用 redis-cli --rdb:通过 SYNC 从主库拉全量 RDB(主库 fork BGSAVE 子进程,不阻塞), 避免直接挂载主库数据卷。
  6. bitnami 镜像下线:同 MySQL,用 bitnamilegacy 仓库 + global.security.allowInsecureImages

7. 应用接入

写: redis-master.redis.svc.cluster.local:6379
读: redis-read.redis.svc.cluster.local:6379
Sentinel 客户端: redis.redis.svc.cluster.local:26379, masterSet=mymaster
密码: xxx .secrets.env