大型群组中的 Ansible 性能问题

大型群组中的 Ansible 性能问题

所以,我有这个主机组,它由 35000 台虚拟机组成。
我需要在其上运行一个剧本。
如果这很重要 - 剧本只是对安装 node_exporter 的社区角色

但我很难让它疯狂运行。
我知道在如此庞大的主机组上运行它肯定会导致 OOM,所以我做了很多尝试,让它既可靠(确保它能完成并且不会被杀死)又快速(但实际上它没有)

所以我这样做:

  1. 使用strategy: free
  2. 使用serial: 350
  3. 仅收集我需要的事实:
  gather_facts: true
  gather_subset:
    - "default_ipv4"
    - "system"
    - "service_mgr"
    - "pkg_mgr"
    - "os_family"
    - "selinux"
    - "user"
    - "mounts"
    - "!all"
    - "!min"
  1. 在调用playbook时使用-f 350,使其在350台机器上同时运行playbook。
  2. 使用持久设置使其保持 ssh 连接
use_persistent_connections = True

[ssh_connection]
pipelining = True
ssh_args = -o ControlMaster=auto -o ControlPersist=1800s -o PreferredAuthentications=publickey -o ForwardAgent=yes

[connection]
ansible_pipelining = True

[persistent_connection]
connect_timeout = 1800

而且,嗯......它不起作用。就像我看到的最大问题一样 - 它实际上并没有一次生成 350 个 fork 来执行此操作。我看到的只是大约 3-5 个进程在远程主机上运行某些东西(我见过的最大进程可能是 20 个?),所以它非常慢。在 350 台主机上运行它需要大约 1.5 小时,这太疯狂了,因为在 30 台机器上调用这个剧本/角色大约需要 3-4 分钟才能完成。

另外,无论如何,它都会在某个时候出现 OOM。我目前在专门用于运行这一个剧本的 32 核/64 GB RAM VM 上运行它,无论如何它都会出现 OOM,这太疯狂了。
据我所知,serial设置应该可以防止这种情况发生,因为它会在每次批处理后释放一些内存。但似乎并非如此。它只是不断增长。

现在我使用构建批量机器的 bash 脚本运行它,然后我调用剧本,-l "machine1:machine2:.....:machine350"但这是完全错误的。

所以我的问题是 - 为什么我不能立即在主机组上运行角色/剧本,为什么它这么慢,为什么它会 OOMing 以及如何防止这种情况发生。

感谢 TIA 的所有帮助!

答案1

增加叉子

您拥有大量内存和 CPU,因此即使数百个 fork 又称工作线程占用大量资源,也是合理的。ansible.cfg:

[defaults]
forks = 350

serial 是播放的批处理大小。自动同时运行该数量的主机,直到播放结束。如果您只想增加工作线程,请删除 serial 以恢复默认值 100%。serial 还有其他影响,最明显的是,如果一批中的所有主机都失败,播放将停止。

不好的比较:假设你有一个非常大的项目需要编译。串行就像将其分成较小的目标和其他块。但它仍在运行,因此make --jobs=5并行性受到限制。Ansible fork 设置了工作线程的上限。

测量内存使用情况

查找 Ansible 控制器上启动的所有进程,估计它们的内存使用情况,并找出虚拟内存系统是如何被激怒的。你没有说你的操作系统,详细的性能分析与平台密切相关。

例如,如果您使用 systemd Linux,systemd-cgtop -m将显示所有会话和服务。找出总内存使用情况以及是否违反 cgroup 限制。

Ansible 不仅运行 Python,还运行其他程序。可能使用 ssh 进行连接,每个主机每个任务一个,这很多。理论上这些连接都是短暂的,但连接生命周期将我们引向下一个主题:

使用持久连接

令人困惑的是,use_persistent_connections 不适用于 POSIX 主机,不要费心将其设置为 true。这是为网络设备的 libssh 不是用于 Unix/Linux 主机的 OpenSSH ssh 连接插件。

相比之下,ssh_args 由 ssh 连接插件使用。默认添加的 ControlPersist 将告诉 ssh 保持连接,并且后续到同一主机的低级 ssh 连接将跳过连接和身份验证。通常会加快速度。但是,这会增加正在运行的 ssh 程序的数量,因此如果您快速循环 30k 个主机,则需要运行大量 ssh 程序。

考虑进行修改ssh_args以删除 ControlPersist 内容。每个连接开销都会受到影响,但您没有运行那么多 ssh。

检查您的最大进程数或 pid 数是否很大,大概是 60000。

较小的团体

35k 台主机并不是我听说过的最大规模库存,但它很大。Ansible 在很多方面都很重,因此您可能很难通过扩展来快速完成任务。

考虑一次在较小的主机集上运行剧本。--limit 也可以针对目标组,这比在命令行上提供数千个主机要轻松得多。

可以使您的库存足够智能,以各种方式标记主机,并从中生成组。数据中心区域、可用区域、VM 主机、硬件代。或者创建您自己的组名并将库存分成更小的组。

对于较小的组,您可以并行运行多个ansible-playbook --limit程序,可能使用 xargs 或 GNU parallel。或者在不同的控制器主机之间拆分运行。

推送选项

默认的 Ansible 概念是从中央控制器在许多远程主机上运行。但是,一些托管主机可以安装 Python 并自行运行 ansible。因此,您可以在每个托管主机上安装 ansible,并让它在 cron 或其他任何情况下自行运行。

ansible 附带的 ansible-pull 脚本就是一个例子。从版本控制下载剧本,并自动 --limit 到此主机。

这是一种非常不同的操作方法,可能不适用于您想要在托管主机上运行的内容。但这是一种选择。

答案2

你应该尝试使用Ansible 中的 Mitogen它使用不同的方法替换了 Ansible 中的主机通信部分,用他们的话来说,执行速度提高了 1.25 倍 - 7 倍,CPU 使用率降低了 2 倍。

我已经在我的项目中使用了它多年,并没有遇到任何问题。

相关内容