- 人工智能
- 大模型
- 模型推理服务
- 后端
【免费下载链接】Mooncake
Mooncake is the serving platform for Kimi, a leading LLM service provided by Moonshot AI.
导读
本文介绍 Mooncake 项目中如何通过FileStorage既有卸载路径,将对象数据以 key-based 形式卸载(Offload)到 OSS/S3 等对象存储服务。你将掌握 OSS 卸载的部署拓扑、完整环境变量配置表、master 与 real client 的启动方式,以及初始化失败、鉴权报错、副本不可读等常见故障的排查思路。文中同时结合 oss_adapter_config.cpp 等源码实现,说明每个配置项的解析逻辑与取值边界,帮助你在真实集群中正确落地。
概览:OSS 卸载是什么
对象存储服务(如阿里云 OSS、AWS S3)提供基于 key 的存储语义。Mooncake Store 通过ObjectStorageAdapter在现有FileStorage卸载路径中接入对象存储:与本地 SSD、NVMe KV 后端一致,master 记录 real client 所拥有的LOCAL_DISK副本,读取方仍然通过该 owner 访问数据负载。对象存储在这里不是一种独立的一等副本类型,而是LOCAL_DISK副本背后的一种存储载体。
需要特别强调的是:本文示例使用的是 OSS 适配器。其他对象存储服务需要与之兼容的适配器实现,仅更换 endpoint 并不能获得 S3 支持——OSS 适配器的签名协议是 OSS 特有的,S3 必须使用专门的适配器。
更底层的设计细节(读写路径、物理 key 映射、批量执行与失败语义)可参考 OSS Backend Design。
前置条件
在部署 OSS 卸载之前,需要准备:
- 一个已存在的 OSS bucket,且其 endpoint 可以从每个卸载 owner 所在节点访问。不需要挂载 OSS 文件系统。
- 在所选命名空间内具备 PUT、GET、HEAD、LIST、DELETE 权限的凭证;支持 STS 临时凭证。
- 每个卸载 owner 使用独立的对象 key 前缀。
- 一个已存在的、绝对路径、可写、非符号链接的目录,用于
MOONCAKE_OFFLOAD_FILE_STORAGE_PATH——这是通用FileStorage初始化所必需的。需要说明:该目录不会为 OSS 启用本地 SSD 缓存。 - libcurl 与 OpenSSL 的开发库及头文件。
构建支持
当环境中存在 libcurl 与 OpenSSL 时,构建会自动启用 OSS 适配器,无需 OSS SDK,也不需要额外的 OSS 专用构建开关。构建与安装 Mooncake 的完整步骤请参考 构建指南。
批量 I/O 使用curl_multi_wait,因此不要求libcurl 7.66.0 以上版本。上传缓冲区调优是可选能力:当 libcurl 头文件版本早于 7.62.0 时,将使用库默认值(见下文配置章节)。
部署拓扑
拓扑中只有一个关键结论值得记住:只有卸载 owner 需要 OSS 凭证。master 与请求方客户端都不会直接读写 OSS 对象——读取方通过 owner 上的batch_get_offload_objectRPC 与 Transfer Engine 获取数据。
从源码看,请求链路是:请求方客户端查询 master 获得LOCAL_DISKowner 与对象大小 → 向 owner 发起batch_get_offload_object→ owner 的FileStorage调用BatchLoad填充 staging buffer → OSS 适配器并发执行GetBatch→ 字节经 Transfer Engine 传回请求方。该 RPC 协程把阻塞工作投递到既有 blocking pool,worker 等待 HTTP 批量完成后返回,不引入专用 OSS worker 池(见 oss-backend.md 的 Read Path 章节)。
配置
在每个卸载 owner 的环境中设置后端与 OSS 相关变量:
export MOONCAKE_OFFLOAD_STORAGE_BACKEND_DESCRIPTOR=distributed_storage_backend export MOONCAKE_OFFLOAD_FILE_STORAGE_PATH=/data/file_storage export MOONCAKE_DISTRIBUTED_FS_TYPE=oss export MOONCAKE_DISTRIBUTED_ROOT_DIR=/mooncake/my-cluster/owner-1 export MOONCAKE_OSS_ENDPOINT=https://oss-cn-hangzhou.aliyuncs.com export MOONCAKE_OSS_BUCKET=my-mooncake-bucket export MOONCAKE_OSS_REGION=cn-hangzhou # MOONCAKE_OSS_ACCESS_KEY_ID 与 MOONCAKE_OSS_ACCESS_KEY_SECRET # 请通过你的凭证管理机制提供,不要写死在脚本中。请将示例中的 endpoint、bucket、region 与 owner 前缀替换为你自己的部署值。注意:每个FileStorage实例只选择一个后端,OSS 不会与本地文件或 NVMe KV 后端在同一实例内并存。
后端与命名空间
| 环境变量 | OSS 取值 | 说明 |
|---|---|---|
MOONCAKE_OFFLOAD_STORAGE_BACKEND_DESCRIPTOR | distributed_storage_backend | 选择承载 OSS 适配器的后端。 |
MOONCAKE_OFFLOAD_FILE_STORAGE_PATH | 默认/data/file_storage | 通用初始化所需的本地目录;对象负载实际写入 OSS。 |
MOONCAKE_DISTRIBUTED_FS_TYPE | oss | 选择对象存储模式,而非文件系统适配器。 |
MOONCAKE_DISTRIBUTED_ROOT_DIR | owner 专属前缀 | 使用绝对风格路径;适配器会去除首尾斜杠。这不是挂载点。 |
OSS 卸载不需要Master 侧的 DFS 配置,也不需要禁用单独配置的 DFS tier。但在卸载 owner 环境中,MOONCAKE_DFS_FS_ADAPTER与MOONCAKE_DFS_ROOT_DIR会覆盖对应的MOONCAKE_DISTRIBUTED_*值(两者共享同一配置解析器),因此使用上述示例时请保持这些 override 不设置。
Endpoint 与凭证
| 环境变量 | 默认值 | 说明 |
|---|---|---|
MOONCAKE_OSS_ENDPOINT | 必填 | 包含http://或https://的 endpoint。别名:OSS_ENDPOINT。 |
MOONCAKE_OSS_BUCKET | 必填 | 已存在的 bucket。别名:OSS_BUCKET。 |
MOONCAKE_OSS_REGION | 必填 | OSS 签名区域。别名:OSS_REGION。 |
MOONCAKE_OSS_ACCESS_KEY_ID | 非匿名时必填 | AccessKey ID。别名:OSS_ACCESS_KEY_ID。 |
MOONCAKE_OSS_ACCESS_KEY_SECRET | 非匿名时必填 | AccessKey Secret。别名:OSS_ACCESS_KEY_SECRET。 |
MOONCAKE_OSS_SECURITY_TOKEN | 空 | 可选的 STS token。别名:OSS_SESSION_TOKEN。 |
MOONCAKE_OSS_PATH_STYLE | false | 使用endpoint/bucket/key路径寻址,而非虚拟主机风格 bucket 寻址。 |
MOONCAKE_OSS_ANONYMOUS | false | 禁用签名;仅用于测试 endpoint 或配置了公共访问的场景。 |
关于配置解析,源码 oss_adapter_config.cpp 给出了几个值得注意的实现事实:
- 主名优先于别名:
ReadPrimaryOrAlias的逻辑是主变量存在(即使显式为空字符串)就使用主变量值,否则回退到别名。对应的 oss_adapter_config_test.cpp 中EmptyPrimaryOverridesCompatibilityAlias用例验证了"显式空主名会覆盖别名"这一行为。 - 配置在初始化时读取:修改环境变量不会重新配置已运行的适配器,也不会刷新其凭证;测试
InitReadsCurrentEnvironmentEachTime表明每次Init()都重新读取当前环境,但运行期不会热更新。 - 字符串归一化:endpoint 会去除尾部
/(while (!config.endpoint.empty() && config.endpoint.back() == '/')),security token 会trim空白字符。 - 必填校验顺序:endpoint/bucket/region 三者缺失最先报错;非匿名模式下 access key 缺失返回
INVALID_PARAMS。无效布尔值(如MOONCAKE_OSS_PATH_STYLE=invalid)会在告警后按默认值false处理,见测试InvalidBoolValuesWarnAndUseFalse。
后端并发与健康检查
| 环境变量 | 默认值 | 说明 |
|---|---|---|
MOONCAKE_OSS_MAX_CONNECTIONS | 64 | 每个批次内最大准入请求数与每 host 连接总数上限;最小值为1。不是进程级限制。 |
MOONCAKE_OSS_RECEIVE_BUFFER_SIZE | 1048576(1 MiB) | 批量请求的 libcurl 接收缓冲区建议值,钳制在 16 KiB–10 MiB;单请求 GET 保持库默认。 |
MOONCAKE_OSS_UPLOAD_BUFFER_SIZE | 1048576(1 MiB) | PutV/PutBatch的上传缓冲区建议值,钳制在 16 KiB–2 MiB;仅在 libcurl 头文件 ≥ 7.62.0 时生效,否则用库默认。 |
MOONCAKE_DISTRIBUTED_HEALTH_CHECK | false | 初始化时写入并回读一个探针对象,随后尽力删除。 |
数值调优参数使用十进制整数。无效或越界整数回退到默认值,然后再应用上述钳制边界——这一点在测试TuningValuesKeepExistingBounds中得到验证:max_connections下限为 1、receive_buffer_size上限 10 MiB、upload_buffer_size上限 2 MiB,且越界/非法输入会打印 "using default ..." 告警后回落。缓冲区大小只是 libcurl 的建议值,不是 TCP socket 缓冲区大小,也不保证吞吐。
通用卸载心跳默认 10 秒,通过MOONCAKE_OFFLOAD_HEARTBEAT_INTERVAL_SECONDS配置。其他通用客户端设置见 SSD Offload。
启动 Mooncake
以启用卸载的方式启动 master:
mooncake_master --rpc_port=50051 --enable_offload=true应用上述后端配置后,创建必需的本地目录并启动一个 real client。以下示例使用本地 master 与 TCP 传输:
mkdir -p /data/file_storage export MOONCAKE_MASTER=127.0.0.1:50051 export MOONCAKE_LOCAL_HOSTNAME=127.0.0.1 export MOONCAKE_PROTOCOL=tcp export MOONCAKE_TE_META_DATA_SERVER=P2PHANDSHAKE export MOONCAKE_OFFLOAD_ENABLED=true python -m mooncake.mooncake_store_service多节点部署请使用可路由地址。该 launcher 示例假设MOONCAKE_CONFIG_PATH未设置;否则服务配置文件优先。
嵌入式 real-client 模式使用相同的后端与 OSS 变量:在调用MooncakeDistributedStore.setup()时传入enable_ssd_offload=True与ssd_offload_path,同时保留常规的连接与内存参数。嵌入式与独立 real-client 两种部署模式的区别详见 SSD Offload guide。
源码视角:批量执行与失败语义
从 oss_adapter.h 与设计文档可以提炼出 OSS 适配器的运行时行为,这对排障很有帮助:
- 物理 key 映射:
physical_key = owner_prefix + "/" + URIEncode(storage_key),对象体为拼接的 payload 分片;前缀为空时省略分隔符。LIST 会把匹配的对象 key 解码回逻辑存储 key,供ScanMeta注册元数据。没有分片/偏移分配、没有对象级 UUID 描述符、没有根 manifest、也没有适配器级校验和信封。 - 批量执行:每次
GetBatch/PutBatch创建一个临时CURLM和每个请求一个 easy handle;同时准入最多MOONCAKE_OSS_MAX_CONNECTIONS个请求,随完成逐批准入。等待准入的请求留在CURLM之外,避免在 libcurl 连接队列中消耗传输超时。连接在批次内复用、跨批次不复用;不同调用线程可并发执行独立批次,限制按批次生效。完成顺序可能与输入顺序不同,但返回的结果向量保持输入顺序与数量。 - 并发与所有权:适配器 API 是同步的(返回前完成批量处理与清理);每个批次独占自己的请求上下文与 libcurl 句柄,无共享
CURLM或全局锁。下载缓冲区、上传 iovec 数组与上传负载必须存活到调用返回,使用中不得修改。失败的读可能已部分改写目标缓冲区,不得将其当作有效数据消费。 - 失败语义(摘自 oss-backend.md 的 Failure Semantics 表):GET 遇到缺失对象返回
FILE_NOT_FOUND;范围 GET 需要 HTTP 206 与请求长度;PUT 非成功状态码视为写失败,不会把该对象报告为成功卸载;超时的 PUT 无法证明 OSS 是否已存储数据;一个对象失败时保留逐对象结果,成功的上传不会自动删除——批量不是事务。
故障排查
适配器无法初始化
依次检查:构建依赖(libcurl、OpenSSL 开发库与头文件)、必填的 endpoint/region/凭证设置、本地目录是否存在且可写、是否存在残留的MOONCAKE_DFS_*override(它们会覆盖MOONCAKE_DISTRIBUTED_*配置)。可选的健康检查会实际访问 OSS,但它只验证 OSS 访问通路,不覆盖完整的 Store 读路径。
请求报鉴权或权限错误
核对 endpoint、签名 region、bucket 权限以及 STS token 的有效期。适配器不会自动刷新凭证——token 过期后需要重启或重新初始化加载新凭证。
对象已在 OSS 中,但无法通过 Store 读取
bucket 里有一个对象不等于可读的 Store 副本。master 必须拥有该 key 的元数据且存在可达的 owner。务必保持前缀 owner 专属:共享同一个 bucket 并不会让不同 owner 变得可互换(owner 前缀防止互相覆盖对象)。
SSD 容量指标与 OSS 实际用量不一致
MOONCAKE_OFFLOAD_TOTAL_SIZE_LIMIT_BYTES提供的是一个配置的容量值(默认 2 TiB),而非查询 OSS bucket 得到的容量。master 的用量统计追踪的是已注册的LOCAL_DISK副本。这里 OSS 没有后端配额强制,也没有自动对象 GC——删除 master 元数据不会触发 OSS DELETE,因此这些指标既不是物理 bucket 用量,也不是云成本限额。当前实现同样不支持multipart 上传、自动并行范围切分与自动凭证刷新(见 oss-backend.md 的 Current Limitations)。
- 人工智能
- 大模型
- 模型推理服务
- 后端
【免费下载链接】Mooncake
Mooncake is the serving platform for Kimi, a leading LLM service provided by Moonshot AI.
相关推荐
Mooncake Store OSS 对象存储后端深度解析:LOCAL_DISK 卸载路径、OSS V4 签名与 libcurl 并发批次实现
Mooncake Store OSS 对象存储后端深度解析:LOCAL_DISK 卸载路径、OSS V4 签名与 libcurl 并发批次实现 导读 本篇文章以
人工智能大模型模型推理服务后端Mooncake Store SSD 存储部署指南:本地 SSD Offload、NVMe KV 后端与 NVMe-oF 共享存储池
Mooncake Store SSD 存储部署指南:本地 SSD Offload、NVMe KV 后端与 NVMe oF 共享存储池 本文以 Mooncake
人工智能大模型模型推理服务后端Thanos Store Gateway 组件完全指南:对象存储上的 Store API 网关架构、配置与调优
Thanos Store Gateway 组件完全指南:对象存储上的 Store API 网关架构、配置与调优 Thanos Store Gateway(即 t
可观测性云原生时序数据库运维
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考