I’ve been trying to establish a container backup routine and arrived at the script below. I’m posting it here in the event others find it useful, but I’m really curious what others think about my approach, given that I am very new to LXD containers. Also, I’m not particularly skilled at writing code, but by stealing code snippets from multiple places I think I have something that works well.
Assumptions:
- Production server (lxd_source) is an LXD server using btrfs and configured to allow remote connections
- Backup server (lxd_target) is an LXD server using btrfs and configured to connect remotely to lxd_source
#!/bin/bash umask 027 LXC=/usr/bin/lxc GREP=/bin/grep AWK=/usr/bin/awk DATE=/bin/date RSYNC=/usr/bin/rsync # List of containers on lxd_source. s_containers=`$LXC list lxd_source: -c ns --format csv | $GREP RUNNING | $AWK -F"," '{print $1}'` # Functions lecho () { logger "lxdbackup: $@" echo "$@" } #-------------------------------------- # Backup #-------------------------------------- # For each running container on lxd_source: # 1) Create a snapshot on lxd_source called 'current'. # 2) If the container does not exist on lxd_target, copy the container to lxd_target, and we're done with that container. # 3) If the container does exist on lxd_target, rsync the lxd_source snapshot to the lxd_target container. for container in $s_containers; do # Note that awk on the next line is used to strip new line characters, which appear to exist and break the '-z' test. # If a snapshot called "current" exists for the container on lxd_source, then delete it from lxd_source. if [ ! -z `$LXC info lxd_source:$container | $GREP 'current (taken at' | $AWK '{print $1}'` ]; then lecho "Attempting to delete snapshot '$container/current' on lxd_source . . ." if $LXC delete lxd_source:$container/current ; then lecho " Success -- deleted snapshot" else lecho " FAILED to delete snapshot" lecho " ABORTING BACKUP of container" continue fi fi # Create a snapshot of the container on lxd_source called "current". lecho "Attempting to create snapshot '$container/current' on lxd_source . . ." if $LXC snapshot lxd_source:$container current ; then lecho " Success -- created snapshot" else lecho " FAILED to create snapshot" lecho " ABORTING BACKUP of container" continue fi # Check if container exists on lxd_target. if [ ! -z `$LXC list ^${container}$ -c n --format=csv` ]; then lecho "'$container' exists on lxd_target" lecho "Attempting to rsync '$container/current' on lxd_source to '$container' on lxd_target . . ." if $RSYNC -az -e 'ssh -i /root/.ssh/lxd_target-rsync-ssh-key' \ root@lxd_source.example.com:/var/lib/lxd/storage-pools/default/snapshots/$container/current/ \ /var/lib/lxd/storage-pools/default/containers/$container/.; then lecho " Success -- rsync complete" else lecho " FAILED to rsync snapshot" lecho " ABORTING BACKUP of container" continue fi else lecho "'$container' does NOT exist on lxd_target" # Copy container/snapshot from lxd_source to lxd_target. lecho "Attempting to copy '$container/current' from lxd_source to lxd_target . . ." if $LXC copy lxd_source:$container/current $container 2>&1 > /dev/null ; then lecho " Success -- copied container" else lecho " FAILED to copy container" lecho " ABORTING BACKUP of container" continue fi lecho "--------------------------------------------" fi # Set boot.autostart on backed up container to 'false'. lecho "Attempting to set boot.autostart on '$container' on lxd_target to 'false' . . ." if $LXC config set $container boot.autostart false 2>&1 > /dev/null ; then lecho " Success -- set boot.autostart to 'false'" else lecho " FAILED to set boot.autostart to 'false'" fi lecho "--------------------------------------------" done