AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / server / 问题 / 1061100
Accepted
Mikhail T.
Mikhail T.
Asked: 2021-04-22 07:23:49 +0800 CST2021-04-22 07:23:49 +0800 CST 2021-04-22 07:23:49 +0800 CST

Systemd 和灾难恢复备用系统

  • 772

我们使用 systemd 在生产环境中运行各种服务。(呃……)

我们正在构建一个匹配的“灾难恢复”站点,该站点将安装相同的应用程序——使用相同的 systemd-units 以在发生灾难时启动其各种组件。

这种 DR 环境是“热的”,准备在短时间内接管(越短越好)——从而成为生产本身。然后,当“灾难”解决后,另一个环境将成为 DR。

我的问题是,如何让这些 systemd-services 准备好启动,但直到某个条件变为真才真正启动?

为了得出结论,特定站点当前是主要站点(生产),命令 ( amIthePrimary) 需要运行并以 0 退出代码退出。检查既简单又快速——可以每分钟执行一次。但是,因为它需要运行命令,所以 systemd 没有Condition提供它。

我是否将该命令放入每个单元的 ExecPre中,或者这会成为一个嘈杂的错误,不必要地惹恼管理员?我是否将其与所有其他服务一起放入一个独立的单元中Require?

另外,一旦条件为真——服务启动——我如何继续检查它,所以它们都将关闭,它是否应该再次变为假?

redhat disaster-recovery systemd rhel7
  • 1 1 个回答
  • 105 Views

1 个回答

  • Voted
  1. Best Answer
    mattpr
    2021-11-20T09:26:43+08:002021-11-20T09:26:43+08:00

    由于您的用例是非常自定义的,并且您的需求将来可能会发生变化,所以您为什么不执行以下操作...

    failover-manager在每分钟运行一次的两台机器上创建一个新的 systemd 计时器(例如)。systemd 计时器将定期启动关联的一次性 systemd 服务。

    该一次性 systemd 服务可以只运行一个包含您的逻辑的 bash 脚本:

    • 运行amIthePrimary检查
    • 如果是主要的,请启动您的 systemd 服务并检查它是否已正确启动。
    • 如果不是主要的,则停止您的 systemd 服务(如果它正在运行)。
    • 如果您的脚本无法启动/停止/验证运行,那么它应该会失败(可监控),否则会成功。
    • 这个计时器脚本不需要输出任何东西(噪音方面),除非它做出改变,即:
      • “我是主要的,但服务没有运行。正在启动......等待几秒钟......经过验证的服务正在运行且没有错误。” 或者
      • “我不是主要的,但服务正在运行。停止。”

    通过这种方式,您始终知道您可以监控您的常规/计时器检查是否正在无错误地运行。如果您的计时器服务有问题(非零退出),您可以通过监控来捕捉它。您可以单独监控主应用程序服务的故障。

    如果您的需求发生变化,您可以轻松调整计时器脚本或其运行频率。

    可能有更简洁的方法可以做到这一点,但它们可能取决于您amIthePrimary检查背后的任何事物所生成的事件......并且您没有提供任何详细信息。即事件驱动的故障转移而不是轮询。

    您也可以将您的amIthePrimary检查放入ExecStartPre=... 但是当它无法阻止服务启动时,您的服务将处于 FAILED 状态,这可能会混淆您的监控,因为它不是严重失败,而是故意失败。因此,您可能更喜欢使用计时器方法,因为这样您就可以分别监控计时器进程和主服务进程。计时器应始终运行、活动且不会失败。您的服务(如果正在运行)永远不应处于失败状态或监控应该关闭。还有一个问题是如何从监控的角度知道服务是否应该运行,但这超出了问题的范围。

    更新 - 包括示例实现示例

    未经测试,但只是为了让我的建议更清楚。

    failover-manager.sh

    假设这个脚本部署到/opt/failover-manager/failover-manager.sh

    #!/bin/bash
    
    # expected ENV.  Provided by the service that starts this script.
    #
    # APP_SERVICE (your main application)
    # SECONDS_TO_START (e.g. some java apps start very slowly)
    
    if [ -z "$APP_SERVICE" -o -z "$SECONDS_TO_START" ]; then
        echo "Missing environment"
        exit 1
    fi
    
    function is_running {
        systemctl is-active --quiet $1
        return $?
    }
    
    if amIthePrimary; then
        if is_running $APP_SERVICE; then   # no change, no log
            exit 0
        else
            echo "I AM primary, but service NOT running.  STARTING..."
            systemctl start $APP_SERVICE
            sleep $SECONDS_TO_START
            if is_running $APP_SERVICE; then 
                echo "Verified service is STARTED without error: $APP_SERVICE."
                exit 0
            else
                echo "Service $APP_SERVICE has not yet STARTED after $SECONDS_TO_START seconds."
                exit 1
            fi
        fi
    else
        if is_running $APP_SERVICE; then 
            echo "I am NOT primary, but service IS running.  Stopping..."
            systemctl stop $APP_SERVICE
            sleep $SECONDS_TO_START
            if is_running $APP_SERVICE; then 
                echo "Service $APP_SERVICE has not yet STOPPED after $SECONDS_TO_START seconds."
                exit 1
            else
                echo "Verified service is STOPPED: $APP_SERVICE."
                exit 0
            fi
        else   # no change, no log
            exit 0
        fi
    fi
    
    

    failover-manager.timer

    [Unit]
    Description=Timer that starts failover-manager.service
    Requires=failover-manager.service
    
    [Timer]
    Unit=failover-manager.service
    # every 1 minute
    OnCalendar=*:0/1
    AccuracySec=1s
    Persistent=true
    
    
    [Install]
    WantedBy=timers.target
    

    failover-manager.service

    这家伙是由上面的计时器运行的。

    [Unit]
    Description=Checks if we need to start or stop our application.
    
    [Service]
    Type=oneshot
    Environment=APP_SERVICE="my-application.service" SECONDS_TO_START="5"    
    WorkingDirectory=/opt/failover-manager/
    ExecStart=/opt/failover-manager/failover-manager.sh
    
    User=root
    Group=root
    
    

    纯系统选项?

    如果您正在寻找一种纯粹的 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 的故障转移到不同的数据中心/区域。

    • 1

相关问题

  • 如何设置 Redhat 对 ActiveDirectory 的用户进行身份验证

  • 如何从 RHEL 5 迁移到 CentOS 5?

  • 我应该将 Rails 应用程序部署到哪个目录?

  • 如何移动 MySQL 的数据目录?

  • RHEL 5.3 上可用的 yum 存储库

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    新安装后 postgres 的默认超级用户用户名/密码是什么?

    • 5 个回答
  • Marko Smith

    SFTP 使用什么端口?

    • 6 个回答
  • Marko Smith

    命令行列出 Windows Active Directory 组中的用户?

    • 9 个回答
  • Marko Smith

    什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同?

    • 3 个回答
  • Marko Smith

    如何确定bash变量是否为空?

    • 15 个回答
  • Martin Hope
    Tom Feiner 如何按大小对 du -h 输出进行排序 2009-02-26 05:42:42 +0800 CST
  • Martin Hope
    Noah Goodrich 什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同? 2009-05-19 18:24:42 +0800 CST
  • Martin Hope
    Brent 如何确定bash变量是否为空? 2009-05-13 09:54:48 +0800 CST
  • Martin Hope
    cletus 您如何找到在 Windows 中打开文件的进程? 2009-05-01 16:47:16 +0800 CST

热门标签

linux nginx windows networking ubuntu domain-name-system amazon-web-services active-directory apache-2.4 ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve