更成熟的配置管理 (CM) 系统(如 Puppet 和 Chef)采用基于拉取的方法:客户端定期轮询集中式主服务器以获取更新。其中一些系统提供无主方法也很好(所以,基于推送),但声明它“不适用于生产”(Saltstack)或“可扩展性较差”(Puppet)。据我所知,唯一从一开始就基于推送的系统是亚军 Ansible。
基于拉动的系统在可扩展性方面的具体优势是什么?为什么添加更多拉动主控比添加推送代理更容易?
例如,agiletesting.blogspot.nl写道:
在“拉”系统中,客户端彼此独立地联系服务器,因此整个系统比“推”系统更具可扩展性
另一方面,Rackspace 证明他们可以处理 15K 系统采用推送模型。
基础设施写道:
我们坚信使用 SUP、CVSup、rsync 服务器或 cfengine 之类的工具来维护基础设施,而不是将更改推送到客户端。每台单独的客户端机器都需要负责在启动时轮询黄金服务器,并在之后定期轮询,以维护自己的转速水平。在采用这种观点之前,我们开发了大量基于 ssh、rsh、rcp 和 rdist 的推送脚本。我们发现 r 命令(或 ssh)的问题是:当您运行基于 r 命令的脚本将更改推送到目标机器时,如果您有超过 30 台目标主机,那么其中一台很可能会随时宕机。维护已委托机器的列表变成了一场噩梦。在编写代码来纠正这个问题的过程中,您最终将得到复杂的包装器代码来处理:死主机超时;记录和重试死主机;分叉和运行并行作业以尝试在合理的时间内访问许多主机;最后检测并防止所有出站 rsh 会话耗尽源计算机上所有可用的 TCP 套接字的情况。然后,您仍然需要解决将刚刚执行的操作放入将来要安装的所有新主机的安装映像中的问题,以及对任何死机并必须在明天重建的主机重复此操作的问题。在经历了实施基于 r 命令的复制的麻烦之后,我们发现这根本不值得。我们不打算再使用 r 命令或任何其他推送机制来管理基础设施。它们的扩展性不如基于拉的方法。
这难道不是实现问题而不是架构问题吗?为什么编写线程推送客户端比编写线程拉取服务器更难?
答案1
基于推送的系统的问题在于你必须在中央推送节点上拥有整个架构的完整模型。你无法将数据推送到你不了解的机器上。
它显然可以起作用,但要保持同步则需要做大量的工作。
使用 Mcollective 之类的工具,您可以将 Puppet 和其他 CM 转换为基于推送的系统。通常,将拉动系统转换为基于推送的系统很简单,但反过来却并不总是那么简单。
还有组织政治的问题。基于推送的系统将所有控制权都交给中央管理员。以这种方式管理复杂性可能非常困难。我认为扩展问题是一个转移注意力的话题,如果你只看客户端数量,这两种方法都可以扩展。在许多方面,推送更容易扩展。然而,动态配置或多或少意味着你至少有一个客户端注册的拉动版本。
最终,这取决于哪种系统适合您组织的工作流程和所有权。一般来说,拉动系统更灵活。
答案2
如果有人对此感兴趣,我想我至少可以提供一份用户体验报告,这是我第一次在 Amazon 云中任务关键型系统的多主机设置补丁管理环境中使用 Ansible 的开箱即用推送功能。为了理解我的先入之见或偏见,我应该解释一下,我在自动化脚本级别上偏爱 Ruby,并且过去曾设置项目使用主代理 puppet 配置每个项目 Vpc。因此,我的经验掩盖了过去的偏见(如果有的话)。
我最近的经验非常有利于动态推送到不断变化的服务器,这些服务器从几十台到几百台,可以扩大或缩小规模,终止和刷新。在我的情况下,一个简单的 Ansible 1.7 临时命令就是我制作补丁所需的全部内容。然而,考虑到为此目的在每个 Vpc 上设置一个 AnsibleController(在 t2.micro 上)的有效性,我打算在未来扩展该技术以满足更复杂的要求。
因此,让我回到这个主题中提出的问题:在动态变化的庄园中推动的利与弊。
我针对的服务器类型的假设是:
- 不假设 IP 地址或亚马逊生成的本地主机名会长期存在 - 它们可以随时更换
- 所有实例都是从机器映像创建的,这些映像已经能够让单个特权管理用户进行 ssh 访问
- 为了根据功能或开发阶段(例如测试或生产)对服务器进行单独划分,并可能将其划分为组,这将通过启动约定的常规名称的特定 Amazon 标签来实现
- 我将使用不同的临时命令分别对 Linux 和 Windows 服务器进行补丁管理,因此在连接 Windows 服务器时,只需允许 Linux 特定的登录失败,这是完全可以接受的
考虑到这些条件,创建 AnsibleController 的机器映像以放入众多 Vpc 并在现有服务器帐户中现场配置(使用凭据)非常简单。在从映像创建的每个实例中自动执行的是
- 一个 cron 任务,用于定期将补丁推送到正在运行的服务器,以便定期持续访问所需的资产
- 在每个这样的间隔内计算 Ansible 库存的方法。
如果需要,第二项可以做得相对复杂(通过 Ansible 清单的信息结构)。但如果不需要复杂,这里有一个非常简单的脚本示例,用于在每个 cron 间隔计算所有 Amazon EC2 实例,并将结果定向到适当的清单文件(例如 /etc/ansible/hosts)...
#!/bin/bash
# Assumes aws-cli/1.3.4 Python/2.6.9 Linux/3.4.73-64.112.amzn1.x86_64 or greater
# http://aws.amazon.com/releasenotes/8906204440930658
# To check yum list aws-cli
# Assumes that server is equipped with AWS keys and is able to access some or all
# instances in the account within it is running.
# Provide a list of host IPs each on a separate line
# If an argument is passed then treat it as the filename, whether local or absolute
# path, to which the list is written
function list-of-ips {
/usr/bin/aws ec2 describe-instances --filters '[ {"Name": "instance-state-code", "Values": [ "16" ] } ]' | grep -w PrivateIpAddress | awk '{x=$2; gsub("\"","", x); gsub(",","", x); if(x && FNR!=1){print x;}}' | uniq
}
if [ -n "$1" ]; then
list-of-ips > "$1"
else
list-of-ips
fi
用例的唯一警告是补丁命令应该是幂等的。最好进行预先测试以确保满足这一点,作为确保补丁完全按照预期执行的一部分。
总而言之,我已说明了一个用例,其中动态推送对于我设定的目标很有效。它是一种可重复的解决方案(封装在可在多个帐户和区域中推出的映像中)。根据我迄今为止的经验,动态推送技术比我们目前可用的工具集中提供的替代方案更容易提供和实施。
答案3
这是一篇老帖子,但有趣的是历史会重演。
现在嵌入式物联网设备需要配置管理,基础设施/网络拓扑似乎更加复杂,因为防火墙、NAT 甚至移动网络都混杂其中。
基于推送或拉取的决策同样重要,但设备数量甚至更多。当我们开发物联网嵌入式设备配置管理工具时qbee.io我们选择了一种基于拉取的方法,其中代理以承诺理论为基础。这意味着代理拉取配置并自主收敛到所需状态。优点是即使主服务器关闭,配置也会被主动维护,并且系统不需要跟踪哪个设备已收到哪些配置更改。此外,通常很难知道设备的本地网络状况如何。所以我们不关心,直到设备 ping 服务器。在嵌入式用例的情况下,基于拉取的解决方案的另一个示例和论据是这些设备的长生命周期。如果设备发生故障并被备用设备替换(例如在石油钻井平台上),该设备将立即接收其特定组的配置并收敛到该配置。例如,如果出于安全原因每 6 个月轮换一次 ssh 密钥,则将自动应用备用设备组的最后一个有效密钥。
关注这些年来这一讨论如何继续将会很有趣。此外,容器和一次性基础设施也是长期维持配置的系统的替代方案。