debugging 如何调试Ansible问题?

bxfogqkk  于 2023-01-21  发布在  其他
关注(0)|答案(7)|浏览(164)

有时候,ansible并不能满足你的需求。增加冗长也无济于事。例如,我现在正在尝试启动coturn服务器,它在systemd操作系统(Debian杰西)上附带了init脚本。Ansible认为它正在运行,但实际上它并没有运行。我该如何查看引擎盖下发生了什么?执行了哪些命令,输出/退出代码是什么?

hs1rzwqc

hs1rzwqc1#

调试模块

  • 最基本的方法是通过将-vvv添加到执行行来以更高的详细级别运行ansible/ansible-playbook
  • 对于用Python(Linux/Unix)编写的模块,最彻底的方法是运行ansible/ansible-playbook,并将环境变量ANSIBLE_KEEP_REMOTE_FILES设置为1(在控制机器上)。

这会导致Ansible在目标机器上保留它执行的Python脚本的精确副本(无论成功与否)。
脚本的路径打印在Ansible日志中,对于常规任务,它们存储在SSH用户的主目录下:~/.ansible/tmp/.
确切的逻辑嵌入在脚本中,并取决于每个模块。有些使用带有标准或外部库的Python,有些调用外部命令。
调试行动手册

  • 与调试模块类似,使用-vvv参数增加详细级别会导致更多数据打印到Ansible日志
  • 自Ansible 2.1以来,Playbook Debugger允许调试交互失败的任务:检查、修改数据;重新运行任务。

调试连接

  • -vvvv参数添加到ansible/ansible-playbook调用会使日志包含连接的调试信息。
r7xajy2e

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工具。

k4ymrczo

k4ymrczo3#

这是我想到的。
Ansible将模块发送到目标系统并在那里执行。因此,如果您在本地更改模块,您的更改将在运行剧本时生效。在我的计算机上,模块位于/usr/lib/python2.7/site-packages/ansible/modulesansible-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日志中看到一些调试输出,至少可以看到调用消息和错误消息(如果有的话)。
还有一件事,如果你尝试调试本地运行的pdbimport pdb; pdb.set_trace())代码,你很可能会遇到BdbQuit异常。这是因为python在创建线程(ansible工作线程)时关闭了stdin。这里的解决方案是在运行pdb.set_trace()之前重新打开stdin,如建议here

sys.stdin = open('/dev/tty')
import pdb; pdb.set_trace()
6qfn3psc

6qfn3psc4#

调试角色/行动手册

基本上,在大型网络上调试大型库存的可靠自动化就是调试分布式网络应用程序,它可能非常繁琐和微妙,而且没有足够的用户友好工具。
因此,我相信你的问题的答案也是我之前所有答案的并集+小加法,所以这里:

  • 绝对强制性:您必须想知道正在发生什么,即您正在自动化什么,您预期会发生什么。例如,ansible无法检测到systemd单元正在运行或已停止的服务通常意味着服务单元文件或服务模块中存在错误,因此您需要1.识别错误,2.向供应商/社区报告错误,3.为您的解决方案提供TODO并链接到错误。4.修复错误后-删除您的解决方案
  • 为了使代码更易于调试,请尽可能多地使用模块
  • 给予所有任务和变量起一个有意义的名字。
  • 使用像ansible-lint这样的静态代码分析工具,这样可以避免一些愚蠢的小错误。
  • 使用详细标志和日志路径
  • 明智使用debug模块
  • “了解你的事实”-有时将目标机器的事实转储到文件中并将其拉到ansible master是有用的
  • 在某些情况下,使用strategy: debug可能会遇到任务调试器出错的情况。然后,您可以评估任务正在使用的所有参数,并决定下一步要做什么
  • 最后一种方法是使用Python调试器,将其附加到本地ansible run和/或执行模块的远程Python。这通常很棘手:您需要允许计算机上的其他端口打开,打开端口的代码是否是导致问题的代码?

此外,有时候“旁观”也很有用--连接到目标主机并提高它们的可调试性(更详细的日志记录)
当然,日志收集使跟踪由于不可预知的操作而发生的更改变得更容易。
正如您所看到的,像任何其他分布式应用程序和框架一样,调试能力仍然不如我们所希望的那样。

过滤器/插件

这基本上是Python开发,调试与任何Python应用程序一样

模块

根据技术的不同,并且由于您需要同时查看本地和远程发生的情况而变得复杂,因此您最好选择易于远程调试的语言。

ymzxtsji

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

92dk7w1h

92dk7w1h6#

您可能需要多个级别的调试,但最简单的一个级别是添加ANSIBLE_STRATEGY=debug环境变量,该变量将在出现第一个错误时启用调试器。

gmol1639

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)。

相关问题