Skip to main content
Kafka Connect is a popular framework for moving data in and out of Apache Kafka via connectors. There are many different connectors available, such as the S3 sink for writing data from Kafka to S3 and Debezium source connectors for writing change data capture records from relational databases to Kafka. It has a straightforward, decentralized, distributed architecture. A cluster consists of a number of worker processes, and a connector runs tasks on these processes to perform the work. Connector deployment is configuration driven, so generally no code needs to be written to run a connector.

Apache Iceberg Sink Connector

The Apache Iceberg Sink Connector for Kafka Connect is a sink connector for writing data from Kafka into Iceberg tables.

Features

Commit Coordination

Centralized Iceberg commits for consistency

Exactly-Once Delivery

Guarantees no duplicate or lost data

Multi-Table Fan-Out

Route records to different tables dynamically

Auto Table Creation

Automatically create tables and evolve schemas
  • Commit coordination for centralized Iceberg commits
  • Exactly-once delivery semantics
  • Multi-table fan-out
  • Automatic table creation and schema evolution
  • Field name mapping via Iceberg’s column mapping functionality

Installation

The connector zip archive is created as part of the Iceberg build. You can run the build via:
The zip archive will be found under ./kafka-connect/kafka-connect-runtime/build/distributions. There is one distribution that bundles the Hive Metastore client and related dependencies, and one that does not.
Copy the distribution archive into the Kafka Connect plugins directory on all nodes.

Requirements

The sink relies on KIP-447 for exactly-once semantics. This requires Kafka 2.5 or later.

Configuration

Core Properties

Table-Specific Properties

Control Topic Properties

Catalog and Hadoop Properties

If iceberg.tables.dynamic-enabled is false (the default) then you must specify iceberg.tables. If iceberg.tables.dynamic-enabled is true then you must specify iceberg.tables.route-field which will contain the name of the table.

Catalog Configuration

The iceberg.catalog.* properties are required for connecting to the Iceberg catalog. The core catalog types are included in the default distribution, including REST, Glue, DynamoDB, Hadoop, Nessie, JDBC, Hive and BigQuery Metastore.
JDBC drivers are not included in the default distribution, so you will need to include those if needed. When using a Hive catalog, you can use the distribution that includes the Hive metastore client, otherwise you will need to include that yourself.
To set the catalog type, you can set iceberg.catalog.type to rest, hive, or hadoop. For other catalog types, you need to instead set iceberg.catalog.catalog-impl to the name of the catalog class.

REST Example

Hive Example

Use the distribution that includes the HMS client (or include the HMS client yourself). Use S3FileIO when using S3 for storage and GCSFileIO when using GCS (the default is HadoopFileIO with HiveCatalog).

Glue Example

Nessie Example

BigQuery Metastore Example

Depending on your setup, you may need to also set iceberg.catalog.s3.endpoint, iceberg.catalog.s3.staging-dir, or iceberg.catalog.s3.path-style-access. See the Iceberg docs for full details on configuring catalogs.

Cloud Storage Configuration

Azure ADLS Configuration

When using ADLS, Azure requires the passing of AZURE_CLIENT_ID, AZURE_TENANT_ID, and AZURE_CLIENT_SECRET for its Java SDK. If you’re running Kafka Connect in a container, be sure to inject those values as environment variables.
Where:
  • CLIENT_ID is the Application ID from App Registrations
  • TENANT_ID is from your Azure Tenant Properties
  • CLIENT_SECRET is created within “Certificates & Secrets”
Ensure the App Registration is granted the Role Assignment “Storage Blob Data Contributor” in your Storage Account’s Access Control (IAM).
Connector configuration:

Google GCS Configuration

By default, Application Default Credentials (ADC) will be used to connect to GCS. Details on how ADC works can be found in the Google Cloud documentation.

Hadoop Configuration

When using HDFS or Hive, the sink will initialize the Hadoop configuration. First, config files from the classpath are loaded. Next, if iceberg.hadoop-conf-dir is specified, config files are loaded from that location. Finally, any iceberg.hadoop.* properties from the sink config are applied.
When merging these, the order of precedence is: sink config > config dir > classpath.

Examples

Initial Setup

1

Create source topic

This assumes the source topic already exists and is named events.
2

Create control topic

If your Kafka cluster has auto.create.topics.enable set to true (the default), then the control topic will be automatically created. If not, create it manually:
Clusters running on Confluent Cloud have auto.create.topics.enable set to false by default.
3

Configure Iceberg catalog

Configuration properties with the prefix iceberg.catalog. will be passed to Iceberg catalog initialization. See the Iceberg docs for details on how to configure a particular catalog.

Single Destination Table

This example writes all incoming records to a single table.
1

Create the destination table

2

Configure connector

This example config connects to an Iceberg REST catalog:

Multi-Table Fan-Out (Static Routing)

This example writes records with type set to list to the table default.events_list, and writes records with type set to create to the table default.events_create. Other records will be skipped.
1

Create two destination tables

2

Configure connector with routing

Multi-Table Fan-Out (Dynamic Routing)

This example writes to tables with names from the value in the db_table field. If a table with the name does not exist, then the record will be skipped. For example, if the record’s db_table field is set to default.events_list, then the record is written to the default.events_list table.

SMTs for the Apache Iceberg Sink Connector

This project contains some SMTs (Single Message Transforms) that could be useful when transforming Kafka data for use by the Iceberg sink connector.

CopyValue

This SMT is experimental.
The CopyValue SMT copies a value from one field to a new field. Configuration: Example:

DmsTransform

This SMT is experimental.
The DmsTransform SMT transforms an AWS DMS formatted message for use by the sink’s CDC feature. It will promote the data element fields to top level and add the following metadata fields: _cdc.op, _cdc.ts, and _cdc.source.

DebeziumTransform

This SMT is experimental.
The DebeziumTransform SMT transforms a Debezium formatted message for use by the sink’s CDC feature. It will promote the before or after element fields to top level and add the following metadata fields: _cdc.op, _cdc.ts, _cdc.offset, _cdc.source, _cdc.target, and _cdc.key. Configuration:

JsonToMapTransform

This SMT is experimental.
The JsonToMapTransform SMT parses Strings as JSON object payloads to infer schemas. The iceberg-kafka-connect connector for schema-less data (e.g. the Map produced by the Kafka supplied JsonConverter) is to convert Maps into Iceberg Structs. This is fine when the JSON is well-structured, but when you have JSON objects with dynamically changing keys, it will lead to an explosion of columns in the Iceberg table due to schema evolutions.
You must use the stringConverter as the value.converter setting for your connector, not jsonConverter. It expects JSON objects ({...}) in those strings. Message keys, tombstones, and headers are not transformed and are passed along as-is by the SMT.
Configuration:

KafkaMetadataTransform

This SMT is experimental.
The KafkaMetadata injects topic, partition, offset, timestamp which are properties of the Kafka message. Configuration:

MongoDebeziumTransform

This SMT is experimental.
The MongoDebeziumTransform SMT transforms a Mongo Debezium formatted message with before/after BSON strings into before/after typed Structs that the DebeziumTransform SMT expects.
It does not (yet) support renaming columns if MongoDB column is not supported by your underlying catalog type.
Configuration: Value array (the default) will encode arrays as the array datatype. It is user’s responsibility to ensure that all elements for a given array instance are of the same type. This option is a restricting one but offers easy processing of arrays by downstream clients. Value document will convert the array into a struct of structs in the similar way as done by BSON serialization. The main struct contains fields named _0, _1, _2 etc. where the name represents the index of the element in the array. Every element is then passed as the value for the given field.