Oracle Linux ZFS: OpenZFS on UEK Storage Guide
A practical guide to deploying and tuning OpenZFS on Oracle Linux using the Unbreakable Enterprise Kernel (UEK), covering DKMS kernel header alignment, ashift storage pool creation, dataset optimization, ARC memory caps, and snapshot workflows.
Why OpenZFS on Oracle Linux requires DKMS and matching kernel-uek-devel headers instead of standard kmod RPMs.
Creating pools with -o ashift=12 for 4K drives using persistent /dev/disk/by-id/ symlinks to survive reboots.
Capping ZFS ARC memory in /etc/modprobe.d/zfs.conf and configuring recordsize and compression per workload.
What Is OpenZFS on Oracle Linux?
OpenZFS is an advanced enterprise storage system and volume manager for Linux. On Oracle Linux, administrators frequently pair OpenZFS with the Unbreakable Enterprise Kernel (UEK) to provide self-healing storage, native inline compression, snapshots, and data integrity verification.
Think of OpenZFS on Linux as an all-in-one storage manager, volume manager, and software RAID controller operating directly inside the kernel, taking direct responsibility for disk blocks rather than stacking separate software layers like LVM, mdadm, and traditional filesystems.
Unbreakable Enterprise Kernel (UEK) is Oracle’s customized Linux kernel optimized for enterprise workloads, database performance, and hardware stability. Because UEK tracks newer upstream Linux kernels than standard Enterprise Linux releases, running OpenZFS requires configuring Dynamic Kernel Module Support (DKMS) to compile and load the ZFS kernel drivers cleanly.
Prerequisites & UEK Kernel Module Installation
Installing OpenZFS on Oracle Linux differs from standard RHEL installation because pre-compiled zfs-kmod packages are built for the Red Hat Compatible Kernel (RHCK). Running OpenZFS on UEK requires installing zfs-dkms and the exact matching kernel-uek-devel package for your active kernel.
Before installing, confirm your running kernel release using uname -r. You must ensure that kernel-uek-devel matches your running UEK version before DKMS compiles the ZFS module.
# Check active kernel release
uname -r
# Install EPEL and OpenZFS release repository
sudo dnf install -y https://zfsonlinux.org/epel/zfs-release-2-3$(rpm --eval "%{dist}").noarch.rpm
# Install kernel-uek-devel and DKMS build tools matching the running kernel
sudo dnf install -y kernel-uek-devel-$(uname -r) dkms gcc make
# Install OpenZFS DKMS module and userspace utilities
sudo dnf install -y zfs-dkms zfs
# Trigger manual DKMS build if needed
sudo dkms autoinstall
# Load the ZFS kernel module
sudo modprobe zfs
# Verify the ZFS module and userspace version match
zfs version
| Command / Package | Purpose |
|---|---|
kernel-uek-devel-$(uname -r) |
Provides kernel header files for the running Unbreakable Enterprise Kernel required by DKMS. |
zfs-dkms |
Compiles the ZFS kernel modules automatically whenever a new UEK kernel is installed. |
zfs |
Installs administrative binaries including zpool, zfs, and systemd services. |
modprobe zfs |
Loads the compiled ZFS module into the active Linux kernel space. |
zfs version |
Confirms both userspace tools and kernel module are running identical versions. |
scl run gcc-toolset-11 bash provides an updated GCC compiler toolset matching newer UEK kernel requirements.
Creating the ZFS Storage Pool (zpool)
A ZFS storage pool (zpool) aggregates physical hard drives or NVMe SSDs into a unified storage space. Never use raw device names like /dev/sdb or /dev/sdc when creating pools, because Linux drive letter ordering can change across system reboots.
Always use persistent device paths from /dev/disk/by-id/. Additionally, specify -o ashift=12 during pool creation to ensure 4096-byte (4K) sector alignment, preventing write amplification on modern Advanced Format drives and enterprise SSDs.
# Identify persistent disk IDs
ls -l /dev/disk/by-id/
# Create a mirrored storage pool (RAID 10 equivalent) with 4K alignment and LZ4 compression
sudo zpool create -o ashift=12 -O compression=lz4 datapool mirror \
/dev/disk/by-id/nvme-eui.002538b811a00001 \
/dev/disk/by-id/nvme-eui.002538b811a00002
# Create a dual-parity pool (RAIDZ2) for high-capacity HDD storage
sudo zpool create -o ashift=12 -O compression=zstd storagepool raidz2 \
/dev/disk/by-id/ata-WDC_WD101KRYZ-01_1EGH101 \
/dev/disk/by-id/ata-WDC_WD101KRYZ-02_1EGH102 \
/dev/disk/by-id/ata-WDC_WD101KRYZ-03_1EGH103 \
/dev/disk/by-id/ata-WDC_WD101KRYZ-04_1EGH104
# Verify pool status and health
sudo zpool status -v
# Inspect overall storage space allocation
sudo zpool list
ashift setting cannot be changed after a virtual device (VDEV) is added to a pool. Failing to set -o ashift=12 on 4K disks causes severe write performance penalties that require recreating the entire pool to fix.
Dataset Configuration & Workload Tuning
ZFS datasets are lightweight virtual filesystems created within a storage pool. Unlike traditional partitions, datasets inherit pool capacity dynamically and can be configured with distinct compression algorithms, record sizes, access time rules, and quotas.
Tuning the dataset recordsize property to match your application’s disk I/O pattern drastically improves throughput and reduces cache churn. Database workloads perform best with smaller block sizes, while general file servers benefit from larger record sizes.
# Create datasets for general files, database, and virtual machine disks
sudo zfs create datapool/general
sudo zfs create datapool/oracle-db
sudo zfs create datapool/vms
# Configure optimal settings for general file storage
sudo zfs set compression=zstd datapool/general
sudo zfs set recordsize=128k datapool/general
sudo zfs set atime=off datapool/general
# Tune dataset specifically for Oracle Database or PostgreSQL (8k recordsize)
sudo zfs set recordsize=8k datapool/oracle-db
sudo zfs set logbias=latency datapool/oracle-db
sudo zfs set primarycache=metadata datapool/oracle-db
sudo zfs set atime=off datapool/oracle-db
# Set storage quotas and reservation rules
sudo zfs set quota=500G datapool/general
sudo zfs set reservation=100G datapool/oracle-db
# View all active datasets and properties
sudo zfs list -o name,used,avail,refer,mountpoint,compression,recordsize
| Dataset Property | Recommended Value | Purpose |
|---|---|---|
compression |
lz4 or zstd |
Transparent inline compression. lz4 is lightning fast; zstd offers higher compression ratios. |
recordsize |
8k (Databases) / 128k (Files) |
Matches ZFS block size to application I/O size, avoiding partial-block read-modify-write overhead. |
atime |
off |
Disables updating file access timestamps on every read, eliminating unnecessary disk write IOPS. |
logbias |
latency |
Optimizes synchronous writes (O_SYNC / fsync) for low latency using SLOG / ZIL intent logs. |
quota |
500G |
Caps maximum storage consumption for a dataset, preventing a single dataset from filling the pool. |
Managing ZFS ARC Memory Limits
OpenZFS uses an Adaptive Replacement Cache (ARC) stored in system RAM to cache frequently and recently accessed data. By default, OpenZFS on Linux allocates up to 50% of total host RAM for the ARC.
On an Oracle Linux server hosting memory-intensive applications such as Oracle Database, Java enterprise services, or KVM virtual machines, unconstrained ARC growth causes severe memory contention, swapping, or triggers Linux Out-Of-Memory (OOM) killer terminations.
# Check current ZFS ARC memory consumption (in bytes)
grep -E 'c_max|size' /proc/spl/kstat/zfs/arcstats
# Limit ZFS ARC maximum size to 16 GB in /etc/modprobe.d/zfs.conf
echo "options zfs zfs_arc_max=17179869184" | sudo tee /etc/modprobe.d/zfs.conf
# Apply the ARC limit immediately to the running kernel without rebooting
echo 17179869184 | sudo tee /sys/module/zfs/parameters/zfs_arc_max
# Monitor ARC hit rate and memory health
arcstat 1
arcstat 1. Monitor the read, hits, and miss columns. A healthy ZFS cache maintains an ARC hit rate above 85-90% while respecting your configured zfs_arc_max limit.
Snapshots, Rollbacks, and Replication
ZFS snapshots are read-only point-in-time copies of a dataset created instantly using Copy-on-Write (CoW). Because snapshots consume zero additional storage space when created, administrators can take automatic hourly or daily snapshots for instant disaster recovery.
In addition to local rollbacks, OpenZFS supports stream-based replication via zfs send and zfs recv. This allows sending full or incremental dataset snapshots across SSH to a remote backup server or secondary Oracle Linux host.
# Create a manual snapshot of the database dataset
sudo zfs snapshot datapool/oracle-db@pre-upgrade-20260907
# List all active snapshots and space consumed
sudo zfs list -t snapshot
# Roll back dataset to a previous snapshot state
sudo zfs rollback datapool/oracle-db@pre-upgrade-20260907
# Export an incremental snapshot stream to a compressed file
sudo zfs send -i datapool/oracle-db@snap-v1 datapool/oracle-db@snap-v2 | gzip > /backups/db-incr.gz
# Replicate dataset snapshot to a remote server over SSH
sudo zfs send -v datapool/oracle-db@pre-upgrade-20260907 | ssh admin@backup-node.example.com sudo zfs recv backup-pool/remote-db
# Destroy a stale snapshot when no longer needed
sudo zfs destroy datapool/oracle-db@pre-upgrade-20260907
zfs send to replicate critical snapshots to separate physical hardware.
Troubleshooting Cheat Sheet
Use this reference table to resolve common OpenZFS module, pool health, and performance issues on Oracle Linux servers.
| Symptom | Likely Cause | Fix |
|---|---|---|
modprobe: FATAL: Module zfs not found |
UEK kernel was updated without rebuilding the DKMS module or kernel-uek-devel is missing. |
Confirm kernel headers match uname -r and trigger a rebuild: sudo dkms autoinstall. |
| High memory usage / OOM killer terminating apps | ZFS ARC consuming default memory limit (50% host RAM). | Set maximum ARC size in configuration: echo "options zfs zfs_arc_max=17179869184" | sudo tee /etc/modprobe.d/zfs.conf. |
| High disk latency / poor I/O throughput | Pool created without ashift=12 on 4K sector drives causing write amplification. |
Recreate the storage pool specifying sector alignment: sudo zpool create -o ashift=12 .... |
Pool status shows UNAVAIL after reboot |
Pool created using raw /dev/sdX paths that changed letter assignment after boot. |
Export the pool and re-import using persistent IDs: sudo zpool import -d /dev/disk/by-id datapool. |
| DKMS build error during kernel compilation | System GCC compiler version differs from compiler used to build UEK. | Enable updated compiler toolset before building: scl run gcc-toolset-11 bash then re-run DKMS. |
Final Thoughts
Deploying OpenZFS on Oracle Linux brings enterprise-grade storage resiliency, compression, and snapshot management to enterprise infrastructure. By aligning DKMS with the Unbreakable Enterprise Kernel, using 4K ashift=12 pool parameters, and explicitly managing ZFS ARC memory caps, you create a fast, self-healing storage layer capable of supporting demanding database and virtualization workloads.
Next, we will explore Proxmox Backup Server (PBS) integration with ZFS storage targets for automated enterprise backups.