有时候,ansible并不能满足你的需求。增加冗长也无济于事。例如,我现在正在尝试启动coturn服务器,它在systemd操作系统(Debian杰西)上附带了init脚本。Ansible认为它正在运行,但实际上它并没有运行。我该如何查看引擎盖下发生了什么?执行了哪些命令,输出/退出代码是什么?
ansible
coturn
systemd
hs1rzwqc1#
调试模块
-vvv
ansible-playbook
ANSIBLE_KEEP_REMOTE_FILES
1
这会导致Ansible在目标机器上保留它执行的Python脚本的精确副本(无论成功与否)。脚本的路径打印在Ansible日志中,对于常规任务,它们存储在SSH用户的主目录下:~/.ansible/tmp/.确切的逻辑嵌入在脚本中,并取决于每个模块。有些使用带有标准或外部库的Python,有些调用外部命令。调试行动手册
~/.ansible/tmp/
调试连接
-vvvv
r7xajy2e2#
如果任务不是你自己的,调试Ansible任务几乎是不可能的。与Ansible网站所说的相反。无需特殊的编码技能Ansible需要 * 高度专业化的编程 * 技能,因为它不是YAML或Python,而是两者的混乱混合。使用标记语言进行编程的想法以前就已经尝试过了,XML曾经在Java社区非常流行,XSLT也是一个很好的例子。随着Ansible项目的增长,复杂性也随之呈指数级增长。以OpenShift Ansible项目为例,该项目的任务如下:
- name: Create the master server certificate command: > {{ hostvars[openshift_ca_host]['first_master_client_binary'] }} adm ca create-server-cert {% for named_ca_certificate in openshift.master.named_certificates | default([]) | lib_utils_oo_collect('cafile') %} --certificate-authority {{ named_ca_certificate }} {% endfor %} {% for legacy_ca_certificate in g_master_legacy_ca_result.files | default([]) | lib_utils_oo_collect('path') %} --certificate-authority {{ legacy_ca_certificate }} {% endfor %} --hostnames={{ hostvars[item].openshift.common.all_hostnames | join(',') }} --cert={{ openshift_generated_configs_dir }}/master-{{ hostvars[item].openshift.common.hostname }}/master.server.crt --key={{ openshift_generated_configs_dir }}/master-{{ hostvars[item].openshift.common.hostname }}/master.server.key --expire-days={{ openshift_master_cert_expire_days }} --signer-cert={{ openshift_ca_cert }} --signer-key={{ openshift_ca_key }} --signer-serial={{ openshift_ca_serial }} --overwrite=false when: item != openshift_ca_host with_items: "{{ hostvars | lib_utils_oo_select_keys(groups['oo_masters_to_config']) | lib_utils_oo_collect(attribute='inventory_hostname', filters={'master_certs_missing':True}) }}" delegate_to: "{{ openshift_ca_host }}" run_once: true
我想我们都同意这是用YAML编程。不是一个好主意。这个特定的代码片段可能会失败,并显示如下消息致命错误:[主0]:失败!=〉{“消息”:“条件检查'item!= openshift_ca_host'失败。错误为:计算条件时出错(项目!= openshift_ca_host):未定义“item”\n\n错误可能出现在“/home/user/openshift-ansible/roles/openshift_master_certificates/tasks/main. yml”中:第39行,第3列,但可能\n位于文件的其他位置,具体取决于语法问题。\n\n出错行可能是:\n\n\n- name:在\n ^此处\n”}创建主服务器证书如果你点击了这样的消息,你就完了。但是我们有调试器,对吗?好的,让我们看看是怎么回事。
master0] TASK: openshift_master_certificates : Create the master server certificate (debug)> p task.args {u'_raw_params': u"{{ hostvars[openshift_ca_host]['first_master_client_binary'] }} adm ca create-server-cert {% for named_ca_certificate in openshift.master.named_certificates | default([]) | lib_utils_oo_collect('cafile') %} --certificate-authority {{ named_ca_certificate }} {% endfor %} {% for legacy_ca_certificate in g_master_legacy_ca_result.files | default([]) | lib_utils_oo_collect('path') %} --certificate-authority {{ legacy_ca_certificate }} {% endfor %} --hostnames={{ hostvars[item].openshift.common.all_hostnames | join(',') }} --cert={{ openshift_generated_configs_dir }}/master-{{ hostvars[item].openshift.common.hostname }}/master.server.crt --key={{ openshift_generated_configs_dir }}/master-{{ hostvars[item].openshift.common.hostname }}/master.server.key --expire-days={{ openshift_master_cert_expire_days }} --signer-cert={{ openshift_ca_cert }} --signer-key={{ openshift_ca_key }} --signer-serial={{ openshift_ca_serial }} --overwrite=false"} [master0] TASK: openshift_master_certificates : Create the master server certificate (debug)> exit
有什么用?没有用。这里的重点是,使用YAML作为编程语言是一个非常糟糕的主意。它是一个烂摊子。我们正在制造的烂摊子的症状无处不在。一些额外的事实。Openshift Ansible在Azure上提供先决条件阶段需要+50分钟。部署阶段需要+70分钟。每次!第一次运行或后续运行。而且没有办法限制提供给单个节点。这个limit问题在2012年是Ansible的一部分,今天仍然是Ansible的一部分。这个事实告诉我们一些事情。这里的重点是Ansible应该按预期使用。用于没有YAML编程的简单任务。对于大量服务器很好,但不应该用于复杂的配置管理任务。Ansible不是基础设施即代码(IaC)工具。如果你问如何调试Ansible问题,你是在以一种不应该使用它的方式使用它,不要把它当作IaC工具。
limit
k4ymrczo3#
这是我想到的。Ansible将模块发送到目标系统并在那里执行。因此,如果您在本地更改模块,您的更改将在运行剧本时生效。在我的计算机上,模块位于/usr/lib/python2.7/site-packages/ansible/modules(ansible-2.1.2.0)。并且service模块位于core/system/service.py。(在module_utils/basic.py处声明的AnsibleModule类的示例)具有log方法,该方法将消息发送到systemd journal(如果可用)或福尔斯退到syslog。因此,在目标系统上运行journalctl -f,添加调试语句(module.log(msg='test'))到本地模块,然后运行剧本。你会在ansible-basic.py单元名称下看到调试语句。此外,当您使用-vvv运行ansible-playbook时,您可以在systemd日志中看到一些调试输出,至少可以看到调用消息和错误消息(如果有的话)。还有一件事,如果你尝试调试本地运行的pdb(import pdb; pdb.set_trace())代码,你很可能会遇到BdbQuit异常。这是因为python在创建线程(ansible工作线程)时关闭了stdin。这里的解决方案是在运行pdb.set_trace()之前重新打开stdin,如建议here:
/usr/lib/python2.7/site-packages/ansible/modules
ansible-2.1.2.0
service
core/system/service.py
module_utils/basic.py
AnsibleModule
log
syslog
journalctl -f
module.log(msg='test')
ansible-basic.py
pdb
import pdb; pdb.set_trace()
BdbQuit
python
stdin
pdb.set_trace()
sys.stdin = open('/dev/tty') import pdb; pdb.set_trace()
6qfn3psc4#
调试角色/行动手册
基本上,在大型网络上调试大型库存的可靠自动化就是调试分布式网络应用程序,它可能非常繁琐和微妙,而且没有足够的用户友好工具。因此,我相信你的问题的答案也是我之前所有答案的并集+小加法,所以这里:
ansible-lint
debug
strategy: debug
此外,有时候“旁观”也很有用--连接到目标主机并提高它们的可调试性(更详细的日志记录)当然,日志收集使跟踪由于不可预知的操作而发生的更改变得更容易。正如您所看到的,像任何其他分布式应用程序和框架一样,调试能力仍然不如我们所希望的那样。
过滤器/插件
这基本上是Python开发,调试与任何Python应用程序一样
模块
根据技术的不同,并且由于您需要同时查看本地和远程发生的情况而变得复杂,因此您最好选择易于远程调试的语言。
ymzxtsji5#
您可以使用register模块和debug模块来打印返回值。例如,我想知道我的脚本执行“www.example.com“的返回代码是什么somescript.sh,所以我将在播放中有我的任务,如:
- name: my task shell: "bash somescript.sh" register: output - debug: msg: "{{ output.rc }}"
要获取Ansible中可以访问的完整返回值,您可以查看此页面:http://docs.ansible.com/ansible/latest/common_return_values.html
92dk7w1h6#
您可能需要多个级别的调试,但最简单的一个级别是添加ANSIBLE_STRATEGY=debug环境变量,该变量将在出现第一个错误时启用调试器。
ANSIBLE_STRATEGY=debug
gmol16397#
第一种方法:通过q模块调试Ansible模块,并通过q模块将调试日志打印为q('Debug statement')。请检查q模块页面,以检查在大多数情况下,日志将在tmp目录中的何处生成:$TMPDIR\q或\tmp\q,因此可以执行tail -f $TMPDIR\q来检查Ansible模块运行后生成的日志(参考:q module)。第二种方法:如果播放在localhost上运行,则可以使用pdb模块调试播放,如下所示:https://docs.ansible.com/ansible/latest/dev_guide/debugging.html第三种方法:使用Ansible debug模块打印播放结果并调试模块(参考:Debug module)。
q
q('Debug statement')
tmp
$TMPDIR\q
\tmp\q
tail -f $TMPDIR\q
localhost
7条答案
按热度按时间hs1rzwqc1#
调试模块
-vvv
添加到执行行来以更高的详细级别运行ansible
/ansible-playbook
。ansible
/ansible-playbook
,并将环境变量ANSIBLE_KEEP_REMOTE_FILES
设置为1
(在控制机器上)。这会导致Ansible在目标机器上保留它执行的Python脚本的精确副本(无论成功与否)。
脚本的路径打印在Ansible日志中,对于常规任务,它们存储在SSH用户的主目录下:
~/.ansible/tmp/
.确切的逻辑嵌入在脚本中,并取决于每个模块。有些使用带有标准或外部库的Python,有些调用外部命令。
调试行动手册
-vvv
参数增加详细级别会导致更多数据打印到Ansible日志调试连接
-vvvv
参数添加到ansible
/ansible-playbook
调用会使日志包含连接的调试信息。r7xajy2e2#
如果任务不是你自己的,调试Ansible任务几乎是不可能的。与Ansible网站所说的相反。
无需特殊的编码技能
Ansible需要 * 高度专业化的编程 * 技能,因为它不是YAML或Python,而是两者的混乱混合。
使用标记语言进行编程的想法以前就已经尝试过了,XML曾经在Java社区非常流行,XSLT也是一个很好的例子。
随着Ansible项目的增长,复杂性也随之呈指数级增长。以OpenShift Ansible项目为例,该项目的任务如下:
我想我们都同意这是用YAML编程。不是一个好主意。这个特定的代码片段可能会失败,并显示如下消息
致命错误:[主0]:失败!=〉{“消息”:“条件检查'item!= openshift_ca_host'失败。错误为:计算条件时出错(项目!= openshift_ca_host):未定义“item”\n\n错误可能出现在“/home/user/openshift-ansible/roles/openshift_master_certificates/tasks/main. yml”中:第39行,第3列,但可能\n位于文件的其他位置,具体取决于语法问题。\n\n出错行可能是:\n\n\n- name:在\n ^此处\n”}创建主服务器证书
如果你点击了这样的消息,你就完了。但是我们有调试器,对吗?好的,让我们看看是怎么回事。
有什么用?没有用。
这里的重点是,使用YAML作为编程语言是一个非常糟糕的主意。它是一个烂摊子。我们正在制造的烂摊子的症状无处不在。
一些额外的事实。Openshift Ansible在Azure上提供先决条件阶段需要+50分钟。部署阶段需要+70分钟。每次!第一次运行或后续运行。而且没有办法限制提供给单个节点。这个
limit
问题在2012年是Ansible的一部分,今天仍然是Ansible的一部分。这个事实告诉我们一些事情。这里的重点是Ansible应该按预期使用。用于没有YAML编程的简单任务。对于大量服务器很好,但不应该用于复杂的配置管理任务。
Ansible不是基础设施即代码(IaC)工具。
如果你问如何调试Ansible问题,你是在以一种不应该使用它的方式使用它,不要把它当作IaC工具。
k4ymrczo3#
这是我想到的。
Ansible将模块发送到目标系统并在那里执行。因此,如果您在本地更改模块,您的更改将在运行剧本时生效。在我的计算机上,模块位于
/usr/lib/python2.7/site-packages/ansible/modules
(ansible-2.1.2.0
)。并且service
模块位于core/system/service.py
。(在module_utils/basic.py
处声明的AnsibleModule
类的示例)具有log
方法,该方法将消息发送到systemd journal(如果可用)或福尔斯退到syslog
。因此,在目标系统上运行journalctl -f
,添加调试语句(module.log(msg='test')
)到本地模块,然后运行剧本。你会在ansible-basic.py
单元名称下看到调试语句。此外,当您使用
-vvv
运行ansible-playbook
时,您可以在systemd
日志中看到一些调试输出,至少可以看到调用消息和错误消息(如果有的话)。还有一件事,如果你尝试调试本地运行的
pdb
(import pdb; pdb.set_trace()
)代码,你很可能会遇到BdbQuit
异常。这是因为python
在创建线程(ansible
工作线程)时关闭了stdin
。这里的解决方案是在运行pdb.set_trace()
之前重新打开stdin
,如建议here:6qfn3psc4#
调试角色/行动手册
基本上,在大型网络上调试大型库存的可靠自动化就是调试分布式网络应用程序,它可能非常繁琐和微妙,而且没有足够的用户友好工具。
因此,我相信你的问题的答案也是我之前所有答案的并集+小加法,所以这里:
ansible-lint
这样的静态代码分析工具,这样可以避免一些愚蠢的小错误。debug
模块strategy: debug
可能会遇到任务调试器出错的情况。然后,您可以评估任务正在使用的所有参数,并决定下一步要做什么此外,有时候“旁观”也很有用--连接到目标主机并提高它们的可调试性(更详细的日志记录)
当然,日志收集使跟踪由于不可预知的操作而发生的更改变得更容易。
正如您所看到的,像任何其他分布式应用程序和框架一样,调试能力仍然不如我们所希望的那样。
过滤器/插件
这基本上是Python开发,调试与任何Python应用程序一样
模块
根据技术的不同,并且由于您需要同时查看本地和远程发生的情况而变得复杂,因此您最好选择易于远程调试的语言。
ymzxtsji5#
您可以使用register模块和debug模块来打印返回值。例如,我想知道我的脚本执行“www.example.com“的返回代码是什么somescript.sh,所以我将在播放中有我的任务,如:
要获取Ansible中可以访问的完整返回值,您可以查看此页面:http://docs.ansible.com/ansible/latest/common_return_values.html
92dk7w1h6#
您可能需要多个级别的调试,但最简单的一个级别是添加
ANSIBLE_STRATEGY=debug
环境变量,该变量将在出现第一个错误时启用调试器。gmol16397#
第一种方法:通过
q
模块调试Ansible模块,并通过q
模块将调试日志打印为q('Debug statement')
。请检查q
模块页面,以检查在大多数情况下,日志将在tmp
目录中的何处生成:$TMPDIR\q
或\tmp\q
,因此可以执行tail -f $TMPDIR\q
来检查Ansible模块运行后生成的日志(参考:q module)。第二种方法:如果播放在
localhost
上运行,则可以使用pdb
模块调试播放,如下所示:https://docs.ansible.com/ansible/latest/dev_guide/debugging.html第三种方法:使用Ansible
debug
模块打印播放结果并调试模块(参考:Debug module)。