Apache Iceberg
使用 Docker Compose 运行 Apache Iceberg、Spark、REST catalog 和 RustFS 对象存储。
本指南将运行 Apache Iceberg、Spark、Iceberg REST catalog,并将 RustFS 用作兼容 S3 的仓库。你将创建一个 Iceberg 表、写入并查询数据行,然后验证表文件是否存储在 RustFS 中。
如需使用 RustFS 内置 REST 目录,请参阅 S3 Tables 配置和 PyIceberg 指南。下文的部署方式会运行独立的目录服务。
你需要安装带 Compose 插件的 Docker,并具备足够的本地资源来运行四个容器。此部署仅用于本地集成测试,不适用于生产环境。
上游状态
Apache Iceberg PR #14928 展示了相同的 Spark、REST catalog、S3FileIO 和 RustFS 工作流,包括表创建与写入。该拉取请求已关闭且未合并,当前的 Spark 快速入门 仍使用另一种兼容 S3 的存储。因此,以下配置记录的是 RustFS 集成方式,而不是 Apache Iceberg 的默认配置。
架构
Spark 使用 REST 服务执行 catalog 操作。Spark 和 REST catalog 都会接收 RustFS 端点、区域、凭证和路径样式设置,以便访问 s3://my-bucket/warehouse 中的元数据和数据文件。
创建项目文件
创建工作目录:
mkdir rustfs-iceberg
cd rustfs-iceberg创建环境文件并替换两个凭证占位符:
RUSTFS_ACCESS_KEY=<your-access-key>
RUSTFS_SECRET_KEY=<your-secret-key>请为仓库存储桶使用专用凭证。不要将 .env 提交到源代码管理系统。
创建 Spark catalog 配置:
spark.sql.extensions org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions
spark.sql.catalog.demo org.apache.iceberg.spark.SparkCatalog
spark.sql.catalog.demo.type rest
spark.sql.catalog.demo.uri http://rest:8181
spark.sql.catalog.demo.io-impl org.apache.iceberg.aws.s3.S3FileIO
spark.sql.catalog.demo.warehouse s3://my-bucket/warehouse
spark.sql.catalog.demo.s3.endpoint http://rustfs:9000
spark.sql.catalog.demo.s3.path-style-access true
spark.sql.defaultCatalog demo
spark.sql.catalogImplementation in-memory此容器网络端点必须使用路径样式访问。主机名 rustfs 只能在 Compose 网络内部解析;在主机上运行的客户端应改用 http://localhost:9000。
创建 Compose 文件:
services:
rustfs:
image: rustfs/rustfs:1.0.0-alpha.83
environment:
RUSTFS_ACCESS_KEY: ${RUSTFS_ACCESS_KEY}
RUSTFS_SECRET_KEY: ${RUSTFS_SECRET_KEY}
RUSTFS_VOLUMES: /data
RUSTFS_ADDRESS: ":9000"
RUSTFS_CONSOLE_ADDRESS: ":9001"
RUSTFS_CONSOLE_ENABLE: "true"
RUSTFS_OBS_LOGGER_LEVEL: error
RUSTFS_OBS_LOG_DIRECTORY: /var/log/rustfs/
volumes:
- rustfs-data:/data
ports:
- "9000:9000"
- "9001:9001"
networks:
- iceberg
create-bucket:
image: rustfs/rc:latest
depends_on:
- rustfs
environment:
RUSTFS_ACCESS_KEY: ${RUSTFS_ACCESS_KEY}
RUSTFS_SECRET_KEY: ${RUSTFS_SECRET_KEY}
entrypoint:
- /bin/sh
- -c
- |
until /usr/bin/rc alias set rustfs http://rustfs:9000 "$${RUSTFS_ACCESS_KEY}" "$${RUSTFS_SECRET_KEY}"; do
echo "Waiting for RustFS..."
sleep 2
done
/usr/bin/rc ls rustfs/my-bucket >/dev/null 2>&1 || /usr/bin/rc mb rustfs/my-bucket
networks:
- iceberg
rest:
image: apache/iceberg-rest-fixture
depends_on:
create-bucket:
condition: service_completed_successfully
environment:
AWS_ACCESS_KEY_ID: ${RUSTFS_ACCESS_KEY}
AWS_SECRET_ACCESS_KEY: ${RUSTFS_SECRET_KEY}
AWS_REGION: us-east-1
CATALOG_WAREHOUSE: s3://my-bucket/warehouse
CATALOG_IO__IMPL: org.apache.iceberg.aws.s3.S3FileIO
CATALOG_S3_ENDPOINT: http://rustfs:9000
CATALOG_S3_PATH__STYLE__ACCESS: "true"
ports:
- "8181:8181"
networks:
- iceberg
spark-iceberg:
image: tabulario/spark-iceberg
depends_on:
create-bucket:
condition: service_completed_successfully
rest:
condition: service_started
environment:
AWS_ACCESS_KEY_ID: ${RUSTFS_ACCESS_KEY}
AWS_SECRET_ACCESS_KEY: ${RUSTFS_SECRET_KEY}
AWS_REGION: us-east-1
volumes:
- ./spark-defaults.conf:/opt/spark/conf/spark-defaults.conf:ro
ports:
- "8888:8888"
- "8080:8080"
networks:
- iceberg
networks:
iceberg:
volumes:
rustfs-data:rc 镜像提供官方 RustFS 命令行客户端。初始化程序会在创建 my-bucket 前检查其是否存在,因此重复启动不会删除现有仓库数据。RustFS 卷会在容器重新创建后继续保留仓库对象。
镜像版本
Apache Iceberg 快速入门镜像在上游示例中发布时没有稳定版本标签。在将此模式用于本地测试之外的场景前,请将每个镜像固定到经过测试的标签或摘要,并同时验证 Spark、Iceberg runtime 和 REST catalog 的版本。
验证并启动部署
启动容器前解析 Compose 文件:
docker compose config启动服务并等待存储桶初始化程序完成:
docker compose up -d
docker compose ps -acreate-bucket 服务应显示退出代码 0。如果该服务未完成,请检查其日志:
docker compose logs create-bucket在 http://localhost:9001 打开 RustFS 控制台。REST catalog 位于 http://localhost:8181,Spark notebook 服务器位于 http://localhost:8888。
创建并查询 Iceberg 表
启动 Spark SQL:
docker compose exec spark-iceberg spark-sql创建命名空间和分区表:
CREATE NAMESPACE IF NOT EXISTS demo.nyc;
CREATE TABLE demo.nyc.taxis
(
vendor_id bigint,
trip_id bigint,
trip_distance float,
fare_amount double,
store_and_fwd_flag string
)
PARTITIONED BY (vendor_id);插入并查询示例数据行:
INSERT INTO demo.nyc.taxis
VALUES
(1, 1000371, 1.8, 15.32, 'N'),
(2, 1000372, 2.5, 22.15, 'N'),
(2, 1000373, 0.9, 9.01, 'N'),
(1, 1000374, 8.4, 42.13, 'Y');
SELECT * FROM demo.nyc.taxis ORDER BY trip_id;查询应返回四行:
1 1000371 1.8 15.32 N
2 1000372 2.5 22.15 N
2 1000373 0.9 9.01 N
1 1000374 8.4 42.13 Y验证 RustFS 中的对象
使用存储桶初始化程序镜像列出仓库内容:
docker compose run --rm --entrypoint /bin/sh create-bucket -c \
'/usr/bin/rc alias set rustfs http://rustfs:9000 "$RUSTFS_ACCESS_KEY" "$RUSTFS_SECRET_KEY" >/dev/null && /usr/bin/rc find rustfs/my-bucket/warehouse'输出应包含 warehouse/nyc/taxis 前缀下的 Iceberg 元数据和数据对象。你也可以在 RustFS 控制台中检查 my-bucket 存储桶。
停止或重置服务栈
停止容器但保留 RustFS 数据卷:
docker compose down要删除本地仓库并从空的 RustFS 卷重新开始,请显式添加 --volumes:
docker compose down --volumes故障排除
Spark 无法连接 RustFS
在 Compose 内部使用 http://rustfs:9000。在 spark-defaults.conf 中使用 http://localhost:9000 时,它指向的是 Spark 容器自身。
确认 spark.sql.catalog.demo.s3.path-style-access 为 true。虚拟主机样式请求需要额外的 RustFS 域名和 DNS 配置。
Catalog 返回 S3 错误
检查 .env 中的凭证是否与 RustFS 凭证一致,以及 create-bucket 服务是否成功完成:
docker compose logs create-bucket restREST catalog 属性 CATALOG_IO__IMPL 和 CATALOG_S3_PATH__STYLE__ACCESS 使用双下划线;fixture 会将它们转换为带点号和连字符的 Iceberg 属性名。
后续步骤
- 在采用其他 Iceberg 操作前,请查看 S3 兼容性说明。
- 通过访问密钥管理创建专用的生产凭证。
- 按照 Apache Iceberg Spark 文档配置现有 Spark 环境。