CubeFS Object Gateway 深度解析:S3 兼容对象存储的架构、语义转换与权限体系 存储分布式文件系统对象存储云原生【免费下载链接】cubefscloud-native distributed storage项目地址https://gitcode.com/gh_mirrors/cu/cubefs点击查看免费下载CubeFS 的 Object GatewayObjectNode是一套完整兼容 Amazon S3 接口的对象存储网关让一个集群同时对外提供 POSIX 文件系统与 S3 对象存储两套通用接口用户可以直接使用原生 AWS SDK 读写 CubeFS 中的文件。本文围绕 docs/source/design/objectnode.md 展开结合 objectnode/ 目录下的真实实现系统讲解其整体框架、POSIX/S3 语义转换规则、用户与鉴权模型、原子写流程以及对象命名冲突等核心机制帮助读者掌握 ObjectNode 的设计原理、配置方式与实战要点。一、Object Gateway 是什么Object Gateway 为 CubeFS 提供了兼容 S3 的对象存储接口是 CubeFS 能够同时融合POSIX与S3 兼容两类通用接口的关键子系统。用户无需学习 CubeFS 私有协议即可使用 Amazon S3 SDKGo、Java、Python 等对 CubeFS 中的文件进行增删改查实现一套存储、两种协议的融合存储。支持原生 Amazon S3 SDK 的对象存储接口支持 POSIX 与 S3 兼容接口两种通用接口的融合存储无状态设计高可靠、高可扩展。::: warning 注意 在v3.2.1之前的版本中ObjectNode 不支持纠删码erasure-coded卷。 :::二、整体框架无状态的 ObjectNodeCubeFS 对象子系统架构图ObjectNode 是 CubeFS 对象子系统的功能节点其整体框架如上图所示接入层Amazon S3 SDKGo / Java / Python / ...通过标准 S3 REST API 接入 ObjectNode。ObjectNode 内部分为APIsS3 接口的 API 解析层与Volume Operators卷操作层两部分前者负责解析 S3 协议语义后者负责把解析结果转换为对底层子系统的 POSIX 操作。下行交互ObjectNode 按需从资源管理器Master获取卷视图卷拓扑信息并直接与元数据子系统MetaNode和副本子系统DataNode通信。从源码结构看ObjectNode 的启动与运行逻辑集中在 objectnode/server.go其中handleStart依次完成配置加载、从 Master 获取集群信息GetClusterInfo、创建 EBS 客户端若集群配置了 BlobStore 地址、注册 HTTP 路由并启动服务服务端基于gorilla/mux构建见 objectnode/router.go 中的registerApiRouters。ObjectNode 是无状态设计任意节点都可以直接操作 CubeFS 集群中存储的全部文件无需任何卷加载mount操作因此可以水平扩展任意横向扩容节点即可提升吞吐。在 objectnode/server.go 的startMuxRestAPI中所有请求还会依次经过审计audit、Expect头处理、链路追踪trace、鉴权auth、CORS、策略检查policy check与内容协商content等中间件形成完整的请求处理流水线auditMiddleware → expectMiddleware → traceMiddleware → authMiddleware → corsMiddleware → policyCheckMiddleware → contentMiddleware → handler三、语义转换Volume 即 BucketPath 即 KeyCubeFS 本身是基于 POSIX 兼容设计构建的因此来自对象存储接口的每一次文件操作请求都需要做一次POSIX 语义转换映射关系如下POSIXObject StorageVolume卷Bucket桶Path路径Key对象键POSIX 与 S3 语义映射示意图上图直观展示了转换规则在卷example对应 bucket内POSIX 路径/a/b.txt对应对象键a/b.txt路径/b.log对应对象键b.log目录层级被展平为带/分隔符的对象键。::: tip 提示 Put objectexample/a/b.txt会在卷example中创建并写入文件/a/b.txt即对象键中的/会被真实展开为 POSIX 目录层级。 :::四、用户体系AccessKey / SecretKey 与两种创建方式使用对象存储功能前用户需要先通过资源管理器Master创建用户。创建用户时会为每个用户生成一对AccessKey与SecretKey其中 AccessKey 在整个 CubeFS 集群内是唯一的16 位字符串。CubeFS 将卷的Owner字段视为用户 ID创建用户有以下两种方式随卷自动创建通过资源管理器 API 创建卷时如果集群中不存在与 Owner 同名的用户系统会自动创建一个以 Owner 为 ID 的用户显式调用用户管理 API 创建调用资源管理器的用户管理接口创建用户具体接口细节参见 用户管理文档。在 objectnode/server.go 中可以看到ObjectNode 启动时会通过NewUserInfoStore(masters, strict)构建用户信息存储运行期间从 Master 同步用户与卷信息用于鉴权与授权判定。4.1 用户管理 API 实操在 用户管理文档 中提供了完整的 REST 操作示例此处给出核心命令。创建用户curl -H Content-Type:application/json -X POST --data {id:testuser,pwd:12345,type:3} http://10.196.59.198:17010/user/create集群启动时会自动创建 root 用户type 值为0x1。查询用户信息按用户 IDcurl -v http://10.196.59.198:17010/user/info?usertestuser | python -m json.tool查询用户信息按 AccessKeycurl -v http://10.196.59.198:17010/user/akInfo?ak0123456789123456 | python -m json.tool用户信息响应示例{ user_id: testuser, access_key: gDcKaBvqky4g8StT, secret_key: ZVY5RHlrnOrCjImW9S3MajtYZyxSegcf, policy: { own_vols: [vol1], authorized_vols: { ltptest: [ perm:builtin:ReadOnly, perm:custom:PutObjectAction ] } }, user_type: 3, create_time: 2020-05-11 09:25:04 }其中policy.own_vols表示该用户为 Owner 的卷列表policy.authorized_vols表示其他用户授权给该用户的卷及相应权限限制。4.2 授权与权限类别用户对其名下的卷拥有全部访问权限也可以把指定权限授予其他用户。权限分为以下三类只读或读写权限perm:builtin:ReadOnly或perm:builtin:Writable单操作权限例如 GetObject、PutObject 等格式为action:oss:XXX如action:oss:GetObject自定义权限格式为perm:custom:XXX其中XXX由用户自定义。设置授权的 API 示例curl -H Content-Type:application/json -X POST --data {user_id:testuser,volume:vol,policy:[perm:builtin:ReadOnly,perm:custom:PutObjectAction]} http://10.196.59.198:17010/user/updatePolicy::: danger 警告 如果该用户对目标卷已存在权限配置本次updatePolicy操作会覆盖原有权限。 :::移除权限curl -H Content-Type:application/json -X POST --data {user_id:testuser,volume:vol} http://10.196.59.198:17010/user/removePolicy传输卷所有权curl -H Content-Type:application/json -X POST --data {volume:vol,user_src:user1,user_dst:user2,force:true} http://10.196.59.198:17010/user/transferVolforce为true时即使user_src与卷 Owner 字段不一致也会强制将卷转移给目标用户。五、授权与认证完整兼容 AWS S3 签名算法对象存储接口的签名校验算法完全兼容 Amazon S3 服务。用户通过管理 API 获取 AccessKey / SecretKey参见 用户管理文档后即可使用该算法生成签名访问对象存储功能。从源码看签名实现位于 objectnode/auth.go、objectnode/auth_header.go、objectnode/auth_query.go、objectnode/auth_signature_v2.go、objectnode/auth_signature_v4.go 等文件覆盖了 S3 的多种认证形态Header 认证Authorization请求头与Query 认证URL 携带X-Amz-*参数常用于预签名 URLSignature V2AWS/ HMAC-SHA1与Signature V4AWS4-HMAC-SHA256含aws-chunked流式签名POST policy 表单认证见 objectnode/auth_form.go 与 objectnode/post_policy.go。objectnode/auth.go 中定义了签名相关的校验约束例如MaxSignatureExpires 7 * 24 * 60 * 60预签名 URL 的过期时间最长 7 天MinSignatureExpires 1最短 1 秒MaxRequestSkewedSeconds 15 * 60请求时间偏差容忍 15 分钟UnsignedPayload UNSIGNED-PAYLOAD支持未签名载荷模式。当用户通过对象存储功能执行某个操作时CubeFS 会校验该用户是否具备当前操作的权限。此外ObjectNode 还支持在配置中声明signatureIgnoredActions忽略签名校验的操作与disabledActions禁止访问的操作两者均在 objectnode/server.go 的loadConfig中被解析为proto.Actions集合并应用于请求处理。六、临时隐藏数据对象存储的原子写语义对象存储接口中的写操作是原子执行的每次写操作都会先创建数据并写入一个不可见的临时对象。具体而言ObjectNode 中的卷操作器Volume Operator将文件数据写入临时文件临时文件的元数据只包含 inode不包含 dentry因此在目录树中完全不可见当全部文件数据成功落盘后卷操作器在元数据中创建或更新 dentry使文件对用户可见。该机制在 objectnode/fs_volume.go 的PutObject实现中有非常完整的对应代码。在写入文件数据之前代码首先调用v.mw.InodeCreate_ll(parentId, DefaultFileMode, ...)创建一个仅含 inode、不含 dentry 的临时 inode源码注释明确说明中间数据通过不可见文件管理只有 inode 没有 dentry从而做到真正意义上的不可见避免其他用户操作对临时数据造成不良影响随后通过v.ec.OpenStream打开数据流写入热卷走streamWriteFlush冷卷/纠删码卷走ebsWrite写入 BlobStore数据全部写完后调用v.applyInodeToDEntry把新 inode 挂到目标 dentry 上完成可见化。同时整个写入过程中若发生错误defer逻辑会执行InodeUnlink_llEvict清理临时 inode 并释放已写数据保证失败场景下不留脏数据对象自身的 ETagoss:etag、MIME 类型oss:mime、标签oss:tagging、ACL、用户自定义元数据等则以扩展属性XAttr形式批量写入BatchSetXAttr_ll参见 objectnode/const.go 中XAttrKeyOSS*系列常量与 objectnode/fs_volume.go。七、对象命名冲突重要POSIX 与对象存储是两种不同类型的存储产品对象存储本质上是 key-value 存储服务。因此在对象存储语义下名为a/b/c与a/b的两个对象是完全不冲突的两个对象——前者键为a/b/c后者键为a/b。然而 CubeFS 基于 POSIX 设计。按照第三节的语义转换规则对象名a/b/c中的b部分会被转换为文件夹a下的文件夹b对象名a/b中的b部分会被转换为文件夹a下的文件b。于是问题出现了a/b/c把b当目录与a/b把b当文件这两个对象名在 CubeFS 中是冲突的。这种冲突在实现层面有直接体现在 objectnode/fs_volume.go 的PutObject流程中写入前会先Lookup_ll检查目标名称的既有 inode 与 mode若该名称已存在且为目录类型则直接报错syscall.EINVAL在applyInodeToDEntry中同样会检查已有 dentry 的 mode若已是目录os.FileMode(existMode).IsDir()则返回syscall.EINVAL。相应地objectnode/result_error.go 定义了ObjectModeConflict错误Object already exists but file mode conflictsHTTP 409 Conflict在多处对象上传/分片操作中被返回。因此在实际使用中应避免同时以a/b和a/b/c这种互为文件/目录前缀的形式命名对象防止命名冲突导致的写入失败。八、部署与配置要点ObjectNode 作为独立子系统运行其核心配置项定义在 objectnode/server.go 的loadConfig中主要参数整理如下配置项类型默认值说明listenstring80服务监听端口必须是纯数字字符串masterAddrstring 数组无Master 节点主机名或 IP 列表启动与运行期间用于同步集群、用户和卷信息必填domainsstring 数组无绑定到对象存储接口的域名可绑定多个ObjectNode 据此实现泛域名自动解析例如配置object.cube.io即可自动解析*.object.cube.iostrictboolfalse兼容性测试专用为true时不缓存用户信息与卷拓扑保证拓扑信息与集群实时一致开启后性能急剧下降仅限协议兼容性测试使用disableCreateBucketByS3boolfalse禁止通过 S3 接口创建 bucket卷signatureIgnoredActionsstring 数组无忽略签名校验的操作列表disabledActionsstring 数组无禁止访问的操作列表stsNotAllowedActionsstring 数组无禁止 STS 用户访问的操作列表auditLogobject无审计日志配置支持本地文件与 Kafka/Webhook 两类外部通道enableObjMetaCacheboolfalse启用对象元数据缓存以 S3 对象键的各级路径为缓存键映射到 POSIX inodecacheRefreshIntervalSecint600缓存刷新间隔秒仅在enableObjMetaCachetrue时生效maxDentryCacheNumint1000000目录项dentry缓存上限maxInodeAttrCacheNumint1000000inode 属性缓存上限enableBcacheboolfalse读取冷卷纠删码卷数据时启用块缓存bStoreWriteThreads/bStoreReadThreadsint4/4读写 EBSBlobStore的线程数s3QoSRefreshIntervalSecint300S3 QoS 配置刷新间隔秒QoS 配置文件名固定为s3qosInfo.conf典型的 ObjectNode 配置示例{ role: objectnode, listen: 80, masterAddr: [ master1.cube.io, master2.cube.io, master3.cube.io ], domains: [ object.cube.io ], logDir: /var/logs/cubefs/object, auditLog: { local: { logdir: ./run/auditlog/object/, no_2xx_body: true }, kafka: { cubefs: { enable: true, topic: audit_log_topic, brokers: 192.168.80.130:9095,192.168.80.131:9095,192.168.80.132:9095 } } } }strict模式下 ObjectNode 不缓存用户信息与卷拓扑对应 objectnode/server.go 中NewVolumeManager(masters, strict)与NewUserInfoStore(masters, strict)两个构造参数仅用于协议兼容性测试domains配置则对应路由层bRouter.Host({bucket:.}.d)的泛域名 bucket 解析见 objectnode/router.go既支持bucket.object.cube.io形式的虚拟主机风格访问也支持/{bucket}路径风格访问。九、S3 API 覆盖范围从 objectnode/router.go 的路由注册可以看出ObjectNode 按 HTTP 方法HEAD / GET / POST / PUT / DELETE / OPTIONS注册了大量 S3 兼容 API主要包括桶级操作CreateBucket、DeleteBucket、HeadBucket、ListBuckets、Get/Put Bucket ACL、Get/Put Bucket Policy、Get/Put Bucket Tagging、Get/Put Bucket CORS、Get/Put Bucket Lifecycle Configuration、Get/Put Bucket Object Lock Configuration、GetBucketLocation、ListObjectsv1/v2、ListMultipartUploads 等对象级操作PutObject、GetObject、HeadObject、DeleteObject、DeleteObjects批量、CopyObject、PostObject、Get/Put/Delete Object Tagging、Get/Put Object ACL、GetObjectRetention、范围读取Range等分片上传CreateMultipartUpload、UploadPart、UploadPartCopy、ListParts、CompleteMultipartUpload、AbortMultipartUpload扩展能力XAttr 操作oss:xattrCubeFS 自有 API、Get Federation TokenSTSobjectnode/sts.go、CORSobjectnode/cors.go。其中相当一部分高级桶功能如版本控制 Versioning、桶加密 Encryption、网站托管 Website、复制 Replication、公共访问块 PublicAccessBlock、请求付费 RequestPayment 等在路由中显式注册为unsupportedOperationHandler即返回不支持语义router.NotFoundHandler同样指向该处理器。这意味着 ObjectNode 主打与 S3 高度兼容的核心读写能力而不是对 AWS 全部服务特性的逐项克隆使用时应对照 objectnode/router.go 确认所需 API 的支持状态。十、总结CubeFS Object Gateway 的核心设计可以概括为三点无状态网关 语义转换ObjectNode 无状态、可水平扩展通过Volume → Bucket、Path → Key的语义转换把 S3 请求落到 MetaNode 与 DataNode 之上实现 POSIX 与 S3 双接口融合S3 原生兼容签名算法V2/V4、Header/Query/表单、错误码与 API 形态均对齐 AWS S3AccessKey/SecretKey 鉴权与用户授权策略内置/单操作/自定义三类权限完整可配原子写与一致性通过仅 inode、无 dentry的临时隐藏对象实现原子写全部数据落盘后才挂载 dentry 可见化失败自动清理同时需警惕 POSIX 语义下的对象命名冲突a/b与a/b/c互斥。如需深入阅读可继续查看 docs/source/design/objectnode.md 原始设计文档、objectnode/ 目录下的实现源码以及 用户管理文档 中的完整用户 API 说明。赞分享存储分布式文件系统对象存储云原生【免费下载链接】cubefscloud-native distributed storage项目地址https://gitcode.com/gh_mirrors/cu/cubefs点击查看免费下载相关推荐CubeFS 对象网关ObjectNode深度解析S3 兼容对象存储、POSIX 语义转换与权限模型实战CubeFS 对象网关ObjectNode深度解析S3 兼容对象存储、POSIX 语义转换与权限模型实战 本篇技术指南以 CubeFS 官方设计文档《对象存储分布式文件系统对象存储云原生Ceph 对象网关Ceph Object Gateway / radosgw架构与实战指南S3/Swift 兼容对象存储从部署到管理Ceph 对象网关Ceph Object Gateway / radosgw架构与实战指南S3/Swift 兼容对象存储从部署到管理 Ceph Objec存储分布式文件系统对象存储后端高可用dokku对象存储MinIO/S3兼容存储dokku对象存储MinIO/S3兼容存储 你是否在为应用部署时的文件存储问题烦恼还在手动配置云存储服务吗本文将详细介绍如何使用dokku的存储插件实现与云原生DevOps后端上一篇终极ROS机器人仿真指南wpr_simulation从入门到精通下一篇OBS Studio新手快速上手指南从零开始的直播配置教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考