我们使用 systemd 在生产环境中运行各种服务。(呃……)
我们正在构建一个匹配的“灾难恢复”站点,该站点将安装相同的应用程序——使用相同的 systemd-units 以在发生灾难时启动其各种组件。
这种 DR 环境是“热的”,准备在短时间内接管(越短越好)——从而成为生产本身。然后,当“灾难”解决后,另一个环境将成为 DR。
我的问题是,如何让这些 systemd-services 准备好启动,但直到某个条件变为真才真正启动?
为了得出结论,特定站点当前是主要站点(生产),命令 ( amIthePrimary
) 需要运行并以 0 退出代码退出。检查既简单又快速——可以每分钟执行一次。但是,因为它需要运行命令,所以 systemd 没有Condition
提供它。
我是否将该命令放入每个单元的 ExecPre
中,或者这会成为一个嘈杂的错误,不必要地惹恼管理员?我是否将其与所有其他服务一起放入一个独立的单元中Require
?
另外,一旦条件为真——服务启动——我如何继续检查它,所以它们都将关闭,它是否应该再次变为假?
由于您的用例是非常自定义的,并且您的需求将来可能会发生变化,所以您为什么不执行以下操作...
failover-manager
在每分钟运行一次的两台机器上创建一个新的 systemd 计时器(例如)。systemd 计时器将定期启动关联的一次性 systemd 服务。该一次性 systemd 服务可以只运行一个包含您的逻辑的 bash 脚本:
amIthePrimary
检查通过这种方式,您始终知道您可以监控您的常规/计时器检查是否正在无错误地运行。如果您的计时器服务有问题(非零退出),您可以通过监控来捕捉它。您可以单独监控主应用程序服务的故障。
如果您的需求发生变化,您可以轻松调整计时器脚本或其运行频率。
可能有更简洁的方法可以做到这一点,但它们可能取决于您
amIthePrimary
检查背后的任何事物所生成的事件......并且您没有提供任何详细信息。即事件驱动的故障转移而不是轮询。您也可以将您的
amIthePrimary
检查放入ExecStartPre=
... 但是当它无法阻止服务启动时,您的服务将处于 FAILED 状态,这可能会混淆您的监控,因为它不是严重失败,而是故意失败。因此,您可能更喜欢使用计时器方法,因为这样您就可以分别监控计时器进程和主服务进程。计时器应始终运行、活动且不会失败。您的服务(如果正在运行)永远不应处于失败状态或监控应该关闭。还有一个问题是如何从监控的角度知道服务是否应该运行,但这超出了问题的范围。更新 - 包括示例实现示例
未经测试,但只是为了让我的建议更清楚。
failover-manager.sh
假设这个脚本部署到
/opt/failover-manager/failover-manager.sh
failover-manager.timer
failover-manager.service
这家伙是由上面的计时器运行的。
纯系统选项?
如果您正在寻找一种纯粹的 systemd 机制来以干净的方式完成此任务,那可能是不可能的。
您的用例是自定义的,IMO 超出了 systemd 的范围。
ExecStartPre
因此,您可以在使用或使用requires
/类型依赖机制时“破解”它wants
......但所有这些方法都依赖于一个进程,或者由于失败而处于停止状态(中断监控......它是预期的失败还是失败的失败) ...或者那个进程被“某事”启动/停止,该“某事”知道系统世界之外的某事。后者不会破坏监控,但确实需要 systemd 之外的东西,而我提出的是一种方法。备择方案
就像@anx 建议的那样......也许重新设计您的 DR 故障转移的工作方式。
这也是我们采取的方法。如果我们有一个备用盒/云/机架/等,那么我们希望确保一切都已经在运行(例如服务等)。
那么问题就是......如何进行切换。
有两种常见的方式可以完成故障转移到备用端点......
1 - DNS 故障转移
为您的关键端点设置一个较低的 DNS ttl(缓存时间),并在检测到故障时更新您的 DNS 记录以指向备用端点(例如 CNAME、A、AAAA DNS 更新)。
许多托管 DNS 提供商(例如 dnsmadeeasy、dynect)将此作为其服务(检测和故障转移)的一部分提供。当然,您可以使用自己的 DNS 或任何 DNS 提供商来实现此功能,使您能够设置低 TTL 并轻松手动或自动(监控 + DNS API)更新您的 DNS 记录。
这里的一个潜在问题是您可能会担心机器人会向“非活动”端点发出请求。这肯定会发生,但如果您的应用程序设计得很好,它不会破坏任何东西,让一些请求进入备用 DR 端点。
好消息是这迫使您考虑如何使您的应用程序架构在接收流量的多个并发端点(共享数据库、复制等)方面更加健壮。
如果这很重要,您可以添加 iptables 规则来管理它...但是您可能会遇到与以前相同的问题...如何触发更改(因为现在需要更改的是 DNS 和 iptables发生故障转移)。
2 - 负载平衡器故障转移
在负载均衡器中不活动的备用服务器很常见,并且可以快速添加/交换到负载均衡器后面的活动服务器池中。
在这种情况下,负载均衡器或第三个组件可以管理健康检查并更新负载均衡器配置以将健康的服务器替换为不健康的服务器。
这不适用于 DR 案例,因为负载平衡器通常是本地机架或数据中心。因此,对于 DR,您可能最好构建基于 DNS 的故障转移到不同的数据中心/区域。