news 2026/10/2 1:47:48

Ceph分布式存储作为K8s后端存储的选型与接入实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Ceph分布式存储作为K8s后端存储的选型与接入实践

做K8s久了的人迟早会跟存储打正面交道。带公网云盘的场景还算省心,但私有化部署、数据合规、机房自建这些环境里,最常被拉出来当主力方案的名字就是Ceph。我刚看到一位朋友的项目标题是“最新版Ceph(tentacle版本)文件存储(k8s后端存储)”,加上几组围绕Ceph、文件存储、K8s的关联词,这套需求摆在一起,基本就是一套私有云场景下分布式存储的标准开局。我结合自己这些年跑Ceph和K8s集群的实操经历,把这套方案从选型思路、部署细节、CSI接入到排障实录,整条链路拆开讲一遍。适合正在规划存储选型的K8s维护者,也适合刚入门分布式存储、想在K8s上接一套靠谱后端存储的朋友。

1. 整体设计思路:为什么是Ceph

1.1 K8s后端存储的几个常见选择与Ceph的位置

先看K8s里常见的存储方案对比,你才能理解Ceph在“后端存储”这个位置上到底解决了什么别人解决不了的问题。第一种是本地磁盘,emptyDir也好、hostPath也好,优点是真的快、真的简单,但Pod一漂移数据就跟着完蛋,节点坏了也没人帮你恢复,只适合放缓存和临时数据。第二种是传统NFS,部署简单、共享方便,但单机NFS服务本身就是单点,性能上不去,网络抖动时整个集群都在等IO,K8s节点一多就卡成幻灯片。第三种是公有云云盘,性能和数据可靠性都有云厂商兜底,但在内网、私有化、政务金融这些环境里根本用不了,或者说成本高到离谱。

Ceph能成为K8s后端存储的常见选择,核心原因是它把“一套集群、多种接口”这件事做成了。底层是RADOS这个自愈的分布式对象存储层,往上长出了三种访问接口:RBD块存储、CephFS文件系统、RGW对象网关。K8s里的PVC要块设备给数据库用,RBD顶上;业务要一个多Pod共享的文件目录,CephFS顶上;海量上传文件要做对象归档,RGW以S3协议提供。一套存储集群同时喂饱不同的业务形态,这比每种存储都重新搭一套省太多事。

你标题里写的是“tentacle版本”。我手头跑过的Ceph版本从Luminous到Quincy、Reef都有接触,版本代号这东西在社区更替很快,但核心架构和接口逻辑保持得很稳。在实际运维里,版本号代表的是新特性和运维方式的变化,不会推翻你已有的存储架构认知。所以下面讲的接入方法,换到不同版本同样成立,新版本只是在部署工具、Dashboard能力和部分性能上有改进,接入K8s的CSI流程基本不变。

1.2 文件存储场景下:RBD、CephFS、RGW怎么分配

很多人混淆“文件存储”这个词,以为CephFS才是文件存储,RBD不算。实际上从K8s视角看,PV的访问模式才是决定选型的关键。

类型协议K8s访问模式典型场景局限
RBD块设备RWO(少数场景支持ROX)MySQL、PostgreSQL、Redis等需要独立块设备的工作负载默认同一时刻只允许一个节点挂载,共享能力弱
CephFS文件系统RWX(多节点共享)多Pod共享目录、用户上传文件、Java外部文件存储、数据流水线元数据性能是关键,小文件多时需要单独调优
RGW对象存储/S3对外API海量非结构化数据、备份归档、图片视频存储不适合K8s直接做PV,适合业务通过SDK读写

如果你的“文件存储”指的是K8s里的共享文件目录,那主选就是CephFS。如果只是说Ceph这套系统作为K8s后端存储来用,那RBD其实是默认主力,因为K8s里绝大多数有状态应用要的是一块独立、可靠的块设备。我在实际规划中一般这样分配:数据库、消息队列这类有状态中间件用RBD;需要多副本共享目录、业务代码要把外部文件落到统一路径的应用,用CephFS;对象存储有S3兼容需求时直接给RGW。这样一层一层分下来,存储方案会非常立体。

1.3 为什么新集群推荐直接用Cephadm

老资格的Ceph运维以前用ceph-deploy、手动改配置文件那套,步骤多还容易出低级错误。新版本官方已经统一推荐cephadm,所有组件都容器化,一条命令就能拉起bootstrap,后续添加OSD、管理Dashboard都通过CLI完成,K8s侧接入时只需要从同一个集群拿keyring和monitor地址,不存在因为手工配置产生的版本错位问题。

有个很重要但容易被忽略的点:Ceph和K8s都是吃资源的大户,规划时必须提前隔离好网络和机器。K8s节点和Ceph OSD节点不推荐混部,尤其是Ceph要求低延迟、高吞吐的网络,一旦跟K8s的Pod网段抢带宽,两边都难受。后面部署环节我会给出更具体的规划建议。

2. 部署准备与关键配置细节

2.1 集群规划:节点、数据盘、网络、PG数

Ceph不是装完就能跑的玩具,前期规划决定了后面几年你睡不睡得着觉。我按常见的生产环境规模给出一个参考方案:正式环境至少3个物理节点同时承担mon和OSD角色,数据盘每节点建议4到10块SSD或HDD,单独一块系统盘装操作系统。如果有条件,mon、mgr和OSD分离到物理机上更好,但最小规模下合并跑也能接受,前提是机器配置别太寒碜。

网卡方面,Ceph的公共网络和集群网络建议分开。公共网络走业务流量,集群网络专门跑OSD之间的数据复制和心跳,两套网络至少万兆起步。千兆网络跑Ceph会卡到你怀疑人生,rebalance和慢请求轮着来。交换机上记得开启足够的MTU,配置9000字节巨型帧能明显改善大块顺序读写性能。

时钟同步是另一个老生常谈但翻车率极高的点。Ceph的RADOS层依赖各节点时间偏差很小,建议所有节点统一配置chrony同步NTP服务器。我碰到过因为某台机器时间慢了几十秒,OSD之间反复报错、PG状态来回震荡的情况,排查一整天最后发现就是时钟问题,接入K8s时PVC都正常,但集群健康度始终蹦红灯。

PG(归置组)数量在创建存储池前就要算清楚。PG数不是越多越好,一个OSD承载的PG太多会耗内存;太少又可能影响数据分布均衡。常用的参考公式是:PG总数 ≈ (OSD总数 × 100) / 副本数,然后向上取到2的幂次。举个例子,3个节点、每节点10块OSD,总OSD数30,副本数3,计算结果是(30 × 100) / 3 = 1000,向上取2的幂就是1024。这是单个池的理想PG值,如果创建几个池,再按池分配。

2.2 cephadm部署流程与关键参数

新版Ceph用cephadm拉起集群非常快,先把docker或podman装好,然后执行:

cephadm bootstrap --mon-ip 192.168.10.10 --initial-dashboard-password <admin密码> --allow-fqdn-hostname

bootstrap完成后,cephadm会把CLI写到/usr/local/bin/ceph,直接用ceph命令操作即可。这一步会自动部署mon、mgr和Dashboard,然后通过ceph orch命令添加OSD:

ceph orch device ls ceph orch apply osd all --placement="node1,node2,node3"

CephFS需要单独创建,默认不会自动生成:

ceph fs volume create fs_data ceph fs ls ceph fs status fs_data

创建完成之后,可以看到文件系统的元数据池和数据池,后面给K8s用的时候,StorageClass需要引用这些存储池。

生产环境中我还会调整几个参数:关闭scrub高峰期的资源抢占可以设置ceph config set osd osd_max_backfills 1;网络丢包较敏感的环境可以调整ceph config set global osd_pool_default_min_size 1,允许降级写。但这些参数要结合你的业务容忍度来调,不要照抄。

2.3 部署完成后必须做的健康检查

接入K8s之前,先确保Ceph集群本身是干净的。重点看三条命令的输出:

ceph -s ceph osd tree ceph fs status

ceph -s里如果HEALTH_ERR,先处理到HEALTH_WARN甚至HEALTH_OK再往K8s走。我第一次在有少量PG处于degraded状态时就直接接CSI,结果PVC创建成功后读写偶尔报IO错误,排查时根本分不清是Ceph的问题还是CSI的问题,白白浪费一个晚上。先让存储集群洗干净,这是铁律。

3. K8s接入Ceph的完整实操

3.1 CSI驱动安装与授权

现阶段的K8s接入Ceph,标准做法是通过Ceph CSI插件。官方提供两个driver:rbd.csi.ceph.com和cephfs.csi.ceph.com,对应块存储和文件系统。Rook也是常见的部署方式,但它本质上是用Operator帮你管理Ceph和CSI,更重一些,如果你只是想用Ceph做后端存储而不打算把它交给Rook统一运维,直接用官方CSI更轻、更透明。

从GitHub拉取ceph/ceph-csi仓库的release版本,进入deploy/目录,依次应用RBAC和ConfigMap:

kubectl create -f deploy/cephcsi/rbac/ kubectl create -f deploy/cephcsi/config/

CSI插件对外提供服务时,需要知道Ceph集群的monitor地址、用户名和keyring。先把这些信息提取出来:

ceph mon dump | grep mon_host ceph auth get client.admin

你会在输出里找到mon地址和client.admin的key。接下来创建独立的K8s Secret,保存这些信息:

cat <<EOF | kubectl apply -f - apiVersion: v1 kind: Secret metadata: name: csi-rbd-secret namespace: default stringData: userID: admin userKey: <client.admin的key> EOF

CephFS同理,需要另一份Secret存管理员的key。实际生产环境不建议直接用admin,可以单独创建只读权限或按池授权的最小权限账号,但最小权限账号较复杂,初学者先用admin跑通链路,后续再收敛权限。

3.2 动态PV:RBD块存储接入K8s

RBD是K8s后端存储中最常用的接口,因为它天然适合有状态应用。通过StorageClass + PVC的方式,可以让K8s在PVC创建时自动在Ceph里建立对应的RBD image,这个过程叫动态供给,省去手动创建块设备再绑定PV的繁琐操作。

先创建StorageClass:

apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: csi-rbd-sc provisioner: rbd.csi.ceph.com parameters: clusterID: <请填入Ceph集群ID> pool: fs_data.data csi.storage.k8s.io/fstype: ext4 imageFeatures: layering csi.storage.k8s.io/controller-expand-secret-name: csi-rbd-secret csi.storage.k8s.io/controller-expand-secret-namespace: default reclaimPolicy: Delete volumeBindingMode: Immediate allowVolumeExpansion: true

clusterID可以通过ceph fsid拿到,这是Ceph集群的唯一标识。pool指定你要在那个池里创建RBD image,比如CephFS的数据池或单独的rbd池。allowVolumeExpansion设为true是很实用的一个参数,后续PVC容量不够时可以动态扩容。

StorageClass准备好后,创建PVC和测试Pod:

apiVersion: v1 kind: PersistentVolumeClaim metadata: name: rbd-pvc spec: accessModes: - ReadWriteOnce storageClassName: csi-rbd-sc resources: requests: storage: 10Gi
apiVersion: v1 kind: Pod metadata: name: rbd-demo spec: containers: - name: app image: nginx volumeMounts: - name: data mountPath: /data volumes: - name: data persistentVolumeClaim: claimName: rbd-pvc

PVC创建后,K8s会调CSI provisioner去Ceph集群创建RBD image,完成后PV自动绑定,Pod起来后直接能读写。整个过程里K8s集群里会出来PV对象,Ceph集群里能看到对应的rbd image。

3.3 CephFS文件存储接入K8s:多Pod共享的解决办法

如果业务场景里有多个Pod需要同时读写同一个目录,RBD的RWO模式就不够用了。比如Java应用处理用户上传文件,一台Pod处理完把文件存储在挂载路径,另一台Pod同步消费这批文件,这时候需要CephFS提供ReadWriteMany能力。

先给CephFS创建StorageClass:

apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: csi-cephfs-sc provisioner: cephfs.csi.ceph.com parameters: clusterID: <Ceph集群ID> fsName: fs_data pool: fs_data.data csi.storage.k8s.io/controller-expand-secret-name: csi-cephfs-secret csi.storage.k8s.io/controller-expand-secret-namespace: default reclaimPolicy: Delete allowVolumeExpansion: true

然后创建PVC时把accessModes设为ReadWriteMany。多个Pod挂载同一个PVC后,在各自容器内看到的是同一个CephFS后端目录,文件写入后其他Pod立即可见,这和传统NFS的体验一致,但底层是分布式的,不怕单点故障。

CephFS的动态供给默认会在文件系统里创建独立的子卷。实际上CephFS支持用静态PV的方式手动指定已有的子卷路径,这在从旧NFS迁移到CephFS时非常有用:先在CephFS里建好目录,然后把目录路径写进PV的volumeHandle,Pod直接挂载指定目录,不用动业务代码就完成存储替换。

我遇到过一个需求,业务侧希望把手机上传输到电脑上的文件存储路径统一变到共享存储上,听着像是本地软件设置问题,但在企业内部其实是一个典型场景:各种散落在各台机器上的文件、上传目录,要统一收拢到一个可共享、可扩容、可备份的地方。CephFS在K8s里做后端存储之后,业务代码只要把文件写到挂载路径,底层就落在CephFS里,存储路径的“迁移”变成了K8s应用发布时的一次配置变更,不需要改代码,也不需要每台机器手工调整,这是文件存储方案比本地路径最有优势的地方。

3.4 对象网关RGW:给Java等外部业务提供S3存储

RGW走的是S3协议,对于Java这类生态成熟的语言,通过AWS SDK就能直接访问。数据不经过K8s的CSI挂载,而是业务代码用SDK读写,特别适合处理海量图片、日志、附件。

在Ceph侧只需要配置RGW服务:

ceph orch apply rgw rgw_svc --placement="node1,node2,node3"

RGW默认监听80端口,Cephadm会自动生成服务地址。之后Java应用里引入AmazonS3客户端库,配置endpoint为RGW服务地址、access key和secret key,就能对桶做PUT/GET操作。Java外部文件存储“如何实现”这个问题,如果数据量不大就用CephFS挂载路径,文件量大了走RGW+S3才是更合理的路线,对象存储不需要做文件系统目录规划,桶内存储海量对象也不存在目录层级性能衰减的问题。

3.5 数据安全与备份策略

K8s接入Ceph后,存储层面还要做一些基本功。RBD快照可以通过CSI的VolumeSnapshot机制在K8s里创建,这意味着应用层可以定期给PVC做快照,配合CephFS的快照功能,数据恢复就能秒级完成。我通常建议按业务重要程度设置快照频率:核心数据库每天至少一次快照,保留7到14天;普通文件存储每周一次快照。Ceph快照本身不占太大空间,但保留太多会拖累集群性能,要严格控制保留策略。

CephFS还支持ceph fs set fs_data allow_new_snapshots true来开启快照功能。此外,容灾层面如果预算允许,可以做跨机房的RBD镜像,但实际维护成本不低,很多团队会退而求其次用快照+定期导出的方式做异地备份。我个人经验是,快照能救99%的误删误改场景,先把快照机制在K8s侧配好,比纠结容灾架构更实际。

4. 常见故障与排查技巧实录

4.1 Ceph集群健康问题排查

接入K8s之后,最怕的是Ceph集群本身出问题但K8s侧毫无感知,只会报IO错误。常用的排查入口就是ceph -s和ceph health detail。如果出现HEALTH_ERR,ceph health detail会把具体的PG异常原因列出来。常见的有PG peering失败、PG stuck inactive、scrub错误,处理方式各不相同。

我遇到最多的一个坑是时钟不同步。几台机器的时间差超过50ms,OSD之间就会出现间歇性的心跳超时,ceph -s里能看到clock skew detected,明明所有磁盘都正常,但OSD反复up和down。解决办法就是把chrony配置检查一遍,确认所有节点跑的是同一个NTP源。这个坑太典型了,接入K8s前我做健康检查时基本都会先看一眼时间。

慢请求是另一个高频问题。执行ceph daemon osd.<id> dump_ops_in_flight能看到当前OSD上执行时间过长的操作。慢请求通常由三个原因引起:网络重传率高、磁盘性能不足、或者rebalance和业务IO抢带宽。前者检查网卡丢包率,后者可以在业务低峰期调低rebalance速率,例如ceph config set osd osd_max_backfills 1,给正常的业务IO让路。

4.2 K8s侧挂载失败排查

PVC一直Pending,首先确认事件:

kubectl describe pvc <pvc-name> kubectl get events --sort-by=.lastTimestamp

如果报错是failed to provision volume with StorageClass: storageclass.storage.k8s.io "csi-rbd-sc" not found,说明StorageClass名字没对上,或者CSI插件没有注册成功。先检查CSI插件pod是否Running:

kubectl get pods -n ceph-csi

CSI插件异常常见原因有三个:RBAC授权不足、Secret中的key格式多了换行或空格、monitor地址填错。Secret里的userKey如果从ceph auth get client.admin的返回里复制,经常会带上多余的空格或制表符,导致认证失败。处理办法是复制key后先放到文本编辑器里检查一下,或用echo -n确认字符数。

Pod挂载失败时,报错信息往往在kubelet侧。查看kubelet日志或dmesg里可能出现:`mount: /var/lib/kubelet/pods/xxx: permission denied`。这类问题通常是缺少内核模块或节点没有rbd命令。新版Ceph CSI使用librbd直接实现块设备映射,不依赖宿主机上的rbd命令,但要求内核开启rbd模块。检查方法:

modprobe rbd lsmod | grep rbd

K8s发行版默认不会自动加载rbd模块,最好在节点上配置开机自动加载,否则节点重启后RBD挂载全部失效。

还有一种藏在K8s侧但根因在Ceph侧的场景:Ceph集群正好在做大规模数据均衡或出现慢盘,PVC的创建请求迟迟等不到RBD image分配完成,PVC一直Pending或报超时。这时候在Ceph侧执行ceph -s看有没有大范围rebalancing,先等集群恢复稳定再来看K8s侧是否恢复。

4.3 性能问题与资源规划

跑了几个月后,很多团队会碰到性能劣化。最常见的是把大量小文件放进CephFS。CephFS对小文件场景不算友好,元数据池的压力大,建议适当调大元数据池的缓存,或者干脆把高频小文件场景迁移到RGW对象存储。K8s里用CephFS挂载跑日志聚合这类高并发、小IO的业务,IOPS会很难看。

容量问题也不能忽视。Ceph集群磁盘使用率达到85%左右就必须启动预警。满到nearfull时,新写入会被阻塞,K8s里的新Pod可能起不来,那时候再扩容就慢了。监控方面建议给Dashboard配置告警,或者直接拉Prometheus来采集Ceph exporter指标,和K8s监控打通。

数据库等延迟敏感型的应用,如果跑在RBD上还觉得慢,先检查是不是单副本池或者没有开启分层缓存。我的经验是保留Ceph默认的三副本配置,它的数据可靠性本身就是最有价值的部分,为省空间改副本数往往得不偿失。

4.4 常见问题速查表

现象可能原因排查命令对策
ceph -s显示clock skewNTP未配置或时间漂移chronyc sources -v统一NTP源,重启chronyd
OSD反复up/down网络不稳定或磁盘异常ceph osd tree,dmesg检查网口、光模块,替换故障盘
PVC一直PendingStorageClass配置错误或CSI未注册kubectl describe pvc检查provisioner、Secret、clusterID
Pod挂载失败rbd内核模块未加载modprobe rbd,lsmod配置内核模块开机加载
挂载成功但读写卡顿Ceph集群正在rebalancingceph -s限流backfill,错峰
K8s master初始化报api server不健康容器运行时或网络组件未就绪journalctl -u kubelet检查CRI配置、CNI插件、apiserver证书
CephFS目录大小增长异常业务写入未清理ceph fs status结合快照策略定期清理
Java写文件到CephFS很慢大量小文件导致元数据压力大ceph daemon mds. perf dump优化目录结构、换RGW/S3方案

4.5 从另一个方向抽身看问题:Ceph与K8s协同运维的边界

Ceph和K8s是两个独立的分布式系统,接入之后彼此会互相影响。但我认为运维的边界感很重要:Ceph提供的是存储能力,K8s提供的是应用编排能力。别让存储问题和应用问题缠成一团。

排障时我总是从上往下查:先看应用日志,再查PVC、PV状态,然后进入CSI组件日志,最后才进入Ceph集群内部细节。反过来会被一堆指标淹没。很多K8s集群的Pod频繁Evicted,我觉得大概率要查的不只是Ceph,包括节点资源压力、Pod资源limit、调度器配置等等。Ceph与K8s的协同,排障逻辑先“由外向内”再“由内向外”,效率会高很多。

结尾的最后一点经验

这套Ceph + K8s存储方案,我搭过也救过不少次。踩过的坑里,最深的不是技术文档查不到,而是起初对“存储是大规模基础设施”这件事缺少敬畏,以为装上就能用,出了问题就在各个组件之间来回跳。现在我团队里的约定是先做好容量与网络规划,再考虑新特性,动作可以慢一点,但每一步都要在可控范围内验证。如果你正准备跑一套最新版Ceph做K8s后端存储,我会建议你先在一个两三台机器的小集群上把CSI链路完整跑一遍,拿一个非核心业务上量跑两周,再上生产。这套方案长期用下来的上限很高,可玩性也远非云盘能比,但前提是你愿意给它时间和耐心。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/2 1:46:51

WinForm扫码枪出入库系统:从条码模式到业务事务的完整实践

简介&#xff1a;Windows窗体扫码枪货物出入库与订单管理系统是一套桌面应用程序工程&#xff0c;面向仓库、门店及小型企业&#xff0c;解决货物收发和订单处理依赖人工录入、效率低且容易出错的问题。系统利用扫码枪自动扫描条码或二维码&#xff0c;通过正则表达式匹配扫描结…

作者头像 李华
网站建设 2026/10/2 1:46:37

SpringBoot+SpringCloud电商课设源码调试指南:从SQL导入到微服务启动

简介&#xff1a;这份资源是面向计算机相关专业在校学生、教师及企业开发者的电商系统课程设计/毕业设计源码包&#xff0c;基于Spring Boot与Spring Cloud构建&#xff0c;采用Spring Security、MyBatis、Redis、Docker、Elasticsearch等技术栈&#xff0c;并运用分布式微服务…

作者头像 李华
网站建设 2026/10/2 1:45:58

UFS3.1与MIPI物理层耦合机制深度解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/2 1:43:46

STM32CubeMX本质解析:从图形配置到HAL代码生成的核心逻辑

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/2 1:40:07

汽车电子实战笔记:ECU、CAN、OTA与BCM核心解析

汽车电子这个领域&#xff0c;外行看着是一堆黑盒子&#xff0c;内行看着是一张密密麻麻的网。我干了十多年汽车电子&#xff0c;从最早的纯CAN总线节点&#xff0c;到后来带OTA的域控制器&#xff0c;踩过的坑比写过的代码还多。这篇东西不是教科书&#xff0c;是我自己这些年…

作者头像 李华