Skip to main content
RunBook Academy

← All labs in Proxmox VE

Lab · intermediate · ~75 min

Configure ZFS replication and run a planned failover

A · Physical hardwareB · Nested virtualisation

Objectives

  • Set up ZFS storage on two PVE nodes
  • Schedule a replication job for a VM
  • Trigger a planned failover to the secondary node
  • Verify the replicated VM starts cleanly

Prerequisites

  • A 2-node PVE cluster with ZFS storage on both
  • A VM with the disk on the source ZFS pool
  • Network connectivity between the nodes (replication link)

ZFS replication lab

This lab sets up ZFS-based VM replication between two nodes and walks through a planned failover. It demonstrates a simple DR scenario.

Steps

1. Verify ZFS storage on both nodes

# On both nodes
zpool list
# Expected: a pool named "tank" (or similar) with sufficient capacity

2. Identify a VM to replicate

pvesh get /nodes/<source-node>/qemu/<vmid>/config
# Look for scsi0 referencing the ZFS pool

3. Add the replication target storage

In the GUI: Datacenter → Storage → Add → ZFS.

On the target node, this storage should already exist (the same pool name, but on different physical disks). If not, add it.

4. Schedule replication

In the GUI: Datacenter → Replication → Add.

Source node: pve-01
Target node: pve-02
Schedule: */15 (every 15 minutes)
VM: 100
Rate limit: (none)
Remove pending: yes

Or via CLI:

# Substitute your own values before running. The job id is
# <vmid>-<jobnum>, so the first job for VM 100 is 100-0:
JOB_ID=100-0
TARGET_NODE=pve-02

pvesr create-local-job "$JOB_ID" "$TARGET_NODE" --schedule "*/15" \
  --rate 0 --remove_snapshots

5. Trigger a sync

pvesr schedule-now
# Or wait for the next 15-minute mark

Verify:

pvesr status
# Expected: VM 100 with last_sync time = recent

6. Perform a planned failover

On the target node (pve-02):

# Substitute your own value before running:
VMID=100

# Migrate the replicated VM to the target
qm migrate "$VMID" pve-02 --with-local-disks

7. Verify the failed-over VM

# Substitute your own value before running:
VMID=100

qm status "$VMID"
# Expected: running on pve-02

# Inside the VM
df -h | grep tank
# Expected: ZFS dataset mounted
# Application should be intact

8. Reverse replication

Now that the VM is on pve-02, set up reverse replication:

# The reverse job needs its own job number, so 100-1 rather than 100-0:
JOB_ID=100-1

pvesr create-local-job "$JOB_ID" pve-01 --schedule "*/15" \
  --rate 0

9. Test a planned failover back

# Substitute your own value before running:
VMID=100

qm migrate "$VMID" pve-01 --with-local-disks

Verify both directions work and the VM returns cleanly.

Verification

  • Replication completes within the schedule window (15 min in this lab)
  • Migrating the VM to the target node works without losing data
  • The replicated VM is identical (same disk content, same config)
  • Reverse replication completes the loop

Cleanup

# Substitute your own values before running:
VMID=100
JOB_ID=100-0

# Remove replication jobs (repeat for the reverse job, 100-1)
pvesr delete "$JOB_ID"
# Destroy the test VM
qm stop "$VMID" && qm destroy "$VMID"

Notes

  • For real DR, combine ZFS replication with PBS backups. ZFS gives you near-zero RPO; PBS gives you immutable, offsite copies.
  • Replication is per-VM; a 100-VM environment means 100 replication jobs (or use scheduler groups).
  • For multi-site, add an SDN zone with VPN between the sites and configure cross-site replication.

Cleanup details

Replication jobs are listed with pvesr list. Delete with pvesr delete <job-id>.

Deliverables

  • · A ZFS replication job running on schedule
  • · A VM that has been failed over to the secondary node
  • · Verified that the failed-over VM has the expected data

Verification status

Executed end to end
not yet run on hardware

The commands and configuration here have been reviewed against the verified software versions, but nobody has run this lab start to finish on a system meeting its prerequisites. Treat the Expected Outcome as the intended result rather than an observed one, and keep the Cleanup section to hand.