HDFS
Polars on-premises provides experimental support for using HDFS (Hadoop Distributed Filesystem) as a storage back-end, from a polars cluster. Accessing HDFS directly from the client is not included. This functionality is considered unstable.
Polars HDFS support provides pure-Rust access to the data, no JVM required on the cluster. When Iceberg is used, HDFS support also provides Rust-based native access to the metadata.
Support for accessing data and/or metadata requires explicit configuration, and may require additional infrastructure to function.
Once enabled, HDFS storage is accessible through the standard polars API, using the
hdfs://host:port/ URI syntax, in combination with the use of storage_options.
Installation and Configuration
HDFS must be explicitly enabled in the cluster configuration, as follows.
[worker.extras]
hdfs.enabled = true
To access Iceberg metadata from HDFS, pyiceberg must also be enabled.
[worker.extras]
hdfs.enabled = true
pyiceberg.enabled = true
In addition, for metadata access, two python packages must be installed on the worker virtual
environment, i.e. hdfs-native and pyiceberg. This can be done by configuring the virtual
environment using your management tools, or as follows:
pip install polars-on-premises[hdfs, pyiceberg]
Note, the python dependencies are not required for direct data access.
Under the hood, polars HDFS support uses the hdfs_native crate, which is responsible for handling
the Hadoop configuration, see Native Rust HDFS client
for details.
By default, he HDFS client running on the worker will look for a configuration directory, which must be made available locally on the worker. In the case of Kubernetes, this can be done by configuring volume mounts in the helm chart as part of the deployment.
When Kerberos is used with the dynamic library libgssapi-krb5-2, the runtime image must include
this library, which will require an explicit runtime image update, or a ticket cache must be made
available locally from disk on every worker.
Usage: Data access
Once enabled, direct HDFS data access is available using the standard polars API, for example:
src = "hdfs://localhost:9005/data/foods1.parquet"
result = (
pl.scan_parquet(src)
.remote(context=ctx)
.execute()
.lazy()
.collect()
)
Note that the URI contains both the scheme and the location.
In this case, no storage_options are required, but any storage_options provided will be shared
with the native Rust HDFS client, see
Native Rust HDFS client for details.
Usage: Iceberg metadata-path or table access
An Iceberg table with metadata stored on HDFS can be used for reading and writing by passing its metadata path or by providing a table object.
The storage_options MUST include:
- the
py-io-implkey with the value as shown below to select the no-JVM native Rust HDFS client, and - the
hdfs.hostand optionallyhdfs.portfields to the location, per the pyiceberg spec. The host/port from the URI will be ignored.
In future versions, polars will normalize the storage_options fields and URI elements to make the
API and configuration management more ergonomic.
With a known metadata path:
storage_options = {
"py-io-impl": "pyiceberg.io.fsspec.FsspecFileIO",
"hdfs.host": "localhost",
"hdfs.port": "9005"
}
metadata_path = "hdfs://localhost:9005/warehouse/db/test/metadata/00001-a770f692-2344-4b87-b217-65b98ed7033b.metadata.json"
result = (
pl.scan_iceberg(metadata_path, storage_options=storage_options)
.remote(context=ctx)
.execute()
.lazy()
.collect()
)
Similarly, a table object can be used:
storage_options = {
"py-io-impl": "pyiceberg.io.fsspec.FsspecFileIO",
"hdfs.host": "localhost",
"hdfs.port": "9005"
}
(
df.lazy()
.remote(context=ctx)
.distributed()
.sink_iceberg(table, storage_options=storage_options, mode="append")
.await_result()
)
Without py-io-impl set, pyiceberg will not function.
Note: accessing HDFS locally from the client is not supported. Only HDFS access from the cluster nodes is currently supported.