Консистентное резервное копирование контейнеров в Proxmox встроенными средствами

12 Июль 2023 17:25 Сергей Морозов (изменено 12 Июль 2023 18:45)

Суть проблемы: по умолчанию, в случае с резервным копированием контейнеров в Proxmox штатными средствами, мы получаем "грязную" копию. Например, если в контейнере находится MySQL, он не знает, что его копируют, и не сохраняет изменения на диск.

В случае с виртуальными машинами эта проблема решается средствами Qemu Guest Agent. Для контейнеров такого средства нет, но vzdump (встроенное в Proxmox средство резервного копирования) может запускать скрипт на каждую операцию, и в этом скрипте можно выполнить pct exec для того, чтобы подготовить контейнер к резервному копированию.

Добавляем в /etc/vzdump.conf строку:

script: /var/lib/vz/snippets/proxmox-hook-backup.sh

Код скрипта /var/lib/vz/snippets/proxmox-hook-backup.sh:

#!/bin/bash

ACTION=${1}
METHOD=${2}
CTID=${3}

run-hook-pct() {
        HOOK=${1}
        pct exec ${CTID} -- /bin/sh -c "[ -x /etc/proxmox-hook-backup.sh ] && /etc/proxmox-hook-backup.sh ${HOOK}" || true
}

backup-start() {
        if pct status ${CTID} ; then
                run-hook-pct backup-start
        fi
}

backup-end() {
        if pct status ${CTID} ; then
                run-hook-pct backup-end
        fi
}

pre-stop() {
        if pct status ${CTID} ; then
                run-hook-pct pre-stop
        fi
}
pre-restart() {
        if pct status ${CTID} ; then
                run-hook-pct pre-restart
        fi
}
post-restart() {
        if pct status ${CTID} ; then
                run-hook-pct post-restart
        fi
}

case ${ACTION} in
        backup-start) backup-start ;;
        backup-end) backup-end ;;
        pre-stop) pre-stop ;;
        pre-restart) pre-restart ;;
        post-restart) post-restart ;;
esac

Теперь на каждую операцию vzdump внутри каждого контейнера будет выполняться скрипт /etc/proxmox-hook-backup.sh (при его наличии), а в первом параметре будет передано имя хука. Вот пример такого скрипта для резервного копирования MySql:

#!/bin/sh

MYSQL_USER="backup"
MYSQL_PASSWORD="super-secret-password"

cd /tmp

backup_start() {
        echo "Locking mysql tables"
        echo "FLUSH TABLES WITH READ LOCK;" | mysql -u "${MYSQL_USER}" -p "${MYSQL_PASSWORD}"
        sync
}

post_restart() {
        echo "Unlocking mysql tables"
        echo "UNLOCK TABLES;" | mysql -u "${MYSQL_USER}" -p "${MYSQL_PASSWORD}"
}

case $1 in
        backup-start) backup_start ;;
        post-restart) post_restart ;;
esac

Этот скрипт в хуке backup-start (перед резервным копированием) выполняет FLUSH TABLES WITH READ LOCK, затем, в хуке post-restart (после резервного копирования) разблокирует таблицы, выполняя UNLOCK TABLES.