Ceph RBD编程接口Librbd(C++) -- 映像创建与数据读写

Ceph RBD编程:Librbd接口详解与数据操作
本文介绍了如何使用Ceph的RBD编程接口Librbd进行C++开发,包括连接Ceph集群、创建I/O上下文、管理存储池以及进行映像的创建、打开、读写等操作。详细讲解了RBD映像的各种属性检查以及同步、异步的数据读写方法,并强调了在结束操作时必须正确释放资源。

目前我们有两种路径使用Ceph的块存储:
- 利用QEMU/KVM通过librbd与 Ceph 块设备交互,主要为虚拟机提供块存储设备,如下图所示;
- 利用kernel module与Host kernel交互,主要为物理机提供块设备支持。

OpenStack/Ceph 技术栈

Librbd 是Ceph提供的块存储接口的抽象,它提供C/C++、Python等多种接口。对于C++,最主要的两个类就是RBDImageRBD 主要负责创建、删除、克隆映像等操作,而Image 类负责映像的读写等操作。

准备工作

对于任何客户端应用,都需要首先连接到一个运行良好的Ceph集群。

获取集群句柄

//声明Rados对象,并初始化
librados::Rados rados;
ret = rados.init("admin"); // just use the client.admin keyring
if (ret < 0) { // let's handle any error that might have come back
    std::cerr << "couldn't initialize rados! err " << ret << std::endl;
    ret = EXIT_FAILURE;
    return EXIT_FAILURE;
} else {
    std::cout << "we just set up a rados cluster object" << std::endl;
}

//获取配置文件信息: /etc/ceph/ceph.conf
// 1. 根据命令行参数
/*
ret = rados.conf_parse_argv(argc, argv);
if (ret < 0) {
    // This really can't happen, but we need to check to be a good citizen.
    std::cerr << "failed to parse config options! error " << ret << std::endl;
    ret = EXIT_FAILURE;
    return EXIT_FAILURE;
} else {
    std::cout << "we just parsed our config options" << std::endl;
    // We also want to apply the config file if the user specified
    // one, and conf_parse_argv won't do that for us.
    for (int i = 0; i < argc; ++i) {
   
   
        if ((strcmp(argv[i], "-c") == 0) || (strcmp(argv[i], "--conf") == 0)) {
            ret = rados.conf_read_file(argv[i+1]);
            if (ret < 0) {
                // This could fail if the config file is malformed, but it'd be hard.
                std::cerr << "failed to parse config file " << argv[i+1]
                        << "! error" << ret << std::endl;
                ret = EXIT_FAILURE;
                return EXIT_FAILURE;
            }
            break;
        }
    }
}
*/
// 2. 程序里面指定
ret = rados.conf_read_file("/etc/ceph/ceph.conf");
if (ret < 0) {
    // This could fail if the config file is malformed, but it'd be hard.
    std::cerr << "failed to parse config file! err " << ret << std::endl;
    ret = EXIT_FAILURE;
    return EXIT_FAILURE;
}

连接集群

ret = rados.connect();
if (ret < 0) {
    std::cerr << "couldn't connect to cluster! err " << ret << std::endl;
    ret = EXIT_FAILURE;
    return EXIT_FAILURE;
} else {
    std::cout << "we just connected to the rados cluster" << std::endl;
}

创建I/O上下文环境

如果没有存储池,需要先新建一个存储池。

新建存储池

const char *pool_name = "gnar";
ret = rados.pool_create(pool_name);
if (ret < 0) {
    std::cerr << "couldn't create pool! error " << ret << std::endl;
    ret = EXIT_FAILURE;
    
<think> 嗯,用户遇到了ceph-csi服务组件(cephfs和rbd)的pod持续CrashLoopBackOff和Error状态的问题,这通常是CSI驱动部署中的典型故障。结合用户提供的四个引用内容,需要系统性排查。 引用[1]提到ceph-csi的三大服务类型和Controller/Node/Identity三个核心组件的职责,这提示排查时需要区分组件类型。引用[2]中PVC卡在pending状态的根本原因是MDS服务未启动,说明底层Ceph集群状态直接影响CSI表现。引用[3]展示了成功的rbd部署案例,可对比组件版本差异。引用[4]的官方文档链接则暗示配置准确性至关重要。 用户深层需求显然是恢复集群存储功能,而非单纯解决pod状态。因此方案设计要覆盖: 1. 核心依赖检查:优先确认Ceph集群健康(引用[2]的教训),特别是MDS(cephfs必需)和OSD(rbd必需)状态 2. 权限配置复查:引用[1]提到ControllerServer需要cephx密钥操作存储池,密钥错误会导致组件崩溃 3. 版本兼容性:CSI版本需匹配K8s和Ceph版本(引用[3]成功案例的提示) 4. 日志定位:CrashLoopBackOff必定产生错误日志,需按组件分类获取 特别要注意引用[1]中livenessType组件的探活机制——如果socket配置错误,即使主服务正常也会被误判死亡。这可能是部分pod反复重启的隐藏原因。 针对用户提供的错误现象,下面给出具体解决步骤: </think> 基于引用内容和常见故障排查经验,解决ceph-csi-cephfs/ceph-csi-rbd的Pod处于CrashLoopBackOff或Error状态的方法如下(按优先级排查): --- ### 🔍 **核心排查步骤** #### 1️⃣ **检查Ceph集群基础服务** ```bash # 在Ceph管理节点执行 ceph -s # 确认集群状态为HEALTH_OK ceph mds stat # 检查cephfs必需的MDS服务(引用[2]关键点) ceph osd stat # 检查OSD状态 ceph mon stat # 检查Mon节点 ``` - **关键点**:若MDS未运行(cephfs问题)或OSD异常(rbd问题),CSI组件必然失败(引用[2]已验证) #### 2️⃣ **检查CSI组件日志(首要操作)** ```bash kubectl logs -f <故障Pod名称> -c <具体容器名> # 示例(引用[3]组件结构): kubectl logs -f csi-rbdplugin-provisioner-xxx -c csi-provisioner ``` - **常见日志线索**: - `connection refused` → Ceph Monitor地址/端口错误 - `permission denied` → Ceph密钥问题 - `no mds server is up` → MDS服务未启动(引用[2]的直接原因) - `Volume ID already exists` → 残留冲突(引用[2]的报错) #### 3️⃣ **验证核心配置文件** - **检查`ceph-conf.yaml`(引用[4])**: ```yaml # 确认monitor地址Ceph集群实际IP和端口匹配(默认6789) monitors: - 10.0.0.1:6789 - 10.0.0.2:6789 ``` - **检查密钥配置**: ```bash # 查看Secret内容是否正确 kubectl get secret ceph-csi-secret -o yaml ``` - 密钥需通过`ceph auth get-key client.admin`获取 #### 4️⃣ **排查存储类(StorageClass)配置** - **检查pool名称是否存在**: ```bash ceph osd lspools # 确认rbd/cephfs池已创建 ``` - **验证StorageClass参数**: ```yaml parameters: clusterID: <fsid> # 必须ceph -s显示的fsid一致 pool: mypool # 真实存在的池名称 ``` #### 5️⃣ **检查Kubernetes节点兼容性** ```bash # 在K8s节点验证内核模块 lsmod | grep rbd # rbd需要加载内核模块 mount.ceph --version # 确认ceph-common工具已安装 ``` --- ### ⚠️ **高频问题解决方案** | 问题类型 | 解决方案 | |-------------------------|--------------------------------------------------------------------------| | **MDS未启动(cephfs)** | 在Ceph集群执行: `ceph-deploy mds create <节点名>`(引用[2]的直接解决方案) | | **Monitor端口错误** | 核对`ceph-conf.yaml`中端口号(非默认端口需显式指定) | | **密钥权限问题** | 重新生成Secret:`kubectl create secret generic ceph-csi-secret --from-literal=userKey=$(ceph auth get-key client.admin)` | | **残留PV冲突** | 删除冲突PV:`kubectl delete pvc <pvc-name> --force --grace-period=0`(引用[2]的错误场景) | | **CSI驱动版本不兼容** | 检查[官方兼容矩阵](https://github.com/ceph/ceph-csi/#supported-versions) 📌 | --- ### 📌 **补充建议** 1. **版本对齐**: 确保Ceph集群版本、ceph-csi镜像版本、Kubernetes版本三者兼容(引用[3][4]的部署实践) ```bash kubectl describe pod csi-rbdplugin-xxx | grep Image ``` 2. **存活探针调优**: 若日志提示`liveness probe failed`(引用[1]的livenessType),适当增加超时时间: ```yaml livenessProbe: timeoutSeconds: 10 # 默认值可能不足 ``` --- ### 📚 **相关问题** 1. 如何诊断 Kubernetes 中 PersistentVolumeClaim (PVC) 长时间处于 Pending 状态的问题? 2. Ceph CSI 部署中常见哪些权限(cephx)相关的错误?如何解决? 3. 当 Ceph 集群状态为 `HEALTH_WARN` 时,哪些警告可能影响 CSI 正常工作? 4. 如何验证 ceph-csi 组件 Ceph 集群之间的网络连通性? > 引用说明: > [^1]: ceph-csi组件架构Controller/Node/Identity服务职责 > [^2]: MDS服务未启动导致PVC卡Pending的关键案例 > [^3]: 成功部署的组件状态参考 > [^4]: 官方部署配置文件来源
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值