Ceph / Rook 面试题
30 道题- 分类
- 存储
- 题目数
- 30 道
1 Ceph 的核心架构组件
答案:
Ceph 是统一分布式存储系统,以 RADOS(Reliable Autonomic Distributed Object Store)为底层对象存储层,向上提供块存储、文件存储和对象存储三种接口。核心组件包括:
| 组件 | 全称 | 职责 |
|---|---|---|
| MON | Monitor | 维护集群 Map(Monitor Map / OSD Map / PG Map / CRUSH Map / MDS Map),通过 Paxos 协议保证强一致性 |
| OSD | Object Storage Daemon | 负责数据存储、复制、恢复、再平衡,直接与磁盘交互,一个磁盘对应一个 OSD 进程 |
| MDS | Metadata Server | 维护 CephFS 的目录树和文件元数据(inode / dentry),允许将元数据与数据分离以提升性能 |
| RGW | RADOS Gateway | 提供 S3 / Swift 兼容的对象存储 RESTful 接口,基于 librgw 将 HTTP 请求转换为 RADOS 操作 |
| MGR | Manager | 收集集群运行时指标(PG 状态 / 磁盘利用率 / 性能计数器),提供 Dashboard / Prometheus / RESTful 管理接口 |
架构分层
应用层 RBD (块设备) CephFS (文件系统) RGW (对象存储)
──────────────────────────────────────────
内核/用户态 librbd libcephfs librgw
──────────────────────────────────────────
底层存储 RADOS (librados)
──────────────────────────────────────────
MON 集群 (Paxos) + OSD 集群 (CRUSH)
集群 Map 的分发与 Epoch 机制
MON 集群维护全局一致的多份 Map 副本。每个 Map 带有递增 epoch 版本号。客户端携带自身 epoch 发起 I/O 时,OSD 若检测到 epoch 落后,拒绝写入并返回最新 Map,避免向已下线的 OSD 写入脏数据。整个过程无需全局锁。
2 Ceph 的 CRUSH 算法与数据分布
答案:
CRUSH(Controlled Replication Under Scalable Hashing)是 Ceph 的伪随机数据分布算法,取代传统中心化元数据查询,客户端可直接计算数据存储位置,实现去中心化 I/O。
核心机制
- CRUSH Map:描述集群拓扑层级(Root -> Datacenter -> Room -> Row -> Rack -> Host -> OSD),每个节点附有权重。
- CRUSH Rule:定义数据的故障域放置策略,如
replicated_rule指定 3 副本分布在不同 Host 上。 - Hash 计算:对象名 -> Hash -> PG -> CRUSH Rule -> OSD 集合,全程确定性计算,无需查询元数据表。
- Bucket 类型:Uniform / List / Tree / Straw / Straw2,推荐 Straw2,OSD 增减时迁移量最小。
CRUSH Rule 示例
rule replicated_rule {
id 0
type replicated
min_size 1
max_size 10
step take default
step chooseleaf firstn 0 type host // 选择不同 Host 上的 OSD
step emit
}
与传统中心化方案的对比
| 维度 | CRUSH | 传统元数据服务器 |
|---|---|---|
| 扩展性 | 无中心瓶颈,随 OSD 线性扩展 | 元数据服务器成为瓶颈 |
| 故障域 | 天然支持多层故障域隔离 | 需额外规划 |
| 数据迁移 | 增减 OSD 仅迁移必要数据 | 依赖中心调度 |
| I/O 路径 | 客户端直连 OSD,无中间跳转 | 需经元数据服务器 |
3 Ceph 的 PG(Placement Group)机制
答案:
PG 是 Ceph 数据管理的逻辑粒度单位,介于对象(Object)和 OSD 之间,用于聚合 OSD 故障检测、复制、恢复和再平衡等操作,避免以对象为最小单位导致元数据爆炸。
层级关系
Pool (逻辑存储池)
└── PG (Placement Group)
└── Object (实际存储对象)
关键概念
- PG 数量公式:
Total PGs = (OSDs × 100) / Replica_Size,单 OSD 承载 100~200 PG 为推荐区间。 - PG 状态:
active+clean(正常)、degraded(副本不全)、peering(PG 内 OSD 协商状态)、recovering(数据恢复中)、backfilling(数据回填)、stale(MON 超时未收到 OSD 上报)。 - PGP(PG Placement):控制 PG 到 OSD 的映射,PGP 总数应与 PG 总数保持一致,否则数据分布不均。
- Peering 过程:PG 内 OSD 通过互相交换日志(PG Log)协商权威副本,达成一致后开始恢复。
PG 分裂(Split)
当 Pool 的 pg_num 增大时,原有 PG 分裂为多个新 PG。分裂过程中会产生大量数据迁移,应在业务低峰操作,分多次小幅增加。
4 Ceph 的 BlueStore 存储引擎
答案:
BlueStore 从 Ceph Luminous(v12.x)起成为默认存储引擎,专为 SSD / NVMe 设计,废弃了传统 FileStore 的 POSIX 文件系统中间层,直接管理裸盘。
架构组成
| 组件 | 存储内容 | 存储介质 |
|---|---|---|
| RocksDB | 对象元数据、PG 日志、WAL、Omap、分配器元数据 | 高速介质(NVMe / SSD) |
| BlueFS | RocksDB 的轻量文件系统 | 同 RocksDB 介质 |
| Block Device | 实际对象数据 | 主存储设备(HDD / SSD / NVMe) |
WAL 与 DB 设备分离策略
配置 (bluestore) rocksdb WAL rocksdb DB 对象数据
────────────────────────────────────────────────────────────────────────────
仅主盘 主盘 主盘 主盘
主盘 + DB/WAL 分区 主盘独立分区 主盘独立分区 主盘
主盘 + 独立 SSD 独立 SSD 独立 SSD 主盘
主盘 + 独立 WAL (NVMe) + 独立 DB (SSD) 独立 NVMe 独立 SSD 主盘
性能对比
| 维度 | BlueStore | FileStore |
|---|---|---|
| 写放大 | 天然双写(WAL + Data),无文件系统日志开销 | 文件系统日志 + OSD 日志,三重写入 |
| 元数据管理 | RocksDB 键值存储,高效 | 文件系统 xattr 或 LevelDB,受限于 POSIX |
| 校验 | 端到端 checksum | 依赖文件系统 |
| SSD 优化 | 原生支持,直接管理裸设备 | 受文件系统抽象层限制 |
| GC / 压缩 | RocksDB 后台 Compaction | 依赖文件系统 |
BlueStore 延迟优化参数
[osd]
bluestore_cache_size_hdd = 4GB # HDD OSD 缓存
bluestore_cache_size_ssd = 4GB # SSD OSD 缓存
bluestore_cache_trim_interval = 0.05 # Trim 间隔
bluestore_throttle_cost_per_io = 1.5 # I/O 节流系数
5 Rook 的架构与核心 CRD
答案:
Rook 是 CNCF 毕业项目,将 Ceph 编排为 Kubernetes 原生存储解决方案。Rook Operator 自动处理部署、配置、扩展、升级和灾难恢复。
核心架构组件
graph TD
subgraph RookOperator["Rook Operator"]
CC["Cluster\nController"]
BC["Block\nController"]
FC["Filesys\nController"]
OC["Object\nController"]
end
subgraph RookAgent["Rook Agent - DaemonSet"]
Agent["每节点运行,管理 OSD / 设备发现 / 配置注入"]
end
subgraph CephPods["Ceph 守护进程 Pod"]
MON["MON Pod"]
OSD["OSD Pod"]
MDS["MDS Pod"]
RGW["RGW Pod"]
MGR["MGR Pod"]
end
subgraph CSI["CSI 驱动 Pod"]
RBD["RBD CSI Plugin"]
CephFS["CephFS CSI Plugin"]
end
RookOperator --> RookAgent
RookAgent --> CephPods
CephPods --> CSI
核心 CRD
| CRD | API Group | 职责 |
|---|---|---|
| CephCluster | ceph.rook.io/v1 | 定义 Ceph 集群全局配置:版本、MON 数量、网络、存储、Dashboard、监控 |
| CephBlockPool | ceph.rook.io/v1 | 定义 RBD 块存储池:副本数、故障域、PG 数量、QoS |
| CephBlockPoolRadosNamespace | ceph.rook.io/v1 | 定义 RBD 池下的 RADOS Namespace,实现多租户隔离 |
| CephFilesystem | ceph.rook.io/v1 | 定义 CephFS 文件系统:MDS 数量、池配置、保留策略 |
| CephFilesystemSubVolumeGroup | ceph.rook.io/v1 | 定义 CephFS SubVolumeGroup,NFS-Ganesha 导出单元 |
| CephObjectStore | ceph.rook.io/v1 | 定义 RGW 对象存储:实例数、端口、TLS 证书、Multi-Site |
| CephObjectStoreUser | ceph.rook.io/v1 | 定义 RGW 用户及 S3 凭据 |
| CephClient | ceph.rook.io/v1 | 为外部消费方生成 ceph.conf 和 keyring |
| CephNFS | ceph.rook.io/v1 | 定义 NFS-Ganesha 导出,基于 RGW 或 CephFS 后端 |
| CephRBDMirror | ceph.rook.io/v1 | 定义 RBD 异步镜像复制 |
Operator 协调循环
Rook Operator Watch CRD -> 读取期望状态 Spec -> 对比集群实际状态 -> 生成 Ceph 原生配置 -> 通过 Ceph 命令行工具或守护进程 API 执行变更 -> 更新 Status。
6 Rook CephCluster 的部署与配置
答案:
Rook CephCluster 的部署分为 Operator 安装和 CephCluster CR 创建两个阶段。
部署流程
# 1. 克隆 Rook 仓库,部署 Operator
git clone --single-branch --branch v1.14.0 https://github.com/rook/rook.git
kubectl create -f rook/deploy/examples/crds.yaml # 创建 CRD
kubectl create -f rook/deploy/examples/common.yaml # 创建 RBAC / ServiceAccount
kubectl create -f rook/deploy/examples/operator.yaml # 部署 Operator
# 2. 创建 CephCluster CR
kubectl apply -f cluster.yaml
CephCluster 核心配置
apiVersion: ceph.rook.io/v1
kind: CephCluster
metadata:
name: rook-ceph
namespace: rook-ceph
spec:
cephVersion:
image: quay.io/ceph/ceph:v18.2.0
dataDirHostPath: /var/lib/rook
mon:
count: 3 # MON 数量,建议奇数 ≥ 3
allowMultiplePerNode: false # 禁止同一节点多 MON
mgr:
count: 2
modules:
- name: pg_autoscaler
enabled: true
dashboard:
enabled: true
ssl: true
network:
provider: host # host 或 multus
selectors:
public: public-network
cluster: cluster-network
storage:
useAllNodes: true # 自动发现节点
useAllDevices: true # 自动发现空白设备
deviceFilter: "^sd[b-d]" # 设备名过滤
config:
osdsPerDevice: "1" # 每设备 OSD 数(NVMe 可设为 > 1)
nodes:
- name: node-1
devices:
- name: /dev/nvme0n1
config:
osdsPerDevice: "4"
resources:
osd:
limits:
cpu: "4"
memory: "16Gi"
requests:
cpu: "2"
memory: "8Gi"
Ceph 网络隔离
| 网络类型 | 用途 | 配置字段 |
|---|---|---|
| Public Network | 客户端 I/O 请求,MON 间通信 | network.selectors.public |
| Cluster Network | OSD 间数据复制与恢复 | network.selectors.cluster |
CephCluster 状态检查
kubectl -n rook-ceph get cephcluster
kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- ceph status
kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- ceph osd tree
7 Rook CephBlockPool(RBD)的创建与使用
答案:
CephBlockPool 定义 RBD 块存储池,通过 CSI 驱动为 Pod 提供 PersistentVolume。
CephBlockPool 创建
apiVersion: ceph.rook.io/v1
kind: CephBlockPool
metadata:
name: replicapool
namespace: rook-ceph
spec:
failureDomain: host # 故障域级别
replicated:
size: 3 # 副本数
requireSafeReplicaSize: true # 要求可用副本才允许写入
enableRBDStats: true # 开启 RBD 性能统计
parameters:
pg_num: "128"
pgp_num: "128"
compression_mode: aggressive
target_size_ratio: 0.3 # PG Autoscaler 权重
StorageClass 定义
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: rook-ceph-block
provisioner: rook-ceph.rbd.csi.ceph.com
parameters:
clusterID: rook-ceph
pool: replicapool
imageFormat: "2"
imageFeatures: layering,exclusive-lock,object-map,fast-diff,deep-flatten
csi.storage.k8s.io/provisioner-secret-name: rook-csi-rbd-provisioner
csi.storage.k8s.io/node-stage-secret-name: rook-csi-rbd-node
csi.storage.k8s.io/fstype: ext4
allowVolumeExpansion: true
reclaimPolicy: Delete
mountOptions:
- discard # 启用 TRIM / UNMAP
应用使用示例
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-data
spec:
storageClassName: rook-ceph-block
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 100Gi
apiVersion: v1
kind: Pod
metadata:
name: mysql
spec:
containers:
- name: mysql
image: mysql:8.0
volumeMounts:
- name: data
mountPath: /var/lib/mysql
volumes:
- name: data
persistentVolumeClaim:
claimName: mysql-data
Volume Expansion 在线扩容
kubectl patch pvc mysql-data -p '{"spec":{"resources":{"requests":{"storage":"200Gi"}}}}'
RBD Snapshot 快照与恢复
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshotClass
metadata:
name: csi-rbdplugin-snapclass
driver: rook-ceph.rbd.csi.ceph.com
deletionPolicy: Delete
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
name: mysql-snapshot
spec:
volumeSnapshotClassName: csi-rbdplugin-snapclass
source:
persistentVolumeClaimName: mysql-data
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-restore
spec:
storageClassName: rook-ceph-block
dataSource:
name: mysql-snapshot
kind: VolumeSnapshot
apiGroup: snapshot.storage.k8s.io
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 100Gi
8 Rook CephFilesystem(CephFS)的创建与使用
答案:
CephFilesystem 定义 CephFS 分布式文件系统,支持 ReadWriteMany(RWX)访问模式,适用于共享存储场景。
CephFilesystem 创建
apiVersion: ceph.rook.io/v1
kind: CephFilesystem
metadata:
name: myfs
namespace: rook-ceph
spec:
metadataPool:
replicated:
size: 3
parameters:
pg_num: "128"
compression_mode: "none" # 元数据池不建议压缩
dataPools:
- name: replicated
failureDomain: host
replicated:
size: 3
parameters:
pg_num: "256"
compression_mode: aggressive
- name: ec-data # 纠删码数据池
failureDomain: host
erasureCoded:
dataChunks: 6
codingChunks: 2 # 6+2 EC,1.33x 冗余率
preserveFilesystemOnDelete: false
metadataServer:
activeCount: 1
activeStandby: true # 启用 standby MDS
resources:
limits:
cpu: "4"
memory: "8Gi"
requests:
cpu: "2"
memory: "4Gi"
StorageClass 定义
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: rook-cephfs
provisioner: rook-ceph.cephfs.csi.ceph.com
parameters:
clusterID: rook-ceph
fsName: myfs
pool: myfs-replicated
csi.storage.k8s.io/provisioner-secret-name: rook-csi-cephfs-provisioner
csi.storage.k8s.io/node-stage-secret-name: rook-csi-cephfs-node
allowVolumeExpansion: true
reclaimPolicy: Delete
RWX 多 Pod 共享示例
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: shared-data
spec:
storageClassName: rook-cephfs
accessModes:
- ReadWriteMany
resources:
requests:
storage: 500Gi
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-shared
spec:
replicas: 3
selector:
matchLabels:
app: nginx-shared
template:
spec:
containers:
- name: nginx
image: nginx:1.25
volumeMounts:
- name: data
mountPath: /usr/share/nginx/html
volumes:
- name: data
persistentVolumeClaim:
claimName: shared-data
SubVolumeGroup 租户隔离
CephFS SubVolumeGroup 在多租户场景下提供命名空间隔离和配额控制。通过 CephFilesystemSubVolumeGroup CRD 创建子卷组,每个租户的应用 PVC 限定在其 SubVolumeGroup 内。
apiVersion: ceph.rook.io/v1
kind: CephFilesystemSubVolumeGroup
metadata:
name: tenant-a-group
namespace: rook-ceph
spec:
filesystemName: myfs
# StorageClass 通过 subvolumegroup 参数指向租户组
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: rook-cephfs-tenant-a
provisioner: rook-ceph.cephfs.csi.ceph.com
parameters:
clusterID: rook-ceph
fsName: myfs
subvolumegroup: tenant-a-group
9 Rook CephObjectStore(RGW / 对象存储)的创建与使用
答案:
CephObjectStore 定义 RADOS Gateway 对象存储服务,提供 S3 / Swift 兼容 API。
CephObjectStore 创建
apiVersion: ceph.rook.io/v1
kind: CephObjectStore
metadata:
name: my-store
namespace: rook-ceph
spec:
metadataPool:
replicated:
size: 3
dataPool:
replicated:
size: 3
erasureCoded:
dataChunks: 4
codingChunks: 2
preservePoolsOnDelete: true
gateway:
type: s3
port: 80
securePort: 443
instances: 3
sslCertificateRef: rgw-tls-cert # TLS Secret 引用
resources:
limits:
cpu: "4"
memory: "8Gi"
requests:
cpu: "2"
memory: "4Gi"
healthCheck:
bucket:
disabled: false
interval: 60s
用户与凭据创建
apiVersion: ceph.rook.io/v1
kind: CephObjectStoreUser
metadata:
name: my-user
namespace: rook-ceph
spec:
store: my-store
displayName: "S3 ReadWrite User"
quotas:
maxBuckets: 100
maxSize: 1024Gi
maxObjects: 1000000
capabilities:
- user: "*"
- bucket: "*"
- usage: read
- metadata: read
获取 S3 凭据与 Endpoint
# 获取 Access Key
kubectl -n rook-ceph get secret rook-ceph-object-user-my-store-my-user \
-o jsonpath='{.data.AccessKey}' | base64 --decode
# 获取 Secret Key
kubectl -n rook-ceph get secret rook-ceph-object-user-my-store-my-user \
-o jsonpath='{.data.SecretKey}' | base64 --decode
# 获取 RGW Service Endpoint
kubectl -n rook-ceph get svc rook-ceph-rgw-my-store -o jsonpath='{.spec.clusterIP}'
S3 客户端验证
s3cmd --access_key=<AccessKey> --secret_key=<SecretKey> \
--host=<RGW-Endpoint> --host-bucket="" \
--no-ssl mb s3://my-bucket
RGW 负载均衡与 Ingress 暴露
apiVersion: v1
kind: Service
metadata:
name: rgw-external-lb
namespace: rook-ceph
spec:
type: LoadBalancer
selector:
app: rook-ceph-rgw
rgw: my-store
ports:
- name: http
port: 80
targetPort: 8080
- name: https
port: 443
targetPort: 8443
10 Rook 的 CephBlockPoolRadosNamespace 与 RBD 镜像
答案:
CephBlockPoolRadosNamespace 在已有 RBD Pool 内创建 RADOS Namespace 逻辑分区,实现存储层多租户隔离。每个 Namespace 拥有独立的 RBD 镜像集合,不同 Namespace 中的同名镜像互不影响。
RADOS Namespace 创建
apiVersion: ceph.rook.io/v1
kind: CephBlockPoolRadosNamespace
metadata:
name: tenant-x-ns
namespace: rook-ceph
spec:
blockPoolName: replicapool
# StorageClass 指向特定 Namespace
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: rook-ceph-block-tenant-x
provisioner: rook-ceph.rbd.csi.ceph.com
parameters:
clusterID: rook-ceph
pool: replicapool
radosNamespace: tenant-x-ns
RBD Mirroring 异步镜像复制
apiVersion: ceph.rook.io/v1
kind: CephRBDMirror
metadata:
name: rbd-mirror
namespace: rook-ceph
spec:
count: 1
resources:
limits:
cpu: "2"
memory: "4Gi"
peers:
secretNames:
- cluster-b-peer-secret
pool: replicapool
mode: pool # pool 或 image 级别
snapshotSchedules:
- interval: 15m
startTime: "00:00:00"
RBD 镜像的 Snapshot 与 Trash 管理
RBD 镜像支持分层快照和延迟删除(Trash)。删除镜像时先进 Trash,在延迟期(默认 7 天)内可恢复。
# 查看 Trash 中的镜像
rbd trash ls -p replicapool
# 恢复已删除镜像
rbd trash restore -p replicapool <image-id>
11 Rook 的 CSI 驱动(RBD CSI / CephFS CSI)
答案:
Rook 集成 CSI(Container Storage Interface)规范,通过 RBD CSI 和 CephFS CSI 驱动实现 Kubernetes 原生卷的生命周期管理。
CSI 组件架构
graph TD
subgraph K8sMaster["Kubernetes Master"]
Prov["CSI Provisioner"]
Snap["CSI Snapshotter / Resizer"]
Prov --> Ctrl
Snap --> Ctrl
Ctrl["CSI Controller Plugin\nrook-ceph.rbd.csi.ceph.com /\nrook-ceph.cephfs.csi.ceph.com"]
end
subgraph K8sNode["Kubernetes Node"]
Node["CSI Node Plugin\nDaemonSet: csi-rbdplugin /\ncsi-cephfsplugin"]
Stage["NodeStage\nVolume"]
Publish["NodePublish\nVolume"]
end
Ctrl --> Node
RBD CSI 卷生命周期
| 阶段 | 方法 | 操作 |
|---|---|---|
| CreateVolume | Controller | 调用 rbd create 创建 RBD 镜像 |
| DeleteVolume | Controller | 调用 rbd rm 删除 RBD 镜像 |
| ControllerPublishVolume | Controller | rbd map + 将设备路径返回给 kubelet |
| NodeStageVolume | Node | 格式化为文件系统 + mount 到 global mount 路径 |
| NodePublishVolume | Node | bind mount 到 Pod 的 volumeMount 路径 |
| NodeUnpublishVolume | Node | unmount Pod 路径 |
| NodeUnstageVolume | Node | unmount global mount 路径 |
| ControllerUnpublishVolume | Controller | rbd unmap |
CSI 侧车容器(Sidecar)
| 侧车 | 功能 |
|---|---|
| csi-provisioner | 监听 PVC 事件,调用 CSI CreateVolume / DeleteVolume |
| csi-snapshotter | 监听 VolumeSnapshot 事件,管理快照生命周期 |
| csi-resizer | 监听 PVC 扩容事件,调用 ControllerExpandVolume |
| csi-attacher | 监听 VolumeAttachment 事件,完成 Attach / Detach |
| livenessprobe | CSI 驱动健康检查 |
多集群 Ceph 访问
通过 clusterID 映射,在多个 Kubernetes 集群中配置相同 clusterID 和对应 Secret,实现多个集群共享同一 Ceph 集群。
# 外部 K8s 集群 StorageClass
parameters:
clusterID: rook-ceph-external
pool: replicapool
csi.storage.k8s.io/provisioner-secret-namespace: external-ns
12 Rook 的存储分类(DeviceClass / CrushDeviceClass)
答案:
CrushDeviceClass 将 OSD 按设备类型分类(HDD / SSD / NVMe),允许不同性能等级的存储设备归属于不同的 CRUSH 规则,实现存储分层。
设备自动分类
Rook 根据设备属性自动设置 crushDeviceClass:
| 设备属性 | crushDeviceClass |
|---|---|
| 旋转磁盘(HDD) | hdd |
| 固态磁盘(SSD / SATA) | ssd |
| NVMe 设备 | nvme |
基于 DeviceClass 的 CephBlockPool 创建
apiVersion: ceph.rook.io/v1
kind: CephBlockPool
metadata:
name: nvme-fast-pool
namespace: rook-ceph
spec:
failureDomain: host
deviceClass: nvme
replicated:
size: 3
apiVersion: ceph.rook.io/v1
kind: CephBlockPool
metadata:
name: hdd-archive-pool
namespace: rook-ceph
spec:
failureDomain: host
deviceClass: hdd
replicated:
size: 2
自定义 CRUSH Rule 与 DeviceClass
apiVersion: ceph.rook.io/v1
kind: CephBlockPool
metadata:
name: ssd-primary-pool
namespace: rook-ceph
spec:
failureDomain: rack
deviceClass: ssd
replicated:
size: 3
crushRoot: ssd-root # 限定 CRUSH tree 根节点
不同 DeviceClass 的 StorageClass 映射
# NVMe 高性能 StorageClass
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: rook-nvme-block
provisioner: rook-ceph.rbd.csi.ceph.com
parameters:
pool: nvme-fast-pool
# HDD 归档 StorageClass
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: rook-hdd-block
provisioner: rook-ceph.rbd.csi.ceph.com
parameters:
pool: hdd-archive-pool
13 Rook 的 Placement Group 自动扩缩(PG Autoscaler)
答案:
PG Autoscaler 根据 Pool 的实际使用量或预期使用量自动调整 pg_num,避免人工估算不准确导致的 PG 过多或不足。
PG Autoscaler 模式
| 模式 | 行为 | 适用场景 |
|---|---|---|
| off | 完全禁用自动调整 | 静态环境 / 精确控制 |
| warn | 提示建议调整值,不自动执行 | 生产环境过渡期 |
| on | 自动执行 PG 数量调整 | 动态变化环境 |
PG Autoscaler 参数
apiVersion: ceph.rook.io/v1
kind: CephBlockPool
metadata:
name: replicapool
namespace: rook-ceph
spec:
parameters:
pg_autoscale_mode: "on"
target_size_ratio: 0.3 # Pool 占集群总容量比例,用于计算 PG
原理与计算
PG Autoscaler 基于两个关键输入计算 PG 数量:
target_size_ratio:Pool 容量占集群总容量的比值(如 0.3 表示 30%)。target_size_bytes:Pool 的绝对容量目标(与 ratio 互斥)。- 最终 PG 数 =
(OSD 数 × Mon PG Per OSD) / Replica Size,结合target_size_ratio加权分配。
手动触发调优
# 查看 Pool 的 PG Autoscaler 状态
ceph osd pool autoscale-status
# 手动为 Pool 设置 target ratio
ceph osd pool set replicapool target_size_ratio 0.5
14 Rook 的 OSD 管理(添加 / 移除 / 替换磁盘)
答案:
Rook 通过 OSD 守护进程管理底层磁盘的生命周期,支持添加新盘、移除故障盘和替换失效盘。
OSD 添加流程
- 节点上新插入磁盘后,Rook Agent(DaemonSet)自动检测。
- Agent 调用 ceph-volume 创建 OSD(分区 / 格式化 BlueStore / 注册到集群)。
- OSD Pod 启动,Ceph 集群自动触发数据再平衡(CRUSH rebalance)。
- 观察 PG 状态:
ceph -s/ceph pg stat。
# 查看 OSD 树
kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- ceph osd tree
# 查看 OSD 状态
kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- ceph osd df
OSD 移除流程
# 1. 标记 OSD 为 out(集群自动迁移数据)
kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- ceph osd out osd.<N>
# 2. 等待数据迁移完成
kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- ceph -w
# 3. 停止 OSD 进程
kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- ceph osd down osd.<N>
# 4. 删除 OSD(从 CRUSH Map 和 Auth 中移除)
kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- ceph osd purge osd.<N>
# 5. 清理节点上的设备
# 如使用 Rook 管理的 OSD,通过删除对应 deployment 触发清理 Job
kubectl -n rook-ceph delete deployment rook-ceph-osd-<N>
# 6. 物理移除磁盘
OSD 替换流程
替换场景下优先执行逐出再移除,避免多盘同时故障导致数据丢失。
# 1. 执行逐出(evict),替换 out
ceph osd destroy osd.<N> --force
# 2. 物理更换磁盘
# 3. Rook Agent 检测到新盘,自动创建新 OSD
# 4. 集群自动再平衡
OSD 权重调节
# 调整 OSD 权重(根据容量差异微调)
ceph osd crush reweight osd.<N> <weight>
# 批量平衡(upmap 优化器)
ceph balancer mode upmap
ceph balancer on
15 Rook 的 MON 高可用与仲裁机制
答案:
Ceph MON 集群使用 Paxos 协议维护集群 Map 的强一致性,要求多数 MON 在线才能形成法定人数(quorum)。
MON 数量的选择
| MON 数量 | 可容忍故障数 | 推荐场景 |
|---|---|---|
| 1 | 0 | 开发 / 测试环境 |
| 3 | 1 | 生产环境(最小推荐) |
| 5 | 2 | 大型集群(> 100 OSD) |
| 7 | 3 | 超大规模集群 |
CephCluster MON 配置
apiVersion: ceph.rook.io/v1
kind: CephCluster
spec:
mon:
count: 3
allowMultiplePerNode: false
volumeClaimTemplate:
spec:
storageClassName: local-storage # MON 数据使用本地 PV
resources:
requests:
storage: 20Gi
MON 高可用设计要点
| 策略 | 说明 |
|---|---|
| 反亲和性调度 | MON Pod 通过 PodAntiAffinity 分布在不同 Node 上 |
| 独立存储 | 每个 MON 绑定独立持久化卷,不可共享 |
| 网络隔离 | MON 通信使用独立 cluster network |
| 时钟同步 | 所有 MON 节点必须配置 NTP,时钟偏差不可超过 50ms(默认 mon_clock_drift_allowed) |
仲裁故障恢复
当 MON 数量降至 quorum 以下时集群不可用。恢复方式:
# 1. 检查 MON 状态
kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- ceph mon stat
# 2. 如 MON 数据完整,重启失败 MON Pod
kubectl -n rook-ceph delete pod rook-ceph-mon-a-xxxx
# 3. 如 MON 数据损坏,从健康 MON 提取 monmap 注入新 MON
kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- ceph-monstore-tool \
/var/lib/rook/mon-a get monmap -- --out /tmp/monmap
# 4. 将 MON 从集群中移除并重建
ceph mon remove a
16 Rook 的 MDS(Metadata Server)与 CephFS 性能
答案:
MDS 负责管理 CephFS 文件系统的元数据(目录树、文件 inode、权限),与数据 I/O 分离,是可水平扩展的无状态服务。
MDS 部署模式
| 配置 | 行为 |
|---|---|
| activeCount: 1 | 单 Active MDS,可配合 standby |
| activeCount: 2+ | 多 Active MDS,以子树分区方式负载均衡 |
| activeStandby: true | 启用 Standby-Replay MDS,Active MDS 故障时快速接管 |
多 Active MDS 配置
apiVersion: ceph.rook.io/v1
kind: CephFilesystem
metadata:
name: myfs
namespace: rook-ceph
spec:
metadataServer:
activeCount: 2
activeStandby: true
resources:
limits:
cpu: "8"
memory: "16Gi"
requests:
cpu: "4"
memory: "8Gi"
MDS 性能调优
[mds]
mds_cache_memory_limit = 16GB # MDS 内存缓存上限
mds_cache_reservation = 0.05 # 缓存保留比例
mds_recall_state_timeout = 60 # 客户端状态回收超时
mds_session_timeout = 60 # 客户端会话超时
mds_bal_interval = 10 # MDS 负载均衡间隔(秒)
mds_log_max_segments = 128 # MDS 日志段数量
mds_max_file_recover = 32 # 恢复期间最大打开文件数
MDS 性能监控
# MDS 性能计数器
ceph daemon mds.myfs-a perf dump
# 客户端会话
ceph tell mds.myfs:a client ls
# 查看子树分区分布
ceph fs status myfs
CephFS 内核客户端 vs FUSE 客户端
| 维度 | Kernel Client (kcephfs) | FUSE Client (ceph-fuse) |
|---|---|---|
| 性能 | 高,零拷贝 | 较低,需用户态-内核态切换 |
| 部署 | 需内核模块支持 | 用户态部署,不依赖内核 |
| 配额 | 部分版本不支持 | 完整支持 |
| 安全 | 需 root 挂载 | 普通用户可挂载 |
| Snapshot | 支持 | 支持 |
17 Rook 的 RGW(RADOS Gateway)S3 兼容 API
答案:
RADOS Gateway 将 S3 / Swift RESTful API 请求转换为 RADOS 对象操作,提供云原生对象存储能力。
RGW 架构
graph TD
Req["HTTP/HTTPS Request"]
LB["LoadBalancer\nEnvoy / HAProxy / Nginx"]
RGW1["RGW Pod"]
RGW2["RGW Pod"]
RGW3["RGW Pod"]
RADOS["RADOS"]
Req --> LB
LB --> RGW1
LB --> RGW2
LB --> RGW3
RGW1 --> RADOS
RGW2 --> RADOS
RGW3 --> RADOS
RGW 多项配置
apiVersion: ceph.rook.io/v1
kind: CephObjectStore
metadata:
name: cluster-a-store
namespace: rook-ceph
spec:
gateway:
instances: 5
port: 80
securePort: 443
zone:
name: zone-a
healthCheck:
bucket:
interval: 30s
S3 API 兼容性
| 功能 | 支持情况 |
|---|---|
| Bucket CRUD | 完整支持 |
| Object CRUD | 完整支持 |
| Multipart Upload | 支持 |
| Versioning | 支持(Bucket Versioning) |
| Lifecycle Policy | 支持(过期 / 转换) |
| Cross-Origin (CORS) | 支持 |
| Server-Side Encryption (SSE-S3) | 支持 |
| Object Lock / Legal Hold | 支持 |
| Bucket Policy / ACL | 支持 |
| Static Website Hosting | 支持 |
| S3 Select | 不支持 |
| Object Lambda | 不支持 |
RGW 性能参数
[client.rgw]
rgw_frontends = "beast port=80"
rgw_thread_pool_size = 512
rgw_max_concurrent_requests = 1024
rgw_cache_enabled = true
rgw_cache_lru_size = 100000
rgw_gc_max_objs = 32
rgw_gc_processor_period = 3600
Beast HTTP 引擎优化
RGW 默认使用 Beast 作为 HTTP 前端,相比 Civetweb 性能和稳定性均有提升。
# Beast 绑核(减少上下文切换)
rgw_frontends = "beast port=80 num_threads=4"
# 限制请求体大小
rgw_max_put_size = 5GiB
rgw_max_get_size = 10GiB
18 Rook 的 Dashboard 管理界面
答案:
Ceph Dashboard 提供 Web 图形化管理界面,集成集群状态、性能指标、配置管理和容量可视化。
Dashboard 启用
apiVersion: ceph.rook.io/v1
kind: CephCluster
spec:
dashboard:
enabled: true
ssl: true
urlPrefix: /
port: 8443
sslCertificateSecretName: dashboard-cert # 自定义 TLS
Dashboard 初始密码
# 首次部署后获取 admin 密码
kubectl -n rook-ceph get secret rook-ceph-dashboard-password \
-o jsonpath="{['data']['password']}" | base64 --decode
Dashboard 功能模块
| 模块 | 功能 |
|---|---|
| Cluster | 集群健康状态、PG 状态、OSD 状态 |
| Block (RBD) | 镜像列表、I/O 性能、快照管理 |
| NFS | NFS-Ganesha 导出管理 |
| Filesystem (CephFS) | MDS 状态、客户端会话 |
| Object Gateway (RGW) | 用户、Bucket、用量统计 |
| Pools | 池列表、PG 状态、配额管理 |
| Hosts | 主机列表、OSD 分布、守护进程状态 |
通过 Ingress 暴露 Dashboard
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: rook-ceph-dashboard
namespace: rook-ceph
annotations:
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
spec:
rules:
- host: ceph-dashboard.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: rook-ceph-mgr-dashboard
port:
number: 8443
tls:
- hosts:
- ceph-dashboard.example.com
secretName: dashboard-tls
Dashboard 用户管理
# 创建只读用户
kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- \
ceph dashboard ac-user-create readonly-user <password> read-only
# 授予特定权限
ceph dashboard ac-user-set-roles admin-user administrator
19 Rook 的备份与灾难恢复(RBD Mirroring / RGW Multi-Site)
答案:
Rook 支持两大灾备机制:RBD Mirroring 实现块存储异步镜像复制,RGW Multi-Site 实现对象存储跨集群同步。
RBD Mirroring 架构
graph LR
subgraph ClusterA["集群 A"]
RBD1["RBD Image<br/>(Primary)<br/>Snapshot Schedule"]
Mirror1["CephRBD Mirror Daemon"]
RBD1 --> Mirror1
end
subgraph ClusterB["集群 B"]
RBD2["RBD Image<br/>(Secondary)<br/>Snapshot Schedule"]
Mirror2["CephRBD Mirror Daemon"]
RBD2 --> Mirror2
end
RBD1 -->|"Journal 同步"| RBD2
RBD Mirroring 配置
apiVersion: ceph.rook.io/v1
kind: CephRBDMirror
metadata:
name: rbd-mirror
namespace: rook-ceph
spec:
count: 2
pool: replicapool
mode: image
peers:
secretNames:
- cluster-b-peer-secret
apiVersion: ceph.rook.io/v1
kind: CephBlockPool
metadata:
name: replicapool
namespace: rook-ceph
spec:
mirroring:
enabled: true
mode: image
snapshotSchedules:
- interval: 5m
startTime: "00:00:00"
maxSnapshots: 5
RGW Multi-Site 架构
graph TD
Realm["Realm: global"]
ZoneA["Zone A<br/>(Primary)<br/>Site: beijing"]
ZoneB["Zone B<br/>(Secondary)<br/>Site: shanghai"]
Realm --> ZoneA
Realm --> ZoneB
ZoneA <-->|"Sync"| ZoneB
RGW Multi-Site CR 配置
apiVersion: ceph.rook.io/v1
kind: CephObjectRealm
metadata:
name: global-realm
namespace: rook-ceph
apiVersion: ceph.rook.io/v1
kind: CephObjectZoneGroup
metadata:
name: default-group
namespace: rook-ceph
spec:
realm: global-realm
apiVersion: ceph.rook.io/v1
kind: CephObjectZone
metadata:
name: zone-a
namespace: rook-ceph
spec:
zoneGroup: default-group
metadataPool:
replicated:
size: 3
dataPool:
replicated:
size: 3
灾难恢复 RPO / RTO 对比
| 方案 | RPO | RTO | 复杂度 |
|---|---|---|---|
| RBD Mirroring (Journal) | 秒级(异步) | 分钟级 | 中 |
| RBD Mirroring (Snapshot) | 分钟级 | 分钟级 | 低 |
| RGW Multi-Site | 秒级(异步) | 分钟级 | 高 |
20 Rook 的 Ceph 版本升级(滚动升级 / 跨大版本升级)
答案:
Rook Operator 支持通过修改 CephCluster CR 中的 cephVersion.image 实现 Ceph 滚动升级。Rook 会按依赖顺序逐个更新守护进程,确保升级期间集群可用。
升级流程
# 1. 检查当前集群状态
kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- ceph versions
kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- ceph status
# 2. 更新 CephCluster 镜像
kubectl -n rook-ceph patch cephcluster rook-ceph --type merge \
-p '{"spec":{"cephVersion":{"image":"quay.io/ceph/ceph:v18.2.1","allowUnsupported":false}}}'
# 3. 观察升级进度
kubectl -n rook-ceph logs -f deploy/rook-ceph-operator
kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- ceph versions
升级顺序
Rook Operator 按照以下顺序逐步升级 Ceph 守护进程:
- MGR(Manager)
- MON(Monitor)
- MDS(Metadata Server)
- RGW(RADOS Gateway)
- OSD(Object Storage Daemon)
- RBD Mirror / NFS-Ganesha 等其他组件
升级安全策略
| 策略 | 说明 |
|---|---|
| 健康检查前置 | 升级前要求集群 HEALTH_OK,任意 PG 非 active+clean 状态阻止升级 |
| canary 升级 | 可以逐 OSD 灰度,观察单个 OSD 升级后的行为 |
| 禁止跨大版本 | 小版本(v16.2.x -> v16.2.y)直接升级;大版本(v16 -> v17)需逐个跃迁 |
| 自动回滚 | OSD 单例升级失败不影响服务,Operator 保持旧版本 OSD 运行 |
跨大版本升级路径
v15.2.x (Octopus) → v16.2.x (Pacific) → v17.2.x (Quincy) → v18.2.x (Reef)
21 Rook 的多集群 Ceph(CephCluster Federation)
答案:
Rook 支持在多个 Kubernetes 集群中运行独立的 CephCluster,通过 CSI 的 clusterID 映射和外部集群连接实现跨集群存储共享。
多集群部署模型
| 模型 | 架构 | 适用场景 |
|---|---|---|
| 独立集群 | 每个 K8s 集群独立的 CephCluster,互不感知 | 完全隔离的多环境 |
| 外部连接 | 一个 CephCluster 作为存储后端,多个 K8s 集群通过 CSI 外部模式消费 | 共享存储后端 |
| RBD Mirroring | 多个 CephCluster 通过 RBD 镜像异步复制 | 灾备 / 多活 |
外部集群连接配置
# 1. 从 Ceph 集群导出连接信息
kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- \
python3 /etc/ceph/create-external-cluster-resources.py \
--rbd-data-pool-name replicapool \
--cephfs-filesystem-name myfs \
--namespace rook-ceph-external
# 2. 在外部 K8s 集群上创建连接 Secret
kubectl create -f external-cluster-secret.yaml
# 3. 外部 K8s 集群 StorageClass 指向外部 Ceph
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: rook-ceph-block-external
provisioner: rook-ceph.rbd.csi.ceph.com
parameters:
clusterID: rook-ceph-external
pool: replicapool
CephCluster Federation 关键点
| 维度 | 注意事项 |
|---|---|
| 网络互通 | 外部 K8s 集群节点必须能访问 Ceph 集群的 MON/OSD 网络 |
| 认证隔离 | 通过 Ceph Auth 为每个外部集群创建独立 keyring,限制 Pool 访问权限 |
| 性能影响 | 跨集群 I/O 路径增加网络延迟,建议同数据中心部署 |
| CSI 版本 | 外部集群的 CSI 驱动版本应与 Ceph 版本兼容 |
22 Rook 的性能调优(Network / BlueStore / PG 数量 / OSD 内存)
答案:
Ceph 集群性能受网络、存储引擎、PG 数量和 OSD 资源等因素共同影响,需从多个维度系统调优。
网络层调优
[global]
ms_type = async+posix # 异步消息层
ms_async_op_threads = 4 # OSD 工作线程
ms_bind_port_min = 6800
ms_bind_port_max = 7300
[osd]
osd_op_num_threads_per_shard = 2 # SSD 建议 2~4,HDD 建议 1
osd_op_num_shards = 8 # OSD 分片数
内核网络参数
# /etc/sysctl.d/90-ceph.conf
net.core.rmem_max = 134217728 # 128MB 接收缓冲区
net.core.wmem_max = 134217728 # 128MB 发送缓冲区
net.ipv4.tcp_rmem = 4096 87380 134217728
net.ipv4.tcp_wmem = 4096 65536 134217728
net.core.netdev_max_backlog = 300000
BlueStore 缓存调优
[osd]
# HDD 优化
bluestore_cache_size_hdd = 4GB
bluestore_cache_size_ssd = 4GB
bluestore_cache_kv_ratio = 0.6 # 60% 给 RocksDB 缓存,40% 给 onode 缓存
bluestore_cache_meta_ratio = 0.6 # 元数据缓存占比
# RocksDB 调优
bluestore_rocksdb_options = "compression=kLZ4Compression,max_write_buffer_number=8,min_write_buffer_number_to_merge=2,write_buffer_size=256MB,max_bytes_for_level_base=4GB,max_background_jobs=8"
PG 数量调优
| 每 OSD PG 数 | 影响 | 建议 |
|---|---|---|
| < 50 | 数据分布可能不均 | 增加 PG |
| 50 ~ 100 | 资源消耗低,Variance 略高 | 可接受 |
| 100 ~ 200 | 平衡数据分布与资源消耗 | 推荐区间 |
| > 300 | OSD 内存和 CPU 压力大,Peering 时间长 | 减少 PG 或增加 OSD |
OSD 内存配置
[osd]
osd_memory_target = 8GB # Ceph 自动管理 OSD 内存上限
osd_memory_cache_min = 512MB # 保留缓冲
bluestore_cache_autotune = true # 自动调整 BlueStore 缓存
Rook 集群资源配置
apiVersion: ceph.rook.io/v1
kind: CephCluster
spec:
resources:
osd:
limits:
cpu: "8"
memory: "16Gi"
requests:
cpu: "2"
memory: "4Gi"
mon:
limits:
cpu: "2"
memory: "4Gi"
mgr:
limits:
cpu: "1"
memory: "2Gi"
网络延迟要求
| 存储类型 | 推荐延迟 | 最低要求 |
|---|---|---|
| HDD 集群 | < 5ms | < 15ms |
| SSD 集群 | < 2ms | < 5ms |
| NVMe 集群 | < 500us | < 2ms |
23 Rook 的监控与 Prometheus 集成
答案:
Ceph 通过 MGR Prometheus 模块暴露集群级别指标,Rook 集成 Ceph Mixin 提供预配置的 Prometheus 告警规则和 Grafana Dashboard。
Prometheus 指标暴露
apiVersion: ceph.rook.io/v1
kind: CephCluster
spec:
monitoring:
enabled: true
rulesNamespace: rook-ceph
mgr:
modules:
- name: prometheus
enabled: true
ServiceMonitor 自动创建
Rook 检测到集群中运行 Prometheus Operator 后自动创建 ServiceMonitor:
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: rook-ceph-mgr
namespace: rook-ceph
spec:
endpoints:
- port: http-metrics
interval: 15s
selector:
matchLabels:
app: rook-ceph-mgr
核心监控指标
| 指标类型 | Prometheus Metric | 关注点 |
|---|---|---|
| 集群健康 | ceph_health_status | 0=OK / 1=WARN / 2=ERR |
| OSD 状态 | ceph_osd_up / ceph_osd_in | UP=在线 / IN=参与数据分布 |
| PG 状态 | ceph_pg_total / ceph_pg_active / ceph_pg_clean | active+clean 比例 |
| 容量 | ceph_cluster_total_bytes / ceph_cluster_total_used_bytes | 使用率与剩余容量 |
| OSD I/O | ceph_osd_op_r / ceph_osd_op_w / ceph_osd_op_latency | 读写 I/O 延迟 |
| RGW | ceph_rgw_req / ceph_rgw_get / ceph_rgw_put | RGW 吞吐量 |
| 网络 | ceph_osd_network_send_bytes / ceph_osd_network_recv_bytes | OSD 间复制流量 |
关键告警规则
groups:
- name: ceph.rules
rules:
- alert: CephClusterDown
expr: ceph_health_status > 0
for: 5m
labels:
severity: critical
annotations:
summary: "Ceph 集群不健康"
- alert: CephOsdDown
expr: ceph_osd_up == 0
for: 5m
labels:
severity: critical
annotations:
summary: "Ceph OSD XQOPEN $labels.ceph_daemon XQCLOSE 已下线"
- alert: CephPGsInactive
expr: ceph_pg_inactive > 0
for: 1m
labels:
severity: critical
annotations:
summary: "XQOPEN $value XQCLOSE 个 PG 处于 inactive 状态"
- alert: CephPGsStuck
expr: ceph_pg_stuck_inactive / ceph_pg_total > 0.01 or
ceph_pg_stuck_unclean / ceph_pg_total > 0.01
for: 10m
labels:
severity: critical
- alert: CephClusterNearFull
expr: ceph_cluster_total_used_bytes / ceph_cluster_total_bytes > 0.85
labels:
severity: critical
Grafana Dashboard
通过 Ceph Mixin 导入 JSON Dashboard 文件,内置以下面板组:
- OSD 概览(延迟 / 吞吐量 / 容量)
- Pool 概览(I/O / 容量 / PG 状态)
- RGW 概览(请求量 / 延迟 / 错误数)
- Host 概览(CPU / 内存 / 磁盘 / 网络)
24 Ceph 的纠删码(Erasure Coding)与多副本对比
答案:
纠删码将数据分片为 k 个数据块和 m 个校验块,通过计算校验块实现冗余保护。相比多副本,纠删码以更低的存储开销获得同等容错能力。
EC 配置示例
apiVersion: ceph.rook.io/v1
kind: CephBlockPool
metadata:
name: ec-pool
namespace: rook-ceph
spec:
failureDomain: host
erasureCoded:
dataChunks: 4
codingChunks: 2
parameters:
crush-failure-domain: host
EC 冗余率对照
| EC 策略 | 数据块数 (k) | 校验块数 (m) | 允许故障数 | 存储效率 |
|---|---|---|---|---|
| 4+1 | 4 | 1 | 1 | 80% |
| 4+2 | 4 | 2 | 2 | 67% |
| 6+2 | 6 | 2 | 2 | 75% |
| 8+2 | 8 | 2 | 2 | 80% |
| 8+3 | 8 | 3 | 3 | 73% |
| 16+4 | 16 | 4 | 4 | 80% |
EC vs Replication 对比
| 维度 | Erasure Coding | Replication |
|---|---|---|
| 存储效率 | 高(6+2 = 1.33x) | 低(3 副本 = 3x) |
| 小 I/O 性能 | 差(需 stripe 对齐) | 好(单副本读) |
| 大 I/O 性能 | 好(多盘并发读) | 好 |
| 写入延迟 | 较高(编码计算) | 较低 |
| 恢复速度 | 慢(需解码计算) | 快(直接复制) |
| CPU 开销 | 较高 | 无 |
| 适用场景 | 对象存储 / 冷数据 / 大规模归档 | 块存储 / 数据库 / 热数据 |
EC 适用约束
| 约束 | 说明 |
|---|---|
| 仅全写 | RBD EC 池需要 imageFeatures: layering,不支持部分写入 |
| 故障域要求 | EC 中的 m 个校验块必须分布在 m 个故障域,因此 host 故障域要求节点数 >= k+m |
| 不适合小 I/O | 每次写入需要重新计算 stripe,小于 stripe 宽度的写入触发 RMW(Read-Modify-Write) |
| 仅 RGW 天然支持 | EC 对 RGW 对象存储是透明支持的;RBD 从 Luminous 开始支持 |
25 Ceph 的 CRUSH Map 手动调优与故障域隔离
答案:
CRUSH Map 定义集群的物理拓扑和故障域层次,精细调优 CRUSH Map 可以有效提升故障容错能力和数据分布均衡性。
CRUSH Map 层次结构示例
# buckets
host node-1 {
id -3
alg straw2
hash 0
item osd.0 weight 7.275
item osd.1 weight 7.275
}
host node-2 {
id -4
alg straw2
hash 0
item osd.2 weight 7.275
item osd.3 weight 7.275
}
rack rack-a {
id -10
alg straw2
hash 0
item node-1 weight 14.550
item node-2 weight 14.550
}
rack rack-b {
id -11
alg straw2
hash 0
item node-3 weight 14.550
item node-4 weight 14.550
}
root default {
id -1
alg straw2
hash 0
item rack-a weight 29.100
item rack-b weight 29.100
}
CRUSH Rule 示例
// 在不同 Rack 上放置 3 副本
rule replicated_rack {
id 1
type replicated
min_size 1
max_size 10
step take default
step chooseleaf firstn 0 type rack
step emit
}
// 在不同 Host 上放置 EC 6+2
rule ec_host {
id 2
type erasure
min_size 6
max_size 8
step set_chooseleaf_tries 5
step set_choose_tries 100
step take default
step choose indep 0 type host
step choose indep 8 type osd
step emit
}
CRUSH Map 注入与验证
# 导出当前 CRUSH Map
ceph osd getcrushmap -o /tmp/crushmap.bin
crushtool -d /tmp/crushmap.bin -o /tmp/crushmap.txt
# 编辑 /tmp/crushmap.txt 后的注入
crushtool -c /tmp/crushmap.txt -o /tmp/crushmap_new.bin
ceph osd setcrushmap -i /tmp/crushmap_new.bin
# 验证 PG 分布
ceph osd df tree | sort -nk4
CRUSH 权重调整技巧
| 场景 | 操作 |
|---|---|
| OSD 容量差异大 | 通过 reweight-by-utilization 按使用率动态调整权重 |
| 新节点加入后数据不均 | 调高新节点 OSD 权重,运行 balancer |
| 临时下线 OSD | 先 reweight 0 轻柔逐出,而非直接 out |
| 长期容量规划 | 统一 OSD 磁盘容量,避免同集群混合不同大小 OSD |
26 Ceph 的 QoS 与 Scrub / Deep-Scrub 机制
答案:
Ceph 通过 mClock QoS 调度器和 Scrub / Deep-Scrub 机制分别实现 I/O 优先级控制和数据完整性校验。
mClock QoS 调度器
mClock 将 OSD 操作分为三类,以 Reservation / Weight / Limit 三维控制:
| 操作类型 | 说明 | 优先级 |
|---|---|---|
| Client Ops | 用户 I/O(读写请求) | 高 |
| Recovery Ops | 数据恢复(degraded PG) | 中 |
| Scrub / Snaptrim | 数据校验与快照清理 | 低 |
mClock 配置参数
[osd]
osd_mclock_profile = high_client_ops # 生产推荐
# 可选: high_recovery_ops / balanced / high_client_ops
osd_mclock_profile_custom_parameters = "reservation,weight,limit"
osd_mclock_max_capacity_iops_hdd = 315 # HDD 默认 IOPS 容量
osd_mclock_max_capacity_iops_ssd = 21500 # NVMe 默认 IOPS 容量
Scrub 与 Deep-Scrub 对比
| 维度 | Scrub (Light) | Deep-Scrub |
|---|---|---|
| 校验内容 | 对象元数据(大小、属性)与 checksum | 对象完整数据字节级比对 |
| 频率 | 每天(默认) | 每周(默认) |
| I/O 开销 | 低 | 高(读取全量数据) |
| 目的 | 检测元数据不一致 | 检测静默数据损坏(bit rot) |
| 调度控制 | osd_scrub_begin_hour / osd_scrub_end_hour | 同 |
Scrub 调度配置
[osd]
osd_scrub_begin_hour = 0 # Scrub 允许开始时间(0 点)
osd_scrub_end_hour = 6 # Scrub 允许结束时间(凌晨 6 点)
osd_scrub_sleep = 0.1 # Scrub 间隔休眠(秒),降低对业务影响
osd_deep_scrub_interval = 604800 # Deep-Scrub 间隔(7 天,秒)
osd_scrub_max_interval = 2592000 # 最大 Scrub 间隔(30 天)
osd_deep_scrub_stride = 524288 # Deep-Scrub 一次读取块大小(字节)
osd_max_scrubs = 1 # 单 OSD 同时进行的 Scrub 数
osd_scrub_auto_repair = false # 是否自动修复 Scrub 错误(默认仅告警)
Scrub 冲突处理
Scrub 与 Client I/O 冲突时,mClock 自动降低 Scrub 操作优先级,保障用户 I/O 响应。
监控 Scrub 状态
# 查看 Scrub 错误
ceph pg dump | grep -E "scrub|inconsistent"
# 查看 PG 的 Deep Scrub 时间戳
ceph pg dump pgs | awk '{print $1, $20, $21}'
# 手动触发 Scrub
ceph pg scrub <pgid>
ceph pg deep-scrub <pgid>
27 Rook 的节点故障恢复流程
答案:
当 Kubernetes 节点发生故障(宕机 / 网络分区 / 内核崩溃),其上运行的 Ceph 守护进程(OSD / MON 等)随之不可用,集群按以下流程自动恢复:
节点故障检测与响应时序
| 时间线 | 事件 | Ceph 行为 | K8s 行为 |
|---|---|---|---|
| T+0s | 节点不可达 | 与故障节点上 OSD 的 heartbeat 中断 | Node NotReady |
| T+30s | 对端 OSD 报告故障 | ceph osd down | 开始等待 Pod 驱逐超时 |
| T+5min | MON 标记 OSD 为 down | 开始等待 mon_osd_down_out_interval | Pod 可能被驱逐到其他节点 |
| T+10min | MON 标记 OSD 为 out (默认600s) | 触发数据恢复(backfill / recovery) | 替换节点或修复后重新加入 |
| T+N | 数据恢复完成 | PG 重新变为 active+clean | — |
关键超时参数
[mon]
mon_osd_down_out_interval = 600 # OSD down 后标记 out 的延迟(秒)
mon_osd_report_timeout = 900 # MON 等待 OSD 上报的超时
[global]
osd_heartbeat_grace = 20 # OSD 心跳宽限时间(秒)
osd_heartbeat_interval = 6 # OSD 心跳间隔(秒)
Rook 层面节点故障处理
# 1. 检查 OSD 部署情况
kubectl -n rook-ceph get pods -l app=rook-ceph-osd -o wide
# 2. 如节点彻底故障,清理该节点 OSD 以提高恢复速度
kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- \
ceph osd crush remove <node-name>
# 3. 如节点预计长时间不可用,提前手动标记 OSD out
ceph osd out osd.<N> # 手动 out,不等待 mon_osd_down_out_interval
# 4. 节点恢复后重新加入
# Rook Agent 自动检测设备并重建 OSD
节点故障恢复时间优化
| 优化手段 | 效果 |
|---|---|
降低 mon_osd_down_out_interval | 减少等待恢复启动的时间 |
增加 osd_max_backfills | 加速 backfill 并发 |
启用 osd_recovery_sleep = 0 | 取消恢复节流 |
| 部署更多 OSD | 分散恢复 I/O 压力 |
| 使用独立 cluster network | 隔离恢复流量与客户端流量 |
Rook 生产建议
- 设置
allowMultiplePerNode: false避免 MON 单节点多实例。 - 通过
topologySpreadConstraints或podAntiAffinity将 MON / MGR 分散到不同节点和可用区。 - OSD 使用节点本地 PV(hostPath 或 local-storage StorageClass),避免依赖网络存储。
28 Rook 与 Longhorn 对比
答案:
Rook(Ceph)和 Longhorn 均为 CNCF 项目中的 Kubernetes 原生存储方案,但在架构、性能、复杂度和适用场景上存在显著差异。
架构对比
| 维度 | Rook / Ceph | Longhorn |
|---|---|---|
| 存储后端 | 分布式对象存储(RADOS),数据分布由 CRUSH 算法决定 | 每个卷独立副本链,Engine 实例为每个卷创建独立控制器 |
| 元数据管理 | MON 集群独立管理,Paxos 强一致 | 直接存储于 Kubernetes CRD |
| 组件数量 | MON / OSD / MDS / RGW / MGR / CSI(多组件) | Manager / Engine / CSI / UI(轻量) |
| 部署复杂度 | 高(需规划 OSD / MON 数量和拓扑) | 低(Helm 一键部署,自动发现节点磁盘) |
| 最小节点数 | 3 节点(生产推荐) | 2 节点 |
性能对比
| 维度 | Rook / Ceph | Longhorn |
|---|---|---|
| IOPS (4K Random RW) | 高(NVMe 集群可达 100万+) | 中等(受副本 Engine 网络延迟约束) |
| 延迟 | NVMe 集群 < 500us,SSD 集群 < 2ms | 通常 > 1ms(取决于网络和存储介质) |
| 副本开销 | 3 副本 = 3x,EC 模式 6+2 = 1.33x | 3 副本 = 3x,无 EC 选型 |
| 快照 | RBD 原生快照,轻量级 | 基于 QCOW2 层的差分快照 |
| 写放大 | BlueStore 双写(WAL + Data) | 三重写(Volume Head + Snapshot + Replica 同步) |
功能对比
| 功能 | Rook / Ceph | Longhorn |
|---|---|---|
| 块存储 (RWO) | 支持 | 支持 |
| 共享文件存储 (RWX) | 原生 CephFS | NFS-Ganesha(v1.4+) |
| 对象存储 (S3) | 原生 RGW | 不支持 |
| 纠删码 | 支持 | 不支持 |
| 多站点 DR | RBD Mirroring + RGW Multi-Site | Volume Backup + Restore |
| 备份到 S3/NFS | 需额外配置 | 内置 Backup Target 支持 |
| UI 管理 | Ceph Dashboard | 内置简洁 UI |
| Prometheus 集成 | 原生支持 | 原生支持 |
| 灾备自动切换 | 手动 | 手动 |
适用场景
| 场景 | 推荐方案 | 原因 |
|---|---|---|
| 大规模生产(100+ 节点,PB 级) | Rook / Ceph | 成熟稳定,EC 低冗余,性能优秀 |
| 中小规模(10~50 节点) | Longhorn 或 Rook | 根据团队能力选择 |
| 边缘 / 轻量部署(3~10 节点) | Longhorn | 部署简单,维护成本低 |
| 数据库(MySQL / PostgreSQL) | Rook / Ceph(RBD) | 低延迟,高 IOPS,Snapshots 支持 |
| 共享存储(Nginx 静态内容 / AI 训练数据) | Rook / Ceph(CephFS) | 原生 RWX |
| 对象存储需求 | Rook / Ceph | RGW 原生 S3 API |
29 Rook 的常见故障排查(OSD Flapping / PG Stuck / Slow Request)
答案:
Ceph 集群稳定运行期间可能遇到 OSD Flapping、PG 卡住、慢请求等故障,需系统排查定位。
OSD Flapping
OSD 频繁 up/down 切换,导致持续 Peering 和恢复。
排查步骤
# 1. 确认 OSD 震荡模式
ceph osd tree | grep -E "up|down"
ceph -w | grep -i osd
# 2. 查看 OSD 日志
kubectl -n rook-ceph logs rook-ceph-osd-<N> --tail=200 | grep -iE "heartbeat|timeout"
# 3. 检查节点资源
kubectl top node <node-name>
# 4. 检查网络延迟
ping -c 100 <osd-node-ip> | grep avg
常见原因与解决方案
| 原因 | 症状 | 解决方案 |
|---|---|---|
| OSD 内存不足 | OOM Kill | 增加 osd_memory_target 或节点内存 |
| 磁盘 I/O 超时 | slow request 日志 | 更换磁盘或增加 bluestore_cache_size |
| 网络丢包 / 高延迟 | Heartbeat timeout | 检查网络设备、MTU、交换机 |
| 磁盘满 | osd full | 清理或扩容 |
| 时钟不同步 | MON 拒绝心跳 | 配置 NTP |
PG Stuck(PG 卡住)
PG 长期处于非 active+clean 状态。
# 1. 查看 stuck PG
ceph pg dump_stuck inactive
ceph pg dump_stuck unclean
ceph pg dump_stuck stale
# 2. 查询特定 PG 的详细信息
ceph pg <pgid> query | jq '.state, .blocked_by, .peering_blocked_by'
# 3. 检查 OSD 是否 up 且 in
ceph osd tree
# 4. 检查 MON 是否形成 quorum
ceph mon stat
PG 卡住常见原因
| PG 状态 | 原因 | 解决方案 |
|---|---|---|
| stale | MON 长时间未收到 OSD 心跳 | 检查 OSD 进程是否运行,网络是否可达 |
| inactive | Peering 未完成,OSD 间无法达成一致 | 检查故障 OSD 是否过多,网络连通性 |
| degraded | 副本数不足 | 等待恢复完成或 manual repair |
| incomplete | PG 日志不完整,数据可能丢失 | 检查 osd_find_best_info_ignore_history_les 高级修复 |
| remapped | OSD out 后 PG 重新映射 | 等待 backfill 完成 |
Slow Request(慢请求)
# 1. 查看慢请求
ceph daemon osd.<N> ops | jq '.slow_ops'
# 2. 查看 OSD 延迟
ceph osd perf
# 3. 查看实时 I/O
ceph -w | grep -i slow
# 4. 分析具体阻塞原因
ceph daemon osd.<N> dump_historic_ops | jq '.ops[] | select(.description | contains("blocked"))'
慢请求排查清单
| 检查项 | 命令 | 阈值参考 |
|---|---|---|
| 磁盘利用率 | ceph osd df | > 85% 触发 nearfull |
| 磁盘延迟 | iostat -x 1 | HDD await > 20ms / SSD await > 5ms |
| CPU / 内存 | kubectl top pod | CPU > 80% / Memory > 90% |
| 网络丢包 | ping / iperf3 | 丢包 > 0.1% |
| PG 恢复进度 | ceph -s | 大量 degraded / misplaced objects |
30 Rook Ceph on Kubernetes 生产环境最佳实践
答案:
生产环境部署 Rook Ceph 需从集群规划、资源配置、安全隔离、监控告警、备份恢复和运维流程等多个维度系统设计。
集群规划
| 维度 | 推荐配置 | 说明 |
|---|---|---|
| 最小节点数 | 5 节点(3 MON + OSD) | 满足 MON quorum 并为 OSD 提供足够节点 |
| MON 数量 | 3(奇数) | 允许 1 个 MON 故障 |
| OSD 磁盘类型 | 同质化(统一 HDD 或 SSD) | 避免容量和性能差异导致数据倾斜 |
| 网络 | 10Gbps+ 双网分离(Public + Cluster) | OSD 间恢复流量与客户端 I/O 隔离 |
| Kubernetes 版本 | 与 Rook 兼容版本(参考 Rook 官方兼容矩阵) | 避免 API 弃用 |
资源配置
apiVersion: ceph.rook.io/v1
kind: CephCluster
spec:
# 版本锁定
cephVersion:
image: quay.io/ceph/ceph:v18.2.1
allowUnsupported: false
# 节点亲和性:MON 跨 AZ
placement:
mon:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app: rook-ceph-mon
topologyKey: kubernetes.io/hostname
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
# PG Autoscaler
mgr:
modules:
- name: pg_autoscaler
enabled: true
# 存储:使用 local-storage PV
storage:
useAllNodes: false # 关闭自动发现
nodes:
- name: node-1
devices:
- name: /dev/nvme0n1
config:
osdsPerDevice: "1"
deviceClass: nvme
# 健康检查
healthCheck:
daemonHealth:
mon:
interval: 45s
osd:
interval: 60s
livenessProbe:
mon:
periodSeconds: 10
mgr:
periodSeconds: 10
osd:
periodSeconds: 10
# 日志保留
logCollector:
enabled: true
periodicity: daily
maxLogSize: 500M
# 监控集成
monitoring:
enabled: true
安全加固
| 策略 | 配置 |
|---|---|
| TLS 通信 | 启用 Dashboard SSL,RGW HTTPS |
| Secret 加密 | CephCluster 配置 security.kms 集成外部 KMS |
| 网络策略 | 通过 NetworkPolicy 限制 MON / OSD 间通信仅允许必要端口 |
| RBAC 最小权限 | Rook Operator 使用专用 ServiceAccount,Role 限定 rook-ceph Namespace |
| 禁用不安全访问 | Dashboard 密码使用 Secret 管理,定期轮换 |
| Ceph Auth 最小权限 | CSI 驱动使用独立的 client keyring,仅授权特定 Pool 和 MDS 访问 |
存储池设计
# 热数据池:SSD / NVMe,3 副本,高性能
apiVersion: ceph.rook.io/v1
kind: CephBlockPool
metadata:
name: fast-pool
spec:
deviceClass: ssd
failureDomain: host
replicated:
size: 3
requireSafeReplicaSize: true
# 温数据池:HDD,EC 6+2,大容量低成本
apiVersion: ceph.rook.io/v1
kind: CephBlockPool
metadata:
name: archive-pool
spec:
deviceClass: hdd
failureDomain: rack
erasureCoded:
dataChunks: 6
codingChunks: 2
运维检查清单
| 频率 | 检查项 | 命令 / 指标 |
|---|---|---|
| 每日 | 集群健康状态 | ceph -s / ceph health detail |
| 每日 | OSD 容量均衡 | ceph osd df tree 关注 Variance |
| 每周 | Deep-Scrub 进度 | `ceph pg dump |
| 每周 | Rook Operator 日志 | kubectl -n rook-ceph logs deploy/rook-ceph-operator --tail=500 |
| 每月 | Ceph 版本更新评估 | 对比 Rook Release Notes 与当前版本 |
| 每月 | 备份验证 | 测试 RBD Snapshot 恢复和 S3 备份可读性 |
| 每季度 | 容灾演练 | 模拟节点故障、MON 故障恢复流程 |
| 每季度 | 容量规划 | 根据趋势预测 6 个月后容量需求 |
升级建议
- Rook Operator 先升级,再升级 Ceph 版本。
- 升级前执行
ceph osd set noout防止短暂的 OSD 震荡触发不必要的数据迁移。 - 逐节点或逐 OSD 灰度升级,观察 PG 状态和 I/O 延迟。
- 升级完成后执行
ceph osd unset noout。 - 大版本升级(如 Pacific -> Quincy)前创建 MON 数据备份(
ceph-monstore-tool)。
节点故障恢复 SOP
- 确认节点故障范围和影响面(哪些 OSD / MON 受影响)。
- 若为 MON 故障且 quorum 已丢失,优先恢复 MON。
- 若为 OSD 故障,评估是否需手动
ceph osd out以加速恢复。 - 监控 PG 恢复进度,关注恢复 I/O 是否挤占客户端 I/O(必要时调整 mClock)。
- 节点恢复后验证 OSD 重新加入集群。
- 复盘故障原因,更新监控告警阈值。