Ansible剧本的6个排查技巧

译文
开发 前端
本文介绍的六个方法可供您在运行Ansible脚本时检查问题。Ansible是一种功能很强大的工具,可以跨服务器、云、网络和容器等更多系统自动化管理各种平台。

[[407898]]

【51CTO.com快译】Ansible是一种功能很强大的工具,可以跨服务器、云、网络和容器等更多系统自动化管理各种平台。

您常常只需重用现有的角色和集合,就可以自动执行想要完成的操作。还有许多模块可供选择,可以在剧本中使用它们。

但是当您开始开发和测试更复杂的剧本时,最终需要一些故障排查方法。比如检查Ansible任务流、确认变量的数据类型,甚至在某个特定点暂停以检查它们的值。

本文讨论的一些技巧仅适用于通过命令行执行Ansible。其他技巧从Ansible Tower运行时也适用。

1. 你的Ansible环境和参数

如果您需要分析为什么某内容在剧本中没有按预期运行,最好先检查您的Ansible环境。

您在运行Ansible二进制文件和Python的哪些版本和路径?

如果您添加了剧本所需的操作系统包或Python模块,Ansible解释器会“看到”它们吗?

可以通过多种不同的方式获取这些基本信息。从命令行运行ansible --version命令。

  1. > ansible --version 
  2.  
  3. ansible 2.9.10 
  4.  
  5.   config file = /etc/ansible/ansible.cfg 
  6.   configured module search path = ['/home/admin/.ansible/plugins/modules''/usr/share/ansible/plugins/modules'
  7.   
  8.  ansible python module location = /usr/lib/python3.6/site-packages/ansible 
  9.   executable location = /usr/bin/ansible 
  10.   python version = 3.6.8 (default, Mar 18 2021, 08:58:41) [GCC 8.4.1 20200928 (Red Hat 8.4.1-1)] 

可以通过运行其他Ansible命令来获取同样的信息,比如使用--version选项的ansible-playbook或ansible-config。

在Ansible Tower中,如果使用VERBOSITY 2(更详细)或更高版本执行作业模板,可显示该信息。

除了Ansible和Python二进制文件的版本和位置之外,仔细检查用于模块的路径总是好事,包括执行是否使用了不是默认的ansible.cfg文件(即不是/etc/ansible /ansible.cfg)。

要调查来自自定义ansible.cfg文件的选项,可以从命令行执行以下操作:

  1. > ansible-config dump --only-changed 
  2. DEFAULT_BECOME(/home/admin/ansible/ansible.cfg) = True 
  3. DEFAULT_BECOME_USER(/home/admin/ansible/ansible.cfg) = root 
  4. DEFAULT_FORKS(/home/admin/ansible/ansible.cfg) = 10 
  5. DEFAULT_HOST_LIST(/home/admin/ansible/ansible.cfg) = ['/home/admin/ansible/inventory'
  6. DEFAULT_ROLES_PATH(/home/admin/ansible/ansible.cfg) = ['/home/admin/ansible/roles'
  7. HOST_KEY_CHECKING(/home/admin/ansible/ansible.cfg) = False 

顾名思义,这将列出与默认参数不同的参数。

2. 以详细模式运行

下一步是在调试模式下运行剧本,以获取有关任务和变量中所发生情况的更多详细信息。

您可以从命令行添加-v(或-vv、-vvv、-vvvv、-vvvvv)。最高的详细级别有时可能含有太多信息,因此最好在多次执行中逐渐增加详细级别,直至获得所需信息。

排查连接问题时级别4有所帮助,级别5适用于排查WinRM问题。

在Tower中,您可以从作业模板定义中选择VERBOSITY级别。

注意:记得在解决问题后禁用调试模式,因为详细信息仅对排查故障有用。

此外,在调试模式下,除非您在任务中使用no_log选项,否则会显示某些变量(比如密码)的值,因此完成后删除输出。

3.使用调试来显示变量

如果您很清楚问题可能出在哪里,可以使用更精准的方法:仅显示您需要查看的变量。

  1.  (...) 
  2.   - name: Display the value of the counter 
  3.      debug: 
  4.       msg: "Counter={{ counter }} / Data type={{ counter | type_debug }}" 
  5. (...) 
  6. TASK [Display the value of the counter]  
  7. *************************************************************************** 
  8. ok: [node1] => { 
  9.     "msg""Counter=42 / Data type=AnsibleUnicode" 

这就是为什么我无法加大计数。过滤器type_debug显示,数据类型是text,而不是我以为的int。

4. 确保变量有合适的内容和数据类型

可以使用assert模块来确认:变量有预期的内容/类型,如果出了岔子,就促使任务失败。

下列剧本表明了这点:

  1. --- 
  2. name: Assert examples 
  3.   hosts: node1 
  4.   gather_facts: no 
  5.   vars: 
  6.     var01: 13 
  7.   tasks: 
  8.   - debug: 
  9.       msg: "Parameter 01 is {{ (param01 | type_debug) }}" 
  10.   - name: Make sure that we have the right type of content before proceeding 
  11.     assert: 
  12.       that:  
  13.       - "var01 is defined" 
  14.       - "(var01 | type_debug) == 'int' " 
  15.       - "param01 is defined " 
  16.       - "(param01 | type_debug) == 'int' " 

如果我从命令行运行剧本,不提供额外变量:

  1. > ansible-playbook xassert.yml 
  2. PLAY [Assert examples]  
  3. *************************************************************************** 
  4. TASK [debug]  
  5. *************************************************************************** 
  6. ok: [node1] => { 
  7.     "msg""Parameter 01 is AnsibleUndefined" 
  8. TASK [Make sure that we have the right type of content before proceeding] *************************************************************************** 
  9. fatal: [node1]: FAILED! => { 
  10.     "assertion""param01 is defined "
  11.     "changed"false
  12.     "evaluated_to"false
  13.     "msg""Assertion failed" 
  14. PLAY RECAP  
  15. *************************************************************************** 
  16. node1 : ok=1 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0   

如果我从命令行运行剧本,使用额外变量:

  1. > ansible-playbook xassert.yml -e "param01=99" 
  2. PLAY [Assert examples]  
  3. *************************************************************************** 
  4. TASK [debug]  
  5. *************************************************************************** 
  6. ok: [node1] => { 
  7.     "msg""Parameter 01 is str" 
  8. TASK [Make sure that we have the right type of content before proceeding] *************************************************************************** 
  9. fatal: [node1]: FAILED! => { 
  10.     "assertion""(param01 | type_debug) == 'int' "
  11.     "changed"false
  12.     "evaluated_to"false
  13.     "msg""Assertion failed" 
  14. PLAY RECAP  
  15. ***************************************************************************node1 : ok=1 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0  

看到数据类型显示为str让我很惊讶,但这里给出了解释和解决方法(https://github.com/ansible/ansible/issues/14179)。

另外,如果您从Tower运行同一个剧本,将参数作为额外变量或调查字段来传递,参数的数据类型就会是int。

是的,这有点复杂,但如果您知道找什么,这些“功能”对您来说不成问题。

5. 列出事实和变量

无论您在库存中定义了变量,还是在剧本执行期间创建和赋予了额外变量,它在某个时候对于检查值很有用:

  1. --- 
  2. name: vars 
  3.   hosts: node1,node2 
  4.   tasks: 
  5.   
  6.   - name: Dump vars 
  7.     copy: 
  8.       content: "{{ hostvars[inventory_hostname] | to_nice_yaml }}" 
  9.       dest: "/tmp/{{ inventory_hostname }}_vars.txt" 
  10.     delegate_to: control 
  11.   - name: Dump facts 
  12.     copy:  
  13.       content: "{{ ansible_facts | to_nice_yaml }}" 
  14.       dest: "/tmp/{{ inventory_hostname }}_facts.txt" 
  15.     delegate_to: control 

这将把变量和事实 (如果您在搜集事实)保存在单独的文件中,供您分析。

6. 使用任务调试器从命令行排查

您还可以使用Ansible调试器,在逐步模式下执行剧本,并以交互方式检查变量和参数的内容。

此外,还可以实时改变变量的值,并继续执行。

可以在任务或剧本层面启用调试器,比如在以下示例中:

  1. --- 
  2. name: Example using debugger 
  3.   hosts: localhost 
  4.   gather_facts: no 
  5.   vars: 
  6.     radius: "5.3" 
  7.     pi: "3.1415926535" 
  8.   debugger: on_failed 
  9.   tasks: 
  10.   - name: Calculate the area of a circle 
  11.     debug: 
  12.       msg: 
  13.       - "Radius.............: {{ radius }}" 
  14.       - "pi................: {{ pi }}" 
  15.       - "Area of the circle: {{ (pi * (radius * radius)) }}" 

事先声明一下:我将变量定义为字符串,我试图执行计算时这显然会引发错误。

  1. > ansible-playbook xdebugger.yml  
  2. PLAY [Example using debugger]  
  3. *************************************************************************** 
  4. TASK [Calculate the area of a circle]  
  5. *************************************************************************** 
  6. fatal: [localhost]: FAILED! => {"msg""Unexpected templating type error occurred on (Area of the circle: {{ (pi * (radius * radius)) }}): can't multiply sequence by non-int of type 'AnsibleUnicode'"
  7. [localhost] TASK: Calculate the area of a circle (debug)> p task_vars['pi'
  8. '3.1415926535' 
  9. [localhost] TASK: Calculate the area of a circle (debug)> p task_vars['radius'
  10.  
  11. '5.3' 
  12.  
  13. [localhost] TASK: Calculate the area of a circle (debug)> task_vars['pi']=3.1415926535 
  14. [localhost] TASK: Calculate the area of a circle (debug)> task_vars['radius']=5.3 
  15. [localhost] TASK: Calculate the area of a circle (debug)> p task_vars['radius'
  16.  
  17. 5.3 
  18.  
  19. [localhost] TASK: Calculate the area of a circle (debug)> task_vars['pi']=3.1415926535 
  20. [localhost] TASK: Calculate the area of a circle (debug)> redo 
  21. ok: [localhost] => { 
  22.     "msg": [ 
  23.         "Radius............: 5.3"
  24.         "pi................: 3.1415926535"
  25.         "Area of the circle: 88.247337636815" 
  26.     ] 
  27. PLAY RECAP  
  28. *************************************************************************** 
  29. localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0   

这里发生了什么:

1. 起初,任务失败,抱怨是非int变量。

2. 调试器被调用。

3. 我使用了 print (p) 命令来显示变量的值。

4. 在这种情况下,我知道问题出在数据类型上,但有人可能认为值是正确的(如果不注意值两边的引号)。

5. 后来,我更新了变量的内容,为它们赋予了数字。

6. 然后,我使用redo命令用新值重新执行任务,结果成功完成。

这是简单的场景,因为我们知道没人会真正使用Ansible来计算圆的面积。但在较复杂的情况下,在长时间的剧本执行过程中找到变量的内容可能很有用,无需从头开始就能在此后继续下去。

原文标题:6 troubleshooting skills for Ansible playbooks,作者:Roberto Nozaki

【51CTO译稿,合作站点转载请注明原文译者和出处为51CTO.com】

 

责任编辑:华轩 来源: 51CTO
相关推荐

2021-03-02 06:32:03

Ansible系统运维

2021-01-24 16:00:22

Ansible系统运维

2020-10-15 15:09:27

Seaborn图表数据集

2021-07-14 13:50:51

Linux命令文件

2021-01-08 10:32:42

项目预算项目经理

2015-10-09 09:33:50

JavaScript思维技巧

2020-05-27 11:25:48

开发技能代码

2018-12-26 09:00:00

2014-11-24 09:39:26

docker云计算

2017-10-30 17:25:11

javascript

2018-09-04 14:53:19

VMware技巧SSH

2015-10-09 08:48:11

javascript思维技巧

2017-09-14 12:45:35

2021-02-03 10:46:31

SQL数据库技巧

2020-06-03 09:08:21

JavaScript开发代码

2020-02-27 10:11:11

自动化IT安全

2019-06-20 05:47:25

云计算成本IT

2020-02-20 22:36:54

物联网项目物联网IOT

2021-01-14 10:45:12

网络安全网络犯罪网络攻击

2015-10-30 09:49:30

点赞
收藏

51CTO技术栈公众号