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 状态即可)

相关推荐
运维老郭16 小时前
【K8s运维实战】Kubernetes临时存储卷实战:emptyDir核心用法与gitRepo弃用迁移指南
运维·云原生·kubernetes
AAA@峥20 小时前
容器数据不丢失:Docker 分层存储 + Volume 共享、备份迁移完整指南
运维·docker·容器
十年磨一剑~1 天前
docker 为何每次 docker tag才能 docker push
docker·容器·eureka
gs801401 天前
记一次多 Agent 架构在单节点 K8s 触发的 PID 耗尽与 Pod 驱逐(Evicted)大摸排
容器·架构·kubernetes
bukeyiwanshui1 天前
20260701 k8s Metric Server
容器·贪心算法·kubernetes
江湖有缘1 天前
基于Docker环境部署tillywork开源工作管理工具
docker·容器·开源
seacracker1 天前
Ceph 太重运维成本高?轻量统一存储 PowerFS 对比测评(HPC/AI 场景首选)
运维·人工智能·ceph·ai存储·统一存储
鸿儒5171 天前
MR-50国产化GPU docker配置方法
docker·容器·mr
Zhu7581 天前
在k8s集群部署ApacheHadoop单节点单数据副本
云原生·容器·kubernetes