Last active
April 23, 2023 21:04
-
-
Save usrflo/f4f62e886490b2efed2a1503aed3e228 to your computer and use it in GitHub Desktop.
lxc copy --refresh workaround: efficient incremental ZFS snapshot sync with send/receive
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
LXCBIN=/snap/bin/lxc | |
LXDBIN=/snap/bin/lxd | |
ZFSBIN=/sbin/zfs | |
SYNCSNAPNAME=bsync | |
LASTSYNCSNAPNAME=bsync-last | |
ZFSROOT=tank/containers/ | |
MOUNTROOT=/var/snap/lxd/common/lxd/storage-pools/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# This cronjob is configured on the target server: | |
# - srclxdremotename: name of the lxd remote that contains the container to be synced | |
# - srclxdcontainername: name of the remote lxd container to be synced | |
# - locallxdcontainertargetname: local target container name to sync to | |
# - root@srcserver: ssh root login to the remote lxd server | |
# lxc-sync jobs | |
25 12,18 * * * /opt/lxc-sync/lxc-sync.sh -o srclxdremotename -r srclxdcontainername -l locallxdcontainertargetname -c "ssh -p2222 -oStrictHostKeyChecking=no root@srcserver" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# This script is meant to run on the sync target server that syncs remote container snapshots to local; | |
# remote and local containers may be running; a remote container is snapshotted and this | |
# snapshot will be restored on the local receiving container. | |
# | |
# IMPORTANT: | |
# - in the local lxc configuration all remotes need to be configured (see `lxc remote list`) | |
# - ssh access to the remote/source servers needs to be available to execute remote zfs send | |
# | |
# Florian Sager, [email protected], 2021-02-23 | |
set -e | |
# set -x | |
DIR="${BASH_SOURCE%/*}" | |
if [[ ! -d "$DIR" ]]; then DIR="$PWD"; fi | |
PROG=${0##*/} | |
# load local system specific sync config | |
. "$DIR/lxc-sync-config" | |
# cron sample: | |
# 45 12,18 * * * /root/tools/lxc-sync.sh -o host01 -r mycontainer -l mycontainer-standby -c "ssh -p2222 -oStrictHostKeyChecking=no [email protected]" | |
function usage { | |
cat <<EOF | |
usage: $PROG [options] | |
$PROG will sync a ZFS based LXD container from a remote origin server to a local target container. | |
Options: | |
-h print this help message | |
-o remote origin host according to the name in 'lxc remote list', e.g. "host01" | |
-r remote origin container name, e.g. "mycontainer" | |
-l local target container in LXD syntax, e.g. "mycontainer-standby" | |
-c ssh command to connect to origin server, e.g. "ssh -p2222 -oStrictHostKeyChecking=no [email protected]" | |
EOF | |
} | |
function localtargetexists { | |
local CONTNAME=$1 | |
$LXCBIN info $CONTNAME > /dev/null | |
RETVAL=$? | |
return $([ "$RETVAL" == 0 ] && echo 1 || echo 0) | |
} | |
function initsync { | |
local LOCALCONTNAME=$1 | |
local LXCREMOTE=$2 | |
local REMOTECONTNAME=$3 | |
local SSHCMD=$4 | |
$LXCBIN snapshot $LXCREMOTE:$REMOTECONTNAME $SYNCSNAPNAME | |
$LXCBIN copy $LXCREMOTE:$REMOTECONTNAME/$SYNCSNAPNAME $LOCALCONTNAME | |
$LXCBIN snapshot $LOCALCONTNAME $SYNCSNAPNAME | |
$ZFSBIN destroy -r $ZFSROOT$LOCALCONTNAME | |
$ZFSBIN create -o mountpoint=$MOUNTROOT$ZFSROOT$LOCALCONTNAME $ZFSROOT$LOCALCONTNAME | |
$SSHCMD $ZFSBIN send -c -L $ZFSROOT$REMOTECONTNAME@snapshot-$SYNCSNAPNAME | $ZFSBIN receive -Fu $ZFSROOT$LOCALCONTNAME | |
} | |
function incrementalsync { | |
local LOCALCONTNAME=$1 | |
local LXCREMOTE=$2 | |
local REMOTECONTNAME=$3 | |
local SSHCMD=$4 | |
set +e | |
$LXCBIN delete $LXCREMOTE:$LOCALCONTNAME/$LASTSYNCSNAPNAME | |
set -e | |
$LXCBIN rename $LXCREMOTE:$REMOTECONTNAME/$SYNCSNAPNAME $LXCREMOTE:$REMOTECONTNAME/$LASTSYNCSNAPNAME | |
$LXCBIN snapshot $LXCREMOTE:$REMOTECONTNAME $SYNCSNAPNAME | |
$ZFSBIN rename $ZFSROOT$LOCALCONTNAME@snapshot-$SYNCSNAPNAME $ZFSROOT$LOCALCONTNAME@snapshot-$LASTSYNCSNAPNAME | |
$SSHCMD $ZFSBIN send -c -L -i $ZFSROOT$REMOTECONTNAME@snapshot-$LASTSYNCSNAPNAME $ZFSROOT$REMOTECONTNAME@snapshot-$SYNCSNAPNAME | $ZFSBIN receive -Fu $ZFSROOT$LOCALCONTNAME | |
$ZFSBIN destroy $ZFSROOT$LOCALCONTNAME@snapshot-$LASTSYNCSNAPNAME | |
$LXCBIN restore $LOCALCONTNAME $SYNCSNAPNAME | |
$LXDBIN sql global "UPDATE instances_snapshots SET creation_date=datetime('now') WHERE instance_id=(SELECT id FROM instances WHERE name='$LOCALCONTNAME') AND name='$SYNCSNAPNAME';" > /dev/null | |
} | |
if [ "$#" == "0" ]; then | |
usage; | |
exit 1; | |
fi | |
# read arguments | |
while getopts o:r:l:c:h option; do | |
case "${option}" in | |
o) LXCREMOTE=${OPTARG};; | |
r) REMOTECONTNAME=${OPTARG};; | |
l) LOCALCONTNAME=${OPTARG};; | |
c) SSHCMD=${OPTARG};; | |
h) usage; exit 1;; | |
esac | |
done | |
if [ -z "$LXCREMOTE" ] ; then | |
echo 'Missing parameter -o' >&2 | |
exit 3; | |
fi | |
if [ -z "$REMOTECONTNAME" ] ; then | |
echo 'Missing parameter -r' >&2 | |
exit 4; | |
fi | |
if [ -z "$LOCALCONTNAME" ] ; then | |
echo 'Missing parameter -l' >&2 | |
exit 5; | |
fi | |
if [ -z "$SSHCMD" ] ; then | |
echo 'Missing parameter -c' >&2 | |
exit 6; | |
fi | |
set +e | |
localtargetexists $LOCALCONTNAME | |
LOCALCONTEXISTS=$? | |
set -e | |
if [ $LOCALCONTEXISTS == 0 ]; then | |
initsync "$LOCALCONTNAME" "$LXCREMOTE" "$REMOTECONTNAME" "$SSHCMD" | |
else | |
incrementalsync "$LOCALCONTNAME" "$LXCREMOTE" "$REMOTECONTNAME" "$SSHCMD" | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment