Kubernetes Rook-Ceph 高可用存储部署文档
1. 部署前置条件
-
裸盘准备 :Ceph 需要在工作节点(Worker Nodes)上拥有未格式化的裸盘(Raw Devices)或独立的分区。例如
/dev/sdb、/dev/nvme0n1。这些磁盘不能有任何文件系统。如何检查磁盘是否可用?
在目标节点上执行
lsblk -f命令。- 可用(裸盘) :
FSTYPE列为空,且MOUNTPOINT为空。 - 不可用 :
FSTYPE列显示 ext4/xfs 等,或者已被挂载。
如果磁盘有残留的文件系统签名,可以使用
wipefs -a /dev/sdX(替换为实际盘符) 进行擦除。 - 可用(裸盘) :
-
内核模块与依赖 :所有 K8s 节点需要安装
lvm2包。bash# Ubuntu/Debian sudo apt-get update sudo apt-get install -y lvm2 # 临时加载 rbd 模块 sudo modprobe rbd # 配置开机自动加载 rbd 模块 echo "rbd" | sudo tee /etc/modules-load.d/rbd.conf -
资源要求:Ceph 对内存和 CPU 消耗较大,建议每个 OSD(对应一块硬盘)预留 2GB 内存。
2. 下载 Rook 源码
根据 Kubernetes v1.35 的兼容性要求,我们这里选择支持该 K8s 版本的 v1.19 版本进行部署。
bash
git clone --single-branch --branch v1.19.6 https://github.com/rook/rook.git
cd rook/deploy/examples
3. 部署 Rook Operator
Operator 是管理 K8s 中 Ceph 集群生命周期的核心控制器。
bash
# 1. 创建 CRD、RBAC 权限以及 CSI (容器存储接口) 依赖
kubectl create -f crds.yaml -f common.yaml -f csi-operator.yaml
# 2. 部署 Operator 控制器
kubectl create -f operator.yaml
# 3. 检查 Operator 状态 (等待其变为 Running)
kubectl -n rook-ceph get pod
注意 (国内环境加速) :如果你的集群拉取
registry.k8s.io的 csi 镜像困难,可以修改operator.yaml中的ROOK_CSI_*_IMAGE环境变量地址,将其替换为阿里云或 DaoCloud 的镜像源(例如k8s.m.daocloud.io/sig-storage/csi-provisioner:v3.6.0)。
4. 部署 Ceph 集群
创建 Ceph 集群实例。默认配置的 cluster.yaml 中,Rook 会自动寻找所有节点上未格式化的裸盘并将其加入 Ceph 集群。
注意 (指定磁盘加入 Ceph) :如果不希望 Rook 自动接管所有裸盘,可以在执行部署前修改
cluster.yaml文件中的storage配置块:
yamlspec: storage: useAllNodes: false # 关闭自动使用所有节点 useAllDevices: false # 关闭自动使用所有设备 nodes: - name: "node1" # 填入 K8s 节点名称 devices: - name: "sdb" # 指定磁盘名称 (不带 /dev/) - name: "nvme0n1" - name: "node2" devices: - name: "sdc"注意 (开启 HostNetwork 模式) :为了获得更好的存储网络性能,或者需要将存储暴露给外部 K8s 集群使用,建议在执行部署前修改
cluster.yaml文件开启主机网络模式。打开
cluster.yaml,找到network配置块并修改为provider: host:
yamlspec: network: provider: host
bash
kubectl create -f cluster.yaml
观察集群部署过程:
这是一个需要耐心的过程,Rook 会依次启动 mon (监视器)、mgr (管理器)、osd (对象存储守护进程) 等组件。
bash
# 实时查看 pod 状态
kubectl -n rook-ceph get pod -w
当看到类似 rook-ceph-osd-0-xxx、rook-ceph-osd-1-xxx 的 Pod 处于 Running 状态时,说明物理磁盘已经成功挂载并初始化为 OSD。
5. 验证 Ceph 集群状态 (Toolbox)
为了查看 Ceph 内部的详细状态,我们需要部署 Toolbox 工具容器。
bash
# 部署 toolbox
kubectl create -f toolbox.yaml
# 等待 toolbox 启动后,进入容器
kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- bash
# 在容器内执行命令查看集群健康状况
ceph status
# 查看磁盘 (OSD) 状态
ceph osd status
如果 ceph status 显示 health: HEALTH_OK,则证明 Ceph 集群非常健康。
6. 配置存储类 (StorageClass)
为了让 K8s 能够通过 PVC 动态分配存储,我们需要配置 StorageClass。Ceph 主要提供块存储 (RBD) 和 文件存储 (CephFS)。
6.1 配置块存储 (RBD) - 适用于 MySQL/Redis 等单点高IO服务
进入 csi/rbd 目录:
bash
cd csi/rbd
应用 storageclass.yaml,它包含两部分:创建一个 CephBlockPool(存储池)和一个 StorageClass。
bash
kubectl create -f storageclass.yaml
查看 StorageClass:
bash
kubectl get sc
# 你应该能看到名为 rook-ceph-block 的存储类被创建出来了,通常你可以将其设置为默认存储类。
6.2 配置共享文件存储 (CephFS) - 适用于多 Pod 共享目录
步骤 1:切换到正确的目录
在 Rook v1.19 版本中,我们需要回到 examples 根目录来执行操作。
bash
cd ~/rook/deploy/examples
步骤 2:创建 Ceph 文件系统底层资源 (CephFilesystem)
bash
kubectl create -f filesystem.yaml
步骤 3:验证 MDS 服务是否启动
CephFS 依赖 Metadata Server (MDS) 来管理文件元数据。执行以下命令,等待 Pod 状态变为 Running。
bash
kubectl -n rook-ceph get pod -l app=rook-ceph-mds -w
步骤 4:创建对应的 StorageClass
当 MDS 正常运行后,创建 K8s 的存储类,以便后续可以通过 PVC 动态申请文件存储。
bash
kubectl create -f csi/cephfs/storageclass.yaml
6.3 配置对象存储 (Object Storage) - 适用于 S3 兼容的文件上传下载
功能说明 :对象存储网关(RGW)提供与 AWS S3 完全兼容的 API。如果你有图片服务器、备份归档、前端附件直传等需求,可以开启此功能。如果你只需要常规的持久化卷(PVC),则无需开启,可以直接跳过此步骤。
(注意:在 Dashboard 中点击 Object 菜单提示 The Object Gateway Service is not configured 属于正常现象,仅代表未开启此服务,不影响集群健康。)
步骤 1:创建 CephObjectStore 资源
这会启动 RGW 服务并在底层的 Ceph 中划出对应的存储池。
bash
cd ~/rook/deploy/examples
kubectl create -f object.yaml
步骤 2:验证 RGW 服务是否启动
等待 RGW Pod 变为 Running 状态,并且服务已暴露。
bash
kubectl -n rook-ceph get pod -l app=rook-ceph-rgw -w
kubectl -n rook-ceph get svc rook-ceph-rgw-my-store
步骤 3:创建对应的 StorageClass
bash
kubectl create -f storageclass-bucket-delete.yaml
如何关闭并彻底清理对象存储?
如果你测试后发现不需要对象存储,或者它占用了过多的内存资源,可以随时将其关闭:
bash# 1. 删除对象存储实例和 StorageClass(这会停止所有 RGW Pod) kubectl delete -f object.yaml kubectl delete -f storageclass-bucket-delete.yaml # 2. 进入 Toolbox,彻底清理遗留的底层存储池释放磁盘空间 kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- bash ceph osd pool ls | grep my-store | xargs -I {} ceph osd pool delete {} {} --yes-i-really-really-mean-it exit
7. 测试存储动态供应
我们创建一个 PVC (PersistentVolumeClaim) 来测试块存储是否工作正常。
创建一个 test-pvc.yaml 文件:
yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: rbd-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: rook-ceph-block
执行创建:
bash
kubectl apply -f test-pvc.yaml
kubectl get pvc rbd-pvc
如果状态显示为 Bound,说明 Rook-Ceph 的动态存储供应工作完全正常。
8. 暴露 Ceph Dashboard (可视化监控面板)
Rook 默认开启了 Ceph 的 Dashboard。为了方便在集群外部访问,我们可以通过 NodePort 将其暴露出来。
创建一个 dashboard-nodeport.yaml:
yaml
apiVersion: v1
kind: Service
metadata:
name: rook-ceph-mgr-dashboard-nodeport
namespace: rook-ceph
labels:
app: rook-ceph-mgr
rook_cluster: rook-ceph
spec:
ports:
- name: dashboard
port: 8443
protocol: TCP
targetPort: 8443
nodePort: 30844 # 自定义 30000-32767 之间的端口
selector:
app: rook-ceph-mgr
rook_cluster: rook-ceph
type: NodePort
应用配置:
bash
kubectl apply -f dashboard-nodeport.yaml
验证 Dashboard 服务是否就绪:
bash
kubectl -n rook-ceph get svc rook-ceph-mgr-dashboard-nodeport
如果你看到输出结果中的 PORT(S) 列显示了 8443:30844/TCP,说明服务已经成功映射。
现在可以通过浏览器访问 https://<任意工作节点IP>:30844 进入面板。
获取 Dashboard 的默认登录密码 (用户名为 admin):
bash
kubectl -n rook-ceph get secret rook-ceph-dashboard-password -o jsonpath="{['data']['password']}" | base64 --decode && echo
9. 配置监控与报警 (Prometheus/Grafana)
Rook-Ceph 原生支持被 Prometheus 抓取监控指标(Metrics)。只要你的 Kubernetes 集群中部署了 Prometheus Operator(如 kube-prometheus-stack),就可以轻松接入。
9.1 开启 Rook 监控配置
在部署 Ceph 集群时,监控功能需要明确开启。请打开 cluster.yaml,找到 monitoring 配置块并确保它被启用:
yaml
spec:
monitoring:
enabled: true
# 如果你的 prometheus-operator 部署在其他 namespace,可能需要指定 label 或 namespace
修改后,执行 kubectl apply -f ~/rook/deploy/examples/cluster.yaml 更新集群配置。
注意:如果 ServiceMonitor 没有自动创建或需要补充创建
在 Rook v1.19 版本中,除了基础的 MGR 监控,还需要创建 Exporter 和 CSI 的监控入口。
请手动执行以下命令补齐所有的 ServiceMonitor:
bashcd ~/rook/deploy/examples kubectl create -f monitoring/service-monitor.yaml kubectl create -f monitoring/exporter-service-monitor.yaml kubectl create -f monitoring/csi-metrics-service-monitor.yaml为 ServiceMonitor 打标签 (重要!)
默认情况下,使用 Helm 安装的 Prometheus(如
kube-prometheus-stack)只抓取带有特定标签的资源。
先确认你的 Prometheus 需要什么标签:
kubectl -n monitoring get prometheus -o jsonpath='{.items[0].spec.serviceMonitorSelector}'
(假设输出为{"matchLabels":{"release":"prometheus-stack"}})给刚才创建的所有监控资源打上标签:
bashkubectl -n rook-ceph label servicemonitor rook-ceph-mgr release=prometheus-stack kubectl -n rook-ceph label servicemonitor rook-ceph-exporter release=prometheus-stack kubectl -n rook-ceph label servicemonitor csi-metrics release=prometheus-stack
9.2 验证指标抓取
执行以下命令检查 ServiceMonitor 是否成功创建:
bash
kubectl -n rook-ceph get servicemonitor
如果输出包含 rook-ceph-mgr、rook-ceph-exporter 等资源,说明配置已下发。
如何确认 Prometheus 已经成功抓取数据?
打完标签后,等待约 1-2 分钟。
- 打开 Prometheus 网页端 UI。
- 点击顶部菜单的 Status -> Targets。
- 在页面中搜索
ceph。 - 如果能看到名为
rook-ceph/rook-ceph-mgr/...和rook-ceph/rook-ceph-exporter/...的抓取目标,并且它们的状态是绿色的UP,那就说明 Prometheus 已经成功连上 Ceph 并开始抓取监控数据了。
(注:如果搜索时没有看到csi-metrics,属于正常现象。这通常是因为当前集群还没有实际使用存储卷,或者特定版本的配置差异,完全不影响 Ceph 核心健康状态的监控和报警。)
9.3 配置 Grafana 监控面板
Rook 官方提供了现成的 Grafana 仪表盘(Dashboard)模板,可以直接导入到你的 Grafana 中:
- 访问 Rook 官方 GitHub 仓库的 Grafana 模板目录:
Rook Ceph Grafana Dashboards (v1.19) - 你会在该目录下看到以下核心 JSON 文件:
ceph-cluster.json:集群高级监控(推荐)ceph-osd.json:单块磁盘(OSD)详情ceph-pools.json:存储池监控
- 登录你的 Grafana 页面,点击左侧菜单的 Dashboards -> New -> Import。
- 将上述 JSON 文件的内容复制粘贴到输入框中,或者上传文件,选择对应的 Prometheus 数据源,点击导入即可看到图表。
9.4 配置报警规则 (PrometheusRules)
为了在 Ceph 出现故障(如 OSD 宕机、容量快满)时及时收到通知,我们需要配置 Prometheus 的报警规则。
Rook 同样提供了标准的报警规则配置文件。在 v1.19 版本中,默认的本地报警规则文件名为 localrules.yaml。在 examples 目录下执行:
bash
cd ~/rook/deploy/examples
kubectl create -f monitoring/localrules.yaml
注意:如何让 Prometheus Operator 识别到这些规则?
默认情况下,使用 Helm 安装的
kube-prometheus-stack对抓取规则有严格的标签要求。如果应用了localrules.yaml后,在 Prometheus 的 Alerts 页面看不到 Ceph 相关的报警,通常是因为规则没有打上正确的标签。解决方法 A:给规则打标签(推荐)
给刚创建的规则打上 Prometheus Operator 要求的
release标签。(如果你不确定自己的 Prometheus 需要什么标签,可以通过以下命令查看 Prometheus CRD 的配置:
kubectl -n monitoring get prometheus -o jsonpath='{.items[0].spec.ruleSelector}'如果输出形如
{"matchLabels":{"release":"prometheus-stack"}},说明需要的标签是release=prometheus-stack。)
bashkubectl -n rook-ceph label prometheusrules prometheus-ceph-rules release=prometheus-stack打完标签后,等待约 1-2 分钟,刷新 Prometheus 页面,即可看到 Ceph 报警规则出现。
解决方法 B:修改 Prometheus 配置实现全局抓取(备选)
如果你不希望每次创建规则都手动打标签,可以修改 Prometheus 的配置,让它放宽限制,抓取集群内所有的规则。
bash# 找到并编辑你的 Prometheus 实例(假设在 monitoring 命名空间) kubectl -n monitoring edit prometheus在打开的编辑器中,找到
spec部分,将ruleNamespaceSelector和ruleSelector的值都修改为{}:
yamlspec: ruleNamespaceSelector: {} ruleSelector: {}保存退出后,Prometheus 会自动重载配置,扫描并加载所有命名空间中的报警规则。
如何查看报警规则是否生效?
执行命令后,可以通过以下两种方式验证:
- 通过 K8s 命令行查看 :
执行kubectl -n rook-ceph get prometheusrules,如果能看到名为prometheus-ceph-rules的资源,说明规则已成功加载到 K8s 中。 - 通过 Prometheus 界面查看(最直观) :
打开你的 Prometheus 网页 UI,点击顶部菜单的 Alerts (报警)页面。你应该能看到几十条以Ceph开头的报警规则(如CephHealthError、CephOSDDown等)被列出。如果它们处于绿色的Inactive状态,说明规则已生效且当前集群没有触发该报警。
常见的默认报警项包括:
CephHealthError:Ceph 集群处于 ERROR 状态CephHealthWarning:Ceph 集群处于 WARN 状态CephOSDDown:有一块或多块 OSD 磁盘离线CephClusterNearFull:集群存储容量即将耗尽(默认 85% 触发)CephPGsInactive:有归置组(PG)处于非活跃状态,可能导致数据不可读写
配置完成后,当满足触发条件时,报警信息会发送到 Prometheus 的 Alertmanager,你可以通过 Alertmanager 将报警推送到钉钉、企业微信、邮件或飞书等渠道。
10. 常见问题排查 (FAQ)
10.1 Dashboard 中点击特定菜单(如 NVMe/TCP)提示未知任务报错
现象 :成功登录 Dashboard 后,在左侧菜单栏点击 Block -> NVMe/TCP 等特定功能时,右下角弹出红色错误提示 无法执行 未知任务 Unable to retrieve the gateway info: cannot unpack non-iterable NoneType object,同时 mgr 日志中出现对应报错。
原因:这是 Ceph (v19.2.3 Squid 等版本) 的 Dashboard 前端已知 Bug。当你点击特定菜单时,前端会去请求相应的网关后端接口(如 NVMe-oF)。因为我们集群中并没有部署这些多余的网关服务,后端返回空数据,前端没有做良好的空值捕获,从而直接抛出了该异常。
解决方法 :这是一个纯粹的界面展示层报错。
- 该报错完全不会影响 Ceph 集群的任何核心存储、读写、监控功能。
- 目前不需要进行任何修复操作,只需直接点击报错框的关闭按钮(或忽略它),并且在日常运维中避免点击
NVMe/TCP等未启用的功能菜单即可。其他诸如 Cluster、OSDs、Pools 等监控菜单均可正常使用。
10.2 Ceph 状态显示 HEALTH_WARN: TOO_MANY_PGS: too many PGs per OSD
现象 :执行 ceph status 或在 Dashboard 中看到报警,提示每个 OSD 承载的归置组 (PG) 数量过多(例如 265 > max 250)。
原因:创建了过多的存储池(如同时开启了块存储、文件存储、对象存储),或者集群中物理硬盘 (OSD) 数量较少。导致平摊到每块硬盘上的 PG 数量超过了 Ceph 的默认安全上限(250),这会增加 OSD 的内存和 CPU 消耗。
解决方法 :
方法一:开启 PG 自动伸缩(推荐)
让 Ceph 根据实际数据量自动合并多余的空闲 PG。
- 进入 Toolbox 容器:
kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- bash - 检查并确保自动伸缩模块已开启:
ceph mgr module enable pg_autoscaler - 查看当前存储池状态:
ceph osd pool autoscale-status - 将报警的存储池(或所有池)的伸缩模式设置为
on:ceph osd pool set <池名称> pg_autoscale_mode on
(注意:设置完成后,Ceph 会在后台缓慢自动合并 PG,可能需要几十分钟后报警才会消失。)
方法二:调高报警阈值(临时屏蔽)
如果你只是处于测试环境,或者确认硬件性能足够,急需消除这个报警,可以直接调高 Ceph 的单盘 PG 报警线。
-
进入 Toolbox 容器:
kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- bash -
执行以下命令将阈值从默认的 250 调高至 300(或更高):
bashceph config set global mon_pg_warn_max_per_osd 300
(执行后报警会立刻消失,但此方法治标不治本,建议最终还是通过自动伸缩来解决。)
10.3 报警提示:The scrape job for Ceph Exporter is missing from Prometheus
现象 :Prometheus 已经加载了报警规则,但在 Alerts 页面出现此报警,且 Grafana 面板没有数据。
原因 :Prometheus 找不到用于抓取 Ceph 数据的 ServiceMonitor 资源。
解决方法 :
请返回本文档的 9.1 节 ,仔细检查是否漏做了"补充创建所有的 ServiceMonitor"以及"为 ServiceMonitor 打标签"这两个步骤。只要补齐资源并打上正确的标签,Prometheus 即可自动发现目标并开始抓取数据,报警会自动消除。(如果在 Prometheus Targets 中未看到 csi-metrics 属于正常现象,只需确保 mgr 和 exporter 处于 UP 状态即可)。