如何检测 Ansible playbook 在执行期间挂起的原因

Posted

技术标签:

【中文标题】如何检测 Ansible playbook 在执行期间挂起的原因【英文标题】:How to detect why Ansible playbook hangs during execution 【发布时间】:2014-01-14 22:22:35 【问题描述】:

我写的一些任务开始并且永不结束。 Ansible 不提供任何可以解释这一点的错误或日志,即使使用 -vvvv 选项也是如此。剧本只是挂起,经过几个小时不会改变任何事情。

当我尝试手动运行我的任务(通过 SSH 输入命令)时,一切都很好。

挂起的示例任务:

- name: apt upgrade
  shell: apt-get upgrade

有什么方法可以查看 stdout 和 stderr 吗?我试过了:

- name: apt upgrade
  shell: apt-get upgrade
  register: hello
- debug: msg=" hello.stdout "
- debug: msg=" hello.stderr "

但没有任何改变。

我确实拥有所需的权限,并且我传递了正确的 sudo 密码 - 其他需要 sudo 的任务正确执行。

【问题讨论】:

你正在传递 -K 选项? 是的。但是我的问题在这里解决了groups.google.com/forum/#!topic/Ansible-project/mm99yAPVrfc 好酷。仅供参考,您应该将解决方案添加为答案并自己接受..这将有助于其他人查看此问题。 【参考方案1】:

问题的最可能原因是 SSH 连接。当一个任务需要很长的执行时间时 SSH 超时。我曾经遇到过这样的问题,为了克服 SSH 超时问题,在运行 Ansible 的当前目录中创建一个 ansible.cfg 添加以下内容:

[ssh_connection]

ssh_args = -o ServerAliveInterval=n

n 是我们在通过 SSH 连接到服务器时使用的 ServerAliveInterval(秒)。将其设置在 1-255 之间。这将导致 ssh 客户端每隔n 秒向服务器发送一次空包,以避免连接超时。

【讨论】:

以下解决了我的问题:[ssh_connection]\n ssh_args = -o ServerAliveInterval=30 -o ControlMaster=auto -o ControlPersist=60s 一个小笔记。 ServerAliveInterval=100 本身会减慢执行 ansible 任务的速度。您必须将其与 ControlMaster=auto -o ControlPersist=10m 结合使用【参考方案2】:

我在使用剧本时遇到了同样的问题。

它运行完美,直到某个点然后停止,所以我添加了 asyncpoll 参数以避免这种行为

- name: update packages full into each server
  apt: upgrade=full
  ignore_errors: True
  async: 60
  poll: 60

它就像一个魅力!我真的不知道发生了什么,但现在 Ansible 似乎记住了正在发生的事情并且不再冻结!

希望对你有帮助

【讨论】:

发生的事情是,ansible 不会等待命令(并在 ssh 连接上超时),而是会检查命令 - 在这种情况下每 60 秒到最多 60 秒(换句话说,一次)。这回避了 ssh 超时的问题。【参考方案3】:

我遇到了同样的问题,经过一番摆弄后,我发现问题出在收集事实的步骤中。这里有一些提示可以更好地解决任何类似问题。

在你的剧本中禁用事实收集:

---
- hosts: myservers
  gather_facts: no
..

重新运行剧本。如果它有效,则意味着罪魁祸首不在 SSH 本身,而是在收集事实的脚本中。我们可以很容易地调试这个问题。

    SSH 到远程盒子 在 .ansible 文件夹中的某处找到 setup 文件。 使用./setuppython -B setup 运行它

如果它挂起,那么我们肯定知道问题就在这里。要准确找到导致它挂起的原因,您可以简单地使用编辑器打开文件并主要在Factspopulate() 方法中添加print 语句。重新运行脚本,看看它运行了多长时间。

对我来说,这个问题似乎是在尝试解决self.facts['fqdn'] = socket.getfqdn() 行的主机名,然后通过谷歌搜索发现是resolving the remote hostname 的问题。

【讨论】:

如果我的 .ansible 目录没有安装文件,只有一个 ./tmp 目录,它也是空的怎么办?【参考方案4】:

对我来说完全不同的解决方法。我从 Debian Jessie (Linux PwC-Deb64 3.16.0-4-amd64 #1 SMP Debian 3.16.7-ckt25-2+deb8u3 (2016-07-02) x86_64 GNU/Linux) 到我试图在 AWS 中构建的另一个 Debian 映像。

在此处的许多建议对我不起作用之后,我对 SSH“共享”连接产生了怀疑。我去了我的ansible.cfg,找到了ssh_args 行并设置了ControlMaster=no。这现在可能执行缓慢,因为我已经失去了它应该提供的 SSH 性能提升,但似乎这与 apt-get 之间存在一些交互,这导致了问题。

您的ansible.cfg 可能位于您运行ansible 的目录中,也可能位于/etc/ansible 中。如果是后者,您可能希望在开始更改之前将其复制到本地目录!

【讨论】:

【参考方案5】:

就我而言,ansible 是“永远挂起”,因为 apt-get 试图问我一个问题!我是怎么想出来的?我转到目标服务器并运行ps -aef | grep apt,然后在适当的“卡住”apt-get 命令上执行kill

在我这样做之后,我的 ansible playbook 立即恢复了活力并报告了(提供了ansible-playbook -vvv 选项):

    " ==> Deleted (by you or by a script) since installation.",
    " ==> Package distributor has shipped an updated version.",
    "   What would you like to do about it ?  Your options are:",
    "    Y or I  : install the package maintainer's version",
    "    N or O  : keep your currently-installed version",
    "      D     : show the differences between the versions",
    "      Z     : start a shell to examine the situation",
    " The default action is to keep your current version.",
    "*** buildinfo.txt (Y/I/N/O/D/Z) [default=N] ? "

在阅读了有用的诊断输出后,我立即意识到我需要一些合适的 dpkg 选项(例如,参见this devops post)。就我而言,我选择了:

apt:
  name: ' item '
  state: latest
  update_cache: yes
  # Force apt to always update to the newer config files in the package:
  dpkg_options: 'force-overwrite,force-confnew'
loop: ' my_packages '

另外,不要忘记在你用这样的东西杀死 ansible 会话后进行清理,否则你的安装仍然可能会失败:

sudo dpkg --configure -a

【讨论】:

【参考方案6】:

删除我的 SSH 密钥的密码为我修复了它,例如:

ssh-keygen -p

【讨论】:

4 月 1 日答复?打得好,先生。【参考方案7】:

我正在使用 ansible 在 Ubuntu 20.4 虚拟机上安装 OpenDayLight SDN 控制器集群。收集事实是报告一个python版本警告和挂起。在我的 3 个 VM 工作节点上安装 python 3.8 解决了这个问题

【讨论】:

以上是关于如何检测 Ansible playbook 在执行期间挂起的原因的主要内容,如果未能解决你的问题,请参考以下文章

ansible--playbook用法与自己的yml范例总结

Ansible Jinja2 模板

Ansible Jinja2 模板

Ansible Jinja2 模板

ansible学习笔记7-playbooks之执行一个playbook

如何控制Ansible Playbook的执行顺序运行选定的剧本资源