我正在尝试为 500-2000 个地理分布非常分散的主机选择一个配置管理系统。由于网络可靠性各不相同,可能有许多主机在任意给定时间都暂时不可用。出于这个原因,我最初的选择是 Chef,因为它使用“拉”模型,当主机上线并签入时,它们会立即获得当前配置。
但是,如果我的主机每 30 分钟仅轮询 Chef 服务器一次以获取新配置,则无法快速部署。另外,我不是 Ruby 爱好者。我更喜欢使用基于推送的模型,这样我就可以尽快将配置推送到主机。因此,自然的选择似乎是 Ansible 或 SaltStack(可能是 SaltStack)。但我的问题是:Ansible 和 SaltStack 如何处理失败或关闭的主机?有没有办法一直重试推送,直到主机重新上线?是否有现有的模式可以使用这两种工具正确处理关闭主机的最终一致性?谢谢!
答案1
Salt 采用从节点到主节点的拉模型运行。您可以从主节点发出全局命令,例如
salt 'api*.domain.com` state.highstate
这将在所有具有 id(主机名)为 api*.domain.com 的主机上运行 highstate。highstate 类似于完整的 chef 运行。
通常默认情况下人们要么让主计划 highstate 在 minions 上运行,要么让 minions 自己运行计划,比如每 10 分钟运行一次 highstate。
因此,如果某个节点已关闭,而您在主节点上运行命令来运行某个状态,则 salt 将在其运行输出中报告该节点已关闭,该输出可以采用多种不同方式格式化以供您提取。例如,它甚至可以记录到 mysql。
例如,如果您在主服务器上运行上述命令,在所有api*.domain.com
节点上运行 highstate。如果 5000 个节点中的 2 个节点当前正在重新启动,则一旦salt-minion
重新上线,它们将通过消息总线从主服务器获取事件并运行 highstate。
Salt 还有一个称为代理节点的东西来帮助主服务器负载。你可以在某个地方有一个主服务器,每个数据中心都有一个代理节点,主服务器发送的所有命令都会通过代理节点,而这些数据中心的从属节点会访问它们的代理节点,而不会访问主服务器
答案2
我只能针对 Ansible 来回答这个问题。
Ansible 本身不处理无法访问的主机。它会尝试连接,如果无法连接,主机将被从当前播放中丢弃。但 Ansible 为您提供了一些工具来自己处理这个问题。
首先是等待模块。通过这个,您可以等待非常长的超时时间,直到主机可用。
- wait_for:
port: 22
delay: 10
timeout: 3600
host: "{{ inventory_hostname }}"
delegate_to: localhost
但是,当您运行该剧本时,这本身就会成为一个问题,因为默认情况下,Ansible 不会处理任何其他任务,直到所有主机都通过此任务。在这种情况下,这是适得其反的。根据您的描述,当最后一个主机终于可以访问时,第一个主机可能会再次不可用。
为了解决这个问题,你需要使用 Ansible 2,它有一个名为策略.strategy: free
允许您尽快运行每个任务,这意味着只要主机可用,它就会运行所有任务。
但是,连接可能会断开,在这种情况下,没有内置的自动重试方法。如果无法建立 ssh 连接,则会为该主机抛出致命错误,并且自 Ansible ~1.9 以来,没有办法捕获此类连接错误。但这不会影响其他主机,它们都会正常运行。
不过您可以重试。失败的主机将存储在<playbook-name>.retry
剧本本身旁边的文件中。要仅重试失败的主机,您可以运行:
ansible-playbook ... --limit @<playbook-name>.retry
答案3
为了扩展 Mike 的回答,你可以使用 Salt 同时进行推送和拉取。推送非常简单,只需
salt 'api*.domain.com` state.highstate
同时,你的 Minions 可以每隔 X 分钟或几小时通过以下方式执行定时拉取:内置调度程序。我首选的方法是通过 pillar 进行配置,但将其添加到 minion 配置中也是可行的。例如:
schedule:
highstate:
function: state.highstate
maxrunning: 1
hours: 1
splay: 600