跳转到主要内容

Docker插件,用于管理Docker卷作为BTRFS子卷

项目描述

Travis state

BTRFS卷插件用于Docker

Buttervolume能为您做什么?

  • 在您的网站或应用程序遭到攻击或失败后,快速恢复最近的数据

  • 在升级失败后,快速将数据回滚到之前的版本

  • 无需担忧,自动升级您的应用程序

  • 保留您数据的历史记录

  • 创建大量备份,而不会占用比所需更多的磁盘空间

  • 构建具有数据复制的弹性托管集群

  • 快速在不同节点之间移动您的应用程序

  • 创建预配置或模板化应用程序,可在几秒钟内部署

Buttervolume能做什么?

  • 快照您的Docker卷

  • 将快照恢复到其原始卷或新的卷下

  • 列出并删除您卷的现有快照

  • 克隆您的Docker卷

  • 将您的卷复制或同步到另一台主机

  • 计划定期快照、同步或复制您的卷

  • 计划定期删除您的旧快照

它是如何工作的?

Buttervolume是一个Docker卷插件,位于BTRFS分区之上,可以管理和复制Docker卷的BTRFS快照。

简介

BTRFS 是一个下一代写时复制文件系统,具有子卷和快照支持。BTRFS 子卷 可以被视为一个独立的文件命名空间,它可以存在于一个目录中,并且可以作为一个独立的文件系统进行挂载,还可以单独进行快照。

另一方面,Docker卷 通常用于存储有状态容器的持久数据,如MySQL/PostgreSQL数据库或CMS的上传目录。默认情况下,Docker卷只是主机文件系统中的本地目录。已经存在许多 卷插件,用于各种存储后端,包括分布式文件系统,但小型集群通常负担不起部署分布式文件系统。

我们认为BTRFS子卷是Docker卷的一个强大且轻量级的存储解决方案,允许在小集群的多个节点之间快速轻松地进行复制(和备份)。

先决条件

请确保目录 /var/lib/buttervolume/ 位于一个BTRFS文件系统中。它可以是BTRFS挂载点或BTRFS子卷,也可以两者都是。

您还应该在主机上创建配置和ssh目录

sudo mkdir /var/lib/buttervolume
sudo mkdir /var/lib/buttervolume/config
sudo mkdir /var/lib/buttervolume/ssh

作为贡献者构建和运行

如果您想成为贡献者,请阅读本章。否则,跳到下一节。

您首先需要使用提供的Dockerfile为插件创建一个根文件系统

git clone https://github.com/anybox/buttervolume
./build.sh

默认情况下,插件是为最新提交(HEAD)构建的。您可以通过指定如下来构建另一个版本

./build.sh 3.7

在此阶段,您可以通过运行以下命令为插件设置SSH_PORT选项

docker plugin set anybox/buttervolume SSH_PORT=1122

请注意,此选项仅在使用两个节点之间的复制功能时相关。

现在您可以启用插件,它应该在插件容器中启动buttervolume

docker plugin enable anybox/buttervolume:HEAD

您可以通过运行buttervolume命令来检查它是否响应

export RUNCROOT=/run/docker/runtime-runc/plugins.moby/ # or /run/docker/plugins/runtime-root/plugins.moby/
alias drunc="sudo runc --root $RUNCROOT"
alias buttervolume="drunc exec -t $(drunc list|tail -n+2|awk '{print $1}') buttervolume"
sudo buttervolume scheduled

通过编写一个 /var/lib/buttervolume/config/config.ini 文件来增加日志级别

[DEFAULT]
TIMER = 120

然后通过以下命令检查日志

sudo journalctl -f -u docker.service

您还可以使用以下命令在本地以守护进程模式安装和运行插件

python3 -m venv venv
./venv/bin/python setup.py develop
sudo ./venv/bin/buttervolume run

然后您可以使用在venv中以开发者模式安装的buttervolume CLI

./venv/bin/buttervolume --version

作为用户安装和运行

如果插件已经推送到镜像仓库,您可以使用以下命令安装它

docker plugin install anybox/buttervolume

检查它是否正在运行

docker plugin ls

找到您的runc根,然后定义有用的别名

export RUNCROOT=/run/docker/runtime-runc/plugins.moby/ # or /run/docker/plugins/runtime-root/plugins.moby/
alias drunc="sudo runc --root $RUNCROOT"
alias buttervolume="drunc exec -t $(drunc list|tail -n+2|awk '{print $1}') buttervolume"

然后尝试一个buttervolume命令

buttervolume scheduled

或使用驱动程序创建卷。注意,驱动程序的名称就是插件的名称

docker volume create -d anybox/buttervolume:latest myvolume

请注意,您也可以定义函数而不是使用别名,并将这些函数放在您的 .bash_profile 或 .bash_aliases 中

function drunc () {
  RUNCROOT=/run/docker/runtime-runc/plugins.moby/ # or /run/docker/plugins/runtime-root/plugins.moby/
  sudo runc --root $RUNCROOT $@
}
function buttervolume () {
  drunc exec -t $(docker plugin ls --no-trunc  | grep 'anybox/buttervolume:latest' |  awk '{print $1}') buttervolume $@
}

升级

在重新安装之前,您必须强制禁用它(如docker文档中所述)

docker plugin disable -f anybox/buttervolume
docker plugin rm -f anybox/buttervolume
docker plugin install anybox/buttervolume

配置

您可以配置以下变量

  • DRIVERNAME:驱动程序的全名(带有标签)

  • VOLUMES_PATH:BTRFS卷所在的路径

  • SNAPSHOTS_PATH:BTRFS快照所在的路径

  • TEST_REMOTE_PATH:单元测试期间远程BTRFS快照所在的路径

  • SCHEDULE:调度器配置的路径

  • RUNPATH:docker run目录的路径 (/run/docker)

  • SOCKET:buttervolume 监听的 UNIX 套接字路径

  • TIMER:调度器两次运行之间的秒数

  • DTFORMAT:日志中日期时间的格式

  • LOGLEVEL:Python 日志级别(INFO、DEBUG 等)

配置可以按照以下优先级顺序进行

  1. 从以 BUTTERVOLUME_ 为前缀的环境变量(例如:BUTTERVOLUME_TIMER=120

  2. 从容器内部的 /etc/buttervolume/config.ini 文件中的 [DEFAULT] 部分,或主机上的 /var/lib/buttervolume/config/config.ini

config.ini 文件示例

[DEFAULT]
TIMER = 120

如果没有配置上述任何内容,则使用以下默认值

  • DRIVERNAME = anybox/buttervolume:latest

  • VOLUMES_PATH = /var/lib/buttervolume/volumes/

  • SNAPSHOTS_PATH = /var/lib/buttervolume/snapshots/

  • TEST_REMOTE_PATH = /var/lib/buttervolume/received/

  • SCHEDULE = /etc/buttervolume/schedule.csv

  • RUNPATH = /run/docker

  • SOCKET = $RUNPATH/plugins/btrfs.sock # 仅当手动运行时

  • TIMER = 60

  • DTFORMAT = %Y-%m-%dT%H:%M:%S.%f

  • LOGLEVEL = INFO

使用

运行插件

正常运行方式是将它作为上述“安装和运行”部分中描述的新式 Docker 插件运行,这将自动启动它。这将创建一个 /run/docker/plugins/<uuid>/btrfs.sock 文件,由 Docker 守护进程使用。其中 <uuid> 是运行它的 runc/OCI 容器的唯一标识符。这意味着您可能可以同时运行该插件的多个版本,但目前不建议这样做,除非您记住不同版本的卷和快照位于同一位置。否则,您可以使用 config.ini 文件为每个不同版本的卷和快照配置不同的路径。

卷驱动程序的名称是插件的名称

docker volume create -d anybox/buttervolume:latest myvolume

docker volume create --volume-driver=anybox/buttervolume:latest

在创建卷时,您可以选择按卷禁用写时复制。只需使用 -o–opt 选项,如 Docker 文档 中定义的那样

docker volume create -d anybox/buttervolume -o copyonwrite=false myvolume

在本地或旧模式运行插件

如果您将其作为 Python 发行版本地安装,也可以使用以下命令手动启动:

sudo buttervolume run

在这种情况下,它将在 /run/docker/plugins/btrfs.sock 中创建一个 UNIX 套接字,供 Docker 使用传统的插件系统。然后,卷驱动程序的名称是套接字文件的名称

docker volume create -d btrfs myvolume

docker create --volume-driver=btrfs

启动时,插件还将启动自己的调度器以运行定期作业(如快照、复制、清理或同步)

创建和删除卷

一旦插件开始运行,您就可以在创建容器时指定卷驱动程序,使用 docker create --volume-driver=btrfs --name <name> <image>。您也可以使用 docker volume create -d btrfs 手动创建 BTRFS 卷。它也适用于 docker-compose,通过在 compose 文件的 volumes 部分指定 btrfs 驱动程序

当您使用 docker rm -v <container>docker volume rm <volume> 删除卷时,BTRFS 子卷将被删除。如果在同时期间在卷的其他位置进行了快照,快照不会被删除。

管理卷和快照

当安装 buttervolume 时,它提供了一个命令行工具 buttervolume,以下为子命令

run                 Run the plugin in foreground
snapshot            Snapshot a volume
snapshots           List snapshots
schedule            (un)Schedule a snapshot, replication or purge
scheduled           List scheduled actions
restore             Restore a snapshot (optionally to a different volume)
clone               Clone a volume as new volume
send                Send a snapshot to another host
sync                Synchronise a volume from a remote host volume
rm                  Delete a snapshot
purge               Purge old snapshot using a purge pattern

创建快照

您可以使用以下命令为卷创建只读快照

buttervolume snapshot <volume>

卷当前预计位于 /var/lib/buttervolume/volumes,快照将在 /var/lib/buttervolume/snapshots 创建,通过将日期时间附加到卷名,并用 @ 分隔。

列出快照

您可以列出所有快照

buttervolume snapshots

或只列出与某个卷对应的快照

buttervolume snapshots <volume>

<volume> 是卷名,不是完整路径。它预期位于 /var/lib/buttervolume/volumes

恢复快照

您可以将快照恢复为卷。首先快照当前卷,然后删除,最后用快照替换。如果您提供的是卷名而不是快照,则将恢复最新的快照。因此,如果您操作错误,不会丢失数据。请在恢复快照之前停止容器

buttervolume restore <snapshot>

<snapshot> 是快照名,不是完整路径。它预期位于 /var/lib/buttervolume/snapshots

默认情况下,卷名与创建快照的卷对应。但您可以通过添加目标作为第二个参数,选择性地将快照恢复到不同的卷名

buttervolume restore <snapshot> <volume>

克隆卷

您可以将卷克隆为新的卷。当前卷将被克隆为作为参数给出的新卷名。请在克隆卷之前停止容器

buttervolume clone <volume> <new_volume>

<volume> 是要克隆的卷名,不是完整路径。它预期位于 /var/lib/buttervolume/volumes<new_volume> 是新卷的名称,它将作为前一个卷的克隆创建,不是完整路径。它预期在 /var/lib/buttervolume/volumes 中创建。

删除快照

您可以使用以下命令删除快照

buttervolume rm <snapshot>

<snapshot> 是快照名,不是完整路径。它预期位于 /var/lib/buttervolume/snapshots

将快照复制到另一个主机

您可以将快照增量发送到另一台主机,这样数据就会被复制到多台机器上,允许快速将有状态的Docker容器移动到另一台主机。第一个快照首先整体发送,然后使用后续的快照仅发送当前快照与上一个快照之间的差异。这允许频繁复制快照而不会消耗大量的带宽或磁盘空间

buttervolume send <host> <snapshot>

<snapshot> 是快照名,不是完整路径。它预期位于 /var/lib/buttervolume/snapshots 并在远程主机上的相同路径进行复制。

<host> 是远程主机的计算机名或IP地址。快照当前使用通过ssh的BTRFS send/receive发送,插件中直接包含ssh服务器。这要求目标主机上存在ssh密钥,并且已在 /var/lib/buttervolume/ssh 下授权,并且本地主机上的 /var/lib/buttervolume/ssh/config 中启用了 StrictHostKeyChecking no 选项。

请注意,每次您更改ssh配置时,都必须重新启动您的docker守护进程。

插件中包含的ssh服务器的默认SSH_PORT是 1122。您可以在启用插件之前使用 docker plugin set anybox/buttervolume SSH_PORT=<PORT> 来更改它。

从另一个主机的卷同步卷

您可以从远程卷接收数据,因此在远程主机上存在具有相同名称的卷时,它将从远程卷获取最新和最新的数据,并将其替换为本地卷中的数据。在运行 rsync 命令之前,将在本地机器上创建快照以进行恢复管理

buttervolume sync <volume> <host1> [<host2>][...]

目的是在运行容器之间的多主机之间同步卷,因此您应该在所有远程主机上的每个节点上安排此操作。

清除旧快照

您可以使用保留模式删除与指定卷对应的旧快照。

buttervolume purge <pattern> <volume>

如果您不确定保留模式是否正确,可以使用--dryrun选项运行清除,以检查将删除哪些快照,而不删除它们。

buttervolume purge --dryrun <pattern> <volume>

<volume> 是卷名,不是完整路径。它预期位于 /var/lib/buttervolume/volumes

<pattern>是快照保留模式。它是一个由分号分隔的时间长度指定器的列表,带有单位。单位可以是m(分钟)、h(小时)、d(天)、w(周)、y(年)。模式应至少包含2项。

以下是一些保留模式的示例

  • 4h:1d:2w:2y

    保留最后四小时内的所有快照,然后在第一天每小时保留一个快照,然后在前两周每天保留一个快照,然后在第一年每两周保留一个快照,两年后删除所有内容。

  • 4h:1w

    保留最后四小时内的所有快照,然后在第一周每小时保留一个快照,然后删除较旧的快照。

  • 2h:2h

    保留最后两小时内的所有快照,然后删除较旧的快照。

安排作业

您可以安排定期任务,如快照、复制、同步或清除。计划本身存储在/etc/buttervolume/schedule.csv中。

每60分钟安排卷的快照

buttervolume schedule snapshot 60 <volume>

通过指定0分钟的时间器来删除相同的计划

buttervolume schedule snapshot 0 <volume>

安排将卷foovolume复制到remote_host

buttervolume schedule replicate:remote_host 3600 foovolume

删除相同的计划

buttervolume schedule replicate:remote_host 0 foovolume

每小时安排清除卷foovolume的快照,但保留最后4小时内的所有快照,然后在前一周每小时保留一个快照,然后在一年内每周保留一个快照,一年后删除所有快照

buttervolume schedule purge:4h:1w:1y 60 foovolume

删除相同的计划

buttervolume schedule purge:4h:1w:1y 0 foovolume

通过使用快照计划计时器、清除计划计时器和清除保留模式的正确组合,您可以创建自己的备份策略,从最简单的到更复杂的。一个常见的是以下内容

buttervolume schedule snapshot 1440 <volume>
buttervolume schedule purge:1d:4w:1y 1440 <volume>

它应该每天创建一个快照,然后每天清除快照,同时保留最后24小时内的所有快照,然后在一个月内每天保留一个快照,然后在一年内每月保留一个快照。

安排从remote_host1remote_host2同步卷foovolume

buttervolume schedule synchronize:remote_host1,remote_host2 60 foovolume

删除相同的计划

buttervolume schedule synchronize:remote_host1,remote_host2 0 foovolume

列出安排的作业

您可以使用以下命令列出所有计划的任务

buttervolume scheduled

它将以添加计划时使用的相同格式显示计划,这便于删除现有计划或添加类似的新计划。

写时复制

默认启用Copy-On-Write。如果您真的想禁用它,可以禁用它。

为什么要禁用Copy-On-Write?如果您存储数据库的Docker卷,例如PostgreSQL或MariaDB,Copy-On-Write功能可能会影响性能,尽管最新的内核已经做了很多改进。好消息是禁用Copy-On-Write不会阻止创建快照。

测试

如果您的卷目录是BTRFS分区或卷,可以使用以下命令进行测试

./test.sh

在没有BTRFS分区的情况下工作

如果您没有BTRFS分区或卷,您可以按照以下方式设置文件中的虚拟分区(在Debian 8上进行了测试)

设置BTRFS虚拟分区

sudo qemu-img create /var/lib/docker/btrfs.img 10G
sudo mkfs.btrfs /var/lib/docker/btrfs.img

将分区临时挂载到某个位置以创建3个新的BTRFS子卷

sudo -s
mkdir /tmp/btrfs_mount_point
mount -o loop /var/lib/docker/btrfs.img /tmp/btrfs_mount_point/
btrfs subvolume create /tmp/btrfs_mount_point/snapshots
btrfs subvolume create /tmp/btrfs_mount_point/volumes
btrfs subvolume create /tmp/btrfs_mount_point/received
umount /tmp/btrfs_mount_point/
rm -r /tmp/btrfs_mount_point/

停止docker,创建所需的挂载点并重新启动docker

systemctl stop docker
mkdir -p /var/lib/buttervolume/volumes
mkdir -p /var/lib/buttervolume/snapshots
mkdir -p /var/lib/buttervolume/received
mount -o loop,subvol=volumes /var/lib/docker/btrfs.img /var/lib/buttervolume/volumes
mount -o loop,subvol=snapshots /var/lib/docker/btrfs.img /var/lib/buttervolume/snapshots
mount -o loop,subvol=received /var/lib/docker/btrfs.img /var/lib/buttervolume/received
systemctl start docker

完成测试后,您可以卸载这些卷,您将找到之前的docker卷

systemctl stop docker
umount /var/lib/buttervolume/volumes
umount /var/lib/buttervolume/snapshots
umount /var/lib/buttervolume/received
systemctl start docker
rm /var/lib/docker/btrfs.img

迁移到版本3

如果您目前在生产中使用Buttervolume 1.x或2.0,您必须仔细遵循以下指南以迁移到版本3。

首先复制ssh和配置文件,并禁用调度器

sudo -s
docker cp buttervolume_plugin_1:/etc/buttervolume /var/lib/buttervolume/config
docker cp buttervolume_plugin_1:/root/.ssh /var/lib/buttervolume/ssh
mv /var/lib/buttervolume/config/schedule.csv /var/lib/buttervolume/config/schedule.csv.disabled

然后停止所有容器,除了buttervolume

现在快照并删除所有卷

volumes=$(docker volume ls -f driver=btrfs --format "{{.Name}}")
# or: # volumes=$(docker volume ls -f driver=btrfs|tail -n+2|awk '{print $2}')
echo $volumes
for v in $volumes; do docker exec buttervolume_plugin_1 buttervolume snapshot $v; done
for v in $volumes; do docker volume rm $v; done

然后停止buttervolume容器,删除旧的btrfs.sock文件,并重新启动docker

docker stop buttervolume_plugin_1
docker rm -v buttervolume_plugin_1
rm /run/docker/plugins/btrfs.sock
systemctl stop docker

如果您之前使用的是Buttervolume 1.x,您必须将快照移动到新位置

mkdir /var/lib/buttervolume/snapshots
cd /var/lib/docker/snapshots
for i in *; do btrfs subvolume snapshot -r $i /var/lib/buttervolume/snapshots/$i; done

将/var/lib/docker/volumes恢复为原始文件夹

cd /var/lib/docker
mkdir volumes.new
mv volumes/* volumes.new/
umount volumes  # if this was a mounted btrfs subvolume
mv volumes.new/* volumes/
rmdir volumes.new
systemctl start docker

将您的卷配置(在您的compose文件中)更改为使用新的anybox/buttervolume:latest驱动程序名称,而不是btrfs

然后以管理插件的形式启动新的buttervolume 3.x并检查它是否已启动

docker plugin install anybox/buttervolume:latest
docker plugin ls

然后使用新驱动程序重新创建所有卷并从快照中恢复它们

for v in $volumes; do docker volume create -d anybox/buttervolume:latest $v; done
export RUNCROOT=/run/docker/runtime-runc/plugins.moby/ # or /run/docker/plugins/runtime-root/plugins.moby/
alias drunc="sudo runc --root $RUNCROOT"
alias buttervolume="drunc exec -t $(drunc list|tail -n+2|awk '{print $1}') buttervolume"
# WARNING : check the the volume you will restore are the correct ones
for v in $volumes; do buttervolume restore $v; done

然后重新启动您的容器,检查它们是否具有正确的数据

重新启用调度器

mv /var/lib/buttervolume/config/schedule.csv.disabled /var/lib/buttervolume/config/schedule.csv

鸣谢

感谢

  • Christophe Combelles

  • Pierre Verkest

  • Marcelo Ochoa

  • Christoph Rist

  • Philip Nagler-Frank

  • Yoann MOUGNIBAS

变更日志

3.10 (2023-04-09)

  • 更新依赖项

  • 修复bug #45

3.9 (2022-10-11)

  • 修复了未设置option_copyonwrite时的崩溃问题

  • 恢复了测试套件

  • 改进并简化了构建脚本和测试脚本

3.8 (2022-10-07)

  • 默认使用copy-on-write

  • 允许选择为每个卷启用/禁用copy-on-write

  • 允许在插件配置中更改默认的SSH_PORT

  • 更新了基本docker镜像和依赖项

  • 添加了显示版本号的选项

  • 改进了文档

3.7 (2018-12-13)

  • 取消固定urllib3

3.6 (2018-12-11)

  • 修复了插件内的僵尸sshd进程

  • 较小的文档更改

3.5 (2018-06-07)

  • 改进了文档

3.4 (2018-04-27)

  • 在启动时修复权限,以便ssh可以工作

3.3 (2018-04-27)

  • 修复了防止在某些条件下启动的bug

3.2 (2018-04-27)

  • 修复了启动时的套接字路径

3.1 (2018-04-27)

  • 修复了Python 3.6中的声明问题

  • 自动检测btrfs.sock路径

  • 使runpath和drivername可配置

3.0 (2018-04-24)

  • 现在使用docker managed plugin系统

  • 在关闭前停止调度器以避免5秒超时

  • 改进了日志记录

  • 改进了从版本1或2迁移的文档

2.0 (2018-03-24)

  • 重大更改:请阅读从版本1到版本2的迁移路径

    BTRFS卷和快照现在默认存储在/var/lib/buttervolume下的不同目录中

  • 配置可以通过环境变量或config.ini文件进行

  • 实现了VolumeDriver.Capabilities并仅返回'local'

  • 其他一些小修复和改进

1.4 (2018-02-01)

  • 添加克隆命令

  • btrfs filesystem sync替换sync

1.3.1 (2017-10-22)

  • 修复了打包(缺少README)

1.3 (2017-07-30)

  • 修复了恢复命令的cli

1.2 (2017-07-16)

  • 修复了清除算法

1.1 (2017-07-13)

  • 允许将快照恢复到不同的卷名称

1.0 (2017-05-24)

  • 初始发布,用于生产

项目详情


下载文件

下载适用于您平台的自定义文件。如果您不确定选择哪个,请了解更多关于安装包的信息。

源码分发

buttervolume-3.10.tar.gz (31.6 kB 查看哈希值)

上传时间 源码

构建分发

buttervolume-3.10-py3-none-any.whl (23.7 kB 查看哈希值)

上传时间 Python 3

支持者