Iceberg catalog
An Iceberg catalog connects Gravitino to the store that holds an Apache Iceberg catalog's table pointers: a Hive metastore, a JDBC database, or another Iceberg REST catalog. Gravitino manages the catalog's schemas, tables, and views through that backend, and engines reach the same tables through the Iceberg REST catalog service, as described in Iceberg REST clients, or through the Gravitino connectors. The pointer is the top of each table's tree of files; see How Iceberg works.
Quick start
The example connects the catalog iceberg_catalog, which keeps its table pointers in a PostgreSQL
database and its warehouse in S3, then creates the schema sales and the table orders. Creating
the table writes its first metadata file to the bucket, so it is the first step that tests the
storage settings. To vend temporary credentials to engines rather than share a key, see
Amazon S3.
- UI
- REST
-
Start the catalog. Open Connect → Catalogs and click + Catalog. Enter
iceberg_catalogas the Catalog name, keep Relational as the Catalog type, and choose Apache Iceberg in Select provider. -
Fill in the connection.
Field Value Catalog backend JDBC URI jdbc:postgresql://{postgres_host}:5432/{database}User, Password The backend database's user and password Storage S3 Warehouse s3://{bucket}/warehouseAWS region The bucket's region, such as us-west-2Access key ID, AWS secret key An access key that can read and write the bucket -
Test and create it. Click Test connection, which checks the backend database but not the bucket, then Create catalog.
-
Create the schema. In Explore, open
iceberg_catalog, click + Schema, and createsales. Tables are created through engines and the API rather than the UI; see Iceberg tables to create one from Spark.
-
Create the catalog. Over the API,
jdbc-driverhas to be set; the UI fills it in from the URI.Create an Iceberg catalogcurl -sS -X POST "https://{gravitino_host}/api/metalakes/{metalake}/catalogs" \
-H "Accept: application/vnd.gravitino.v1+json" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d '{
"name": "iceberg_catalog",
"type": "RELATIONAL",
"provider": "lakehouse-iceberg",
"properties": {
"catalog-backend": "jdbc",
"uri": "jdbc:postgresql://{postgres_host}:5432/{database}",
"jdbc-driver": "org.postgresql.Driver",
"jdbc-user": "{jdbc_user}",
"jdbc-password": "{jdbc_password}",
"warehouse": "s3://{bucket}/warehouse",
"s3-region": "{region}",
"s3-access-key-id": "{access_key_id}",
"s3-secret-access-key": "{secret_access_key}"
}
}' -
Create the schema.
Create a schemacurl -sS -X POST "https://{gravitino_host}/api/metalakes/{metalake}/catalogs/iceberg_catalog/schemas" \
-H "Accept: application/vnd.gravitino.v1+json" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d '{"name": "sales"}' -
Create the table. Its metadata file lands under
s3://{bucket}/warehouse/sales/orders.Create an Iceberg tablecurl -sS -X POST "https://{gravitino_host}/api/metalakes/{metalake}/catalogs/iceberg_catalog/schemas/sales/tables" \
-H "Accept: application/vnd.gravitino.v1+json" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d '{
"name": "orders",
"columns": [
{"name": "id", "type": "long", "nullable": false},
{"name": "amount", "type": "decimal(10,2)", "nullable": true},
{"name": "order_date", "type": "date", "nullable": true}
],
"properties": {"format-version": "2"}
}'
Requirements and limitations
The server is built with Apache Iceberg 1.11.0. New tables use Iceberg table format version 2
unless format-version is set.
Flink and Spark clients may use a different Iceberg version than the server; the client JAR requirements are on these pages:
Do not mix Iceberg JARs of different versions on one client classpath; the result fails at runtime.
Catalog
Capabilities
- Works as a catalog proxy over a Hive, JDBC, or REST catalog backend.
- Creates, alters, and drops Iceberg schemas and tables.
- Does not manage snapshots; use an engine for snapshot operations such as rollback and expiry.
- Holds tables in several storage systems at once, including S3, GCS, ADLS, OSS, and HDFS.
- Reaches an HDFS warehouse with Kerberos or Hadoop simple authentication, for the Hive and JDBC backends.
- Caches table metadata; see Table metadata cache.
Properties
| Property name | Description | Default value | Required |
|---|---|---|---|
catalog-backend | Catalog backend of Gravitino Iceberg catalog. Supports hive, jdbc, or rest. | (none) | Yes |
uri | The address of the catalog backend, such as thrift://{hms_host}:9083, jdbc:postgresql://{postgres_host}:5432/{database}, jdbc:mysql://{mysql_host}:3306/{database}, or https://{rest_catalog_host}/iceberg. | (none) | Yes |
warehouse | Warehouse location of catalog. Use a physical S3 or HDFS location for hive or jdbc catalog backend, use catalog name for REST catalog backend. | (none) | Yes for hive and jdbc catalog backend |
catalog-backend-name | The catalog name passed to underlying Iceberg catalog backend. Catalog name in JDBC backend is used to isolate namespace and tables. | The property value of catalog-backend, like jdbc for JDBC catalog backend. | No |
A property with the gravitino.bypass. prefix that Gravitino does not define is passed, without the prefix, to the Iceberg catalog properties and the HDFS configuration. For example, gravitino.bypass.list-all-tables passes list-all-tables to the Iceberg catalog.
The trino.bypass. prefix passes a setting to the Trino Iceberg connector when Trino loads the catalog through the Gravitino connector. For example, trino.bypass.iceberg.table-statistics-enabled sets iceberg.table-statistics-enabled.
The spark.bypass. prefix does the same for the Spark Iceberg connector. For example, spark.bypass.io-impl sets io-impl in Spark.
JDBC backend
The JDBC backend needs jdbc-user, jdbc-password, and jdbc-driver for the connection to the database that holds the table pointers. When the warehouse is on Kerberos-secured HDFS, set authentication.type to kerberos and configure the Kerberos properties in Catalog backend security.
The database that holds the table pointers is not the metadata database. The metadata database holds Gravitino's own objects, such as catalogs, schemas, tags, roles, and grants, but not the location of each Iceberg table's current metadata file, which is what Iceberg reads and swaps on every commit. The catalog's own database holds that. Both can live on one PostgreSQL or MySQL server: give the catalog a database and user of its own there, so that its backups and permissions are managed apart from the metadata database. Several Iceberg catalogs can share that database by setting a different catalog-backend-name on each.
CREATE USER {jdbc_user} WITH PASSWORD '{jdbc_password}';
CREATE DATABASE {database} OWNER {jdbc_user};
On MySQL, use the statements in Use MySQL with the catalog's database and user. With jdbc-initialize left at true, Gravitino creates the tables Iceberg needs in the database when the catalog is created.
| Property name | Description | Default value | Required |
|---|---|---|---|
jdbc-user | JDBC user name | (none) | Yes |
jdbc-password | JDBC password | (none) | Yes |
jdbc-driver | com.mysql.jdbc.Driver or com.mysql.cj.jdbc.Driver for MySQL, org.postgresql.Driver for PostgreSQL | (none) | Yes |
jdbc-initialize | Whether to create the Iceberg tables in the database when the catalog is created | true | No |
To connect an existing JDBC Iceberg catalog, set catalog-backend-name to its catalog name so that Gravitino sees its existing namespaces and tables.
The PostgreSQL driver is in the server image. MySQL Connector/J is not, so a MySQL backend needs the chart to supply it; see JDBC driver.
With several JDBC catalog backends in one MySQL database, jdbc-initialize may not create the Iceberg tables; create them in the database before creating the catalog.
REST catalog backend
For the REST catalog backend, warehouse identifies the catalog in the Iceberg REST spec. In the Gravitino Iceberg REST server, warehouse maps to the catalog name. An empty value means the default catalog.
The following properties tune REST backend behavior:
| Property name | Description | Default value | Required |
|---|---|---|---|
data-access | Data access mode for REST catalog backend. Supported values are vended-credentials and remote-signing. | (none) | No |
rest-client-connection-timeout-ms | The HTTP connection timeout in milliseconds for requests to the REST catalog backend. | 10000 | No |
rest-client-socket-timeout-ms | The HTTP socket timeout in milliseconds for requests to the REST catalog backend. | 60000 | No |
vended-credentials: request credential vending from the Iceberg REST server.remote-signing: Gravitino doesn't support this mode yet.
Without warehouse, requests go to the remote service's default catalog, at paths such as https://{rest_catalog_host}/iceberg/v1/namespaces/{namespace}/tables/{table}.
curl -sS -X POST "https://{gravitino_host}/api/metalakes/{metalake}/catalogs" \
-H "Accept: application/vnd.gravitino.v1+json" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d '{
"name": "iceberg_rest",
"type": "RELATIONAL",
"comment": "Iceberg REST catalog",
"provider": "lakehouse-iceberg",
"properties": {
"catalog-backend": "rest",
"uri": "https://{rest_catalog_host}/iceberg",
"rest-client-connection-timeout-ms": "10000",
"rest-client-socket-timeout-ms": "60000",
"data-access": "vended-credentials"
}
}'
To reach a non-default catalog, set warehouse to its name; requests then go to paths such as https://{rest_catalog_host}/iceberg/v1/{catalog}/namespaces/{namespace}/tables/{table}. See Selecting a catalog.
Object storage
If io-impl is not set, the catalog uses org.apache.iceberg.io.ResolvingFileIO, which picks the
FileIO for each file from its URI scheme. The server image includes the storage libraries for every
scheme below, so nothing has to be downloaded.
| Storage | Schemes | Warehouse | Setup |
|---|---|---|---|
| Amazon S3 | s3, s3a, s3n | s3://{bucket}/{path}; s3a:// with the Hive backend | Amazon S3 |
| S3-compatible, such as R2 | s3 | s3://{bucket}/{path}, with s3-endpoint set | S3-compatible storage |
| Azure Data Lake Storage Gen2 | abfs, abfss, wasb, wasbs | abfss://{container}@{account}.dfs.core.windows.net/{path} | Azure Data Lake Storage |
| Google Cloud Storage | gs, gcs | gs://{bucket}/{path} | Google Cloud Storage |
| Alibaba Cloud OSS | oss | oss://{bucket}/{path} | OSS, below |
Each storage page lists the catalog properties the server uses to reach the storage, including the
ADLS service principal (azure-tenant-id, azure-client-id, azure-client-secret) and the GCS key
file (gcs-service-account-file), and the credential providers that vend access to engines.
To pass an Iceberg FileIO property that Gravitino does not manage, such as s3.sse.type,
gcs.project-id or adls.read.block-size-bytes, prefix it with gravitino.bypass. on the catalog:
gravitino.bypass.s3.sse.type. A bypass property is not declared as hidden, so it can come back when
the catalog is loaded; do not pass credentials this way. See Property behavior.
OSS
| Configuration item | Description | Default value | Required |
|---|---|---|---|
io-impl | The IO implementation for FileIO in Iceberg. Set it to org.apache.iceberg.aliyun.oss.OSSFileIO to explicitly use OSSFileIO. | org.apache.iceberg.io.ResolvingFileIO | No |
oss-access-key-id | The static access key ID used to access OSS data. | (none) | No |
oss-secret-access-key | The static secret access key used to access OSS data. | (none) | No |
oss-endpoint | The endpoint of Aliyun OSS service. | (none) | No |
Set warehouse to oss://{bucket_name}/{prefix_name}. Credential providers for OSS are described in
Credential vending.
Other storage
Storage that Gravitino does not support directly can be reached through a custom FileIO.
| Configuration item | Description | Default value | Required |
|---|---|---|---|
io-impl | The IO implementation for FileIO in Iceberg. Use the fully qualified class name to override the default implementation. | org.apache.iceberg.io.ResolvingFileIO | No |
To pass a property such as security-token to a custom FileIO, set gravitino.bypass.security-token; the FileIO receives security-token when it is initialized. A bypass property is not declared as hidden, so a credential passed this way can come back when the catalog is loaded; see Property behavior.
Set warehouse to {storage_scheme}://{bucket}/{prefix}. The custom FileIO and its dependencies must be on the server's classpath.
Catalog backend security
The following properties secure access to the warehouse storage. For example, if you are using a Hive or JDBC catalog backend with a Kerberos-secured HDFS warehouse, set authentication.type to kerberos and provide authentication.kerberos.principal and authentication.kerberos.keytab-uri. For JDBC backend, JDBC username/password authentication for the metadata store is configured separately via jdbc-user and jdbc-password.
| Property name | Description | Default value | Required |
|---|---|---|---|
authentication.type | The authentication type for HDFS warehouse access. Supports kerberos and simple for Hive and JDBC catalog backends. | simple | No |
authentication.impersonation-enable | Whether to enable impersonation for the Iceberg catalog. | false | No |
hive.metastore.sasl.enabled | Whether to enable SASL when connecting to a Kerberos Hive Metastore, passed to Hive unchanged. | false | No. Set to true in most cases when authentication.type is kerberos (some deployments use SSL instead, but that is rare). |
authentication.kerberos.principal | The principal for Kerberos authentication. | (none) | Yes, if authentication.type is kerberos. |
authentication.kerberos.keytab-uri | The URI of the keytab for Kerberos authentication. | (none) | Yes, if authentication.type is kerberos. |
authentication.kerberos.check-interval-sec | The check interval of Kerberos credential for the Iceberg catalog. | 60 | No |
authentication.kerberos.keytab-fetch-timeout-sec | The fetch timeout for retrieving Kerberos keytab from authentication.kerberos.keytab-uri. | 60 | No |
Table metadata cache
Gravitino caches table metadata to avoid rereading metadata files. Before serving a cached entry, it checks the table's current metadata location against the catalog backend, so a table changed by another writer is reread.
| Configuration item | Description | Default value | Required |
|---|---|---|---|
table-metadata-cache-impl | The implementation of the table metadata cache. An empty string ("") turns the cache off. A backend that cannot report a table's metadata location, such as rest, runs without the cache and logs a warning until the property is set to "". | org.apache.gravitino.iceberg.common.cache.LocalTableMetadataCache | No |
table-metadata-cache-capacity | The capacity of the table metadata cache. | 1000 | No |
table-metadata-cache-expire-minutes | The expiration time (in minutes) of the table metadata cache. | 60 | No |
The built-in LocalTableMetadataCache keeps the cache in server memory. A custom cache implements org.apache.gravitino.iceberg.common.cache.TableMetadataCache.
Operations
Refer to Catalogs and schemas for more details.
Sensitive catalog properties such as s3-access-key-id, s3-secret-access-key, oss-access-key-id, and oss-secret-access-key are hidden from the load catalog response. Engines that need storage access get short-lived credentials through credential vending rather than the stored keys.
Schema
Capabilities
- Does not support cascading schema drops; drop the tables first.
- Supports hierarchical (multi-level) schemas, mapping each level to an Iceberg namespace level. See Hierarchical schema.
Properties
Any property can be set except comment, which is a field of the schema itself.
Operations
Refer to Catalogs and schemas for more details.
Hierarchical schema
The Iceberg catalog supports a hierarchical (multi-level) schema, where a schema can be nested under another schema, mapping each level to an Iceberg multi-level namespace.
A hierarchical schema name is a path whose levels are joined by the configured separator
gravitino.schema.separator (default :, see Server settings).
For example, with the default separator the name a:b:c denotes a schema c nested under a:b,
which in turn is nested under a. The separator is only used at the API boundary; Gravitino stores
the name internally using a physical separator that never collides with user input.
To create a hierarchical schema, supply its full hierarchical name. Any missing ancestor schemas are
created automatically, so creating a:b:c also creates a and a:b if they don't already exist.
The following example creates the schema a:b:c:
- REST
- Java
- Python
curl -sS -X POST "https://{gravitino_host}/api/metalakes/{metalake}/catalogs/iceberg_catalog/schemas" \
-H "Accept: application/vnd.gravitino.v1+json" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d '{
"name": "a:b:c",
"comment": "a hierarchical schema",
"properties": {}
}'
// Assuming you have just created an Iceberg catalog named `iceberg_catalog`
Catalog catalog = gravitinoClient.loadCatalog("iceberg_catalog");
SupportsSchemas supportsSchemas = catalog.asSchemas();
// missing ancestors `a` and `a:b` are created automatically
Schema schema = supportsSchemas.createSchema("a:b:c", "a hierarchical schema", Collections.emptyMap());
from gravitino import GravitinoClient
from gravitino.auth.basic_auth_provider import BasicAuthProvider
gravitino_client = GravitinoClient(
uri="https://{gravitino_host}",
metalake_name="{metalake}",
auth_data_provider=BasicAuthProvider("{user}", "{password}"),
)
catalog = gravitino_client.load_catalog(name="iceberg_catalog")
# missing ancestors `a` and `a:b` are created automatically
catalog.as_schemas().create_schema(name="a:b:c", comment="a hierarchical schema", properties={})
To list the schemas directly under a parent schema, pass the parent schema name. Over REST this is
the optional parentSchema query parameter; in the clients it is an argument to the list-schemas
method. Given the schemas a, a:b and a:b:c, listing the children of a:b returns [a:b:c].
When the parent is omitted, only the top-level schemas, such as a, are returned.
- REST
- Java
- Python
curl -sS "https://{gravitino_host}/api/metalakes/{metalake}/catalogs/iceberg_catalog/schemas?parentSchema=a:b" \
-H "Accept: application/vnd.gravitino.v1+json" \
-H "Authorization: Bearer $TOKEN"
Catalog catalog = gravitinoClient.loadCatalog("iceberg_catalog");
SupportsSchemas supportsSchemas = catalog.asSchemas();
String[] children = supportsSchemas.listSchemas("a:b");
from gravitino import GravitinoClient
from gravitino.auth.basic_auth_provider import BasicAuthProvider
gravitino_client = GravitinoClient(
uri="https://{gravitino_host}",
metalake_name="{metalake}",
auth_data_provider=BasicAuthProvider("{user}", "{password}"),
)
catalog = gravitino_client.load_catalog(name="iceberg_catalog")
children = catalog.as_schemas().list_schemas(parent_schema="a:b")
Table
Column types, format versions, partitioning, sort orders, table properties and the changes a table accepts are covered in Iceberg tables. How the tables work, from snapshots and commits to time travel and maintenance, is covered in How Iceberg works.
View
Capabilities
- Supports list, create, load, alter, and drop for views managed by the underlying Iceberg backend.
- Accepts any dialect name, such as
trino,spark,flink, orhive. - Can preserve multiple SQL representations for the same logical view; the full set of representations round-trips through Gravitino.
defaultCataloganddefaultSchemaare stored and returned as-is by the backend.- View support depends on whether the Iceberg catalog backend supports views; the REST and Hive backends do.
A rename cannot be combined with other changes in one alterView call; send it as its own request.
Operations
Refer to Tables and views for more details.
HDFS configuration
The server is built with Hadoop 3.3.6. HDFS client settings, such as the name service settings an
HA cluster needs, are passed as catalog properties with the gravitino.bypass. prefix, which the
catalog adds to its HDFS configuration. For example, gravitino.bypass.dfs.nameservices sets
dfs.nameservices.
The server writes to HDFS as a single HDFS user and does not impersonate other users. See Apache Hadoop access to set that user.