备份策略似乎是一个已解决的问题,但系统管理员经常遇到如何正确备份数据、将数据存储在何处以及如何跨不同软件环境标准化备份过程的问题。 2011 年,我们开发了自定义备份脚本,可以有效地处理客户 Web 项目的备份。这些脚本多年来为我们提供了良好的服务,根据需要将备份存储在我们的存储和外部存储库中。然而,随着我们的软件生态系统的发展和多样化,我们的脚本出现了不足,缺乏对 Redis 和 MySQL/PostgreSQL 等新技术的支持。脚本也变得很麻烦,除了电子邮件警报之外没有任何监控系统。
我们曾经紧凑的脚本演变成一个复杂且难以管理的系统。为不同的客户更新这些脚本变得具有挑战性,特别是当他们使用自定义版本时。到去年初,我们意识到我们需要一个更现代的解决方案。
在这篇文章中,我们将解释我们在开发nxs-backup时遇到的所有困难,并分享我们的经验和挑战。您还可以在您的项目中测试该工具并分享您的经验,我们非常有兴趣听取您的意见。现在,让我们开始吧!
我们列出了新系统的要求:
我们研究了在创建第一个版本的 nxs-backup 之前就已经存在的开源解决方案。但他们都有自己的缺陷。例如,Bacula 对我们来说过载了不必要的功能,由于大量的手动工作(例如,用于编写/搜索数据库备份的脚本),初始配置是相当费力的工作,并且恢复副本需要使用特殊的实用程序等等
毫不奇怪,我们在考虑重写我们的工具时遇到了同样的问题。四年内发生一些变化并且在线出现新工具的可能性并不高,但仍然如此。
我们研究了一些以前没有考虑过的新工具。但是,正如前面所讨论的,这些也不适合我们。因为他们没有完全满足我们的要求。
我们最终得出两个重要结论:
在探索新版本之前,让我们先看看我们之前有什么以及为什么它对我们来说还不够。
旧版本支持MySQL、PostgreSQL、Redis、MongoDB等数据库,文件离散增量复制,多种远程存储(S3;SMB;NFS;FTP;SSH;WebDAV),并具有备份轮换、日志记录等功能、电子邮件通知和外部模块。
现在,更多关于我们关心的事情。
在任何 Linux 上运行二进制文件而无需重新启动源文件
随着时间的推移,我们使用的系统列表已经大大增加。现在我们服务的项目使用非标准 deb 和 rpm 兼容发行版,例如 Arch、Suse、Alt 等。
最近的系统在运行 nxs-backup 时遇到困难,因为我们只收集了 deb 和 rpm 软件包,并且支持的系统版本列表有限。我们在某个地方重新提取了整个包,在某个地方只是二进制文件,在某个地方我们只需要运行源代码。
由于需要使用源代码,使用旧版本对于工程师来说非常不方便。更不用说这种模式下的安装和更新需要更多时间。您不必每小时设置 10 台服务器,而只需在一台服务器上花费一小时。
我们很早就知道,如果您拥有一个没有系统依赖项的二进制文件,可以在任何发行版上运行,并且不会遇到不同版本的库和系统架构差异的问题,那么情况会好得多。我们希望这个工具是一样的。
使用 nxs-backup 最小化 docker 镜像并在配置文件中支持 ENV
最近,很多项目都在容器化环境中运行。这些项目也需要备份,我们在容器中运行 nxs-backup。对于容器化环境,最小化图像大小并能够使用环境变量非常重要。
旧版本没有提供使用环境变量的机会。主要问题是密码必须直接存储在配置中。因此,您必须将整个配置放入一个变量中,而不是一组仅包含密码的变量。编辑大型环境变量需要工程师更加集中精力,并且使故障排除变得更加困难。
此外,在使用旧版本时,我们必须使用已经很大的 Debian 映像,其中我们需要添加多个库和应用程序以进行正确的备份。
即使使用图像的精简版本,我们也得到了约 250Mb 的最小大小,这对于一个小型实用程序来说是相当大的。在某些情况下,这会影响收集的启动过程,因为图像被拉到节点上的时间较长。我们想要获得不大于 50 MB 的图像。
无需保险丝即可使用远程存储
容器环境的另一个问题是使用fuse挂载远程存储。
当您在主机上运行备份时,这仍然是可以接受的:您已经安装了正确的软件包并在内核中启用了熔断器,现在它可以工作了。
当你需要在容器中添加保险丝时,事情就会变得有趣。如果不升级直接访问主机系统核心的权限,问题就没有解决,而且安全级别明显下降。
这需要协调,并不是所有客户都同意削弱安全策略。这就是为什么我们不得不制定大量我们甚至不想回忆的解决方法。此外,附加层增加了故障概率,并且需要对已安装资源的状态进行额外监视。直接使用他们的 API 来使用远程存储会更安全、更稳定。
监控状态并不仅向电子邮件发送通知
如今,团队在日常工作中使用电子邮件的情况越来越少。这是可以理解的,因为在群聊或群组通话中讨论问题要快得多。 Telegram、Slack、Mattermost、MS Teams 和其他类似产品由此广泛传播。
我们还有一个机器人,它会发送各种警报并通知我们。当然,我们希望看到像 Telegram 这样的工作空间中的备份崩溃的报告,而不是电子邮件以及数百封其他电子邮件。顺便说一句,一些客户还希望在其 Slack 或其他通讯工具中查看有关故障的信息。
此外,您很希望能够实时跟踪状态并查看工作的详细信息。为此,您需要更改应用程序的格式,将其变成恶魔。
性能不足
另一个急性疼痛是在某些情况下表现不足。
其中一个客户端有一个几乎 1 TB 的巨大文件转储,并且所有这些文件都是小文件 - 文本、图片等。我们正在收集这些内容的增量副本,并遇到以下问题 - 每年的副本需要三天。是的,好吧,旧版本无法在不到一天的时间内消化掉这一卷。
鉴于目前的情况,我们实际上无法恢复特定日期的数据,这是我们根本不喜欢的。
最初,我们使用 Python 实现了备份解决方案,因为它简单且灵活。然而,随着需求的增长,基于 Python 的解决方案变得不够用了。经过充分讨论,我们决定用 Go 重写系统,原因如下:
寻找解决方案
所有上述问题都或多或少地给IT部门带来了相当明显的痛苦,导致他们将宝贵的时间花费在固然重要的事情上,但这些成本本来是可以避免的。此外,在某些情况下,会给企业主带来一定的风险——某一天没有数据的概率虽然极低,但并非为零。我们拒绝接受现状。
Nxs-备份3.0
我们的工作成果是 nxs-backup v 3.0 的新版本,最近更新到了 v3.8.0
新版本的主要特点:
我们尝试保留大部分配置和应用程序逻辑,但存在一些更改。都与上一版本缺陷的优化和修正有关。
例如,我们将远程存储库的连接参数放入基本配置中,这样我们就不会每次为不同类型的备份指定它们。
下面是备份基本配置的示例。它包含通知通道、远程存储、日志记录和作业列表等常规设置。这是邮件通知的基本主要配置,我们强烈建议使用电子邮件通知作为默认方法。如果您需要更多功能,可以查看文档中的参考。
server_name: wp-server project_name: My Best Project loglevel: info notifications: mail: enabled: true smtp_server: smtp.gmail.com smtp_port: 465 smtp_user: j.doe@gmail.com smtp_password: some5Tr0n9P@s5worD recipients: - j.doe@gmail.com - a.smith@mail.io webhooks: [] storage_connects: [] jobs: [] include_jobs_configs: [ "conf.d/*.conf" ]
关于陷阱的几句话
我们预计会面临某些挑战。否则的话就是愚蠢的。但有两个问题造成了最强烈的伤害。
内存泄漏或非最佳算法
即使在以前版本的 nxs-backup 中,我们也使用自己的文件归档实现。该解决方案的逻辑是尽量避免使用外部工具来创建备份,而使用文件是最简单的步骤。
在实践中,该解决方案被证明是可行的,尽管从测试中可以看出,对于大量文件来说并不是特别有效。当时我们把它写成 Python 的细节,并希望当我们切换到 Go 时看到显着的差异。
当我们最终进行新版本的负载测试时,我们得到了令人失望的结果。性能没有任何提升,内存消耗甚至比以前更高。我们正在寻找解决方案。阅读了很多关于这个主题的文章和研究,但他们都说使用“filepath.Walk”和“filepath.WalkDir”是最好的选择。这些方法的性能只会随着语言新版本的发布而提高。
为了优化内存消耗,我们甚至在创建增量副本时犯了错误。顺便说一句,损坏的选项实际上更有效。由于显而易见的原因,我们没有使用它们。
最终,一切都取决于要处理的文件数量。我们测试了1000万。垃圾收集器似乎无法清除这么多生成的变量。
最终,意识到我们可能会在这里浪费太多时间,我们决定放弃我们的实现,转而采用经过时间考验且真正有效的解决方案 - GNU tar。
当我们想出更有效的解决方案来处理数千万个文件时,我们可能会回到自我实现的想法。
如此不同的ftp
使用 ftp 时出现了另一个问题。事实证明,不同的服务器对于相同的请求表现不同。
对于同一个请求,你要么得到正常的答案,要么得到与你的请求无关的错误,或者在你期望的时候没有得到错误,这是一个非常严重的问题.
因此,我们不得不放弃使用库“prasad83/goftp”,转而使用更简单的“jlaffaye/ftp”,因为第一个库无法与 Selectel 服务器正常工作。错误是在连接时,第一个尝试获取工作目录中的文件列表,并得到了上级目录访问权限的错误。使用“jlaffaye/ftp”就不存在这样的问题,因为它更简单,并且不会向服务器发送任何请求。
下一个问题是没有请求时断开连接。并非所有服务器都这样做,但有些服务器确实如此。所以我们必须在每次请求之前检查连接器是否脱落并重新连接。
最重要的是从服务器获取文件的问题,或者说清楚,尝试获取不存在的文件。有些服务器在尝试访问此类文件时会出错,其他服务器会返回一个甚至可以读取的有效 io.Reader 接口对象,只有你得到一个空字节。
所有这些情况都是凭经验发现的,必须自己处理。
结论
最重要的是,我们修复了旧版本的问题,影响工程师工作并给业务带来一定风险的事情。
我们还有上个版本中未实现的“愿望”,例如:
此列表现已添加新列表:
当然,我们很乐意了解社区的意见。您还看到哪些其他发展机会?您会添加哪些选项?
您可以在其网站上阅读文档并了解有关 nxs-backup 的更多信息,如果您想留下任何问题,我们的网站上还有故障排除部分。
我们已经在 Telegram 频道中对即将推出的功能进行了民意调查。关注我们,参与此类活动,为工具的发展做出贡献!
下次再见!
以上是维护开源备份工具:见解等的详细内容。更多信息请关注PHP中文网其他相关文章!