Kubernetes Rook-Ceph 高可用存储部署文档
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包。# 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 版本进行部署。
git clone --single-branch --branch v1.19.6 https://github.com/rook/rook.git
cd rook/deploy/examples
3. 部署 Rook Operator
Operator 是管理 K8s 中 Ceph 集群生命周期的核心控制器。
# 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配置块:spec: storage: useAllNodes: false # 关闭自动使用所有节点 useAllDevices: false # 关闭自动使用所有设备 nodes: - name: "master-01" # 填入 K8s 节点名称 devices: - name: "vdb" # 指定磁盘名称 (不带 /dev/) - name: "master-02" devices: - name: "vdb" - name: "master-03" devices: - name: "vdb"注意 (开启 HostNetwork 模式):为了获得更好的存储网络性能,或者需要将存储暴露给外部 K8s 集群使用,建议在执行部署前修改
cluster.yaml文件开启主机网络模式。
打开cluster.yaml,找到network配置块并修改为provider: host:spec: network: provider: host dashboard: enabled: true port: 8444 # 强烈建议将默认的 8443 改为 8444,防止与 Ingress Controller 的 Webhook 端口冲突
kubectl create -f cluster.yaml
观察集群部署过程:
这是一个需要耐心的过程,Rook 会依次启动 mon (监视器)、mgr (管理器)、osd (对象存储守护进程) 等组件。
# 实时查看 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 工具容器。
# 确保在 examples 目录下执行
cd ~/rook/deploy/examples
# 部署 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 目录:
cd ~/rook/deploy/examples/csi/rbd
应用 storageclass.yaml,它包含两部分:创建一个 CephBlockPool(存储池)和一个 StorageClass。
# 1. 创建默认的 Delete 策略存储类 (以及底层存储池)
kubectl apply -f storageclass.yaml
# 2. 复制并创建一个 Retain 策略的存储类 (适合生产环境核心数据防误删)
sed -e 's/name: rook-ceph-block/name: rook-ceph-block-retain/' \
-e 's/reclaimPolicy: Delete/reclaimPolicy: Retain/' \
storageclass.yaml | kubectl apply -f -
查看 StorageClass:
kubectl get sc | grep block
你应该能同时看到 rook-ceph-block 和 rook-ceph-block-retain 两个选项。
设置默认存储类(推荐):
为了让开发人员在创建 PVC 时(如果没有显式指定 storageClassName)也能自动分配存储,建议将最常用的块存储(这里我们以默认的 rook-ceph-block 为例,你也可以设为 retain 版本)设置为整个 K8s 集群的默认存储类:
kubectl patch storageclass rook-ceph-block -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
执行后,再次运行 kubectl get sc,你就会看到 rook-ceph-block 变成了 rook-ceph-block (default)。
6.2 配置共享文件存储 (CephFS) - 适用于多 Pod 共享目录
步骤 1:切换到正确的目录
在 Rook v1.19 版本中,我们需要回到 examples 根目录来执行操作。
cd ~/rook/deploy/examples/
步骤 2:创建 Ceph 文件系统底层资源 (CephFilesystem)
kubectl create -f filesystem.yaml
步骤 3:验证 MDS 服务是否启动
CephFS 依赖 Metadata Server (MDS) 来管理文件元数据。执行以下命令,等待 Pod 状态变为 Running。
kubectl -n rook-ceph get pod -l app=rook-ceph-mds -w
步骤 4:创建对应的 StorageClass
当 MDS 正常运行后,创建 K8s 的存储类,以便后续可以通过 PVC 动态申请文件存储。
cd ~/rook/deploy/examples/csi/cephfs
# 1. 创建默认的 Delete 策略存储类
kubectl apply -f storageclass.yaml
# 2. 复制并创建一个 Retain 策略的存储类 (适合生产环境共享数据防误删)
sed -e 's/name: rook-cephfs/name: rook-cephfs-retain/' \
-e 's/reclaimPolicy: Delete/reclaimPolicy: Retain/' \
storageclass.yaml | kubectl apply -f -
步骤 5:验证 CephFS 是否就绪
检查集群中是否成功创建了相关的 StorageClass:
kubectl get sc | grep cephfs
如果列表中出现了 rook-cephfs 和 rook-cephfs-retain,说明文件存储的分配通道已经打通。业务 Pod 可以根据数据的重要程度,通过指定 storageClassName 来申请多读多写(RWX)的共享存储卷了。
6.3 配置对象存储 (Object Storage) - 适用于 S3 兼容的文件上传下载
功能说明:对象存储网关(RGW)提供与 AWS S3 完全兼容的 API。如果你有图片服务器、备份归档、前端附件直传等需求,可以开启此功能。如果你只需要常规的持久化卷(PVC),则无需开启,可以直接跳过此步骤。
(注意:在 Dashboard 中点击 Object 菜单提示 The Object Gateway Service is not configured 属于正常现象,仅代表未开启此服务,不影响集群健康。)
步骤 1:修改并创建 CephObjectStore 资源
这会启动 RGW 服务并在底层的 Ceph 中划出对应的存储池。
进入配置目录:
cd ~/rook/deploy/examples
注意 (避免 80 端口冲突):
当集群开启了 HostNetwork 模式时,RGW 服务默认的 80 端口会与集群中的 Ingress 控制器 (如 Higress 或 Nginx) 发生冲突,导致 RGW Pod 启动失败。因此在部署前,请编辑 object.yaml,将其中的端口修改为 8080:
# vim object.yaml
spec:
gateway:
port: 8080 # 建议将默认的 80 修改为 8080
instances: 1 # 启动 RGW 网关 Pod 的副本数。1 代表单节点提供服务;如果为了高可用和负载均衡,可根据节点数适当增加(如 2 或 3)
修改完成后,执行部署:
kubectl create -f object.yaml
(注:如果之前已经部署了默认的 80 端口,可以通过以下命令在线热修改:)
kubectl patch CephObjectStore my-store -n rook-ceph --type merge -p '{"spec":{"gateway":{"port":8080}}}'
步骤 2:验证 RGW 服务是否启动
等待 RGW Pod 变为 Running 状态,并且服务已暴露。
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
(注:Rook 官方示例提供了两个文件,建议同时创建。测试环境或临时桶可使用 delete 策略(删除 OBC 时自动删除底层 Bucket),生产环境务必使用 retain 策略(删除 OBC 时保留底层 Bucket 及数据,防止误删)。)
# 创建 delete 策略的 StorageClass (适合测试)
kubectl create -f storageclass-bucket-delete.yaml
# 创建 retain 策略的 StorageClass (适合生产,强烈推荐)
kubectl create -f storageclass-bucket-retain.yaml
步骤 4:验证对象存储配置是否就绪
通过以下命令检查集群中是否成功创建了对象存储相关的 StorageClass:
kubectl get sc | grep bucket
如果能看到 rook-ceph-delete-bucket 和 rook-ceph-retain-bucket 这两个 StorageClass,就代表对象存储通道配置成功。后续业务 Pod 可以根据重要程度,指定对应的 StorageClass 动态创建 Bucket(对应 Kubernetes 的 ObjectBucketClaim 资源)并获取访问 S3 的 AK/SK 凭证了。
如何关闭并彻底清理对象存储?
如果你测试后发现不需要对象存储,或者它占用了过多的内存资源,可以随时将其关闭:# 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. 部署测试应用与验证动态供应
7.1 测试块存储 (RBD)
我们创建一个 PVC (PersistentVolumeClaim) 来测试块存储是否工作正常。
创建一个 test-pvc.yaml 文件:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: rbd-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
# storageClassName: rook-ceph-block # 由于已设置默认存储类,这里可省略
执行创建:
kubectl apply -f test-pvc.yaml
kubectl get pvc rbd-pvc
如果状态显示为 Bound,说明 Rook-Ceph 的动态存储供应工作完全正常。
7.2 关于 Retain (保留) 策略的数据清理指南
在生产环境中,我们强烈建议使用 Retain 回收策略的 StorageClass。当业务 Pod 和 PVC(或 OBC)被删除时,底层的 Ceph 数据不会被自动销毁,以防误删导致灾难。
当你确认不再需要这些废弃数据并希望释放存储空间时,请按以下方法手动清理:
清理块存储 (RBD) 或文件存储 (CephFS) 遗留数据:
- 找出状态为
Released(已释放)的闲置 PV:kubectl get pv | grep Released - 手动删除该 PV(注意:执行此操作后,CSI 插件会自动去底层 Ceph 中彻底抹除对应的真实数据):
kubectl delete pv <找到的_PV_名称>
清理对象存储 (RGW Bucket) 遗留数据:
当删除 Retain 策略的 ObjectBucketClaim (OBC) 后,底层的桶依然存在。你有两种方式彻底销毁它:
- 方式一(推荐,图形化):登录 Ceph Dashboard -> Object -> Buckets,找到不需要的桶,点击 Delete,并勾选“Delete all objects inside the bucket”。
- 方式二(命令行):进入 toolbox 容器,使用管理命令强行清除桶及内部所有对象:
kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- bash radosgw-admin bucket rm --bucket=<残留的桶名称> --purge-objects
8. 暴露 Ceph Dashboard (可视化监控面板)
Rook 默认开启了 Ceph 的 Dashboard。为了方便在集群外部访问,你有两种方式:
- 方式一:使用 Ingress 配置域名访问(推荐)
这种方式更优雅,支持配置标准域名(如ceph.aioil.top)并可配合 Cert-Manager 自动签发合法的 HTTPS 证书,无需记忆端口号。 - 方式二:使用 NodePort 直接暴露端口(备选方案)
如果你的集群尚未安装 Ingress 控制器,或者仅仅是内部临时测试不想配置域名,可以使用 NodePort 方式,通过IP:端口的形式访问。
8.1 方式一:使用 Ingress 暴露 (推荐)
Rook 会创建一个名为 rook-ceph-mgr-dashboard 的 Service。由于 Dashboard 默认启用 SSL(HTTPS),我们需要在 Ingress 中配置对应的注解让其正确转发。
创建一个 dashboard-ingress.yaml 文件:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: rook-ceph-dashboard
namespace: rook-ceph
annotations:
# 告诉 Ingress Controller 后端使用的是 HTTPS 协议
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
# 如果使用 cert-manager 自动签发证书,请务必同时取消下方 cluster-issuer 和 spec.tls 部分的注释
# cert-manager.io/cluster-issuer: "letsencrypt-prod-dns"
spec:
ingressClassName: higress # 根据实际情况修改为 higress 或 nginx
# 如果取消了上方 cluster-issuer 的注释,这里也必须取消注释,以指定证书域名和存储位置
# tls:
# - hosts:
# - ceph.aioil.top
# secretName: ceph-dashboard-tls
rules:
- host: ceph.aioil.top
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: rook-ceph-mgr-dashboard
port:
number: 8444 # 与 cluster.yaml 中配置的端口保持一致
应用该配置:
kubectl apply -f dashboard-ingress.yaml
如果开启了自动申请证书(解开了 cert-manager 和 tls 的注释),可以通过以下命令查看证书申请状态:
# 查看证书资源的状态,等待 READY 变为 True
kubectl get certificate ceph-dashboard-tls -n rook-ceph
# 如果长时间未就绪,可查看详细事件排查原因
kubectl describe certificate ceph-dashboard-tls -n rook-ceph
部署完成后,即可通过配置的域名访问 Ceph 的可视化管理面板。默认用户名为 admin,密码可以通过以下命令获取:
kubectl -n rook-ceph get secret rook-ceph-dashboard-password -o jsonpath="{['data']['password']}" | base64 --decode && echo
8.2 方式二:使用 NodePort 暴露 (备选)
创建一个 dashboard-nodeport.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: 8444
protocol: TCP
targetPort: 8444
nodePort: 30844 # 自定义 30000-32767 之间的端口
selector:
app: rook-ceph-mgr
rook_cluster: rook-ceph
type: NodePort
应用配置:
kubectl apply -f dashboard-nodeport.yaml
验证 Dashboard 服务是否就绪:
kubectl -n rook-ceph get svc rook-ceph-mgr-dashboard-nodeport
如果你看到输出结果中的 PORT(S) 列显示了 8444:30844/TCP,说明服务已经成功映射。
现在可以通过浏览器访问 https://<任意工作节点IP>:30844 进入面板。
(获取密码的命令见 8.1 节末尾)
9. 配置监控与报警 (Prometheus/Grafana)
Rook-Ceph 原生支持被 Prometheus 抓取监控指标(Metrics)。只要你的 Kubernetes 集群中部署了 Prometheus Operator(如 kube-prometheus-stack),就可以轻松接入。
9.1 开启 Rook 监控配置
在部署 Ceph 集群时,监控功能需要明确开启。请打开 cluster.yaml,找到 monitoring 配置块并确保它被启用:
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:cd ~/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"}})- 给刚才创建的所有监控资源打上标签:
kubectl -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 是否成功创建:
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 目录下执行:
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。)kubectl -n rook-ceph label prometheusrules prometheus-ceph-rules release=prometheus-stack打完标签后,等待约 1-2 分钟,刷新 Prometheus 页面,即可看到 Ceph 报警规则出现。
解决方法 B:修改 Prometheus 配置实现全局抓取(备选)
如果你不希望每次创建规则都手动打标签,可以修改 Prometheus 的配置,让它放宽限制,抓取集群内所有的规则。# 找到并编辑你的 Prometheus 实例(假设在 monitoring 命名空间) kubectl -n monitoring edit prometheus在打开的编辑器中,找到
spec部分,将ruleNamespaceSelector和ruleSelector的值都修改为{}:spec: 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(或更高):
ceph 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 状态即可)。
11. 实战演练:部署 MySQL 并使用 Ceph 块存储
为了验证 Ceph 块存储(RBD)的实际效果,我们将部署一个 MySQL 数据库,并将其数据目录 /var/lib/mysql 持久化到 Ceph 集群中。由于数据库对读写性能要求较高,这里我们使用 rook-ceph-block(块存储)。
11.1 创建 MySQL 部署文件
创建一个名为 mysql-demo.yaml 的文件,包含 PVC、Service 和 Deployment:
---
# 1. 创建 PVC (持久化存储卷声明)
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pvc
labels:
app: mysql
spec:
accessModes:
- ReadWriteOnce # 块存储通常使用单读单写模式
resources:
requests:
storage: 10Gi # 申请 10GB 空间
# 因为前面已经将 rook-ceph-block 设置为 K8s 的默认存储类,
# 所以这里不需要再显式指定 storageClassName,系统会自动分配。
# storageClassName: rook-ceph-block
---
# 2. 创建 Service (网络服务)
apiVersion: v1
kind: Service
metadata:
name: mysql
labels:
app: mysql
spec:
ports:
- port: 3306
targetPort: 3306
selector:
app: mysql
clusterIP: None # Headless Service (常用于有状态服务)
---
# 3. 创建 Deployment (部署数据库应用)
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
labels:
app: mysql
spec:
selector:
matchLabels:
app: mysql
strategy:
type: Recreate # 【重要】确保旧 Pod 销毁后才创建新 Pod,防止单读单写(RWO)的块存储挂载冲突
template:
metadata:
labels:
app: mysql
spec:
containers:
- image: mysql:8.0
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
value: "root123456" # 请在生产环境中修改为强密码
ports:
- containerPort: 3306
name: mysql
volumeMounts:
- name: mysql-persistent-storage
mountPath: /var/lib/mysql # MySQL 的默认数据目录
volumes:
- name: mysql-persistent-storage
persistentVolumeClaim:
claimName: mysql-pvc
11.2 部署并验证
执行部署:
kubectl apply -f mysql-demo.yaml
验证状态:
-
检查 PVC 是否成功绑定:
kubectl get pvc mysql-pvc如果状态显示为
Bound,说明 Rook-Ceph 已经成功在底层划出了 10GB 的块存储并分配给了这个 PVC。 -
检查 Pod 是否正常运行:
kubectl get pod -l app=mysql等待 Pod 状态变为
Running。 -
进入数据库验证是否正常:
# 1. 进入 MySQL 容器 kubectl exec -it deploy/mysql -- mysql -uroot -proot123456 # 2. 在 MySQL 终端中执行命令,查看默认数据库 mysql> show databases; # 3. (可选) 创建一个测试库,验证写入权限 mysql> create database rook_test; mysql> show databases; # 4. 退出 MySQL mysql> exit -
连接数据库的其他方式(不进入原容器):
在实际生产中,我们通常不会直接进入数据库容器操作。你可以通过以下几种方式进行连接,以模拟真实的业务调用或进行外部管理:方法 A:启动临时测试容器 (模拟集群内微服务调用)
这种方式最接近真实业务程序的行为,它通过 K8s 的内部 DNS(Service 名称)来解析并连接数据库。# 启动一个用完即焚(--rm)的临时 mysql 客户端容器,通过 Service 域名 'mysql' 进行连接 kubectl run -it --rm mysql-client --image=mysql:8.0 -- mysql -h mysql -uroot -proot123456方法 B:临时端口转发 (适合集群外本地快速测试)
如果你想用自己电脑上的 Navicat 或终端连接:# 将本地的 3306 端口转发到集群内的 mysql 服务 kubectl port-forward svc/mysql 3306:3306 # 然后在另外一个终端执行连接: # mysql -h 127.0.0.1 -P 3306 -uroot -proot123456方法 C:修改 Service 为 NodePort (适合集群外长期访问)
# 修改 Service 类型 kubectl patch svc mysql -p '{"spec": {"type": "NodePort"}}' # 查看分配的节点端口 (例如 31234) kubectl get svc mysql # 然后通过任意 K8s 节点的 IP 进行连接: # mysql -h <NodeIP> -P <NodePort> -uroot -proot123456 -
测试数据持久化:
你可以手动删除该 Pod(kubectl delete pod -l app=mysql)。K8s 会自动拉起一个新的 Pod,再次连接数据库查看,你会发现刚刚创建的rook_test库依然存在。这就是 Ceph 块存储带来的持久化保障。
更多推荐


所有评论(0)