我想使用Ansible在多个远程节点上同时执行一个简单的作业。实际工作涉及点击一些日志文件,然后在我的本地主机(其远程节点上没有软件)上对结果进行后处理。
命令行ansible工具似乎不太适合这种用例,因为它们将ansible生成的格式与远程执行的命令的输出混合在一起。 Python API似乎应该能够做到这一点,因为它暴露了未经修改的输出(除了一些潜在的unicode修改,这里不应该相关)。
我提出的Python程序的简化版本如下:
from sys import argv
import ansible.runner
runner = ansible.runner.Runner(
pattern='*', forks=10,
module_name="command",
module_args=(
"""
sleep 10
"""),
inventory=ansible.inventory.Inventory(argv[1]),
)
results = runner.run()
这里,sleep 10
代表实际的日志grepping命令 - 这个想法就是模拟一个不会立即完成的命令。
但是,运行此操作后,我发现所花费的时间似乎与我的广告资源中的主机数量成正比。以下是分别针对2,5和9主机的库存的时间结果:
exarkun@top:/tmp$ time python howlong.py two-hosts.inventory
real 0m24.285s
user 0m0.216s
sys 0m0.120s
exarkun@top:/tmp$ time python howlong.py five-hosts.inventory
real 0m55.120s
user 0m0.224s
sys 0m0.160s
exarkun@top:/tmp$ time python howlong.py nine-hosts.inventory
real 1m57.272s
user 0m0.360s
sys 0m0.284s
exarkun@top:/tmp$
其他一些随机观察:
ansible all --forks=10 -i five-hosts.inventory -m command -a "sleep 10"
表现出相同的行为ansible all -c local --forks=10 -i five-hosts.inventory -m command -a "sleep 10"
似乎同时执行某些事情(但当然只适用于本地连接)ansible all -c paramiko --forks=10 -i five-hosts.inventory -m command -a "sleep 10"
似乎同时执行任务也许这表明问题出在ssh传输上,与通过Python API而不是命令行使用ansible无关。
这里有什么不对,无论我的广告资源中的主机数量是多少,都会阻止默认传输只需大约十秒钟?
答案 0 :(得分:5)
一些调查显示,ansible正在〜/ .ssh / known_hosts中查找我的库存中的主机。我的配置启用了HashKnownHosts。 ansible无法找到它正在寻找的主机条目,因为它不了解哈希已知的主机条目格式。
每当ansible的ssh传输无法找到已知的hosts条目时,它就会在模块执行期间获取全局锁。这种融合的结果是所有执行都是有效序列化的。
通过将host_key_checking = False
放入~/.ansible.cfg
,临时解决方法是放弃一些安全性并禁用主机密钥检查。另一个解决方法是使用paramiko传输(但由于某些原因,这速度非常慢,可能比ssh传输慢几十或几百倍)。另一种解决方法是将一些未散列的条目添加到known_hosts文件中,以便找到ansible的ssh传输。
答案 1 :(得分:3)
由于您启用了HashKnownHosts,因此应升级到最新版本的Ansible。版本1.3添加了对散列known_hosts
的支持,请参阅the bug tracker和changelog。这应该可以在不影响安全性的情况下解决您的问题(使用host_key_checking=False
解决方法)或牺牲速度(使用paramiko解决方法)。
答案 2 :(得分:0)
使用Ansible 2.0 Python API,我用
关闭了StrictHostKeyChecking/etc/ssh/sshd_config
----
UseDNS no
通过在托管计算机上设置以下内容,我设法大大加快了Ansible的速度。我认为较新的sshd具有相反的默认值,因此在您的情况下可能不需要。
namespace App\Http\Controllers;
use App\taxonomy;
use Illuminate\Http\Request;
class newPostController extends Controller {
public function submitArticle(Request $request){
$name = $request->all();
return $name;
}