Ansible 简介
Ansible 是由 Python 开发的一个运维工具,因为工作需要接触到 Ansible,经常会集成一些东西到 Ansible,所以对 Ansible 的了解越来越多。 那 Ansible 到底是什么呢?在我的理解中,原来需要登录到服务器上,然后执行一堆命令才能完成一些操作。而 Ansible 就是来代替我们去执行那些命令。并且可以通过 Ansible 控制多台机器,在机器上进行任务的编排和执行,在 Ansible 中称为 playbook。 那 Ansible 是如何做到的呢?简单点说,就是 Ansible 将我们要执行的命令生成一个脚本,然后通过 sftp 将脚本上传到要执行命令的服务器上,然后在通过 ssh 协议,执行这个脚本并将执行结果返回。 那 Ansible 具体是怎么做到的呢?下面从模块和插件来看一下 Ansible 是如何完成一个模块的执行 PS:下面的分析都是在对 Ansible 有一些具体使用经验之后,通过阅读源代码进一步得出的执行结论,所以希望在看本文时,是建立在对 Ansible 有一定了解的基础上,最起码对于 Ansible 的一些概念有了解,例如 inventory,module,playbooks 等
Ansible 模块
模块是 Ansible 执行的最小单位,可以是由 Python 编写,也可以是 Shell 编写,也可以是由其他语言编写。模块中定义了具体的操作步骤以及实际使用过程中所需要的参数 执行的脚本就是根据模块生成一个可执行的脚本。 那 Ansible 是怎么样将这个脚本上传到服务器上,然后执行获取结果的呢?
Ansible 插件
connection 插件
连接插件,根据指定的 ssh 参数连接指定的服务器,并切提供实际执行命令的接口
shell 插件
命令插件,根据 sh 类型,来生成用于 connection 时要执行的命令
strategy 插件
执行策略插件,默认情况下是线性插件,就是一个任务接着一个任务的向下执行,此插件将任务丢到执行器去执行。
action 插件
动作插件,实质就是任务模块的所有动作,如果 ansible 的模块没有特别编写的 action 插件,默认情况下是 normal 或者 async(这两个根据模块是否 async 来选择),normal 和 async 中定义的就是模块的执行步骤。例如,本地创建临时文件,上传临时文件,执行脚本,删除脚本等等,如果想在所有的模块中增加一些特殊步骤,可以通过增加 action 插件的方式来扩展。
Ansible 执行模块流程
- ansible 命令实质是通过 ansible/cli/adhoc.py 来运行,同时会收集参数信息
- 设置 Play 信息,然后通过 TaskQueueManager 进行 run,
- TaskQueueManager 需要 Inventory (节点仓库),variable_manager (收集变量),options (命令行中指定的参数),stdout_callback (回调函数)
- 在 task_queue_manager.py 中找到 run 中
- 初始化时会设置队列
- 会根据 options,,variable_manager,passwords 等信息设置成一个 PlayContext 信息 (playbooks/playcontext.py)
- 设置插件 (plugins) 信息 callback_loader (回调), strategy_loader (执行策略), module_loader (任务模块)
- 通过 strategy_loader(strategy 插件)的 run(默认的 strategy 类型是 linear,线性执行),去按照顺序执行所有的任务(执行一个模块,可能会执行多个任务)
- 在 strategy_loader 插件 run 之后,会判断 action 类型。如果是 meta 类型的话会单独执行 (不是具体的 ansible 模块时),而其他模块时,会加载到队列_queue_task
- 在队列中会调用 WorkerProcess 去处理,在 workerproces 实际的 run 之后,会使用 TaskExecutor 进行执行
- 在 TaskExecutor 中会设置 connection 插件,并且根据 task 的类型(模块。或是 include 等)获取 action 插件,就是对应的模块,如果模块有自定义的执行,则会执行自定义的 action,如果没有的会使用 normal 或者 async,这个是根据是否是任务的 async 属性来决定
- 在 Action 插件中定义着执行的顺序,及具体操作,例如生成临时目录,生成临时脚本,所以要在统一的模式下,集成一些额外的处理时,可以重写 Action 的方法
- 通过 Connection 插件来执行 Action 的各个操作步骤
扩展 Ansible 实例
执行节点 Python 环境扩展
实际需求中,我们扩展的一些 Ansible 模块需要使用三方库,但每个节点中安装这些库有些不易于管理。ansible 执行模块的实质就是在节点的 python 环境下执行生成的脚本,所以我们采取的方案是,指定节点上的 Python 环境,将局域网内一个 python 环境作为 nfs 共享。通过扩展 Action 插件,增加节点上挂载 nfs,待执行结束后再将节点上的 nfs 卸载。具体实施步骤如下: 扩展代码:
重写 ActionBase 的 execute_module 方法
1 |
# execute_module |
集成到 normal.py 和 async.py 中,记住要将这两个插件在 ansible.cfg 中进行配置
1 |
from __future__ import (absolute_import, division, print_function) |
- 配置 ansible.cfg,将扩展的插件指定为 ansible 需要的 action 插件
- 重写插件方法,重点是 execute_module
- 执行命令中需要指定 Python 环境,将需要的参数添加进去 nfs 挂载和卸载的参数
1 |
ansible 51 -m mysql_db -a "state=dump name=all target=/tmp/test.sql" -i hosts -u root -v -e "ansible_nfs_src=172.16.30.170:/web/proxy_env/lib64/python2.7/site-packages ansible_nfs_dest=/root/.pyenv/versions/2.7.10/lib/python2.7/site-packages ansible_python_interpreter=/root/.pyenv/versions/2.7.10/bin/python" |
来源:https://cuiqingcai.com/4989.html