Curtiss Howard

Backing Up an iSCSI Volume with ZFS


While setting up an instance of PostgreSQL on my home Kubernetes cluster, the issue of how to create a proper persistent volume came up. I wanted to use network-based storage for the pod primarily because I use FreeNAS and backing up the volume to S3 using a Cloud Sync Task would be trivially easy. Right away I ruled out using NFS for PostgreSQL storage over reliability and performance concerns, so that left iSCSI. But, in order to get the best performance out of an iSCSI volume I had to use a zvol (device) instead of a file, which meant that Cloud Sync Tasks couldn't be used.

As it turns out, ZFS makes it rather easy to create a file out of a zvol using snapshots and zfs send. The idea here is to create a cron task that:

  • Creates a snapshot of the iSCSI zvol
  • Compresses the snapshot
  • Sends the compressed snapshot to a backup service (in my case, S3).
  • Deletes the snapshot

This was implemented in a fairly simple Bash script:


snapshot_name=$1@$(date +%Y-%m-%d)

echo "Creating snapshot $snapshot_name..."

zfs snapshot $snapshot_name

echo "Sending to S3 URL ${bucket_url}..."

zfs send -v $snapshot_name | gzip | jexec ioc-backup-s3 aws s3 cp - $bucket_url/${snapshot_name}.gz

echo "Deleting snapshot..."

zfs destroy $snapshot_name

Since you can't (easily) install third-party software into your FreeNAS installation (nor should you, really), I had to create a simple jail with the AWS CLI and my credentials (named backup-s3) that I use as a zfs send target in order to push the backup to S3. The S3 bucket is configured to delete backups after a certain amount of time, ensuring that the bucket doesn't grow endlessly.

aws freenas s3 zfs