Kubernetes Rook-Ceph 高可用存储部署文档

Kubernetes Rook-Ceph 高可用存储部署文档

1. 部署前置条件

  1. 裸盘准备 :Ceph 需要在工作节点(Worker Nodes)上拥有未格式化的裸盘(Raw Devices)或独立的分区。例如 /dev/sdb/dev/nvme0n1这些磁盘不能有任何文件系统。

    如何检查磁盘是否可用?

    在目标节点上执行 lsblk -f 命令。

    • 可用(裸盘)FSTYPE 列为空,且 MOUNTPOINT 为空。
    • 不可用FSTYPE 列显示 ext4/xfs 等,或者已被挂载。

    如果磁盘有残留的文件系统签名,可以使用 wipefs -a /dev/sdX (替换为实际盘符) 进行擦除。

  2. 内核模块与依赖 :所有 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
  3. 资源要求: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 配置块:

yaml 复制代码
spec:
  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

yaml 复制代码
spec:
  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-xxxrook-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:

bash 复制代码
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)只抓取带有特定标签的资源。

  1. 先确认你的 Prometheus 需要什么标签:
    kubectl -n monitoring get prometheus -o jsonpath='{.items[0].spec.serviceMonitorSelector}'
    (假设输出为 {"matchLabels":{"release":"prometheus-stack"}})

  2. 给刚才创建的所有监控资源打上标签:

    bash 复制代码
    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 是否成功创建:

bash 复制代码
kubectl -n rook-ceph get servicemonitor

如果输出包含 rook-ceph-mgrrook-ceph-exporter 等资源,说明配置已下发。

如何确认 Prometheus 已经成功抓取数据?

打完标签后,等待约 1-2 分钟。

  1. 打开 Prometheus 网页端 UI
  2. 点击顶部菜单的 Status -> Targets
  3. 在页面中搜索 ceph
  4. 如果能看到名为 rook-ceph/rook-ceph-mgr/...rook-ceph/rook-ceph-exporter/... 的抓取目标,并且它们的状态是绿色的 UP ,那就说明 Prometheus 已经成功连上 Ceph 并开始抓取监控数据了。
    (注:如果搜索时没有看到 csi-metrics,属于正常现象。这通常是因为当前集群还没有实际使用存储卷,或者特定版本的配置差异,完全不影响 Ceph 核心健康状态的监控和报警。)

9.3 配置 Grafana 监控面板

Rook 官方提供了现成的 Grafana 仪表盘(Dashboard)模板,可以直接导入到你的 Grafana 中:

  1. 访问 Rook 官方 GitHub 仓库的 Grafana 模板目录:
    Rook Ceph Grafana Dashboards (v1.19)
  2. 你会在该目录下看到以下核心 JSON 文件:
    • ceph-cluster.json:集群高级监控(推荐)
    • ceph-osd.json:单块磁盘(OSD)详情
    • ceph-pools.json:存储池监控
  3. 登录你的 Grafana 页面,点击左侧菜单的 Dashboards -> New -> Import
  4. 将上述 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。)

bash 复制代码
kubectl -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 部分,将 ruleNamespaceSelectorruleSelector 的值都修改为 {}

yaml 复制代码
spec:
  ruleNamespaceSelector: {}
  ruleSelector: {}

保存退出后,Prometheus 会自动重载配置,扫描并加载所有命名空间中的报警规则。

如何查看报警规则是否生效?

执行命令后,可以通过以下两种方式验证:

  1. 通过 K8s 命令行查看
    执行 kubectl -n rook-ceph get prometheusrules,如果能看到名为 prometheus-ceph-rules 的资源,说明规则已成功加载到 K8s 中。
  2. 通过 Prometheus 界面查看(最直观)
    打开你的 Prometheus 网页 UI,点击顶部菜单的 Alerts (报警)页面。你应该能看到几十条以 Ceph 开头的报警规则(如 CephHealthErrorCephOSDDown 等)被列出。如果它们处于绿色的 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。

  1. 进入 Toolbox 容器:kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- bash
  2. 检查并确保自动伸缩模块已开启:ceph mgr module enable pg_autoscaler
  3. 查看当前存储池状态:ceph osd pool autoscale-status
  4. 将报警的存储池(或所有池)的伸缩模式设置为 onceph osd pool set <池名称> pg_autoscale_mode on
    (注意:设置完成后,Ceph 会在后台缓慢自动合并 PG,可能需要几十分钟后报警才会消失。)

方法二:调高报警阈值(临时屏蔽)

如果你只是处于测试环境,或者确认硬件性能足够,急需消除这个报警,可以直接调高 Ceph 的单盘 PG 报警线。

  1. 进入 Toolbox 容器:kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- bash

  2. 执行以下命令将阈值从默认的 250 调高至 300(或更高):

    bash 复制代码
    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 属于正常现象,只需确保 mgrexporter 处于 UP 状态即可)

相关推荐
Plastic garden2 小时前
Docker(3)Docker 镜像 & Dockerfile
运维·docker·容器
潮起鲸落入海2 小时前
ceph集群mon 以及池管理
ceph
m0_740859622 小时前
Docker安装常见数据库命令汇总(2026)
数据库·docker·容器
IT策士2 小时前
第16篇 实战:用 Docker Compose 编排 WordPress 与 MySQL
mysql·docker·容器
一个行走的民2 小时前
Ceph OSD CPU 占用高排查:BlueFS Buffered IO 与 NUMA 亲和性深度分析
ceph
Cat_Rocky2 小时前
Jenkins通过kubernetes连接K8s集群
运维·kubernetes·jenkins
Plastic garden2 小时前
Docker(2)数据挂载
运维·docker·容器
Plastic garden2 小时前
Docker(4) Compose
运维·docker·容器
IT策士2 小时前
第17篇 Docker Compose 进阶实战:多 Compose 文件与环境覆盖
docker·容器·eureka