Borg备份的理论和实践



令我们感到惊讶的是,关于出色的数据备份开源工具-Borg并没有任何资料(不要与同名Kubernetes的祖先混淆!) 。 由于我们已经在生产中使用它了一年多,因此在本文中,我将分享我们对博格的“印象”。

背景:Bacula和Bareos的经验


在2017年,我们对Bacula和Bareos感到厌倦,因为从一开始我们就开始使用Bacula和Bareos(即当时的生产时间约为9年)。 怎么了 在运营过程中,我们积累了很多不满:

  • SD(存储守护程序)冻结。 如果已配置并行性,则SD维护将变得更加复杂,并且冻结将阻止按计划进行进一步的备份以及恢复的可能性。
  • 必须同时为客户端和控制器生成配置。 即使我们将其自动化(在我们的情况下,Chef,Ansible和我们自己的开发在不同的时间使用),我们也需要监视导演在重新加载后实际上拾取了配置。 仅在reload命令的输出和之后的消息调用中跟踪此消息 (以获取错误文本本身)。
  • 安排备份。 Bacula的开发人员决定采用自己的方式,并编写了自己的进度表格式,您不能仅将其解析或转换为其他格式。 以下是我们旧安装中标准备份计划的示例:
    • 每周三的每日完整备份,其他日子的增量备份:
      Run = Level=Full Pool="Foobar-low7" wed at 18:00
      Run = Level=Incremental Pool="Foobar-low7" at 18:00
    • 每月两次备份wal文件,并每小时增加一次:
      Run = Level=Full FullPool=CustomerWALPool 1st fri at 01:45
      Run = Level=Full FullPool=CustomerWALPool 3rd fri at 01:45
      Run = Level=Incremental FullPool=CustomerWALPool IncrementalPool=CustomerWALPool on hourly
    • 由于Bacula / Bareos定期发疯,因此在所有情况下(在一周中的不同日期每隔2小时)生成的schedule大约为1665。
  • Bacula-fd(和aredos-fd)具有包含大量数据的目录(例如,40 TB,其中35 TB包含大文件[100+ MB],其余5 TB包含小文件[1 KB至100 MB ])缓慢的内存泄漏开始,这在生产中是非常不愉快的情况。

  • 对于具有大量文件的备份,Bacula和Bareos非常依赖于所用DBMS的性能。 它有什么驱动器? 您如何熟练地调整她以满足这些特定需求? 顺便说一下,在数据库中,创建了一个(!)不可分区表,其中包含所有备份中所有文件的列表,而第二个-包含所有备份中所有路径的列表。 如果您不准备为基础服务器分配至少8 GB的RAM + 40 GB的SSD,请立即做好准备。
  • 数据库依赖性值得一提。 Bacula / Bareos对于每个文件都会询问导演是否已经有这样的文件。 导向器当然会爬入数据库,进入那些非常大的表中……事实证明,可以通过同时启动多个繁重的备份来阻止备份,即使那里的差异只有几兆字节也是如此。



不能说根本没有解决任何问题,这是不公平的,但是到了这一点,我们真的厌倦了各种变通办法,并希望“现在和现在”都有可靠的解决方案。

Bacula / Bareos可以出色地完成少量(10-30)的统一工作。 一周一次有小事打破吗? 没关系:他们将任务交给值班主任(或其他工程师)-他们修理了。 但是,我们有一些项目,其中的作业数为数百,而其中的文件数为数十万。 结果,每周要花费5分钟来修复备份(这之前还不算数小时的设置)开始成倍增长。 所有这些导致了这样一个事实,即每天2小时都需要修复所有项目中的备份,因为实际上到处都是琐碎的事情或严重破坏的事情。

然后有人可能会认为专门为此工作的工程师应该进行备份。 当然,他会变得胡须和严厉,并且从他的表情来看,备用杯会立即修复,而他会平静地喝咖啡。 这个想法可能在某种程度上是正确的……但是总有一个but。 并非每个人都能负担得起全天候修复和监视备份的费用,甚至更多-分配给这些目的工程师。 我们只是确定最好每天将这两个小时花在更具生产力和实用性的东西上。 因此,我们继续寻找“可行”的替代解决方案。

博格作为一种新方式


对其他开放源代码选项的搜索随着时间的流逝而展开,因此很难估算总成本,但在某一时刻(去年),我们的注意力转向了“场合中的英雄-BorgBackup (或简称Borg)。 在某种程度上,这得益于我们的一位工程师(在先前的工作地点)使用它的真实经验。

Borg用Python编写(要求版本> = 3.4.0),而性能要求较高的代码(压缩,加密等)则用C / Cython实现。 根据免费的BSD许可证(3条款)分发。 它支持许多平台,包括Linux,* BSD,macOS以及Windows 10的实验级Cygwin和Linux子系统。对于BorgBackup的安装,可以使用流行的Linux发行版和其他OS的软件包,以及通过pip安装的源, -有关更多详细信息,请参见项目文档

博格为什么这么贿赂我们? 这是它的主要优点:

  • 重复数据删除 :真正且非常有效(以下示例)。 单个Borg存储库中的文件(即Borg特定格式的特殊目录)被分成n兆字节的块,并且重复的Borg块被重复数据删除。 重复数据删除恰好在压缩之前发生。
  • 压缩 :重复数据删除后,数据也会被压缩。 可以使用不同的压缩算法:lz4,lzma,zlib,zstd。 任何备份的标准功能,但这同样有用。
  • 在SSH上工作 :Borg通过SSH备份到远程服务器。 在服务器端,您只需要安装Borg就可以了! 从这里开始,诸如安全性和加密之类的优势立即出现。 您只能通过按键来配置访问权限,此外,进入服务器时,Borg只能执行他的命令之一。 例如,像这样:

     $ cat .ssh/authorized_keys command="/usr/bin/borg serve" ssh-rsa AAAAB3NzaC1yc… 
  • 它以PPA(主要使用Ubuntu)和静态二进制文件形式提供 。 静态二进制形式的Borg使得它几乎可以在至少有一个最低限度的现代glibc的任何地方运行。 (但并非到处都是-例如,不可能在CentOS 5上启动。)
  • 灵活清理旧备份 。 您可以设置最近n个备份的存储,以及每小时/天/周的2个备份。 在后一种情况下,将保留本周末的最后一次备份。 可通过存储过去7天的7个每日备份和4个每周的备份来合并条件。

在小型项目上,向博格的过渡开始缓慢。 最初,这些都是简单的cron脚本,每天都在执行。 这持续了大约六个月。 在这段时间里,我们不得不多次备份...事实证明,Borg根本不需要维修! 怎么了 因为简单的原理在这里起作用:“机制越简单,破坏它的地方就越少。”

实践:如何使用Borg进行备份?


考虑一个创建备份的简单示例:

  1. 将最新版本的二进制文件下载到备份服务器以及我们将从官方存储库备份的计算机:

     sudo wget https://github.com/borgbackup/borg/releases/download/1.1.6/borg-linux64 -O /usr/local/bin/borg sudo chmod +x /usr/local/bin/borg 

    注意 :如果您同时使用本地计算机作为源和接收方进行测试,则整个区别仅在于我们将继续传递的URI中,但是我们记住备份需要单独存储,而不是存储在同一台计算机上。
  2. 在备份服务器上,创建borg用户:

     sudo useradd -m borg 

    简单:无组且具有标准外壳程序,但始终具有主目录。
  3. 客户端上会生成SSH密钥:

     ssh-keygen 
  4. 在服务器上,将生成的密钥添加到borg用户:

     mkdir ~borg/.ssh echo 'command="/usr/local/bin/borg serve" ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDNdaDfqUUf/XmSVWfF7PfjGlbKW00MJ63zal/E/mxm+vJIJRBw7GZofe1PeTpKcEUTiBBEsW9XUmTctnWE6p21gU/JNU0jITLx+vg4IlVP62cac71tkx1VJFMYQN6EulT0alYxagNwEs7s5cBlykeKk/QmteOOclzx684t9d6BhMvFE9w9r+c76aVBIdbEyrkloiYd+vzt79nRkFE4CoxkpvptMgrAgbx563fRmNSPH8H5dEad44/Xb5uARiYhdlIl45QuNSpAdcOadp46ftDeQCGLc4CgjMxessam+9ujYcUCjhFDNOoEa4YxVhXF9Tcv8Ttxolece6y+IQM7fbDR' > ~borg/.ssh/authorized_keys chown -R borg:borg ~borg/.ssh local / bin中/博格服务” SSH-RSA AAAAB3NzaC1yc2EAAAADAQABAAABAQDNdaDfqUUf / XmSVWfF7PfjGlbKW00MJ63zal / E / MXM + vJIJRBw7GZofe1PeTpKcEUTiBBEsW9XUmTctnWE6p21gU / JNU0jITLx + vg4IlVP62cac71tkx1VJFMYQN6EulT0alYxagNwEs7s5cBlykeKk / QmteOOclzx684t9d6BhMvFE9w9r + c76aVBIdbEyrkloiYd + vzt79nRkFE4CoxkpvptMgrAgbx563fRmNSPH8H5dEad44 / Xb5uARiYhdlIl45QuNSpAdcOadp46ftDeQCGLc4CgjMxessam + 9ujYcUCjhFDNOoEa4YxVhXF9Tcv8Ttxolece6y + IQM7fbDR'>〜博格/的.ssh mkdir ~borg/.ssh echo 'command="/usr/local/bin/borg serve" ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDNdaDfqUUf/XmSVWfF7PfjGlbKW00MJ63zal/E/mxm+vJIJRBw7GZofe1PeTpKcEUTiBBEsW9XUmTctnWE6p21gU/JNU0jITLx+vg4IlVP62cac71tkx1VJFMYQN6EulT0alYxagNwEs7s5cBlykeKk/QmteOOclzx684t9d6BhMvFE9w9r+c76aVBIdbEyrkloiYd+vzt79nRkFE4CoxkpvptMgrAgbx563fRmNSPH8H5dEad44/Xb5uARiYhdlIl45QuNSpAdcOadp46ftDeQCGLc4CgjMxessam+9ujYcUCjhFDNOoEa4YxVhXF9Tcv8Ttxolece6y+IQM7fbDR' > ~borg/.ssh/authorized_keys chown -R borg:borg ~borg/.ssh 
  5. 我们从客户端在服务器上初始化borg存储库

     ssh borg@172.17.0.3 hostname #     borg init -e none borg@172.17.0.3:MyBorgRepo 

    -e开关用于选择存储库的加密方法(是的,您还可以使用密码另外加密每个存储库!)。 在这种情况下,因为 这是一个例子,我们不使用加密。 MyBorgRepoborg repo所在目录的名称(您无需提前创建它-Borg会自己做所有事情)。
  6. 使用Borg启动第一个备份:

     borg create --stats --list borg@172.17.0.3:MyBorgRepo::"MyFirstBackup-{now:%Y-%m-%d_%H:%M:%S}" /etc /root 

    关于按键:
    • --stats--list为我们提供有关备份和备份文件的统计信息;
    • borg@172.17.0.3:MyBorgRepo一切都在这里清楚了,这是我们的服务器和目录。 那么魔术的下一步是什么?
    • ::"MyFirstBackup-{now:%Y-%m-%d_%H:%M:%S}"是存储库中存档的名称。 它是任意的,但我们坚持使用_-timestamp格式(Python格式的时间戳)。

接下来是什么? 当然,请查看备份中的内容! 存储库中的档案列表:

 borg@b3e51b9ed2c2:~$ borg list MyBorgRepo/ Warning: Attempting to access a previously unknown unencrypted repository! Do you want to continue? [yN] y MyFirstBackup-2018-08-04_16:55:53 Sat, 2018-08-04 16:55:54 [89f7b5bccfb1ed2d72c8b84b1baf477a8220955c72e7fcf0ecc6cd5a9943d78d] 

我们看到带有时间戳的备份,以及Borg如何询问我们是否真的要访问以前从未使用过的未加密存储库。

我们看一下文件列表:

 borg list MyBorgRepo::MyFirstBackup-2018-08-04_16:55:53 

我们从备份中获取文件(您也可以整个目录):

 borg@b3e51b9ed2c2:~$ borg extract MyBorgRepo::MyFirstBackup-2018-08-04_16:55:53 etc/hostname borg@b3e51b9ed2c2:~$ ll etc/hostname -rw-r--r-- 1 borg borg 13 Aug 4 16:27 etc/hostname 

恭喜,您的第一个Borg备份已准备就绪!

实践:[使用GitLab]自动化!


将所有这些都包装在脚本中之后,我们以类似的方式在大约40台主机上手动配置了备份。 意识到Borg确实有效,他们开始向它转移更多和更大的项目...

在这里,我们面临的是Bareos,而不是Borg! 即:WebUI或某种集中位置来配置备份。 我们真的希望这是暂时的现象,但是到目前为止,我们必须解决一些问题。 搜寻完成的工具并参加视频会议,我们开始做生意。 像以前使用Bacula一样,将Borg与我们的内部服务集成是一个好主意(Bacula本身从集中式API中删除了工作清单,我们将自己的界面与其他项目设置集成在一起)。 我们考虑了如何做,概述了如何以及在何处构建它的计划,但是...现在需要常规备份,但是没有地方制定宏伟的时间计划。 怎么办

问题和要求大致如下:

  • 什么可以用作集中式备份管理?
  • 任何Linux管理员可以做什么?
  • 甚至向客户显示备份计划的经理还能理解和配置什么?
  • 计划任务每​​天在您的系统上做什么?
  • 什么将不会很难配置并且不会损坏?

答案是显而易见的:这是好旧的老土,每天英勇地履行其职责。 很简单 它不会冻结。 甚至从Unix到“您”的管理员也可以修复它。

那么crontab,但是您将所有这些保存在哪里? 是否每次都要去项目机器并用手编辑文件? 当然不是 我们可以将时间表放入Git存储库中并配置GitLab Runner,通过提交将其更新到主机上。

注意 :之所以选择GitLab作为自动化工具,是因为它便于执行任务,在我们的情况下几乎无处不在。 但是我必须说,他绝不是必需品。

您可以通过熟悉的自动化工具或通常手动(在小型项目或家庭安装中)扩展crontab以进行备份。

因此,这是简单自动化所需要的:

1. GitLab和一个存储库 ,其中首先有两个文件:

  • schedule -备份时间表
  • borg_backup_files.sh一个用于备份文件的简单脚本(如上例所示)。

schedule示例:

 # WARNING! CRONTAB MANAGED FROM GITLAB CI RUNNER IN ${CI_PROJECT_URL} # CI_COMMIT_SHA: ${CI_COMMIT_SHA} # Branch/tag: ${CI_COMMIT_REF_NAME} # Timestamp: ${TIMESTAMP} PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin # MyRemoteHost 0 0 * * * ${CI_PROJECT_DIR}/borg_backup_files.sh 'SYSTEM /etc,/opt' 

CI变量用于验证crontab更新是否成功,并且CI_PROJECT_DIR是克隆运行器后存储库所在的目录。 最后一行指示备份每天在午夜执行。

示例borg_backup_files.sh

 #!/bin/bash BORG_SERVER="borg@10.100.1.1" NAMEOFBACKUP=${1} DIRS=${2} REPOSITORY="${BORG_SERVER}:$(hostname)-${NAMEOFBACKUP}" borg create --list -v --stats \ $REPOSITORY::"files-{now:%Y-%m-%d_%H:%M:%S}" \ $(echo $DIRS | tr ',' ' ') || \ echo "borg create failed" 

此处的第一个参数是备份的名称, 第二个参数是备份目录的列表,以逗号分隔。 严格来说,列表也可以是一组单独的文件。

2. GitLab Runner ,在需要备份的计算机上运行,​​并且仅针对此存储库的作业被阻止。

3. CI脚本本身 ,由.gitlab-ci.yml

 stages: - deploy Deploy: stage: deploy script: - export TIMESTAMP=$(date '+%Y.%m.%d %H:%M:%S') - cat schedule | envsubst | crontab - tags: - borg-backup 

4. gitlab-runner访问gitlab-runner服务器的gitlab-runner用户的SSH密钥 (在示例中为10.100.1.1)。 默认情况下,它应位于.ssh/id_rsa主目录( gitlab-runner )中。

5.相同的10.100.1.1上的borg用户 ,只能访问borg serve命令:

 $ cat .ssh/authorized_keys command="/usr/bin/borg serve" ssh-rsa AAAAB3NzaC1yc2EAA... 

现在,当您提交到Runner存储库时,它将填充crontab的内容。 当cron的响应时间到来时,将执行/etc/opt目录的备份,该目录将位于备份服务器上服务器10.100.1.1的MyHostname-SYSTEM目录中。



不能得出结论:您还能做什么?


当然,在此使用博格并不止于此。 以下是一些进一步实施的想法,其中一些我们已经在家中实施:

  • 添加用于不同备份的通用脚本 ,该脚本在执行结束时运行borg_backup_files.sh ,以其工作结果为目标的目录。 例如,您可以备份PostgreSQL(pg_basebackup),MySQL(innobackupex),GitLab(内置rake作业,创建归档文件)。
  • 具有备份计划的中央主机 。 不在每个主机上配置GitLab Runner吗? 不用说它在备份服务器上,启动时crontab会将备份脚本传输到计算机上并在该计算机上运行。 当然,为此,您将需要客户端计算机上的borg用户和ssh-agent ,以便不为每台计算机上的备份服务器分配密钥。
  • 监控方式 哪里没有他! 关于备份未正确完成的警报必须是。
  • 从旧档案中清除borg储存库。 尽管重复数据删除性能很好,但仍必须清除旧备份。 为此,您可以在备份脚本的末尾调用borg prune
  • 计划的Web界面 。 如果您手动或在Web界面中编辑crontab看起来不牢靠/不舒服,它将非常有用。
  • 饼图 。 一些图表以可视方式表示成功完成的备份的百分比,它们的执行时间,“已吃”通道的宽度。 难怪我写道,像Bareos一样,WebUI不够用...
  • 我希望通过按钮收到的简单操作 :按需启动备份,还原到计算机等。

最后,我想在生产环境中的PostgreSQL WAL文件的实际工作备份上添加重复数据删除的有效性示例:

 borg@backup ~ $ borg info PROJECT-PG-WAL Repository ID: 177eeb28056a60487bdfce96cfb33af1c186cb2a337226bc3d5380a78a6aeeb6 Location: /mnt/borg/PROJECT-PG-WAL Encrypted: No Cache: /mnt/borg/.cache/borg/177eeb28056a60487bdfce96cfb33af1c186cb2a337226bc3d5380a78a6aeeb6 Security dir: /mnt/borg/.config/borg/security/177eeb28056a60487bdfce96cfb33af1c186cb2a337226bc3d5380a78a6aeeb6 ------------------------------------------------------------------------------ Original size Compressed size Deduplicated size All archives: 6.68 TB 6.70 TB 19.74 GB Unique chunks Total chunks Chunk index: 11708 3230099 

这是每小时进行WAL文件备份的65天。 使用Bacula / Bareos时,即 不进行重复数据删除,我们将获得6.7 TB的数据。 试想一下:我们有能力存储通过PostgreSQL传递的近7 TB的数据,而实际上仅占用20 GB的空间。

聚苯乙烯


另请参阅我们的博客:

Source: https://habr.com/ru/post/zh-CN420055/


All Articles