跳转至

Ansible 开发

官方开发文档

http://docs.ansible.com/ansible/dev_guide/index.html

非常推荐大家看看 官方文档

环境

本次所用的环境

  • ansible 2.9.6.0

  • os Centos 7.7 X64

  • python 2.7.5

介绍

Ansible 开发分为两大模块,一是modules,二是plugins

首先,要记住这两部分内容在哪个地方执行?

  • modules 文件被传送到 远端主机 并执行。
  • plugins 是在 ansible控制节点 上执行的。

再者是执行顺序?

plugins 先于 modules 执行。

然后大家明确这两部分内容是干啥用的?

  • modules 是ansible的核心内容,它使playbook变得更加简单明了,一个task就是完成某一项功能。ansible模块是被传送到远程主机上运行的。所以它们可以用远程主机可以执行的任何语言编写modules。

  • plugins 是在 ansible控制节点 上执行的,用来辅助modules做一些操作。比如连接远程主机,拷贝文件到远程主机之类的。

最后,学习开发之前,要先学会Debug

Ad-hoc 执行过程

# ansible 192.168.77.130 -m ping -vvv
ansible 2.9.6
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 2.7.5 (default, Aug  7 2019, 00:51:29) [GCC 4.8.5 20150623 (Red Hat 4.8.5-39)]
Using /etc/ansible/ansible.cfg as config file
host_list declined parsing /etc/ansible/hosts as it did not pass its verify_file() method
script declined parsing /etc/ansible/hosts as it did not pass its verify_file() method
auto declined parsing /etc/ansible/hosts as it did not pass its verify_file() method
Parsed /etc/ansible/hosts inventory source with ini plugin
META: ran handlers
<192.168.77.130> ESTABLISH SSH CONNECTION FOR USER: root
<192.168.77.130> SSH: EXEC sshpass -d8 ssh -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o Port=22 -o 'User="root"' -o ConnectTimeout=10 -o ControlPath=/root/.ansible/cp/09e16ea432 192.168.77.130 '/bin/sh -c '"'"'echo ~root && sleep 0'"'"''
<192.168.77.130> (0, '/root\n', '')
<192.168.77.130> ESTABLISH SSH CONNECTION FOR USER: root
<192.168.77.130> SSH: EXEC sshpass -d8 ssh -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o Port=22 -o 'User="root"' -o ConnectTimeout=10 -o ControlPath=/root/.ansible/cp/09e16ea432 192.168.77.130 '/bin/sh -c '"'"'( umask 77 && mkdir -p "` echo /root/.ansible/tmp/ansible-tmp-1586615361.42-9030567083356 `" && echo ansible-tmp-1586615361.42-9030567083356="` echo /root/.ansible/tmp/ansible-tmp-1586615361.42-9030567083356 `" ) && sleep 0'"'"''
<192.168.77.130> (0, 'ansible-tmp-1586615361.42-9030567083356=/root/.ansible/tmp/ansible-tmp-1586615361.42-9030567083356\n', '')
<192.168.77.130> Attempting python interpreter discovery
<192.168.77.130> ESTABLISH SSH CONNECTION FOR USER: root
<192.168.77.130> SSH: EXEC sshpass -d8 ssh -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o Port=22 -o 'User="root"' -o ConnectTimeout=10 -o ControlPath=/root/.ansible/cp/09e16ea432 192.168.77.130 '/bin/sh -c '"'"'echo PLATFORM; uname; echo FOUND; command -v '"'"'"'"'"'"'"'"'/usr/bin/python'"'"'"'"'"'"'"'"'; command -v '"'"'"'"'"'"'"'"'python3.7'"'"'"'"'"'"'"'"'; command -v '"'"'"'"'"'"'"'"'python3.6'"'"'"'"'"'"'"'"'; command -v '"'"'"'"'"'"'"'"'python3.5'"'"'"'"'"'"'"'"'; command -v '"'"'"'"'"'"'"'"'python2.7'"'"'"'"'"'"'"'"'; command -v '"'"'"'"'"'"'"'"'python2.6'"'"'"'"'"'"'"'"'; command -v '"'"'"'"'"'"'"'"'/usr/libexec/platform-python'"'"'"'"'"'"'"'"'; command -v '"'"'"'"'"'"'"'"'/usr/bin/python3'"'"'"'"'"'"'"'"'; command -v '"'"'"'"'"'"'"'"'python'"'"'"'"'"'"'"'"'; echo ENDFOUND && sleep 0'"'"''
<192.168.77.130> (0, 'PLATFORM\nLinux\nFOUND\n/usr/bin/python\n/usr/bin/python2.7\n/usr/libexec/platform-python\n/usr/bin/python\nENDFOUND\n', '')
<192.168.77.130> ESTABLISH SSH CONNECTION FOR USER: root
<192.168.77.130> SSH: EXEC sshpass -d8 ssh -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o Port=22 -o 'User="root"' -o ConnectTimeout=10 -o ControlPath=/root/.ansible/cp/09e16ea432 192.168.77.130 '/bin/sh -c '"'"'/usr/bin/python && sleep 0'"'"''
<192.168.77.130> (0, '{"osrelease_content": "NAME=\\"CentOS Linux\\"\\nVERSION=\\"7 (Core)\\"\\nID=\\"centos\\"\\nID_LIKE=\\"rhel fedora\\"\\nVERSION_ID=\\"7\\"\\nPRETTY_NAME=\\"CentOS Linux 7 (Core)\\"\\nANSI_COLOR=\\"0;31\\"\\nCPE_NAME=\\"cpe:/o:centos:centos:7\\"\\nHOME_URL=\\"https://www.centos.org/\\"\\nBUG_REPORT_URL=\\"https://bugs.centos.org/\\"\\n\\nCENTOS_MANTISBT_PROJECT=\\"CentOS-7\\"\\nCENTOS_MANTISBT_PROJECT_VERSION=\\"7\\"\\nREDHAT_SUPPORT_PRODUCT=\\"centos\\"\\nREDHAT_SUPPORT_PRODUCT_VERSION=\\"7\\"\\n\\n", "platform_dist_result": ["centos", "7.4.1708", "Core"]}\n', '')
Using module file /usr/lib/python2.7/site-packages/ansible/modules/system/ping.py
<192.168.77.130> PUT /root/.ansible/tmp/ansible-local-50740hJgOb9/tmpp7Dy_u TO /root/.ansible/tmp/ansible-tmp-1586615361.42-9030567083356/AnsiballZ_ping.py
<192.168.77.130> SSH: EXEC sshpass -d8 sftp -o BatchMode=no -b - -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o Port=22 -o 'User="root"' -o ConnectTimeout=10 -o ControlPath=/root/.ansible/cp/09e16ea432 '[192.168.77.130]'
<192.168.77.130> (0, 'sftp> put /root/.ansible/tmp/ansible-local-50740hJgOb9/tmpp7Dy_u /root/.ansible/tmp/ansible-tmp-1586615361.42-9030567083356/AnsiballZ_ping.py\n', '')
<192.168.77.130> ESTABLISH SSH CONNECTION FOR USER: root
<192.168.77.130> SSH: EXEC sshpass -d8 ssh -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o Port=22 -o 'User="root"' -o ConnectTimeout=10 -o ControlPath=/root/.ansible/cp/09e16ea432 192.168.77.130 '/bin/sh -c '"'"'chmod u+x /root/.ansible/tmp/ansible-tmp-1586615361.42-9030567083356/ /root/.ansible/tmp/ansible-tmp-1586615361.42-9030567083356/AnsiballZ_ping.py && sleep 0'"'"''
<192.168.77.130> (0, '', '')
<192.168.77.130> ESTABLISH SSH CONNECTION FOR USER: root
<192.168.77.130> SSH: EXEC sshpass -d8 ssh -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o Port=22 -o 'User="root"' -o ConnectTimeout=10 -o ControlPath=/root/.ansible/cp/09e16ea432 -tt 192.168.77.130 '/bin/sh -c '"'"'/usr/bin/python /root/.ansible/tmp/ansible-tmp-1586615361.42-9030567083356/AnsiballZ_ping.py && sleep 0'"'"''
<192.168.77.130> (0, '\r\n{"invocation": {"module_args": {"data": "pong"}}, "ping": "pong"}\r\n', 'Shared connection to 192.168.77.130 closed.\r\n')
<192.168.77.130> ESTABLISH SSH CONNECTION FOR USER: root
<192.168.77.130> SSH: EXEC sshpass -d8 ssh -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o Port=22 -o 'User="root"' -o ConnectTimeout=10 -o ControlPath=/root/.ansible/cp/09e16ea432 192.168.77.130 '/bin/sh -c '"'"'rm -f -r /root/.ansible/tmp/ansible-tmp-1586615361.42-9030567083356/ > /dev/null 2>&1 && sleep 0'"'"''
<192.168.77.130> (0, '', '')
192.168.77.130 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "invocation": {
        "module_args": {
            "data": "pong"
        }
    }, 
    "ping": "pong"
}
META: ran handlers
META: ran handlers

首先,将模块文件读入内存,然后添加传递给模块的参数,最后将模块中所需要的类添加到内存,由zipfile压缩后,再由base64进行编码,写入到模版文件内。

通过默认的连接方式,一般是ssh。ansible通过ssh连接到远程主机,创建临时目录,并关闭连接。然后将打开另外一个ssh连接,将模版文件以sftp方式传送到刚刚创建的临时目录中,写完后关闭连接。然后打开一个ssh连接将任务对象赋予可执行权限,执行成功后关闭连接。

最后,ansible将打开第三个连接来执行模块,并删除临时目录及其所有内容。模块的结果是从标准输出stdout中获取json格式的字符串。ansible将解析和处理此字符串。如果有任务是异步控制执行的,ansible将在模块完成之前关闭第三个连接,并且返回主机后,在规定的时间内检查任务状态,直到模块完成或规定的时间超时。

Note

如果要深入了解执行过程,可以查看更详细的代码执行过程Ansible ad-hoc执行过程

使用了 管道连接 后,与远程主机只有一个连接,命令通过数据流的方式发送执行。

配置方式

vim /etc/ansible/ansible.cfg
pipelining = True

执行过程

# ansible 192.168.77.130 -m ping  -vvv
ansible 2.9.6
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 2.7.5 (default, Aug  7 2019, 00:51:29) [GCC 4.8.5 20150623 (Red Hat 4.8.5-39)]
Using /etc/ansible/ansible.cfg as config file
host_list declined parsing /etc/ansible/hosts as it did not pass its verify_file() method
script declined parsing /etc/ansible/hosts as it did not pass its verify_file() method
auto declined parsing /etc/ansible/hosts as it did not pass its verify_file() method
Parsed /etc/ansible/hosts inventory source with ini plugin
META: ran handlers
<192.168.77.130> Attempting python interpreter discovery
<192.168.77.130> ESTABLISH SSH CONNECTION FOR USER: root
<192.168.77.130> SSH: EXEC sshpass -d8 ssh -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o Port=22 -o 'User="root"' -o ConnectTimeout=10 -o ControlPath=/root/.ansible/cp/09e16ea432 192.168.77.130 '/bin/sh -c '"'"'echo PLATFORM; uname; echo FOUND; command -v '"'"'"'"'"'"'"'"'/usr/bin/python'"'"'"'"'"'"'"'"'; command -v '"'"'"'"'"'"'"'"'python3.7'"'"'"'"'"'"'"'"'; command -v '"'"'"'"'"'"'"'"'python3.6'"'"'"'"'"'"'"'"'; command -v '"'"'"'"'"'"'"'"'python3.5'"'"'"'"'"'"'"'"'; command -v '"'"'"'"'"'"'"'"'python2.7'"'"'"'"'"'"'"'"'; command -v '"'"'"'"'"'"'"'"'python2.6'"'"'"'"'"'"'"'"'; command -v '"'"'"'"'"'"'"'"'/usr/libexec/platform-python'"'"'"'"'"'"'"'"'; command -v '"'"'"'"'"'"'"'"'/usr/bin/python3'"'"'"'"'"'"'"'"'; command -v '"'"'"'"'"'"'"'"'python'"'"'"'"'"'"'"'"'; echo ENDFOUND && sleep 0'"'"''
<192.168.77.130> (0, 'PLATFORM\nLinux\nFOUND\n/usr/bin/python\n/usr/bin/python2.7\n/usr/libexec/platform-python\n/usr/bin/python\nENDFOUND\n', '')
<192.168.77.130> ESTABLISH SSH CONNECTION FOR USER: root
<192.168.77.130> SSH: EXEC sshpass -d8 ssh -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o Port=22 -o 'User="root"' -o ConnectTimeout=10 -o ControlPath=/root/.ansible/cp/09e16ea432 192.168.77.130 '/bin/sh -c '"'"'/usr/bin/python && sleep 0'"'"''
<192.168.77.130> (0, '{"osrelease_content": "NAME=\\"CentOS Linux\\"\\nVERSION=\\"7 (Core)\\"\\nID=\\"centos\\"\\nID_LIKE=\\"rhel fedora\\"\\nVERSION_ID=\\"7\\"\\nPRETTY_NAME=\\"CentOS Linux 7 (Core)\\"\\nANSI_COLOR=\\"0;31\\"\\nCPE_NAME=\\"cpe:/o:centos:centos:7\\"\\nHOME_URL=\\"https://www.centos.org/\\"\\nBUG_REPORT_URL=\\"https://bugs.centos.org/\\"\\n\\nCENTOS_MANTISBT_PROJECT=\\"CentOS-7\\"\\nCENTOS_MANTISBT_PROJECT_VERSION=\\"7\\"\\nREDHAT_SUPPORT_PRODUCT=\\"centos\\"\\nREDHAT_SUPPORT_PRODUCT_VERSION=\\"7\\"\\n\\n", "platform_dist_result": ["centos", "7.4.1708", "Core"]}\n', '')
Using module file /usr/lib/python2.7/site-packages/ansible/modules/system/ping.py
Pipelining is enabled.
<192.168.77.130> ESTABLISH SSH CONNECTION FOR USER: root
<192.168.77.130> SSH: EXEC sshpass -d8 ssh -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o Port=22 -o 'User="root"' -o ConnectTimeout=10 -o ControlPath=/root/.ansible/cp/09e16ea432 192.168.77.130 '/bin/sh -c '"'"'/usr/bin/python && sleep 0'"'"''
<192.168.77.130> (0, '\n{"invocation": {"module_args": {"data": "pong"}}, "ping": "pong"}\n', '')
192.168.77.130 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "invocation": {
        "module_args": {
            "data": "pong"
        }
    }, 
    "ping": "pong"
}
META: ran handlers
META: ran handlers

执行完后,会有一个ssh的管道, 下次连接远程主机时,会直接使用这个管道,而不必重新建立连接。

# ps aux | grep [a]nsible
root      50757  0.0  0.3 176416  3424 ?        Ss   22:29   0:00 ssh: /root/.ansible/cp/09e16ea432 [mux]

最后更新: 2020-12-03 08:40:01

评论