好久没更了。Ansible也算在微博搬砖接触比较多的东西,通过调用其api可以自定义批量配置下发通道,Ansible官方也有Ansible-Tower(然而没开源且付费)。国内少有人尝试api2.0,这里就稍微写一写。
调用Ansible的手段
- 通过命令
- 直接起新进程命令调用Ansible,也有不错的项目是这么做的:
Semaphore
,看了看代码,原理上其实是每次从一个git仓库克隆playbook到本地,然后把hosts写成tmp文件,直接起新进程调命令执行,即时日志输出通过绑定标准输出来取得。 - 这种方案语言无关,而且不大容易受api变动影响,个人也很推荐。(然而要写好多临时文件)
- 直接起新进程命令调用Ansible,也有不错的项目是这么做的:
- 通过API
- 通过api调用和命令调用的区别其实只是Playbook和Inventory的来源是否从文件读取。就算是调用api,每次依然都要走完整的初始化流程,且默认的日志要打在标准输出上。
- Ansible从1.x迁移到了2.x重构了大量代码,这也导致Api 1.x和2.x完全不一样,文档少的可怜,能参考的基本只有看代码。
下面说说方法二
调用流程
首先贴个官方文档,里面只有个最简单的demo: Ansible-api
因为某些蛋疼的缘故,把Ansible执行的关键代码走了一遍,大致说下api的执行流程:
-
准备,在执行前,需要初始化三个实例:
- Inventory: 相当于hosts文件,可包含多个ip或者ip-group,在这里指明连接方式( password或者ssh_key )
- VariableManager: 在这里配置Playbook中对应变量的值
- __ PlaySource__: 相当于Playbook文件,指定运行的任务,调用的role等等
-
连接并执行,通过Ansible的TaskQueueManager,默认调用其中的linear strategy执行
- 解释: 具体没研究,Playbook语法 => python源代码
- 打包: 解释后的python源代码,压缩成字符串,拼上Ansible的最小执行环境成一个py文件
- 连接: 根据-f参数或配置,fork多个进程调用ssh连接到目标机(ssh_key或密码),上传打包的代码,执行
- 执行(远端): 将压缩字符串解压写成多个py文件(对应命令),起新进程(popen())逐个执行,绑定输出到管道,一次性读取,通过ssh连接返回json格式数据
- 回报: 分发机接到json格式返回值并解析,打到标准输出(单步状态返回)
-
回报并清理,最后由TaskQueueManager清理资源 (fork出的多个连接进程)
其他注意事项
-
SSH连接: password OR private_key
- 密码登录省点事。private_key的话不支持从字符串读取,每个ip对应一个ssh文件,所以最后是写缓存文件解决。(顺带一提权限要给600)。
-
API调用线程不安全: not thread safe
- 之前说过,Ansible即使通过api调用,也要走一套完整的初始化流程,包括加载内置的各类plugin。
- 因为项目涉及批量配置下发,自然多线程调用Ansible成为首选,然而发现总是出现不明所以的报错,在多个Ansible线程同时启动时尤为明显,google之,发现问题所在:issue #13823
- 问题原因: 看源码的/ansible/plugins/init.py这里, 注意到第42行,有三个全局变量,这是Ansible的缓存,保存加载后的plugin。然而一个plugin在还必须执行init()方法才能初始化完成。 众所周知,多线程下共享全局变量,这样多线程竞争时,某个线程就会把未初始化完成的plugin当作初始化完成的使用,自然会报错。
- 【 解决方法: 既然竞争,干脆不共享算了,多进程算了.....
-
单个任务停止:
- 因为Ansible这东西的一个特性是幂等性,你中间强行杀掉铁定官方是不滋瓷的,所以要强行实现
- 起初的实现是,分发新任务时记下进程pid,停止时杀死此进程。 然而发现,远端机的执行并未停止....
- 问题原因: 调用Ansible的进程只是管理进程,真正建立连接执行的是子进程,杀死管理进程不仅停不掉远端任务,还会留下僵死进程消耗资源。
- 解决方法: 停止时先对Ansible管理进程发送SIGSTOP信号阻止进一步fork, 然后调用ps命令查询管理进程的子进程,逐个发送SIGKILL,最后杀死管理进程
总结
其实还有自定义callback和module可以写写,之后填坑吧(大概也不会填)
总之感觉Ansible这东西,大概最大的优点就是简单, 虽然名义上避免了agent, 但是写临时文件执行py代码其实也差不多。
国内文档也是少的就没有, 自己折腾一套踩了一堆坑, 好在最后是把东西做出来了。
不过折腾这两周, 学的东西大概还是不少, 希望之后能把混合云开源跟完吧。
(没了..)