rclone拷贝桶对象失败定位过程

Last updated on 7 months ago

背景

某客户 有一套杉岩的对象存储环境(医疗图片),里面的桶容量快满了,于是想把这桶的数据迁移到 我们的集群,于是rclone 工具将 衫岩的的数据拷贝过来,但是总是失败。

问题

有少数的对象无法拷贝,rclone 显示报错(BadDigest),从客户描述 就是直接使用 rclone 命令,发现总是有一部分对象无法拷贝到 我们的对象存储上? 怀疑 是我们的存储有问题?

image-20240312223456654

定位过程

从客户发来的rclone 日志来看 ,出现报错都是 BadDigest ,初步分析,大概是 MD5 校验失败, 但这信息并不足以证明 是客户那边的客户有问题还是我们存储有问题

本质上这是一个上传对象失败的问题,我们先排除rgw网关是否有异常

先询问客户是往那个网关 做拷贝的,从客户给的 rclone 日志找到失败的时间点 ,再从rgw日志找,发现都是 status 都是400 以及 op status 为 2005 ( 这是关键点! )

image-20240312223705000

知道了 op status 为-2005 ,看下代码这个含义是?

image-20240312223715352找到关键字 ERR_BAD_DIGEST ,因为这个是上传的流程,所以再上传流程中 搜这个关键子 ERR_BAD_DIGEST

image-20240312223731101

calc_md5 是rgw通过对象内容 计算出来的, supplied_md5 是通过请求带过来的,两者不同 ,所以导致400错误

难道是rgw 自己计算错了? 这种可能性很小; 更多的可能是 请求带来的 md5 本身就是不正确的? 但是为什么会不正确呢?

现在想验证下客户带来的md5和实际文件的md5是否匹配
在客户的允许下,开启了日志等级 ,看下请求带过来的 md5
image-20240312223804648

以及手动算下这个对象的md5 image-20240312223814675

发现 真的是不一样, 现在可以确定这些失败的对象就是因为带过来的 md5是错的,和rgw实际算的不一致;

还有个问题是: 实际上已经拷贝过很多的对像都是成功的,只有 一部分对象无法拷贝,那是为什么呢? 难道是 rclone的bug?

现在推测是 : rclone 将对象的etag 作为 md5,(etag 在整体上传的时候是md5,而分段并不是 ),有些对象刚好就etag 不是md5,从客户的桶里看都是小对象的,并没有分段上传的

于是就在家里复现下:
手动将 对象的etag 修改,然后使用rclone 复制,看能否出现一样的错误

etag 是是以 xattr形式存放再bi池里面, 刚好rados 有相关接口可以直接修改 (我将 etag 最后的数字4 修改为 3)

image-20240312224028982

修改之后,也是包一模一样的错误
image-20240312224015709

现在可以证明 ,这个错误并不是我们存储的问题,也是不是md5计算的问题, 而是对象的etag 有错误

有什么办法避免这个错误吗?

  • 把对象etag, 从新算一遍,再修改? 这个估计不行

  • 让 rclone 不将etag 作为 md5,看来下 rclone 源码,rclone 机制是 head 下对象,获得元数据(包括etag),如果etag 未空的话 ,rclone 就会重新算一遍,于是就直接改了rclong代码,强制 rclone 算一遍,重新编译,后面也达到了预期效果;

  • 其次也可以用nginx 做网关的代理,把请求头 etag 过滤掉,在转发给 rclone

结论

杉岩那边的对象 etag 不对,rclone 又将这个 etga 作为md5作为请求发过来,rgw这边自己算了一遍,发现不匹配造成的404错误

为什么他那边的etag 不对呢? 目前猜测是 客户业务 pacs , 医疗图像的,他们上传的时候 就对图片做了一次md5, 上传图片后可能会对图片操作,比如加水印什么的,这样导致图片内容有变,从而导致实际的md5 和 etag 不同 (按道理来说流程应该是操作处理完后还要再算一次md5的,不过这也不是我们关心的了)