我的 ansible box(vagrant) 遇到了一些奇怪的问题。
昨天一切顺利,我的剧本也运行良好。
今天 ansible 挂在“收集事实”上?
以下是详细输出:
<5.xxx.xxx.xxx> ESTABLISH CONNECTION FOR USER: deploy
<5.xxx.xxx.xxx> REMOTE_MODULE setup
<5.xxx.xxx.xxx> EXEC ['ssh', '-C', '-tt', '-vvv', '-o', 'ControlMaster=auto', '-
o', 'ControlPersist=60s', '-o', 'ControlPath=/home/vagrant/.ansible/cp/ansible-s
sh-%h-%p-%r', '-o', 'Port=2221', '-o', 'KbdInteractiveAuthentication=no', '-o',
'PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey', '-o
', 'PasswordAuthentication=no', '-o', 'User=deploy', '-o', 'ConnectTimeout=10',
'5.xxx.xxx.xxx', "/bin/sh -c 'mkdir -p $HOME/.ansible/tmp/ansible-tmp-1411372677
.18-251130781588968 && chmod a+rx $HOME/.ansible/tmp/ansible-tmp-1411372677.18-2
51130781588968 && echo $HOME/.ansible/tmp/ansible-tmp-1411372677.18-251130781588
968'"]
答案1
我在 Vagrant 上使用 Ansible ping 时也遇到了类似的问题,它突然无缘无故地卡住了,之前一直运行良好。与 ssh 或连接问题等其他问题不同,它会永远死机,不会超时。
我解决这个问题的方法是清理~/.ansible
目录,然后它又可以正常工作了。我不知道为什么,但问题确实解决了。
如果您再次遇到这种情况,请尝试~/.ansible
在刷新 Vagrant 之前清理该文件夹。
答案2
有很多原因导致 ansible 在事实收集时挂起,但在进一步讨论之前,这是在任何此类情况下您应该进行的第一个测试:
ansible -m ping <hostname>
此测试仅连接到主机,并执行足够的代码以返回:
<hostname> | SUCCESS => {
"changed": false,
"ping": "pong"
}
如果此方法有效,您几乎可以排除任何设置或连接问题,因为这证明您可以解析目标主机名、打开连接、进行身份验证并使用远程 python 解释器执行 ansible 模块。
现在,这里有一个(非详尽的)列表,列出了剧本开始时可能出错的事情:
ansible 执行的命令正在等待交互式输入
我记得这发生在旧版 ansible 上,其中命令会等待永远不会出现的交互式输入,例如 sudo 密码(当您忘记开关时-K
)或接受新的 ssh 主机指纹(对于新的目标主机)。
现代版本的 ansible 可以妥善处理这两种情况,并在正常使用情况下立即引发错误,因此除非您自己执行诸如调用 ssh 或 sudo 之类的操作,否则您不应该遇到此类问题。即使您遇到了,那也是事后才发现的。
SSH 主连接已失效
在这里给出的调试日志中,传递给 ssh 客户端的一些非常有趣的选项:
ControlMaster=auto
ControlPersist=60s
ControlPath=/home/vagrant/.ansible/cp/ansible-ssh-%h-%p-%r
这些选项记录在ssh_config 手册。
默认情况下,ansible 会尝试智能地使用 ssh 连接。对于给定的主机,它不会为剧本中的每个任务创建新连接,而是会打开一次,并在整个剧本(甚至跨剧本)中保持打开状态。
这很好,因为建立新连接比使用现有连接要慢得多,而且计算量也大得多。
实际上,每个 ssh 连接都会检查 处是否存在套接字~/.ansible/cp/some-host-specific-path
。第一个连接找不到它,因此它正常连接,然后创建它。每个后续连接都将使用此套接字来通过已建立的连接。
即使建立的连接最终超时并在长时间未使用后关闭,套接字也会关闭,我们又回到原点。
到目前为止,一切都很好。
但有时,连接实际上已经断开,但 ssh 客户端仍认为它已建立。这种情况通常发生在您从笔记本电脑执行剧本时,并且丢失了 WiFi 连接(或从 WiFi 切换到以太网等...)
最后一个例子是一个可怕的情况:你能使用默认的 ssh 配置通过 ssh 连接到目标机器,但只要您之前的连接仍然被视为活动连接,ansible 甚至不会尝试建立新的连接。
此时,我们只想摆脱这个旧套接字,最简单的方法就是将其删除:
# Delete all the current sockets (may disrupt currently running playbooks)
rm -r ~/.ansible/cp
# Delete only the affected socket (requires to know which one it is)
rm ~/.ansible/cp/<replace-by-your-socket>
这对于一次性修复来说非常完美,但如果这种情况发生得太频繁,您可能需要寻找一个长期修复方案。以下是一些可能有助于实现这一目标的提示:
- 从服务器启动剧本(网络连接比笔记本电脑更稳定)
- 使用ansible 配置或直接ssh 客户端配置禁用连接共享
- 使用相同的资源,但要微调超时,以便主连接崩溃实际上超时更快
请注意,在撰写本文时,一些选项已经发生了变化(例如,我最近的运行给了我ControlPath=/home/toadjaune/.ansible/cp/871b533295
),但总体思路仍然有效。
收集事实实际上花费了太多时间
在每个游戏开始时,ansible 都会收集目标系统的大量信息,并将其放入事实。这些是您可以在剧本中使用的变量,通常非常方便,但有时,获取这些信息可能需要很长时间(错误的挂载点、具有高 i/o 的磁盘、高负载……)
话虽如此,你不需要严格需要事实来运行剧本,而且几乎肯定不是全部,所以让我们尝试禁用我们不需要的内容。为此,有几种选择:
- 完全地禁用设置模块
- 更改配置设置模块仅包含其中的某些部分。
- 通过命令行参数
- 通过ansible 配置文件
为了调试目的,直接从命令行调用设置模块非常方便:
ansible -m setup <hostname>
最后一个命令应该和你的剧本一样挂起,并最终超时(或成功)。现在,让我们再次执行模块,禁用所有我们可以禁用的功能:
ansible -m setup -a gather_subset='!all' <hostname>
如果问题仍然没有解决,您可以尝试在游戏中完全禁用该模块,但问题很可能出在其他地方。
但是,如果它运行良好(并且快速),那么看看模块文档。您有两个选择:
- 将事实收集限制在一个子集内,排除不需要的内容(参见的可能值
gather_subset
) gather_timeout
也可以帮助你解决问题,通过提供更多的时间(虽然这是为了修复超时错误,而不是挂起)
其他事宜
显然,其他事情也可能出错。以下是一些有助于调试的提示:
- 使用 ansible 最大详细级别(
-vvvv
),因为它会显示执行的每个命令 - 如上所述,直接从命令行使用
ping
和模块setup
ansible -m ping
如果不起作用,请尝试手动 ssh
答案3
Ansible 可能会因多种原因而挂起,通常是由于连接问题或设置模块挂起。以下是如何缩小问题范围以便解决问题。
Ansible 无法连接到目标主机
主机密钥 (known_hosts) 问题
1) 在旧版本的 Ansible(2.1 或更早版本)中,Ansible 不会总是告诉您目标的主机密钥是否在源上不存在,或者是否存在不匹配。
解决方案:尝试使用相同的参数打开到该目标的 SSH 连接。您可能会发现需要解决的 SSH 错误,然后该命令就会起作用。
2) 有时 Ansible 会在其他状态中向您显示 SSH 连接消息,导致 Ansible 在该任务上“冻结”:
Warning: the ECDSA host key for 'myhost' differs from the key for the IP address '10.10.1.10'
Offending key for IP in /etc/ssh/ssh_known_hosts:246
Matching host key in /etc/ssh/ssh_known_hosts:477
Are you sure you want to continue connecting (yes/no)?
在这种情况下,只需对所询问的所有 SSH 问题都输入“yes”即可继续播放。之后,您可以修复 root known_hosts 问题。
私钥认证问题
如果使用基于密钥的身份验证而不是密码,其他问题包括:
- 目的地可能未正确设置私钥
- 私钥可能在本地具有不正确的权限(只有运行 Ansible 作业的用户才能读取)
解决方案:尝试ansible -m ping <destination> -k
针对问题主机运行 - 如果不起作用,请尝试主机密钥问题上述解决方案。
Ansible 无法快速收集事实
该setup
模块(在运行开始时自动运行ansible-playbook
或手动运行时ansible -m setup <host>
)在收集硬件事实时通常会挂起(例如,如果从具有高 i/o、坏挂载条目等的主机获取磁盘信息)。
解决方案:尝试运行ansible -m setup -a gather_subset=!all <destination>
。如果可行,您应该考虑在 ansible.cfg 中设置此行:
gather_subset=!hardware
答案4
我在 Gathering Facts 中遇到了类似的 Ansible 挂起问题。我将脚本缩减为没有任务或角色的提示,但它仍然挂起。
我在我的进程列表中发现了一天内积累的 12 个挂起的 ansible 进程。
/usr/bin/python /tmp/ansible_Jfv4PA/ansible_module_setup.py
/usr/bin/python /tmp/ansible_M2T10L/ansible_module_setup.py
一旦我杀死它们,它就会再次开始工作。