Rook-Ceph 生产级部署实践:15 节点全 NVMe 1.44PB 分布式存储
在 Kubernetes 上给数据库、消息队列和分布式多实例应用选存储,是每个规模化集群都绕不开的问题。我的场景是 15 个节点、每节点 12 块 8TB NVMe,总裸容量 1.44PB,需要同时提供 RWO 块存储和 RWX 共享文件存储。本文完整记录从方案调研、选型决策,到 Rook-Ceph 生产级部署与 NVMe 专项调优的全过程。
一、调研过程与最终结论
1.1 方案对比
| 方案 | 存储类型 | 核心优势 | 数据高可用 | 运维复杂度 | 推荐场景 |
|---|---|---|---|---|---|
| Rook-Ceph | 块/文件/对象 | 统一平台,功能全面 | ✅ 集群级自愈 | 高 | 通用生产环境,多存储需求 |
| OpenEBS Mayastor | 块存储 | 极致低延迟,NVMe-oF | ✅ 卷级副本 | 中 | 高性能数据库、消息队列 |
| Longhorn | 块存储 | 简单易用,运维轻松 | ✅ 卷级副本 | 低 | 中小集群,运维资源有限 |
| TopoLVM | 本地块存储 | 拓扑感知,动态本地卷 | ❌ 依赖应用层 | 中 | 自带复制的高性能应用 |
| 本地 PV 直通 | 本地块存储 | 性能无损,实现简单 | ❌ 无 | 极高(大规模) | 临时数据,性能基准 |
1.2 最终结论:Rook-Ceph
选择 Rook-Ceph 的核心理由:
- 规模匹配:15 节点正好是 Ceph 的舒适区,可以构建功能完整的存储平台。
- 统一存储:一套集群同时提供块存储(RBD,RWO)、文件存储(CephFS,RWX)和对象存储(S3/Swift),一次部署满足所有需求。
- 高可用与弹性:数据默认 3 副本,节点故障时数据自动重建,Pod 可漂移,业务不中断。
- NVMe 性能可充分释放:通过
osdsPerDevice参数在单块盘上创建多个 OSD,充分利用 NVMe 内部并行性。对于 8TB 大容量 NVMe,建议设置osdsPerDevice为 4。 - RWX 需求覆盖:CephFS 提供原生 RWX 共享文件存储,不像 Longhorn 的 RWX 需要经过 NFS 协议转换导致性能大幅下降。
1.3 关键硬件规划
15 节点 × 12 块 8TB NVMe,总裸容量 1,440 TB(约 1.44PB),规划如下:
| 项目 | 配置 |
|---|---|
| 总裸容量 | 1,440 TB |
| OSD 总数 | 15 节点 × 12 盘 × 4 OSD/盘 = 720 OSD |
| 数据保护 | 3 副本,可用容量约 480 TB |
| MON 节点 | 3 个(分布在不同节点) |
| MGR 节点 | 2 个(Active/Standby) |
| OSD 内存需求 | 每 OSD 约 1-4 GiB,单节点 48 OSD 约需 48-192 GiB RAM |
| OSD CPU 需求 | 单节点建议 16-32 Core |
⚠️ 注意:每 OSD 进程消耗约 1-4 GiB RAM(取决于缓存配置),每节点 12 盘 × 4 OSD = 48 OSD,请确保每节点内存充足。
二、部署前提条件
2.1 集群要求
- Kubernetes 集群(v1.23+),至少 3 个 worker 节点
kubectl和helm已配置管理员权限- 容器运行时推荐 containerd
2.2 节点准备(在每个 worker 节点执行)
加载内核模块:
1modprobe rbd
2modprobe ceph
3
4# 持久化配置
5echo "rbd" >> /etc/modules-load.d/rook.conf
6echo "ceph" >> /etc/modules-load.d/rook.conf
擦除目标 NVMe 磁盘(以 /dev/nvme0n1 为例,所有 12 块盘都需执行):
1# 确认磁盘无分区、无 LVM 状态
2wipefs -a /dev/nvme0n1
3dd if=/dev/zero of=/dev/nvme0n1 bs=1M count=100
对所有 12 块 NVMe 盘重复上述操作,依次为 /dev/nvme0n1 到 /dev/nvme11n1。
NVMe 内核调优(在每个 worker 节点执行):
1# 设置 I/O 调度器为 none(NVMe 无旋转延迟)
2for dev in /dev/nvme*n1; do
3 echo none > /sys/block/$(basename $dev)/queue/scheduler
4done
5
6# 增大 NVMe 队列深度
7echo 1024 > /sys/block/nvme0n1/queue/nr_requests
将调度器配置持久化(在 /etc/udev/rules.d/60-nvme-scheduler.rules 中添加):
ACTION=="add|change", KERNEL=="nvme*n1", ATTR{queue/scheduler}="none"
禁用透明大页(THP)。Ceph 官方建议禁用 THP,因为它在 OSD 节点上会导致延迟尖峰:
1echo never > /sys/kernel/mm/transparent_hugepage/enabled
2echo never > /sys/kernel/mm/transparent_hugepage/defrag
3
4# 持久化到 /etc/rc.local 或 systemd service
三、部署步骤
3.1 安装 Rook Operator
1helm repo add rook-release https://charts.rook.io/release
2helm repo update
3
4helm install rook-ceph rook-release/rook-ceph \
5 --namespace rook-ceph \
6 --create-namespace \
7 --version 1.18.0 \
8 --set csi.enableCSIHostNetwork=true \
9 --set csi.enableRbdDriver=true \
10 --set csi.enableCephfsDriver=true
3.2 部署 Ceph Cluster
创建 cluster.yaml,针对全 NVMe 15 节点集群做了专项优化:
1apiVersion: ceph.rook.io/v1
2kind: CephCluster
3metadata:
4 name: rook-ceph
5 namespace: rook-ceph
6spec:
7 cephVersion:
8 image: quay.io/ceph/ceph:v18.2.0 # Reef 版本
9 dataDirHostPath: /var/lib/rook
10 mon:
11 count: 3
12 allowMultiplePerNode: false
13 mgr:
14 count: 2
15 modules:
16 - name: pg_autoscaler
17 enabled: true
18 - name: dashboard
19 enabled: true
20 dashboard:
21 enabled: true
22 ssl: true
23 network:
24 connections:
25 compression:
26 enabled: false
27 encryption:
28 enabled: false
29 crashCollector:
30 disable: false
31 storage:
32 useAllNodes: false
33 useAllDevices: false
34 # 全局 NVMe 优化配置
35 config:
36 osdsPerDevice: "4" # 每块 8TB NVMe 创建 4 个 OSD,充分利用并行性
37 deviceClass: "nvme" # 显式指定设备类型,避免 Rook 自动检测不一致
38 metadataDevice: "" # 全 NVMe 场景无需独立元数据设备
39 nodes:
40 - name: "worker-01"
41 devices:
42 - name: "nvme0n1"
43 - name: "nvme1n1"
44 - name: "nvme2n1"
45 - name: "nvme3n1"
46 - name: "nvme4n1"
47 - name: "nvme5n1"
48 - name: "nvme6n1"
49 - name: "nvme7n1"
50 - name: "nvme8n1"
51 - name: "nvme9n1"
52 - name: "nvme10n1"
53 - name: "nvme11n1"
54 - name: "worker-02"
55 devices:
56 - name: "nvme0n1"
57 # ... 同样列出 12 块盘
58 # ... 其余 13 个 worker 节点同样列出 12 块盘
59 resources:
60 osd:
61 requests:
62 cpu: "4"
63 memory: "8Gi"
64 limits:
65 cpu: "8"
66 memory: "16Gi"
关键参数说明:
| 参数 | 值 | 说明 |
|---|---|---|
osdsPerDevice | "4" | 8TB NVMe 推荐值,4 个 OSD 分布在独立 LVM 逻辑卷上,减少锁竞争 |
deviceClass | "nvme" | 显式指定,确保 CRUSH 规则按 NVMe 设备类正确分类 |
osd.requests.cpu | "4" | NVMe OSD 需要更多 CPU 线程保持设备繁忙 |
osd.requests.memory | "8Gi" | 每 OSD 约 2GiB,为 BlueStore 缓存预留空间 |
应用配置:
1kubectl apply -f cluster.yaml
3.3 部署 Toolbox 并验证
1kubectl apply -f https://raw.githubusercontent.com/rook/rook/master/deploy/examples/toolbox.yaml
2
3# 等待 toolbox 就绪
4kubectl -n rook-ceph rollout status deploy/rook-ceph-tools
5
6# 检查集群健康状态
7kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- ceph status
8
9# 检查 OSD 树,确认每节点应有 48 个 OSD(12 盘 × 4 osdsPerDevice)
10kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- ceph osd tree
预期结果:每节点应显示 48 个 OSD 条目,设备类为 nvme,总共 720 个 OSD。
四、NVMe 专项性能调优
集群就绪后,通过 Toolbox 执行以下配置,将 NVMe 性能充分释放。
4.1 BlueStore 缓存优化
1# 增大 BlueStore 缓存至 8GB/OSD(NVMe 高并发随机读场景)
2kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- \
3 ceph config set osd bluestore_cache_size_ssd 8589934592
4
5# 设置最小分配大小为 4KB(匹配 NVMe 页大小,优化小 I/O)
6kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- \
7 ceph config set osd bluestore_min_alloc_size_ssd 4096
8
9# 禁用延迟写入(NVMe 直接写设备,避免 WAL 双写开销)
10kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- \
11 ceph config set osd bluestore_prefer_deferred_size_ssd 0
4.2 OSD 线程与 CPU 亲和性
1# 增加 OSD 操作分片和线程数(NVMe 需要更多 CPU 线程)
2kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- \
3 ceph config set osd osd_op_num_shards 16
4kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- \
5 ceph config set osd osd_op_num_threads_per_shard 4
6
7# 启用 NUMA 自动亲和
8kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- \
9 ceph config set osd osd_numa_auto_affinity true
4.3 恢复参数优化(NVMe 可承受更激进的重建)
1kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- \
2 ceph config set osd osd_recovery_max_active_ssd 10
3kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- \
4 ceph config set osd osd_max_backfills 8
5kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- \
6 ceph config set osd osd_recovery_sleep_ssd 0
7kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- \
8 ceph config set osd osd_backfill_scan_max 512
五、创建 StorageClass、PV、PVC 示例
5.1 创建 CephBlockPool(RBD 池)
先创建 NVMe 专用 CRUSH 规则:
1kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- \
2 ceph osd crush rule create-replicated nvme-rule default host nvme
创建 CephBlockPool:
1apiVersion: ceph.rook.io/v1
2kind: CephBlockPool
3metadata:
4 name: nvme-pool
5 namespace: rook-ceph
6spec:
7 failureDomain: host # 副本跨主机分布,节点故障不影响数据可用性
8 replicated:
9 size: 3 # 3 副本
10 parameters:
11 crush_rule: nvme-rule # 使用 NVMe 专用 CRUSH 规则
12 deviceClass: nvme
⚠️ 重要:如果在任何 Pool 上指定了
deviceClass,则必须在该集群的所有 Pool 上一致指定,以避免 CRUSH 根重叠警告和均衡器混乱。
应用:
1kubectl apply -f cephblockpool.yaml
5.2 创建 RBD StorageClass(RWO 块存储)
这是核心存储类,用于数据库等需要 RWO 卷的应用:
1apiVersion: storage.k8s.io/v1
2kind: StorageClass
3metadata:
4 name: rook-ceph-block
5 annotations:
6 storageclass.kubernetes.io/is-default-class: "true" # 设为默认 StorageClass
7provisioner: rook-ceph.rbd.csi.ceph.com
8parameters:
9 clusterID: rook-ceph
10 pool: nvme-pool
11 imageFormat: "2"
12 imageFeatures: layering,fast-diff,object-map,deep-flatten,exclusive-lock
13 # CSI Secrets
14 csi.storage.k8s.io/provisioner-secret-name: rook-csi-rbd-provisioner
15 csi.storage.k8s.io/provisioner-secret-namespace: rook-ceph
16 csi.storage.k8s.io/controller-expand-secret-name: rook-csi-rbd-provisioner
17 csi.storage.k8s.io/controller-expand-secret-namespace: rook-ceph
18 csi.storage.k8s.io/controller-publish-secret-name: rook-csi-rbd-provisioner
19 csi.storage.k8s.io/controller-publish-secret-namespace: rook-ceph
20 csi.storage.k8s.io/node-stage-secret-name: rook-csi-rbd-node
21 csi.storage.k8s.io/node-stage-secret-namespace: rook-ceph
22 # RBD 映射选项——NVMe 队列深度优化
23 mapOptions: "lock_on_read,queue_depth=1024"
24reclaimPolicy: Delete
25allowVolumeExpansion: true
26volumeBindingMode: Immediate
关键参数说明:
| 参数 | 值 | 说明 |
|---|---|---|
imageFeatures | layering,fast-diff,object-map,deep-flatten,exclusive-lock | 完整 RBD 功能集 |
mapOptions | lock_on_read,queue_depth=1024 | NVMe 队列深度优化,提升并发 I/O 性能 |
allowVolumeExpansion | true | 允许在线扩容 |
应用:
1kubectl apply -f storageclass-rbd.yaml
5.3 创建 CephFilesystem 和 CephFS StorageClass(RWX 共享存储)
创建 CephFilesystem:
1apiVersion: ceph.rook.io/v1
2kind: CephFilesystem
3metadata:
4 name: myfs
5 namespace: rook-ceph
6spec:
7 metadataPool:
8 replicated:
9 size: 3
10 dataPools:
11 - name: data0
12 replicated:
13 size: 3
14 parameters:
15 crush_rule: nvme-rule
16 preserveFilesystemOnDelete: true
17 metadataServer:
18 activeCount: 1
19 activeStandby: true
20 resources:
21 requests:
22 cpu: "2"
23 memory: "4Gi"
24 limits:
25 cpu: "4"
26 memory: "8Gi"
创建 CephFS StorageClass:
1apiVersion: storage.k8s.io/v1
2kind: StorageClass
3metadata:
4 name: rook-cephfs
5provisioner: rook-ceph.cephfs.csi.ceph.com
6parameters:
7 clusterID: rook-ceph
8 fsName: myfs
9 pool: myfs-data0
10 csi.storage.k8s.io/provisioner-secret-name: rook-csi-cephfs-provisioner
11 csi.storage.k8s.io/provisioner-secret-namespace: rook-ceph
12 csi.storage.k8s.io/controller-expand-secret-name: rook-csi-cephfs-provisioner
13 csi.storage.k8s.io/controller-expand-secret-namespace: rook-ceph
14 csi.storage.k8s.io/node-stage-secret-name: rook-csi-cephfs-node
15 csi.storage.k8s.io/node-stage-secret-namespace: rook-ceph
16reclaimPolicy: Delete
17allowVolumeExpansion: true
18volumeBindingMode: Immediate
应用:
1kubectl apply -f cephfilesystem.yaml
2kubectl apply -f storageclass-cephfs.yaml
5.4 创建 PVC 示例
RWO PVC(用于数据库、单实例应用):
1apiVersion: v1
2kind: PersistentVolumeClaim
3metadata:
4 name: my-database-pvc
5 namespace: default
6spec:
7 accessModes:
8 - ReadWriteOnce # RWO——单节点读写
9 storageClassName: rook-ceph-block
10 resources:
11 requests:
12 storage: 100Gi
RWX PVC(用于分布式多实例应用):
1apiVersion: v1
2kind: PersistentVolumeClaim
3metadata:
4 name: my-shared-pvc
5 namespace: default
6spec:
7 accessModes:
8 - ReadWriteMany # RWX——多节点同时读写
9 storageClassName: rook-cephfs
10 resources:
11 requests:
12 storage: 500Gi
应用并验证:
1kubectl apply -f pvc-rwo.yaml
2kubectl apply -f pvc-rwx.yaml
3
4# 验证 PVC 状态
5kubectl get pvc -A
6
7# 验证 PV 自动创建
8kubectl get pv
预期结果:PVC 状态应为 Bound,对应的 PV 由 CSI 驱动自动创建。
5.5 在 Pod 中使用 PVC
RWO 示例(数据库 Pod):
1apiVersion: v1
2kind: Pod
3metadata:
4 name: database-pod
5 namespace: default
6spec:
7 containers:
8 - name: mysql
9 image: mysql:8.0
10 env:
11 - name: MYSQL_ROOT_PASSWORD
12 value: "your-password"
13 volumeMounts:
14 - name: data
15 mountPath: /var/lib/mysql
16 volumes:
17 - name: data
18 persistentVolumeClaim:
19 claimName: my-database-pvc
RWX 示例(多实例共享):
1apiVersion: apps/v1
2kind: Deployment
3metadata:
4 name: shared-app
5 namespace: default
6spec:
7 replicas: 3 # 3 个实例共享同一个 RWX 卷
8 selector:
9 matchLabels:
10 app: shared-app
11 template:
12 metadata:
13 labels:
14 app: shared-app
15 spec:
16 containers:
17 - name: app
18 image: your-app:latest
19 volumeMounts:
20 - name: shared-data
21 mountPath: /data
22 volumes:
23 - name: shared-data
24 persistentVolumeClaim:
25 claimName: my-shared-pvc
六、部署后验证与监控
6.1 集群健康检查
1# 集群整体状态(应显示 HEALTH_OK)
2kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- ceph status
3
4# OSD 树(每节点应有 48 个 OSD)
5kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- ceph osd tree
6
7# 存储池状态
8kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- ceph df
9
10# PG 状态(所有 PG 应处于 active+clean)
11kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- ceph pg stat
6.2 性能基准测试
1# RBD 随机写基准(4K 块,60 秒)
2kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- \
3 rados -p nvme-pool bench 60 write -b 4096 --no-cleanup
4
5# RBD 随机读基准
6kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- \
7 rados -p nvme-pool bench 60 rand
6.3 部署 Dashboard
Dashboard 已在 cluster.yaml 中启用(dashboard.enabled: true)。获取访问方式:
1kubectl -n rook-ceph get service rook-ceph-mgr-dashboard
七、生产环境注意事项
7.1 网络规划
- 建议为 Ceph 配置专用网络(
publicNetwork和clusterNetwork),将 OSD 复制流量与业务 Pod 网络隔离。1.44PB 的全 NVMe 集群,复制流量巨大,与 Pod 网络共享会导致业务抖动。 - 建议使用 25GbE+ 网络,NVMe OSD 的吞吐能力远超万兆网络瓶颈。
- 如果使用 Jumbo Frame(MTU 9000),需要在所有节点和交换机上一致配置。
7.2 MON 和 MGR 节点选择
- MON 节点应分布在 3 个不同的物理节点上,且这些节点应尽量独立于故障域(如不同机架)。
- MGR 节点建议与 MON 节点错开部署,避免单节点故障同时影响 MON 和 MGR。
7.3 PG 数量规划
对于 720 个 OSD 的集群,pg_autoscaler 已启用,会自动根据 Pool 容量和使用情况调整 PG 数量。初始阶段 PG 数可能较少,随着数据写入会自动扩展。不要手动设置过大的 pg_num,让自动缩放器管理即可。
7.4 节点故障恢复
- 单节点故障:720 OSD 中 48 个 OSD 离线(6.7%),3 副本情况下数据仍然可用,Ceph 会自动在其他节点重建数据。
- NVMe 恢复参数已优化(
osd_recovery_max_active_ssd: 10),重建速度会比默认配置快数倍。 - 建议监控
ceph status中的 recovery 进度,确保重建在合理时间内完成。
7.5 硬件选型注意事项
不推荐 RAID 控制器:Ceph 自身提供副本,RAID 会降低性能并导致故障定位困难。推荐使用 HBA 直通模式将 NVMe 盘直接暴露给 OSD。
八、完整部署顺序总结
| 步骤 | 操作 | 命令/文件 |
|---|---|---|
| 1 | 节点准备(内核模块、擦盘、NVMe 调优) | 各节点执行 |
| 2 | 安装 Rook Operator | helm install rook-ceph |
| 3 | 部署 Ceph Cluster | kubectl apply -f cluster.yaml |
| 4 | 部署 Toolbox 并验证集群 | kubectl apply -f toolbox.yaml |
| 5 | NVMe 性能调优(BlueStore、线程、恢复) | ceph config set 系列命令 |
| 6 | 创建 CRUSH 规则 | ceph osd crush rule create-replicated |
| 7 | 创建 CephBlockPool | kubectl apply -f cephblockpool.yaml |
| 8 | 创建 RBD StorageClass | kubectl apply -f storageclass-rbd.yaml |
| 9 | 创建 CephFilesystem 和 CephFS StorageClass | kubectl apply -f cephfilesystem.yaml storageclass-cephfs.yaml |
| 10 | 创建 PVC 并测试 | kubectl apply -f pvc-rwo.yaml pvc-rwx.yaml |
| 11 | 性能基准测试 | rados bench |
按照以上步骤执行,15 节点全 NVMe 的 Rook-Ceph 集群即可投入生产使用,同时提供 RWO 块存储和 RWX 共享文件存储,满足分布式多实例应用的需求。
