Kubernetes 实战:Ceph RBD 动态供给与高可用部署避坑指南
1. 为什么需要Ceph RBD动态供给与高可用部署在Kubernetes生产环境中存储管理一直是运维工作的重点和难点。传统的静态PV配置方式需要管理员手动创建存储卷不仅效率低下还容易造成资源浪费。而Ceph RBD作为分布式块存储方案天然具备高可靠、高性能的特性非常适合作为Kubernetes的后端存储。我曾在多个生产集群中部署过Ceph RBD存储发现动态供给能显著提升运维效率。想象一下当开发团队需要创建100个有状态应用时如果采用静态PV方式管理员需要手动创建100个PV这简直是场噩梦。而动态供给只需要定义好StorageClass开发人员通过PVC就能自动获取存储资源整个过程完全自动化。但动态供给只是第一步高可用部署才是真正的挑战。Ceph RBD虽然本身是分布式存储但在Kubernetes中的使用方式会直接影响应用的可用性。特别是在处理节点故障、滚动更新等场景时如果配置不当很容易出现Pod无法正常调度的情况。2. Ceph RBD动态供给全流程实战2.1 基础环境准备在开始之前我们需要确保Ceph集群和Kubernetes集群都已正确部署。这里我建议使用至少3个节点的Ceph集群每个节点配置10G以上的存储空间。Kubernetes集群建议使用1.21及以上版本因为这个版本对CSI驱动支持更加完善。首先在Ceph管理节点创建专用的存储池ceph osd pool create k8s-dynamic 128 ceph osd pool application enable k8s-dynamic rbd2.2 创建必要的认证信息安全是生产环境不可忽视的一环。我们需要创建一个专门的Ceph用户而不是直接使用admin用户ceph auth add client.k8s mon allow r osd allow rwx poolk8s-dynamic ceph auth get-key client.k8s | base64将输出的密钥保存到Kubernetes Secret中apiVersion: v1 kind: Secret metadata: name: ceph-k8s-secret type: kubernetes.io/rbd data: key: [base64编码的密钥]2.3 配置StorageClass实现动态供给这是实现动态供给的核心配置。我推荐使用CSI驱动而不是传统的in-tree驱动因为CSI驱动维护更活跃功能也更完善apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: ceph-rbd-dynamic provisioner: rbd.csi.ceph.com parameters: clusterID: [你的Ceph集群ID] pool: k8s-dynamic imageFeatures: layering csi.storage.k8s.io/provisioner-secret-name: ceph-k8s-secret csi.storage.k8s.io/provisioner-secret-namespace: default csi.storage.k8s.io/node-stage-secret-name: ceph-k8s-secret csi.storage.k8s.io/node-stage-secret-namespace: default reclaimPolicy: Delete allowVolumeExpansion: true mountOptions: - discard创建完成后可以通过以下命令验证kubectl get sc ceph-rbd-dynamic -o yaml3. 解决高可用部署的关键问题3.1 理解RBD的挂载限制Ceph RBD有一个重要特性它支持在同一个节点上的多个Pod间共享挂载但不支持跨节点共享。这个特性直接影响我们的高可用策略。我在实际项目中遇到过这样的场景一个Deployment有3个副本当Kubernetes尝试将它们调度到不同节点时只有第一个Pod能成功挂载RBD卷其他Pod会报Multi-Attach错误。3.2 使用Pod反亲和性实现高可用为了解决这个问题我们可以使用Pod反亲和性(Anti-Affinity)来确保使用相同RBD卷的Pod不会被调度到同一个节点apiVersion: apps/v1 kind: Deployment metadata: name: nginx-ha spec: replicas: 3 selector: matchLabels: app: nginx-ha template: metadata: labels: app: nginx-ha spec: affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app operator: In values: - nginx-ha topologyKey: kubernetes.io/hostname containers: - name: nginx image: nginx volumeMounts: - mountPath: /data name: data volumes: - name: data persistentVolumeClaim: claimName: ceph-rbd-pvc这个配置确保同一个Deployment的Pod不会被调度到同一个节点避免了RBD挂载冲突。3.3 处理节点故障场景即使配置了反亲和性节点故障时仍可能遇到问题。当节点宕机时上面的Pod会被标记为Terminating状态但RBD卷仍然处于挂载状态导致新Pod无法挂载同一个卷。针对这种情况我们可以配置Pod中断预算(PDB)和适当的terminationGracePeriodSecondsapiVersion: policy/v1 kind: PodDisruptionBudget metadata: name: nginx-pdb spec: minAvailable: 2 selector: matchLabels: app: nginx-ha同时在Deployment中设置spec: template: spec: terminationGracePeriodSeconds: 304. 高级配置与性能优化4.1 RBD镜像参数调优创建RBD镜像时可以调整一些参数来优化性能。以下是我在生产环境中验证过的推荐配置rbd create myimage --size 1024 --pool k8s-dynamic \ --image-feature layering,exclusive-lock \ --image-shared关键参数说明exclusive-lock: 启用独占锁提高多客户端访问时的稳定性image-shared: 允许镜像被多个客户端共享访问4.2 Kubernetes端性能优化在StorageClass中可以配置一些优化参数parameters: ... mounter: rbd-nbd # 使用NBD驱动而不是内核驱动 mapOptions: try-netlink,crush # 优化映射选项 unmapOptions: force # 强制取消映射避免残留4.3 监控与告警配置完善的监控是高可用部署的重要组成部分。建议配置以下监控项RBD镜像使用率监控Ceph集群健康状态监控Kubernetes PV/PVC状态监控Pod挂载失败事件监控可以使用Prometheus配置如下告警规则- alert: RBDMountFailure expr: kubelet_volume_stats_available_bytes{persistentvolumeclaim~.*rbd.*} 0 for: 5m labels: severity: critical annotations: summary: RBD volume mount failure on {{ $labels.pod }}5. 常见问题排查与解决方案5.1 Pod卡在ContainerCreating状态这是最常见的问题之一。排查步骤查看Pod描述信息kubectl describe pod [pod-name]检查kubelet日志journalctl -u kubelet --since 1 hour ago | grep rbd常见原因及解决方案认证失败检查Secret中的密钥是否正确Ceph集群不可达验证monitor地址和网络连通性资源不足检查Ceph集群是否有足够空间5.2 滚动更新时出现Multi-Attach错误这个问题通常发生在Deployment滚动更新时新旧Pod被调度到不同节点。解决方案确保正确配置了Pod反亲和性适当减少maxUnavailable比例spec: strategy: rollingUpdate: maxUnavailable: 1 type: RollingUpdate5.3 RBD镜像残留问题有时删除PVC后底层的RBD镜像没有被自动删除。可以手动清理rbd ls -p k8s-dynamic # 列出所有镜像 rbd rm k8s-dynamic/[image-name] # 删除指定镜像为避免这个问题可以在StorageClass中配置reclaimPolicy: Delete6. RBD与CephFS的选择策略虽然本文重点讨论RBD但在某些场景下CephFS可能是更好的选择。以下是两者的对比特性Ceph RBDCephFS访问模式块设备文件系统多节点共享同一节点多Pod共享跨节点多Pod共享性能特点低延迟高吞吐适合小文件元数据开销较大使用场景数据库需要块存储的应用需要共享存储的应用Kubernetes支持通过CSI驱动通过CSI驱动在实际项目中我通常会根据应用需求选择存储方案对于MySQL、PostgreSQL等数据库使用RBD更合适对于需要多Pod共享存储的Web应用CephFS是更好的选择