【.com快译】Ansible是一个强大的工具,可以跨服务器、云、网络、容器等自动化管理各种平台。您通常可以通过简单地重用现有角色和集合来自动执行您想做的事情。还有许多可用的模块可用于剧本。但是当您开始开发和测试更复杂的剧本时,您最终将需要进行一些故障排除。诸如检查Ansible任务流、确认变量的数据类型,甚至在某个点暂停以检查它们的值之类的事情。本文中讨论的一些技术仅适用于从命令行执行Ansible。从AnsibleTower运行时,其他技巧也有效。1.你的Ansible环境和参数如果你需要分析为什么某些东西没有按playbook中的预期工作,最好先检查你的Ansible环境。您运行Ansible二进制文件和Python的版本和路径是什么?如果你添加你的剧本所需的操作系统包或Python模块,Ansible解释器会“看到”它们吗?有许多不同的方法可以获取这些基本信息。从命令行运行ansible--version命令。>ansible--versionansible2.9.10configfile=/etc/ansible/ansible.cfgconfiguredmodulesearchpath=['/home/admin/.ansible/plugins/modules','/usr/share/ansible/plugins/modules']ansiblepythonmodulolecation=/usr/lib/python3.6/site-packages/ansibleexecutablelocation=/usr/bin/ansiblepythonversion=3.6.8(default,Mar182021,08:58:41)[GCC8.4.120200928(RedHat8.4.1-1)]可以运行其他Ansible命令来获取相同的信息,例如使用--version选项的ansible-playbook或ansible-config。在AnsibleTower中,如果使用VERBOSITY2(更详细)或更高级别执行作业模板,则会显示此信息。除了Ansible和Python二进制文件的版本和位置之外,仔细检查用于模块的路径总是好的,包括执行是否使用非默认的ansible.cfg文件(即不是/etc/ansible/ansible.cfg)。CFG)。要调查自定义ansible.cfg文件中的选项,可以从命令行执行以下命令:ansible/ansible.cfg)=rootDEFAULT_FORKS(/home/admin/ansible/ansible.cfg)=10DEFAULT_HOST_LIST(/home/admin/ansible/ansible.cfg)=['/home/admin/ansible/inventory']DEFAULT_ROLES_PATH(/home/admin/ansible/ansible.cfg)=['/home/admin/ansible/roles']HOST_KEY_CHECKING(/home/admin/ansible/ansible.cfg)=False顾名思义,这将列出不同于默认的。2.以详细模式运行下一步是在调试模式下运行剧本,以获取有关任务和变量中发生的事情的更多详细信息。您可以从命令行添加-v(或-vv、-vvv、-vvvv、-vvvvv)。最高的详细级别有时会包含太多信息,因此最好在多次执行后逐渐增加详细级别,直到获得所需的信息。级别4有助于解决连接问题,级别5有助于解决WinRM问题。在Tower中,您可以从作业模板定义中选择VERBOSITY级别。注意:切记在故障排除后禁用调试模式,因为详细信息仅对故障排除有用。此外,在调试模式下,除非您在任务中使用no_log选项,否则会显示某些变量(如密码)的值,因此在完成后会删除输出。3.使用调试来显示变量如果你已经很清楚问题可能出在哪里,你可以使用更精确的方法:只显示你需要看的变量。(...)-name:Displaythevalueofthecounterdebug:msg:"Counter={{counter}}/Datatype={{counter|type_debug}}"(...)TASK[Displaythevalueofthecounter]**********************************************************************************ok:[node1]=>{"msg":"Counter=42/Datatype=AnsibleUnicode"}这就是我无法增加计数的原因。过滤器type_debug显示数据类型是text,不是我想的int。4.确保变量具有正确的内容和数据类型可以使用断言模块确认:变量具有预期的内容/类型,如果出现问题,将导致任务失败。以下脚本显示了这一点:-name:Assertexampleshosts:node1gather_facts:novars:var01:13tasks:-debug:msg:"Parameter01is{{(param01|type_debug)}}"-name:Makesurethatwehavetherighttypeofcontentbeforeproceedingassert:that:-"var01isdefined"-"(var01|type_debug)=='int'"-"param01isdefined"-"(param01|type_debug)=='int'"如果我??从命令行运行playbook,不会提供额外的变量:>ansible-playbookxassert.ymlPLAY[Assertexamples]**********************************************************************************任务[调试]************************************************************************************ok:[node1]=>{"msg":"Parameter01isAnsibleUndefined"}任务[确保我们在继续之前拥有正确的内容类型]***********************************************************************************致命:[node1]:失败!=>{“断言”:“param01isdefined”,“已更改”:false,“evaluated_to”:false,“msg”:“断言失败"}PLAYRECAP************************************************************************************node1:ok=1changed=0unreachable=0failed=1skipped=0rescued=0ignored=0如果我从命令行运行剧本,使用额外的变量:>ansible-playbookxassert.yml-e"param01=99"PLAY[Assertexamples]*********************************************************************************任务[调试]**********************************************************************************确定:[node1]=>{“msg”:“Parameter01isstr”}任务[确保我们在继续之前拥有正确的内容类型]**********************************************************************************致命:[node1]:失败!=>{"assertion":"(param01|type_debug)=='int'","changed":false,"evaluated_to":false,"msg":"Assertionfailed"}PLAYRECAP*******************************************************************************node1:ok=1changed=0unreachable=0failed=1skipped=0rescued=0ignored=0看到数据类型显示为str令我感到惊讶,但此处给出了解释和解决方法(https://github.com/ansible/ansible/issues/14179)此外,如果您从Tower运行相同的剧本,请将参数作为额外变量传递或调查要传递的字段,参数的数据类型将为int。是的,它有点复杂,但是如果您知道要寻找什么,那么这些“功能”对您来说应该不是问题。5.列出事实和变量无论您在清单中定义了变量,还是在剧本执行期间创建并提供了额外的变量,在某些时候检查值都是有用的:----name:varshosts:node1,node2tasks:-名称:Dumpvarscopy:content:"{{hostvars[inventory_hostname]|to_nice_yaml}}"dest:"/tmp/{{inventory_hostname}}_vars.txt"delegate_to:control-name:Dumpfactscopy:content:"{{ansible_facts|to_nice_yaml}}"dest:"/tmp/{{inventory_hostname}}_facts.txt"delegate_to:control这会将变量和事实(如果您正在收集事实)保存在一个单独的文件中以供您分析。6.使用任务调试器从命令行进行故障排除您还可以使用Ansible调试器以逐步模式执行剧本,并以交互方式检查变量和参数的内容。此外,可以实时更改变量的值并继续执行。可以在任务或脚本级别启用调试器,如下例所示:-name:Exampleusingdebuggerhosts:localhostgather_facts:novars:radius:"5.3"pi:"3.1415926535"debugger:on_failedtasks:-name:Calculatetheareaofacircledebug:msg:-"半径…………:{{radius}}"-"pi......:{{pi}}"-"Areaofthecircle:{{(pi*(radius*radius))}}"一句警告:我将变量定义为字符串,这显然会在我尝试执行计算时引发错误。>ansible-playbookxdebugger.ymlPLAY[使用调试器的示例]**********************************************************************************任务[计算圆的面积]*******************************************************************************致命:[localhost]:失败!=>{“msg”:“Unexpectedtemplatingtypeerroroccurredon(Areaofthecircle:{{(pi*(radius*radius))}}):可以'tmultiplysequencebynon-intoftype'AnsibleUnicode'"}[localhost]TASK:Calculatetheareaofacircle(debug)>ptask_vars['pi']'3.1415926535'[localhost]TASK:Calculatetheareaofacircle(debug)>ptask_vars['radius']'5.3'[本地主机]TASK:Calculatetheareaofacircle(debug)>task_vars['pi']=3.1415926535[localhost]TASK:Calculatetheareaofacircle(debug)>task_vars['radius']=5.3[localhost]TASK:Calculatetheareaofacircle(debug)>ptask_vars['radius']5.3[localhost]TASK:Calculatetheareaofacircle(debug)>task_vars['pi']=3.1415926535[localhost]TASK:Calculatetheareaofacircle(debug)>redook:[localhost]=>{"msg":["半径............:5.3","pi............:3.1415926535","面积圆圈:88.247337636815"]}PLAYRECAP*******************************************************************************localhost:ok=1changed=0unreachable=0failed=0skipped=0rescued=0ignored=0这是发生了什么:1.起初,任务失败,抱怨非int变量2.调试器被调用。3.我用print(p)命令来显示变量的值。4.在这种情况下,我知道问题出在数据类型上,但有人可能认为值是正确的(如果不注意值周围的引号)。5.后来,我更新了变量的内容,给它们编号。6.然后,我用redo命令用新的值重新执行任务,成功完成。这是简单的场景,因为我们知道实际上没有人会使用Ansible来计算圆的面积。但在更复杂的情况下,在长时间执行playbook期间查找变量的内容并在之后继续执行而无需从头开始可能会很有用。原标题:Ansibleplaybook的6个故障排除技巧,作者:RobertoNozaki
