- Posted on
- • Artificial Intelligence
Artificial Intelligence VM Backup Strategies
- Author
-
-
- User
- linuxbash
- Posts by this author
- Posts by this author
-
Artificial Intelligence VM Backup Strategies: Keep Your GPU Hours Safe
Ever watched a multi-day training run crash and take your VM with it? That’s not just frustrating—it’s expensive. AI VMs often hold massive datasets, model checkpoints, and specialized OS/GPU stacks that aren’t trivial to rebuild. A solid backup strategy means your experiments survive hardware failures, operator errors, and cloud hiccups.
This post lays out practical, bash-friendly strategies to back up AI virtual machines (KVM/libvirt focus), get consistent snapshots while models are training, deduplicate big datasets, and automate offsite retention. By the end, you’ll have concrete commands and scripts to protect your GPU time and your results.
Why AI VM backups are different
High write rates and big files: Datasets and checkpoints can be 100s of GB to TB, continuously updated.
Application consistency: Filesystem-consistent backups may still yield corrupted checkpoints. Quiescing training before snapshots helps.
Cost of downtime: Losing a tuned CUDA stack, drivers, and environment can cost days to recreate.
Storage economics: Deduplication and compression matter when your data explodes.
What we’ll use
libvirt/virsh and QEMU for hot, application-consistent snapshots
qemu-guest-agent inside the guest for quiescing filesystems
Borg or Restic for deduplicated, encrypted backups
rsync for frequent lightweight checkpoint syncs
Optional: LVM/ZFS snapshots if your storage supports them
Install on the host
Debian/Ubuntu (apt):
sudo apt update
sudo apt install -y libvirt-clients libvirt-daemon-system qemu-utils borgbackup restic rsync pigz zstd
sudo systemctl enable --now libvirtd
Fedora/RHEL (dnf):
sudo dnf install -y libvirt-client libvirt-daemon qemu-img borgbackup restic rsync pigz zstd
sudo systemctl enable --now libvirtd
openSUSE (zypper):
sudo zypper install -y libvirt libvirt-client qemu-tools borgbackup restic rsync pigz zstd
sudo systemctl enable --now libvirtd
Install inside each VM (guest)
Debian/Ubuntu (apt):
sudo apt update
sudo apt install -y qemu-guest-agent
sudo systemctl enable --now qemu-guest-agent
Fedora/RHEL (dnf):
sudo dnf install -y qemu-guest-agent
sudo systemctl enable --now qemu-guest-agent
openSUSE (zypper):
sudo zypper install -y qemu-guest-agent
sudo systemctl enable --now qemu-guest-agent
Strategy 1: Hot, consistent snapshots with libvirt + qemu-guest-agent
Goal: Back up a running VM without corruption—even while training—by quiescing the filesystem and using an external snapshot. Then back up the stable base image while the VM writes to a temporary overlay. Finally, merge and clean up.
Important:
Works best with file-based disks (qcow2/raw). For LVM/ZFS-backed disks, see Strategy 4 for native snapshots.
You can also pause training briefly before snapshot (see Strategy 3).
Example backup script (host):
#!/usr/bin/env bash
# backup-ai-vm.sh: create external snapshot, back up base image, then blockcommit
# Requires: libvirt/virsh, qemu-utils, borgbackup or restic (choose one)
set -euo pipefail
VM="${1:-ai-vm}" # libvirt domain name
DISK_TARGET="${2:-vda}" # disk target in libvirt (e.g., vda, vdb)
BACKUP_METHOD="${3:-borg}" # "borg" or "restic"
timestamp() { date +%F-%H%M%S; }
# Optional: Ask the guest to checkpoint training (if you have a handler)
# ssh aiuser@"$VM" "pkill -USR1 -f train.py || true; sleep 10" || true
echo "[*] Creating external snapshot for $VM ..."
virsh snapshot-create-as --domain "$VM" \
--name "bk-$(timestamp)" \
--description "AI VM backup snapshot" \
--disk-only --atomic --quiesce
# Find overlay and base
OVERLAY=$(virsh domblklist "$VM" --details | awk -v t="$DISK_TARGET" '$3=="disk" && $4==t {print $5}')
if [[ -z "$OVERLAY" ]]; then
echo "[-] Could not determine overlay path for $DISK_TARGET" >&2
exit 1
fi
# Extract backing file path robustly
BASE=$(qemu-img info "$OVERLAY" | sed -n 's/^backing file: \(.*\) (.*/\1/p')
if [[ -z "$BASE" ]]; then
BASE=$(qemu-img info "$OVERLAY" | awk -F': ' '/backing file:/ {print $2}')
fi
if [[ -z "$BASE" ]]; then
echo "[-] Could not determine base image backing file from $OVERLAY" >&2
exit 1
fi
echo "[*] Overlay is $OVERLAY"
echo "[*] Base image is $BASE (stable for backup)"
# Choose a backup root path for file-based backups
SRC_DIR=$(dirname "$BASE")
# Option A: Borg (local or mounted repo)
if [[ "$BACKUP_METHOD" == "borg" ]]; then
: "${BORG_REPO:?Set BORG_REPO}"
: "${BORG_PASSPHRASE:?Set BORG_PASSPHRASE}"
echo "[*] Running borg create ..."
borg create --stats --compression zstd,10 \
"$BORG_REPO"::"${VM}-$(timestamp)" \
"$BASE" # You can include other disks/paths here
borg prune -v --list --keep-daily=7 --keep-weekly=4 --keep-monthly=6 "$BORG_REPO"
borg check "$BORG_REPO"
fi
# Option B: Restic (works great to S3-compatible storage)
if [[ "$BACKUP_METHOD" == "restic" ]]; then
: "${RESTIC_REPOSITORY:?Set RESTIC_REPOSITORY (e.g., s3:https://...)}"
: "${RESTIC_PASSWORD:?Set RESTIC_PASSWORD}"
echo "[*] Running restic backup ..."
restic backup --one-file-system "$BASE"
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune
restic check
fi
echo "[*] Committing overlay back into base (pivot) ..."
virsh blockcommit "$VM" "$DISK_TARGET" --active --pivot --verbose --bandwidth 0
# Clean up stray overlay if present
if [[ -f "$OVERLAY" ]]; then
rm -f -- "$OVERLAY"
fi
echo "[+] Backup complete for $VM"
Usage:
# With Borg
export BORG_REPO=/backups/borg/ai-vm
export BORG_PASSPHRASE='change-me'
borg init --encryption repokey-blake2 "$BORG_REPO"
./backup-ai-vm.sh ai-vm vda borg
# With Restic (to S3/MinIO)
export RESTIC_REPOSITORY="s3:https://s3.example.com/backups/ai-vm"
export RESTIC_PASSWORD='change-me'
export AWS_ACCESS_KEY_ID=...
export AWS_SECRET_ACCESS_KEY=...
restic init
./backup-ai-vm.sh ai-vm vda restic
Notes:
Add more disks by repeating the sequence or adjusting the script.
If quiesce fails, ensure qemu-guest-agent runs in the guest and that filesystems support freezing.
For very busy disks, consider throttling or snapshotting during a lull.
Strategy 2: Deduplicated, encrypted repositories with Borg or Restic
Big models and datasets benefit from block-level deduplication and compression:
Borg (great local/NFS/SSH repos):
# Install (see package manager sections above), then:
export BORG_REPO=/srv/backups/borg/ai-vm
export BORG_PASSPHRASE='change-me'
borg init --encryption repokey-blake2 "$BORG_REPO"
# Back up VM images, configs, and checkpoints
borg create --stats --compression zstd,19 \
"$BORG_REPO"::ai-vm-{now:%Y-%m-%d_%H-%M} \
/var/lib/libvirt/images/ai-vm/ /etc/libvirt/qemu/ai-vm.xml /data/checkpoints/
# Retention and consistency
borg prune -v --list --keep-daily=7 --keep-weekly=4 --keep-monthly=6 "$BORG_REPO"
borg check "$BORG_REPO"
Restic (shines with S3-compatible object storage and offsite):
export RESTIC_REPOSITORY="s3:https://s3.amazonaws.com/my-bucket/ai-vm"
export RESTIC_PASSWORD='change-me'
export AWS_ACCESS_KEY_ID=...
export AWS_SECRET_ACCESS_KEY=...
restic init
restic backup /var/lib/libvirt/images/ai-vm/ /etc/libvirt/qemu/ai-vm.xml /data/checkpoints/
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune
restic check
Tip:
Store OS disk, data disk, and checkpoints in the same repo for better deduplication.
Use zstd compression for speed/ratio sweet spot.
Strategy 3: Split data domains and checkpoint smartly
Don’t treat everything the same. Assign policies by data type:
OS/driver stack: Back up nightly (smallish, but painful to rebuild).
Datasets: Immutable or slowly changing—snapshot monthly plus incremental sends.
Checkpoints: Frequent and critical—sync every N minutes.
Example: frequent checkpoint sync from inside the VM:
# Run within the VM; sync every 10 minutes via cron/systemd timer
rsync -avh --partial --inplace --info=progress2 \
/mnt/checkpoints/ backup@nas:/backups/ai-vm/checkpoints/
Make training backup-aware. For example, catch SIGUSR1 to save a clean checkpoint before a host snapshot:
# Host before snapshot (optional but recommended)
ssh aiuser@ai-vm "pkill -USR1 -f train.py; sleep 10" || true
Strategy 4: Use your storage’s native snapshots (LVM/ZFS) when available
If your VM disks live on LVM or ZFS, native snapshots are fast and efficient.
LVM example (host):
# Snapshot a logical volume, mount read-only, back it up, then remove
sudo lvcreate -s -n ai-vm-root-snap -L 20G /dev/vg/ai-vm-root
sudo mkdir -p /mnt/ai-vm-root-snap
sudo mount -o ro /dev/vg/ai-vm-root-snap /mnt/ai-vm-root-snap
restic backup /mnt/ai-vm-root-snap
sudo umount /mnt/ai-vm-root-snap
sudo lvremove -y /dev/vg/ai-vm-root-snap
ZFS example (dataset for VM images or training data):
# Create and send an incremental snapshot offsite
SNAP="ai-vm@$(date +%F-%H%M)"
zfs snapshot pool/ai-vm-images@$SNAP
zfs send -Lce pool/ai-vm-images@$SNAP | zstd -T0 -19 | ssh backup@remote "zstd -d | zfs recv -F pool/ai-vm-images"
Strategy 5: Automate and test restores
Backups you can’t restore aren’t backups.
Create a systemd timer to run the snapshot+backup script:
backup-ai-vm.service:
[Unit]
Description=AI VM backup
[Service]
Type=oneshot
Environment="BORG_REPO=/backups/borg/ai-vm"
Environment="BORG_PASSPHRASE=change-me"
ExecStart=/usr/local/sbin/backup-ai-vm.sh ai-vm vda borg
backup-ai-vm.timer:
[Unit]
Description=Run AI VM backup nightly
[Timer]
OnCalendar=03:00
Persistent=true
[Install]
WantedBy=timers.target
Enable:
sudo cp backup-ai-vm.* /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now backup-ai-vm.timer
Quick restore test (Restic example):
# Restore into a scratch directory and verify key files exist
export RESTIC_REPOSITORY="s3:https://s3.example.com/backups/ai-vm"
export RESTIC_PASSWORD='change-me'
export AWS_ACCESS_KEY_ID=...
export AWS_SECRET_ACCESS_KEY=...
mkdir -p /restore/ai-vm-test
restic restore latest --target /restore/ai-vm-test
ls -lh /restore/ai-vm-test/var/lib/libvirt/images/
Optionally boot a throwaway VM from the restored disk to validate end-to-end:
virt-install --name ai-vm-restore --memory 16384 --vcpus 8 \
--import --disk path=/restore/ai-vm-test/var/lib/libvirt/images/ai-vm.qcow2,bus=virtio \
--network network=default --noautoconsole
Real-world pattern that works
Put OS and tooling on one disk, datasets on another, and checkpoints on a fast, separate volume.
Hourly: rsync checkpoints off-VM.
Nightly: libvirt external snapshot → backup base image with Borg/Restic → blockcommit.
Weekly: offsite Restic to S3 with retention; enable object lock/immutability at the bucket level if available.
Monthly: ZFS/LVM snapshot of datasets + incremental sends.
Conclusion and next steps
GPU hours are precious. A few shell commands can be the difference between a near-miss and a week lost. Start by:
1) Installing qemu-guest-agent in your VMs and setting up the host packages.
2) Dropping the backup-ai-vm.sh script on your host and running a manual test.
3) Scheduling nightly backups and weekly offsite syncs.
4) Proving you can restore—at least once a month.
Call to action: Block out one hour this week to implement Strategy 1 + 2. Run a test restore. Then iterate with checkpoint syncs and offsite retention. Your future self (and your training timelines) will thank you.