ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

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

Ceph分布式存储作为K8s后端存储的选型与接入实践 做K8s久了的人迟早会跟存储打正面交道。带公网云盘的场景还算省心但私有化部署、数据合规、机房自建这些环境里最常被拉出来当主力方案的名字就是Ceph。我刚看到一位朋友的项目标题是“最新版Cephtentacle版本文件存储k8s后端存储”加上几组围绕Ceph、文件存储、K8s的关联词这套需求摆在一起基本就是一套私有云场景下分布式存储的标准开局。我结合自己这些年跑Ceph和K8s集群的实操经历把这套方案从选型思路、部署细节、CSI接入到排障实录整条链路拆开讲一遍。适合正在规划存储选型的K8s维护者也适合刚入门分布式存储、想在K8s上接一套靠谱后端存储的朋友。1. 整体设计思路为什么是Ceph1.1 K8s后端存储的几个常见选择与Ceph的位置先看K8s里常见的存储方案对比你才能理解Ceph在“后端存储”这个位置上到底解决了什么别人解决不了的问题。第一种是本地磁盘emptyDir也好、hostPath也好优点是真的快、真的简单但Pod一漂移数据就跟着完蛋节点坏了也没人帮你恢复只适合放缓存和临时数据。第二种是传统NFS部署简单、共享方便但单机NFS服务本身就是单点性能上不去网络抖动时整个集群都在等IOK8s节点一多就卡成幻灯片。第三种是公有云云盘性能和数据可靠性都有云厂商兜底但在内网、私有化、政务金融这些环境里根本用不了或者说成本高到离谱。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少数场景支持ROXMySQL、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-hostnamebootstrap完成后cephadm会把CLI写到/usr/local/bin/ceph直接用ceph命令操作即可。这一步会自动部署mon、mgr和Dashboard然后通过ceph orch命令添加OSDceph orch device ls ceph orch apply osd all --placementnode1,node2,node3CephFS需要单独创建默认不会自动生成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 statusceph -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插件。官方提供两个driverrbd.csi.ceph.com和cephfs.csi.ceph.com对应块存储和文件系统。Rook也是常见的部署方式但它本质上是用Operator帮你管理Ceph和CSI更重一些如果你只是想用Ceph做后端存储而不打算把它交给Rook统一运维直接用官方CSI更轻、更透明。从GitHub拉取ceph/ceph-csi仓库的release版本进入deploy/目录依次应用RBAC和ConfigMapkubectl 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 EOFCephFS同理需要另一份Secret存管理员的key。实际生产环境不建议直接用admin可以单独创建只读权限或按池授权的最小权限账号但最小权限账号较复杂初学者先用admin跑通链路后续再收敛权限。3.2 动态PVRBD块存储接入K8sRBD是K8s后端存储中最常用的接口因为它天然适合有状态应用。通过StorageClass PVC的方式可以让K8s在PVC创建时自动在Ceph里建立对应的RBD image这个过程叫动态供给省去手动创建块设备再绑定PV的繁琐操作。先创建StorageClassapiVersion: 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: trueclusterID可以通过ceph fsid拿到这是Ceph集群的唯一标识。pool指定你要在那个池里创建RBD image比如CephFS的数据池或单独的rbd池。allowVolumeExpansion设为true是很实用的一个参数后续PVC容量不够时可以动态扩容。StorageClass准备好后创建PVC和测试PodapiVersion: v1 kind: PersistentVolumeClaim metadata: name: rbd-pvc spec: accessModes: - ReadWriteOnce storageClassName: csi-rbd-sc resources: requests: storage: 10GiapiVersion: v1 kind: Pod metadata: name: rbd-demo spec: containers: - name: app image: nginx volumeMounts: - name: data mountPath: /data volumes: - name: data persistentVolumeClaim: claimName: rbd-pvcPVC创建后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创建StorageClassapiVersion: 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的volumeHandlePod直接挂载指定目录不用动业务代码就完成存储替换。我遇到过一个需求业务侧希望把手机上传输到电脑上的文件存储路径统一变到共享存储上听着像是本地软件设置问题但在企业内部其实是一个典型场景各种散落在各台机器上的文件、上传目录要统一收拢到一个可共享、可扩容、可备份的地方。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 --placementnode1,node2,node3RGW默认监听80端口Cephadm会自动生成服务地址。之后Java应用里引入AmazonS3客户端库配置endpoint为RGW服务地址、access key和secret key就能对桶做PUT/GET操作。Java外部文件存储“如何实现”这个问题如果数据量不大就用CephFS挂载路径文件量大了走RGWS3才是更合理的路线对象存储不需要做文件系统目录规划桶内存储海量对象也不存在目录层级性能衰减的问题。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_ERRceph health detail会把具体的PG异常原因列出来。常见的有PG peering失败、PG stuck inactive、scrub错误处理方式各不相同。我遇到最多的一个坑是时钟不同步。几台机器的时间差超过50msOSD之间就会出现间歇性的心跳超时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是否Runningkubectl get pods -n ceph-csiCSI插件异常常见原因有三个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 rbdK8s发行版默认不会自动加载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源重启chronydOSD反复up/down网络不稳定或磁盘异常ceph osd treedmesg检查网口、光模块替换故障盘PVC一直PendingStorageClass配置错误或CSI未注册kubectl describe pvc检查provisioner、Secret、clusterIDPod挂载失败rbd内核模块未加载modprobe rbdlsmod配置内核模块开机加载挂载成功但读写卡顿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链路完整跑一遍拿一个非核心业务上量跑两周再上生产。这套方案长期用下来的上限很高可玩性也远非云盘能比但前提是你愿意给它时间和耐心。
返回列表