第 5/15 天
经过前四天的铺垫,我们已经完成了 Ceph 分布式存储的回顾、K8s 存储体系的梳理,并成功将 Ceph RBD 块存储和 CephFS 共享文件存储接入 K8s 集群。从今天开始,我们正式进入「中间件部署实战」阶段,首站便是高吞吐、低延迟的内存数据库——Redis。
本篇将使用 Bitnami 官方维护的 bitnami/redis-cluster Helm Chart,在 K8s 上部署一个 6 节点的 Redis Cluster(3 主 3 从),并通过 Ceph RBD StorageClass 实现数据持久化。我们将覆盖架构设计、values 配置、部署验证、登录连接和日常巡检的完整闭环。
一、Redis Cluster 设计架构
1.1 为什么选择 Redis Cluster
单实例 Redis 虽然性能强劲,但存在两个瓶颈:单节点内存上限和数据丢失风险。Redis Sentinel(下篇讲解)解决了高可用问题,但仍然是单 Master 写入,无法水平扩展。Redis Cluster 则在此基础上引入了数据分片(Sharding)机制,将数据分散到多个 Master 节点上,既解决了容量瓶颈,又保留了高可用能力。
Redis Cluster 的核心特性:
| 特性 | 说明 |
|---|---|
| 数据分片 | 16384 个哈希槽(hash slot)均匀分配到各 Master |
| 自动故障转移 | Master 宕机后,对应 Replica 自动提升为新 Master |
| 去中心化 | 节点间通过 Gossip 协议互相通信,无中心代理 |
| 客户端路由 | 客户端通过 MOVED/ASK 重定向访问正确节点 |
| 多键操作限制 | 跨 slot 的多键操作需使用 hash tag {} 保证同 slot |

1.2 组件拓扑
本次部署的 Redis Cluster 拓扑如下:
┌─────────────────────────────────────┐
│ Kubernetes Cluster │
│ │
│ ┌─────────────────────────────┐ │
│ │ redis-cluster Service │ │
│ │ (ClusterIP: None – Headless)│ │
│ └──────────┬──────────────────┘ │
│ │ │
│ ┌──────────┴──────────────────┐ │
│ │ │ │
│ Master0 Master1 Master2 │ │
│ slot0 slot1 slot2 │ │
│ │ │ │ │ │
│ Replica0 Replica1 Replica2 │ │
│ (slave) (slave) (slave) │ │
│ │ │
└─────┬───────────────────────────────┘
│ PVC (ReadWriteOnce)
▼
┌─────────────┐
│ Ceph RBD │
│ StorageClass│
│ (csi-rbd) │
└─────────────┘
部署规模:6 个 Pod(3 Master + 3 Replica),每个 Pod 绑定一个独立的 Ceph RBD PVC,使用 Headless Service 提供稳定的网络标识(StatefulSet 特性)。
1.3 数据流向
客户端请求
│
▼
任一节点接收命令
│
├─ key 所在 slot 在本节点 → 直接执行并返回
│
└─ key 所在 slot 不在本节点 → 返回 MOVED 重定向
│
▼
客户端缓存 slot → node 映射表
后续请求直接访问正确节点
哈希槽计算公式:slot = CRC16(key) mod 16384。每个 Master 负责一部分槽位区间,例如 6 节点集群中每个 Master 约负责 5461 个槽位。
1.4 高可用机制
Redis Cluster 的高可用依赖以下机制协同工作:
- 心跳检测:节点间持续发送 PING/PONG 消息,超过
cluster-node-timeout(默认 15 秒)未响应则标记为 PFAIL(疑似下线) - 故障判定:超过半数 Master 节点报告某节点 PFAIL,则升级为 FAIL(确定下线)
- 副本选举:故障 Master 的 Replica 发起选举,获得多数 Master 投票后提升为新 Master
- 槽位迁移:新 Master 继承原 Master 的全部哈希槽,集群继续提供服务
1.5 存储规划
Redis 是内存数据库,持久化(RDB/AOF)数据落盘到 Ceph RBD 卷:
| 存储项 | 类型 | 大小 | StorageClass | 说明 |
|---|---|---|---|---|
| Redis 数据卷 | RBD (RWO) | 10Gi/节点 | ceph-rbd-sc | 存储 dump.rdb / appendonly.aof |
| 备份快照 | Ceph snapshot | 按需 | – | 利用 RBD 快照能力做定时备份 |
选择 RBD 而非 CephFS 的原因:Redis 每个节点只需单 Pod 读写(RWO),RBD 的块设备性能更贴近本地磁盘,延迟更低,适合 AOF 追加写入场景。
二、部署实战(Bitnami Helm Chart)
2.1 添加 Bitnami Helm 仓库
# 添加 Bitnami 官方 Chart 仓库
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
# 验证 redis-cluster chart 可用
helm search repo bitnami/redis-cluster
# 预期输出:
# NAME CHART VERSION APP VERSION DESCRIPTION
# bitnami/redis-cluster 11.x.x 7.x.x Redis(R) is an open source, …
# 查看支持的 values 参数(可选)
helm show values bitnami/redis-cluster > /tmp/redis-cluster-default-values.yaml
2.2 编写 values.yaml 自定义配置
核心配置要点:指定 Ceph RBD StorageClass、设置 6 节点集群、配置密码、调整资源限制。
# /tmp/redis-cluster-values.yaml
# Redis Cluster Helm Chart 自定义配置
cluster:
# 6 节点集群:3 Master + 3 Replica
nodes: 6
replicas: 1 # 每个 Master 1 个副本
# 集群初始化超时
initTimeout: 300
# 全局镜像配置
global:
imageRegistry: ""
imagePullSecrets: []
redis:
password: "Redis#Cluster@2026"
# Redis 镜像
image:
registry: docker.io
repository: bitnami/redis-cluster
tag: 7.4.1-debian-12-r0
pullPolicy: IfNotPresent
# 持久化配置 —— 关键:指向 Ceph RBD StorageClass
persistence:
enabled: true
storageClass: "ceph-rbd-sc" # 第 2 天创建的 Ceph RBD StorageClass
accessModes:
– ReadWriteOnce
size: 10Gi
# 数据子目录
path: /bitnami/redis/data
# 每个节点的资源限制
resources:
requests:
cpu: 250m
memory: 512Mi
limits:
cpu: 1000m
memory: 1Gi
# 网络配置
service:
type: ClusterIP
ports:
redis: 6379
bus: 16379 # 集群总线端口,用于节点间 Gossip 通信
# Headless Service —— StatefulSet 稳定网络标识
serviceAccount:
create: true
name: ""
# Pod 安全上下文
podSecurityContext:
enabled: true
fsGroup: 1001
containerSecurityContext:
enabled: true
runAsUser: 1001
runAsNonRoot: true
# 持久化参数
redis:
# 开启 AOF 持久化
configmap: |
appendonly yes
appendfsync everysec
save 900 1
save 300 10
save 60 10000
maxmemory 512mb
maxmemory-policy allkeys-lru
cluster-node-timeout 15000
# 指标导出(配合 Prometheus 监控)
metrics:
enabled: true
image:
registry: docker.io
repository: bitnami/redis-exporter
tag: 1.x.x
serviceMonitor:
enabled: false # 后续监控篇统一开启
# Pod 反亲和 —— 让 6 个节点分散到不同节点
podAntiAffinityPreset: soft
2.3 执行 Helm 部署
# 创建独立命名空间
kubectl create namespace middleware
# 部署 Redis Cluster
helm install redis-cluster bitnami/redis-cluster
–namespace middleware
-f /tmp/redis-cluster-values.yaml
–version 11.4.0
# 预期输出:
# NAME: redis-cluster
# LAST DEPLOYED: Sun Sep 27 00:35:00 2026
# NAMESPACE: middleware
# STATUS: deployed
# REVISION: 1
# NOTES:
# Redis Cluster can be accessed via port 6379 on the following DNS name…
# To get your password run:
# export REDIS_PASSWORD=$(kubectl get secret –namespace middleware redis-cluster -o jsonpath="{.data.redis-password}" | base64 -d)
2.4 验证部署状态
# 查看 StatefulSet Pod 状态(6 个 Pod 依次启动)
kubectl get pods -n middleware -l app.kubernetes.io/instance=redis-cluster -w
# 预期输出:
# NAME READY STATUS RESTARTS AGE
# redis-cluster-0 1/1 Running 0 2m
# redis-cluster-1 1/1 Running 0 2m
# redis-cluster-2 1/1 Running 0 2m
# redis-cluster-3 1/1 Running 0 2m
# redis-cluster-4 1/1 Running 0 2m
# redis-cluster-5 1/1 Running 0 2m
# 查看 Service
kubectl get svc -n middleware -l app.kubernetes.io/instance=redis-cluster
# 预期输出:
# NAME TYPE CLUSTER-IP PORT(S) AGE
# redis-cluster ClusterIP None 6379/TCP,16379/TCP 3m
# redis-cluster-headless ClusterIP None 6379/TCP,16379/TCP 3m
# 查看 PVC(6 个 PVC,均绑定 Ceph RBD)
kubectl get pvc -n middleware -l app.kubernetes.io/instance=redis-cluster
# 预期输出:
# NAME STATUS VOLUME CAPACITY STORAGECLASS AGE
# data-redis-cluster-0 Bound pvc-xxxx-xxxx 10Gi ceph-rbd-sc 3m
# data-redis-cluster-1 Bound pvc-yyyy-yyyy 10Gi ceph-rbd-sc 3m
# …
# data-redis-cluster-5 Bound pvc-zzzz-zzzz 10Gi ceph-rbd-sc 3m
三、登录验证
3.1 获取集群密码并连接
# 提取集群密码
export REDIS_PASSWORD=$(kubectl get secret –namespace middleware redis-cluster
-o jsonpath="{.data.redis-password}" | base64 -d)
echo "Password: $REDIS_PASSWORD"
# 进入 Pod 内执行 redis-cli 连接集群
kubectl exec -it -n middleware redis-cluster-0 — redis-cli
-a "$REDIS_PASSWORD" –cluster check
127.0.0.1:6379
# 预期输出:
# >>> Performing Cluster Check (using node 127.0.0.1:6379)
# ……
# [OK] All nodes agree about slots configuration.
# [OK] All 16384 slots covered.
# [OK] All 16384 slots covered.
# [OK] 0 keys out of 0 are in the cluster.
3.2 查看集群节点信息
# 查看集群节点拓扑(角色、槽位分配、主从关系)
kubectl exec -it -n middleware redis-cluster-0 — redis-cli
-a "$REDIS_PASSWORD" cluster nodes
# 预期输出:
# <id> 10.x.x.x:6379@16379 master – 0 xxxx myself,master – 0 1700000000000 1 connected 0-5460
# <id> 10.x.x.x:6379@16379 master – 0 xxxx master – 0 1700000000000 2 connected 5461-10922
# <id> 10.x.x.x:6379@16379 master – 0 xxxx master – 0 1700000000000 3 connected 10923-16383
# <id> 10.x.x.x:6379@16379 slave <master_id> 0 xxxx slave 0-5460
# <id> 10.x.x.x:6379@16379 slave <master_id> 0 xxxx slave 5461-10922
# <id> 10.x.x.x:6379@16379 slave <master_id> 0 xxxx slave 10923-16383
3.3 验证数据读写
# 写入测试数据(redis-cli 自动路由到正确节点)
kubectl exec -it -n middleware redis-cluster-0 — redis-cli
-a "$REDIS_PASSWORD" -c set testkey "hello-ceph-k8s"
# 读取验证
kubectl exec -it -n middleware redis-cluster-0 — redis-cli
-a "$REDIS_PASSWORD" -c get testkey
# 预期输出: "hello-ceph-k8s"
# 查看集群槽位分配概况
kubectl exec -it -n middleware redis-cluster-0 — redis-cli
-a "$REDIS_PASSWORD" cluster slots
注意:
-c参数启用集群模式,遇到 MOVED 重定向时自动跳转。不加-c则手动重定向会报错。
四、日常巡检命令
4.1 集群健康检查
# 一键检查集群完整性
kubectl exec -n middleware redis-cluster-0 — redis-cli
-a "$REDIS_PASSWORD" –cluster check
redis-cluster-0.redis-cluster-headless.middleware.svc.cluster.local:6379
# 查看集群信息
kubectl exec -n middleware redis-cluster-0 — redis-cli
-a "$REDIS_PASSWORD" cluster info
# 关键指标:
# cluster_state:ok <- 集群状态必须为 ok
# cluster_slots_assigned:16384 <- 槽位全部已分配
# cluster_slots_ok:16384 <- 槽位全部正常
# cluster_known_nodes:6 <- 已知节点数
# cluster_size:3 <- Master 分片数
4.2 节点状态与内存巡检
# 逐节点查看内存使用情况
for i in 0 1 2 3 4 5; do
echo "=== redis-cluster-$i ==="
kubectl exec -n middleware redis-cluster-$i — redis-cli
-a "$REDIS_PASSWORD" info memory | grep -E "used_memory_human|maxmemory_human|mem_fragmentation_ratio"
done
# 预期输出:
# === redis-cluster-0 ===
# used_memory_human:1.2M
# maxmemory_human:512.0M
# mem_fragmentation_ratio:1.05
# 查看各节点 Key 数量
kubectl exec -n middleware redis-cluster-0 — redis-cli
-a "$REDIS_PASSWORD" –cluster call
redis-cluster-0.redis-cluster-headless.middleware.svc.cluster.local:6379 dbsize
4.3 Pod 与 PVC 巡检
# Pod 状态巡检
kubectl get pods -n middleware -l app.kubernetes.io/instance=redis-cluster
-o wide
# PVC 使用率(Ceph RBD 卷)
kubectl get pvc -n middleware -l app.kubernetes.io/instance=redis-cluster
# 查看最近事件(排查 Pod 异常)
kubectl get events -n middleware –sort-by='.lastTimestamp' | tail -20
# 查看 AOF 持久化文件
kubectl exec -n middleware redis-cluster-0 — ls -lh /bitnami/redis/data
# 预期输出:
# -rw-r–r– 1 1001 1001 512 Sep 27 00:40 dump.rdb
# -rw-r–r– 1 1001 1001 1.2K Sep 27 00:40 appendonly.aof
4.4 日志查看
# 查看单个节点日志
kubectl logs -n middleware redis-cluster-0 –tail=50
# 查看所有节点最近日志
for i in 0 1 2 3 4 5; do
echo "=== redis-cluster-$i ==="
kubectl logs -n middleware redis-cluster-$i –tail=10
done
4.5 性能压测(可选)
# 使用 redis-benchmark 压测集群性能
kubectl exec -n middleware redis-cluster-0 — redis-benchmark
-a "$REDIS_PASSWORD" -h redis-cluster-0.redis-cluster-headless.middleware.svc.cluster.local
-p 6379 -t set,get -n 10000 -c 50 -q
# 预期输出(参考值,实际取决于节点规格):
# SET: 85000.00 requests per second
# GET: 92000.00 requests per second

五、常见问题
Q1:Pod 启动报错 CLUSTERDOWN Hash slot not served?
这是因为集群初始化尚未完成,槽位未全部分配。解决方法:等待所有 6 个 Pod 就绪后,手动触发集群初始化:
kubectl exec -n middleware redis-cluster-0 — redis-cli
-a "$REDIS_PASSWORD" –cluster create
redis-cluster-0.redis-cluster-headless:6379
redis-cluster-1.redis-cluster-headless:6379
redis-cluster-2.redis-cluster-headless:6379
redis-cluster-3.redis-cluster-headless:6379
redis-cluster-4.redis-cluster-headless:6379
redis-cluster-5.redis-cluster-headless:6379
–cluster-replicas 1 –cluster-yes
Q2:PVC 一直 Pending,StorageClass 名称写什么?
请确认第 2 天创建的 Ceph RBD StorageClass 名称。执行 kubectl get sc 查看集群中实际可用的 StorageClass,将 values.yaml 中 persistence.storageClass 改为实际名称(如 ceph-rbd-sc 或 csi-ceph-rbd)。RBD 默认只支持 ReadWriteOnce,切勿使用 ReadWriteMany。
Q3:跨节点多键操作报错 CROSSSLOT Keys in request don't hash to the same slot?
Redis Cluster 要求多键操作(MGET、MSET、事务等)的所有 Key 必须映射到同一哈希槽。解决方法:使用 Hash Tag {} 强制同槽,例如 user:{1001}:name 和 user:{1001}:age 会被分配到同一槽位,从而支持多键操作。
六、总结
本篇我们使用 Bitnami 官方 bitnami/redis-cluster Helm Chart,在 K8s 上完成了 6 节点 Redis Cluster 的部署,核心要点回顾:
- 架构设计:Redis Cluster 通过 16384 个哈希槽实现数据分片,3 主 3 从保证高可用,Gossip 协议维护集群状态
- 存储规划:每个 Pod 绑定独立 Ceph RBD PVC(RWO),存储 RDB/AOF 持久化文件,利用 RBD 块设备低延迟特性
- 部署方式:helm repo add + values.yaml 自定义 + helm install 三步完成,storageClass 指向 Ceph RBD 实现开箱持久化
- 验证巡检:
cluster check检查集群完整性、cluster info查看集群状态、逐节点 info memory 巡检内存
Redis Cluster 适合数据量大、需要水平扩展的场景。如果业务量不大但需要高可用,下篇我们将讲解更轻量的 Redis Sentinel 哨兵模式。
下期预告
第 6 天:K8s 部署 Redis Sentinel 哨兵模式(高可用架构 + 登录验证) —— 当你只需要高可用而不需要分片时,Sentinel 模式是更简洁的选择。我们将使用 bitnami/redis Chart 部署 1 主 2 从 3 哨兵的架构,对比 Cluster 与 Sentinel 的适用场景。
系列目录
- ✅ 第 1 天:Ceph 分布式存储回顾与 K8s 存储体系概述
- ✅ 第 2 天:K8s 接入 Ceph RBD 块存储(CSI Driver + StorageClass 配置实战)
- ✅ 第 3 天:K8s 接入 CephFS 共享文件存储(多读场景与性能调优)
- ✅ 第 4 天:K8s 部署 MySQL 高可用集群(Ceph RBD 持久化 + 架构设计 + 登录巡检)
- 🔥 第 5 天:K8s 部署 Redis Cluster 集群(Ceph RBD + 架构设计 + 巡检命令)(本文)
- ⏳ 第 6 天:K8s 部署 Redis Sentinel 哨兵模式(高可用架构 + 登录验证)
- ⏳ 第 7 天:K8s 部署 MinIO 对象存储集群(分布式架构 + 运维巡检)
- ⏳ 第 8 天:K8s 部署 MongoDB 副本集集群(Ceph RBD + 架构设计 + 登录)
- ⏳ 第 9 天:K8s 部署 Nacos 注册配置中心(集群架构 + 登录巡检)
- ⏳ 第 10 天:K8s 部署 Zookeeper 集群(分布式协调架构 + 运维命令)
- ⏳ 第 11 天:K8s 部署 Elasticsearch 集群(Ceph RBD + 架构设计 + 巡检)
- ⏳ 第 12 天:K8s 部署 Kafka 集群(Ceph RBD + 消息队列架构 + 运维)
- ⏳ 第 13 天:K8s 部署 GitLab 代码托管平台(Ceph RBD 持久化 + 架构 + 巡检)
- ⏳ 第 14 天:K8s 部署 ClickHouse 列式数据库集群(Ceph RBD + 架构设计)
- ⏳ 第 15 天:K8s 中间件统一监控与运维巡检总结(Prometheus + Grafana 全景)

















暂无评论内容