Ansible 是一种以配置和编排管理为中心的自动化工具。许多系统管理员和工程师在使用 Ansible 时需要注意的一个重要事项是如何对其进行优化以提高其速度和性能。以下是一些需要牢记的技巧和窍门。
使用 SSH 进行多路复用
从高层次来看,关于 SSH 有两件事需要担心:建立到主机的 新连接所需的时间以及使用该连接时遇到的延迟。Ansible 在主机上执行的每个任务都会为每个主机创建一个 SSH 连接。如果建立连接时存在一些延迟,那么这种延迟会因您要操作的任务数量而加剧。为了帮助解决这个问题,可以使用到主机的 SSH 控制套接字进行多路复用。如果建立了一个连接(并保持打开状态),则后续连接可以使用该套接字,并显着减少建立这些连接所需的时间。
Control Persist 是 SSH 的一项功能,允许已建立的控制套接字在其最后一次使用后保持一段时间。这使得可以使用控制套接字,而无需显式建立长期连接来使用该套接字。启用控制套接字/持久连接后,到主机的第一个连接将建立套接字,该套接字将持久存在一段时间。
持久连接时间应该足够长,以便 playbook 中稍后的任务仍然可以使用该套接字,但又不能太长以至于留下过时的处理程序。每个持久连接都会消耗内存,并且会乘以清单中的主机数量。
对 ssh_connection 和 controlpersist 的更改或修改可以在全局 Ansible 配置文件 (/etc/ansible/ansible.cfg) 中进行,或者您可以创建自己的 ansible.cfg 文件。
启用 SSH 管道
SSH 管道 是不同的但相关的。它更多的是 Ansible 的功能,而不是 SSH 的功能。默认情况下,当 Ansible 使用 SSH 和类 SSH 连接插件时,它将为每个任务多次 SSH 连接到目标主机。细节并不重要,但回想一下,如果您有连接开销,那么每个任务有多个连接会使延迟更加严重。
启用管道功能后,将改为建立到目标的单个连接,并通过该连接远程执行模块。同样,细节并不重要,您只需要知道多个连接被减少为单个连接。默认情况下未启用它,主要是因为它需要在目标主机上进行额外的配置才能使用 sudo(必须禁用 requiretty)。
Forking Ansible
Ansible 最好的功能之一是它能够跨多个主机并行操作。它可以一次操作的主机数量取决于多种因素。最大的因素是 forks 参数。此参数的默认值为 5,这将限制 Ansible 一次只能操作五个主机。第二个因素是 playbook 中目标主机的数量。如果 playbook 目标是四个主机,那么 forks 设置为 5、50 或 500 都无关紧要;Ansible 仍然只会以四个主机为目标。值得庆幸的是,您不必太担心 fork 开销,并尝试为主机定位足够的 fork。Ansible 将仅生成执行目标主机所需的 fork 数量。将 forks 设置为 500 并以四个主机为目标将导致四个 fork。
与目标主机相关的另一个重要因素是 playbook 的设置方式。如果 playbook 设置为使用“serial”模式,您可以配置批处理大小。这是将批量处理并通过 playbook 运行的主机最大数量。(请注意,批处理中的所有主机都在下一个批处理运行之前运行 playbook。)批处理大小可以设置得远小于 fork 大小,并且最小的数字会赢得并行性。
在管理大规模集群时,可能需要配置 forking 以维持超过 100 个 Ansible fork。当涉及到性能和容量时,您可能会遇到问题,例如内存和 CPU 限制。在处理扩展到越来越大的数字时,您可能需要考虑的一件事是对下游的负面影响——因为要求如此多的系统完成一项任务可能会出现问题。例如,要求 300-500 个系统完成诸如从单个源获取文件之类的任务,即使是从单个源获取文件,也可能会耗尽该资源,从而导致失败。
您需要事实收集吗?
事实收集 本质上是一项不成文的任务。当它在每个 playbook 开始时打开(默认设置)时,每个主机都会获得一个从其收集事实的任务。这些事实将变成 hostvars。如果您需要这些信息,这将非常有用,但这确实需要时间。我建议您关闭事实收集,除非您依赖这些事实。这是因为收集事实会消耗大量资源并且非常非常慢;每个主机三秒或更长时间。例如,如果您有 100 个主机和 50 个 fork,那么仅收集事实就需要 20*3 秒,即一分钟。如果您不使用事实,这就是浪费时间。您可以通过添加行 gather_facts: no 将 playbook 设置为不收集事实。
在添加 gather_facts: no 之前,playbook 花费了 5.39 秒,另外花费了 0.24 秒来执行创建文件的任务。在添加行 gather_facts: no 后,playbook 在 0.24 秒内完成。
使用 async 的并发任务
async 任务参数很有趣。它将导致 Ansible 在任务运行后立即关闭连接。Ansible 将在一定时间间隔后重新建立连接,以查看任务是否已完成。这可以用于使大量集群尽快开始处理任务。但是,它也可能增加连接数,因为 Ansible 会频繁连接回来以检查状态。如果此频率设置得较低,您可能会最终导致主机在完成并空闲的情况下等待频率计时器耗尽,以便 Ansible 重新检查。我还应该提到 Async 的 fire-and-forget 和稍后检查功能。它可以用于执行长时间运行的后台任务,您最终可能想要稍后检查。(注意:此功能需要 Ansible 1.8 或更旧版本。)
在 /etc/ansible/ansible.cfg 中所做的更改,尽管您可以将它们添加到实际的 playbook 中。
使用 pull 模式检查更改
Pull 模式是另一种提高效率的策略。正如我在上面写到的,我遇到的一个限制是我的 Ansible 控制主机管理超过 500 个 fork 的能力。Pull 模式 (Ansible-Pull 插件) 是一种将处理需求分散到整个集群的方法。这仅在您不需要集中协调任务何时完成时才有效。如果您的用例可以容忍最终一致性,那么您可以将 playbook 发布到 Git 存储库中,并让主机上的 Ansible 定期检查 playbook 的更改。当发现更改时,主机可以执行 playbook。
总结
我希望您现在对 Ansible 的速度和效率有了更深入的了解。有多种方法可以提高 Ansible 的性能,您应该根据您的需求和当前配置或设置来探索它们。
1 条评论