
目录问题背景湖仓查询为什么要把存储和引擎解耦RustFS 在湖仓里的位置S3 兼容的数据文件底座一键拉起rustfs polaris trino 的 docker-compose跑通直查Iceberg catalog 配置与 SQL 验证边界与取舍path-style 必需、与 DuckDB 单机的区别、生产注意总结与下一步1. 问题背景湖仓查询为什么要把存储和引擎解耦一套湖仓起来之后最常见的痛点不是算不了而是数据在两块地方、权限两套、扩容各扩各的。我给一个做用户行为分析的团队搭查询层时他们原本把 Parquet 直接堆在本地 NFS 上Spark 一并发查询就把 NFS 打满扩容量还受单机文件系统限制。后来那个团队把存储换成 S3 兼容对象存储、计算交给 Trino读写路径和扩缩容就彻底分开了——存储按对象数扩计算按查询并发扩。关键前提是对象存储得够标准Iceberg 的元数据文件、manifest、data file 全走 S3 接口catalog 通过 REST 协议管表结构数据文件落到对象存储。如果存储对 S3 的兼容有偏差List、multipart、path-style 这些细节就会在查询时咬人。RustFS 因为是 100% S3 兼容又能私有化部署正好适合当这个底座。Apache Polaris 的官方 Trino 指南甚至直接用它作示例存储后端下面我照那份指南把链路跑通。2. RustFS 在湖仓里的位置S3 兼容的数据文件底座在 Iceberg 的架构里RustFS 不碰表结构只负责兜住数据文件。分工是这样Trino 是 SQL 查询引擎Polaris 是 Iceberg REST Catalog管 namespace、table、schemaRustFS 提供 S3 兼容接口存 Iceberg 的 metadata 和 data file。三者通过标准协议对接彼此不绑死实现。为什么 RustFS 适合干这个活一是 S3 100% 兼容Iceberg 的s3://路径访问、multipart 上传、path-style 寻址都能直接用不用改连接器二是可以私有化部署在自有机房或任意云数据不出域适合合规和成本敏感的场景三是和 Trino/Spark/PyIceberg 这些 Iceberg REST 客户端共用同一套接入方式换引擎不用换存储。对 AI 训练场景也顺——特征表、样本清单以 Iceberg 落 RustFS训练作业和查询作业共用一块存储。3. 一键拉起rustfs polaris trino 的 docker-composeApache Polaris 的指南给了现成的 docker-compose一个rustfs服务当 S3 存储一个polaris跑 REST Catalog示例用内存 metastore一个polaris-setup引导出 catalog/grant/namespace一个trino带着 Iceberg connector 指向 Polaris。起之前设好端点变量exportS3_ENDPOINThttp://rustfs:9000dockercompose-fsite/content/guides/rustfs/docker-compose.yml\-fsite/content/guides/trino/docker-compose.yml updockerexec-it$(dockerps-q--filternametrino)trino这里有一点值得点出来RustFS 在 compose 里就是个普通 S3 服务Polaris 写 Iceberg 元数据时用内部地址http://rustfs:9000endpointInternal外部客户端用http://localhost:9000。存储和 catalog 解耦之后端点内外分流是标准做法不影响数据落点。4. 跑通直查Iceberg catalog 配置与 SQL 验证Trino 侧真正要配的是 Iceberg catalog 的属性文件catalog/polaris.properties核心是把 S3 端点指到 RustFS并打开 path-style 访问。下面这张表是照 Polaris 指南整理的必填项connector.nameiceberg iceberg.catalog.typerest iceberg.rest-catalog.urihttp://polaris:8181/api/catalog iceberg.rest-catalog.warehousequickstart_catalog iceberg.rest-catalog.securityOAUTH2 iceberg.rest-catalog.vended-credentials-enabledtrue fs.s3.enabledtrue s3.endpointhttp://rustfs:9000 # 指向 RustFS 的 S3 兼容端点默认 9000 s3.path-style-accesstrue # RustFS 必需否则 Iceberg 数据文件寻址失败polaris-setup已经建好了quickstart_catalog连上 Trino CLI 直接建表写数CREATESCHEMApolaris.demo;USEpolaris.demo;CREATETABLEevents(event_idBIGINT,event_typeVARCHAR,user_idBIGINT,created_atTIMESTAMP(6)WITHTIMEZONE);INSERTINTOeventsVALUES(1,page_view,101,TIMESTAMP2024-10-01 10:00:00 UTC),(2,click,102,TIMESTAMP2024-10-01 11:30:00 UTC),(3,purchase,101,TIMESTAMP2024-10-02 09:15:00 UTC);SELECTevent_type,count(*)AScntFROMeventsGROUPBYevent_typeORDERBYcntDESC;跑通这条 SELECT说明数据文件已经落到 RustFS、元数据在 Polaris、查询路径全通。RustFS 控制台默认http://localhost:9001里能看到对应的 bucket 和对象增长。5. 边界与取舍path-style 必需、与 DuckDB 单机的区别、生产注意几个落地时容易踩、但说清就不慌的点s3.path-style-accesstrue是 RustFS 必需项。RustFS 走 path-style 寻址Iceberg 的s3://bucket/key要靠它解析漏了这项查询会找不到数据文件。这是接入边界不是 bug。Trino 官方只测了 AWS S3 与 MinIO 的 S3 兼容。文档原话是其他存储系统需自行测试并咨询厂商RustFS 出现在 Polaris 官方指南里等于这份组合已经被指南作者验证过一轮但真上生产仍建议用自己的表结构和数据量再扫一遍。和 DuckDB 单机的区别DuckDB 适合分析师在笔记本上直接SELECTRustFS 上的 Parquet/Iceberg轻量、无需服务Trino 是分布式 SQL 引擎适合多并发、跨大表的湖仓查询代价是要起 Polaris Trino 一组服务。选型看查询规模和并发不是谁替代谁。示例 metastore 是内存版。Polaris 示例用 in-memory metastore重启即丢 catalog生产要把 metastore 换成持久化后端如 PostgreSQL并给 RustFS 建专用 IAM 用户而非共用管理员凭证。中性边界示例的vended-credentials-enabledtrue让 Polaris 给 Trino 派发访问对象存储的临时凭据凭证由 catalog 侧管理。生产里把 RustFS 的访问 Key 收进 Polaris 的凭证体系比把静态 Key 写进每个 Trino 节点更干净也更容易做轮换。6. 总结与下一步把这条湖仓链路的落地动作收一下存储用 RustFSS3 兼容默认 9000catalog 用 Apache PolarisIceberg REST查询用 Trino。Trino 的 Iceberg catalog 必须设s3.endpointhttp://rustfs:9000与s3.path-style-accesstrue。先用指南的 docker-compose 跑通 CREATE/INSERT/SELECT确认数据文件落在 RustFS bucket。生产把 Polaris metastore 换成持久化后端RustFS 走专用 IAM 用户 凭证派发。单表即席查询用 DuckDB跨大表高并发用 Trino两块存储共用 RustFS。想先动手最快的路子就是照 Polaris 官方那份 Trino 指南把四个容器拉起来十分钟就能看到第一条SELECT从 RustFS 读出结果。RustFS 仓库在这https://github.com/rustfs/rustfs 把它接进你现有的 Iceberg 管线比另起一套封闭存储省力得多。深入学习 RustFS RustFS技术文档 RustFS 技术文档- 提供架构、安装指南和 API 参考。GitHub 仓库 GitHub 仓库 - 获取源代码、提交问题或贡献代码。