3. 环境搭建:安装与配置 Iceberg,以及与主流计算引擎的集成
在掌握了 Iceberg 的核心表格式概念之后,下一步是搭建一个可运行的环境,让 Iceberg 真正服务于数据读写与查询。Iceberg 本身并不提供计算能力,它是一套定义在数据文件之上的表格式规范与 Java 库。因此,所谓“安装 Iceberg”,本质上是在计算引擎(如 Spark、Flink、Trino)中引入 Iceberg 的运行时依赖,并配置 Catalog 指向元数据存储。本章将围绕这一核心思路,讲解环境搭建的完整路径。
3.1 核心原理:Iceberg 在引擎中的角色
理解 Iceberg 的部署模型是避免配置混乱的前提。Iceberg 不会作为一个独立服务常驻运行,而是以插件(Plugin)或依赖库(Library)的形式嵌入到各个计算引擎中。当引擎执行 SQL 时,Iceberg 的代码负责解析表元数据、规划数据文件扫描路径、提交写入事务等操作。
这种架构带来两个关键推论:
- Catalog 是唯一的外部依赖:Iceberg 表的状态(当前快照、Schema、分区信息)都记录在 Catalog 中。Catalog 可以是 Hive Metastore、Hadoop 文件系统、JDBC 数据库或 REST 服务。引擎与 Iceberg 的集成,本质上就是让引擎能够通过 Iceberg 的 API 访问到正确的 Catalog。
- 数据文件与元数据解耦:Iceberg 的数据文件(Parquet/ORC/Avro)存储于分布式文件系统(如 HDFS、S3)中,而元数据文件(`.metadata` 目录下的 JSON、Avro 文件)也存储在同一文件系统。Catalog 只保存指向当前元数据文件的指针。
3.2 方法流程:以 Spark 为例的完整配置步骤
Spark 是目前使用 Iceberg 最广泛的引擎。下面以 Spark 3.5 + Iceberg 1.5.0 为例,演示从零启动一个本地开发环境的完整流程。生产环境仅需将文件路径替换为集群路径。
步骤 1:下载并准备 Spark
确保本机已安装 Java 8/11/17 和 Python 3.8+。从 Apache 官网下载 Spark 预编译包(不带 Hadoop 版本,使用内置 Hadoop 3.3 即可)。解压后,将 Iceberg 的 Spark 运行时 JAR 包放入 Spark 的 jars/ 目录:
# 下载 Iceberg Spark Runtime(需与 Spark 大版本匹配)
wget https://repo1.maven.org/maven2/org/apache/iceberg/iceberg-spark-runtime-3.5_2.12/1.5.0/iceberg-spark-runtime-3.5_2.12-1.5.0.jar
# 复制到 Spark 的 jars 目录
cp iceberg-spark-runtime-3.5_2.12-1.5.0.jar $SPARK_HOME/jars/
步骤 2:启动 Spark SQL Shell 并配置 Catalog
Iceberg 支持通过 --packages 动态加载依赖,但将 JAR 放入 jars/ 目录更稳定。启动时通过 --conf 指定 Catalog 实现。以下示例使用 Hadoop Catalog,将元数据直接存储在本地文件系统,适合开发测试:
spark-sql \
--conf spark.sql.catalog.my_catalog=org.apache.iceberg.spark.SparkCatalog \
--conf spark.sql.catalog.my_catalog.type=hadoop \
--conf spark.sql.catalog.my_catalog.warehouse=/tmp/iceberg_warehouse
配置说明:
spark.sql.catalog.my_catalog:定义名为my_catalog的 Catalog,后续 SQL 中通过my_catalog.db.table访问表。type=hadoop:使用 Hadoop Catalog,表元数据直接以文件形式存储在warehouse路径下,无需额外服务。warehouse:指定 Iceberg 数据仓库的根目录。
步骤 3:验证集成并创建第一张 Iceberg 表
在 Spark SQL 中执行以下命令,验证环境是否正常:
-- 创建命名空间(类似数据库)
CREATE NAMESPACE my_catalog.demo;
-- 创建 Iceberg 表
CREATE TABLE my_catalog.demo.orders (
order_id BIGINT,
customer_id INT,
order_date DATE,
total_amount DECIMAL(10,2)
) USING iceberg
PARTITIONED BY (days(order_date));
-- 插入测试数据
INSERT INTO my_catalog.demo.orders VALUES
(1, 101, DATE '2024-05-01', 299.00),
(2, 102, DATE '2024-05-02', 159.50);
-- 查询验证
SELECT * FROM my_catalog.demo.orders;
如果查询能正确返回两行数据,说明 Iceberg 已成功嵌入 Spark。此时可以查看 /tmp/iceberg_warehouse 目录,会发现自动生成了 demo.db/orders/metadata 和 demo.db/orders/data 两个子目录,分别存放元数据文件与 Parquet 数据文件。
3.3 案例场景:Flink 与 Trino 的集成差异
不同引擎的集成方式各有侧重。Flink 强调流式写入与读取,Trino 则专注于联邦查询。下表对比了三种引擎的集成要点:
| 引擎 | 集成方式 | 关键配置 | 典型场景 |
|---|---|---|---|
| Spark | 添加 Runtime JAR 到 jars/ 或使用 --packages | spark.sql.catalog.<name>.type=hadoop/hive/jdbc/rest | 批处理 ETL、数据湖分析 |
| Flink | 将 iceberg-flink-runtime JAR 放入 Flink lib/ 目录 | 通过 Flink SQL Client 的 CREATE CATALOG 语句指定 | 实时流写入、CDC 入湖 |
| Trino | 在 Trino 插件目录放置 iceberg 插件目录 | 在 etc/catalog/iceberg.properties 中配置 connector.name=iceberg | 跨数据源联邦查询、交互式分析 |
Flink 集成示例
Flink 集成时,需要将 Iceberg 的 Flink 运行时 JAR 放入 Flink 的 lib/ 目录。然后在 SQL Client 中执行:
CREATE CATALOG iceberg_catalog WITH (
'type' = 'iceberg',
'catalog-type' = 'hadoop',
'warehouse' = 's3://my-bucket/warehouse',
'property-version' = '1'
);
USE CATALOG iceberg_catalog;
-- 创建表并启用流式读取
CREATE TABLE flink_orders (
order_id BIGINT,
customer_id INT,
order_timestamp TIMESTAMP(3),
WATERMARK FOR order_timestamp AS order_timestamp - INTERVAL '5' SECOND
) WITH (
'connector' = 'iceberg',
'catalog-name' = 'iceberg_catalog',
'catalog-type' = 'hadoop',
'warehouse' = 's3://my-bucket/warehouse'
);
Flink 的 Iceberg 连接器支持 streaming-read 模式,可以持续监控 Iceberg 表的新快照,实现近实时增量消费。
Trino 集成示例
Trino 的集成不依赖 JAR 手动放置,而是通过插件机制。在 Trino 安装目录的 etc/catalog/ 下创建 iceberg.properties:
connector.name=iceberg
iceberg.catalog.type=hadoop
iceberg.warehouse.location=/data/iceberg
重启 Trino 后,即可通过 SHOW SCHEMAS FROM iceberg; 查看已有命名空间。Trino 的优势在于可以一条 SQL 同时关联 Iceberg 表与 MySQL、PostgreSQL 中的业务表,无需数据迁移。
3.4 误区与复盘:环境搭建中的常见陷阱
Iceberg 的 Runtime JAR 与引擎版本强绑定。例如,
iceberg-spark-runtime-3.5_2.12 只能用于 Spark 3.5 且 Scala 版本为 2.12 的环境。如果使用 Spark 3.4 却加载 3.5 的 JAR,启动时会抛出类加载异常。务必核对引擎的 Scala 版本(通过 spark-shell --version 查看)。
初学者常混淆
hadoop 与 hive Catalog。Hadoop Catalog 不需要 Hive Metastore,但多引擎共享同一张表时无法保证元数据一致。如果生产环境已有 Hive Metastore,应使用 type=hive 并配置 uri=thrift://hive-metastore:9083。否则,Spark 创建的表 Flink 无法识别。
SHOW TABLES 或 SELECT * FROM table LIMIT 1 验证连通性,避免一次性引入过多变量导致问题难以定位。