网络调试和故障排除指南
本节讨论如何在 Ansible 中调试和排除网络模块的故障。
如何进行故障排除
Ansible 网络自动化错误通常属于以下类别之一
- 身份验证问题:
未正确指定凭据
远程设备(网络交换机/路由器)未回退到其他身份验证方法
SSH 密钥问题
- 超时问题:
尝试提取大量数据时可能会发生
可能实际上是在掩盖身份验证问题
- Playbook 问题:
使用
delegate_to
,而不是ProxyCommand
。有关更多信息,请参见 网络代理指南。
警告
无法 打开 shell
无法 打开 shell
消息表示 ansible-connection
守护进程无法成功与远程网络设备通信。这通常表示存在身份验证问题。有关更多信息,请参见本文档中的“身份验证和连接问题”部分。
启用网络日志记录以及如何读取日志文件
平台: 任何
Ansible 包含日志记录,以帮助诊断和解决有关 Ansible 网络模块的问题。
由于日志记录非常详细,因此默认情况下禁用。可以使用 Ansible 控制节点上的 ANSIBLE_LOG_PATH
和 ANSIBLE_DEBUG
选项启用它,即运行 ansible-playbook
的计算机。
在运行 ansible-playbook
之前,运行以下命令以启用日志记录
# Specify the location for the log file
export ANSIBLE_LOG_PATH=~/ansible.log
# Enable Debug
export ANSIBLE_DEBUG=True
# Run with 4*v for connection level verbosity
ansible-playbook -vvvv ...
Ansible 运行完成后,您可以检查在 Ansible 控制节点上创建的日志文件
less $ANSIBLE_LOG_PATH
2017-03-30 13:19:52,740 p=28990 u=fred | creating new control socket for host veos01:22 as user admin
2017-03-30 13:19:52,741 p=28990 u=fred | control socket path is /home/fred/.ansible/pc/ca5960d27a
2017-03-30 13:19:52,741 p=28990 u=fred | current working directory is /home/fred/ansible/test/integration
2017-03-30 13:19:52,741 p=28990 u=fred | using connection plugin network_cli
...
2017-03-30 13:20:14,771 paramiko.transport userauth is OK
2017-03-30 13:20:15,283 paramiko.transport Authentication (keyboard-interactive) successful!
2017-03-30 13:20:15,302 p=28990 u=fred | ssh connection done, setting terminal
2017-03-30 13:20:15,321 p=28990 u=fred | ssh connection has completed successfully
2017-03-30 13:20:15,322 p=28990 u=fred | connection established to veos01 in 0:00:22.580626
从日志中注意
p=28990
是ansible-connection
进程的 PID(进程 ID)u=fred
是 运行 Ansible 的用户,而不是您尝试连接的 remote-usercreating new control socket for host veos01:22 as user admin
主机:端口作为用户control socket path is
持久连接套接字在磁盘上的创建位置using connection plugin network_cli
通知您正在使用持久连接connection established to veos01 in 0:00:22.580626
在远程设备上获取 shell 所花费的时间
注意
端口 None creating new control socket for host veos01:None
如果日志报告端口为 None
,则表示正在使用默认端口。未来的 Ansible 版本将改进此消息,以便始终记录端口。
由于日志文件非常详细,因此您可以使用 grep 来查找特定信息。例如,一旦从 creating new control socket for host
行中标识出 pid
,您就可以搜索其他连接日志条目
grep "p=28990" $ANSIBLE_LOG_PATH
启用网络设备交互日志记录
平台: 任何
Ansible 在日志文件中包含设备交互日志记录,以帮助诊断和解决有关 Ansible 网络模块的问题。消息记录在 Ansible 配置文件中由 log_path
配置选项指向的文件中,或者通过设置 ANSIBLE_LOG_PATH
。
警告
设备交互消息包括在目标设备上执行的命令和返回的响应。由于此日志数据可能包含敏感信息,包括纯文本密码,因此默认情况下禁用此功能。此外,为了防止意外的数据泄漏,每次启用此设置的任务都会显示警告,指定哪个主机启用了该设置以及数据记录在何处。
请务必充分了解启用此选项的安全影响。设备交互日志记录可以在配置文件中全局设置,也可以通过设置环境或通过将特殊变量传递给任务在每个任务的基础上启用。
在运行 ansible-playbook
之前,请运行以下命令以启用日志记录
# Specify the location for the log file
export ANSIBLE_LOG_PATH=~/ansible.log
为给定任务启用设备交互日志记录
- name: get version information
cisco.ios.ios_command:
commands:
- show version
vars:
ansible_persistent_log_messages: True
要使其成为全局设置,请将以下内容添加到您的 ansible.cfg
文件中
[persistent_connection]
log_messages = True
或启用环境变量 ANSIBLE_PERSISTENT_LOG_MESSAGES
# Enable device interaction logging
export ANSIBLE_PERSISTENT_LOG_MESSAGES=True
如果任务在连接初始化本身就失败,您应该全局启用此选项。如果单个任务间歇性失败,则可以为该任务本身启用此选项,以查找根本原因。
Ansible 运行完成后,您可以检查在 Ansible 控制节点上创建的日志文件
注意
请务必充分了解启用此选项的安全影响,因为它可能会在日志文件中记录敏感信息,从而造成安全漏洞。
隔离错误
平台: 任何
与任何故障排除工作一样,尽可能简化测试用例非常重要。
对于 Ansible,可以通过确保只针对一个远程设备运行来实现。
使用
ansible-playbook --limit switch1.example.net...
使用即席
ansible
命令
即席 指的是使用 /usr/bin/ansible
运行 Ansible 以执行一些快速命令,而不是编排语言 /usr/bin/ansible-playbook
。在这种情况下,我们可以通过尝试在远程设备上执行单个命令来确保连接性
ansible -m arista.eos.eos_command -a 'commands=?' -i inventory switch1.example.net -e 'ansible_connection=ansible.netcommon.network_cli' -u admin -k
在上面的示例中,我们
连接到清单文件
inventory
中指定的switch1.example.net
使用模块
arista.eos.eos_command
运行命令
?
使用用户名
admin
连接通过指定
-k
通知ansible
命令提示输入 SSH 密码
如果 SSH 密钥配置正确,则无需指定 -k
参数。
如果连接仍然失败,您可以将其与 enable_network_logging 参数结合使用。例如
# Specify the location for the log file
export ANSIBLE_LOG_PATH=~/ansible.log
# Enable Debug
export ANSIBLE_DEBUG=True
# Run with ``-vvvv`` for connection level verbosity
ansible -m arista.eos.eos_command -a 'commands=?' -i inventory switch1.example.net -e 'ansible_connection=ansible.netcommon.network_cli' -u admin -k
然后查看日志文件,并在本文档的其余部分中查找相关的错误消息。
排查套接字路径问题
平台: 任何
套接字 路径 不存在 或 无法 找到
和 无法 连接 到 套接字
消息表明用于与远程网络设备通信的套接字不可用或不存在。
例如
fatal: [spine02]: FAILED! => {
"changed": false,
"failed": true,
"module_stderr": "Traceback (most recent call last):\n File \"/tmp/ansible_TSqk5J/ansible_modlib.zip/ansible/module_utils/connection.py\", line 115, in _exec_jsonrpc\nansible.module_utils.connection.ConnectionError: Socket path XX does not exist or cannot be found. See Troubleshooting socket path issues in the Network Debug and Troubleshooting Guide\n",
"module_stdout": "",
"msg": "MODULE FAILURE",
"rc": 1
}
或
fatal: [spine02]: FAILED! => {
"changed": false,
"failed": true,
"module_stderr": "Traceback (most recent call last):\n File \"/tmp/ansible_TSqk5J/ansible_modlib.zip/ansible/module_utils/connection.py\", line 123, in _exec_jsonrpc\nansible.module_utils.connection.ConnectionError: Unable to connect to socket XX. See Troubleshooting socket path issues in Network Debug and Troubleshooting Guide\n",
"module_stdout": "",
"msg": "MODULE FAILURE",
"rc": 1
}
解决建议
验证您是否具有对错误消息中描述的套接字路径的写入权限。
按照启用网络日志记录中详细说明的步骤进行操作。
如果日志文件中标识的错误消息是
2017-04-04 12:19:05,670 p=18591 u=fred | command timeout triggered, timeout value is 30 secs
或
2017-04-04 12:19:05,670 p=18591 u=fred | persistent connection idle timeout triggered, timeout value is 30 secs
按照超时问题中详细说明的步骤进行操作
类别“无法打开 shell”
平台: 任何
无法 打开 shell
消息表示 ansible-connection
守护程序无法成功与远程网络设备通信。这通常意味着存在身份验证问题。这是一个“包罗万象”的消息,这意味着您需要启用 日志记录 来查找根本问题。
例如
TASK [prepare_eos_tests : enable cli on remote device] **************************************************
fatal: [veos01]: FAILED! => {"changed": false, "failed": true, "msg": "unable to open shell"}
或
TASK [ios_system : configure name_servers] *************************************************************
task path:
fatal: [ios-csr1000v]: FAILED! => {
"changed": false,
"failed": true,
"msg": "unable to open shell",
}
解决建议
按照enable_network_logging中详细说明的步骤进行操作。
一旦您从日志文件中识别出错误消息,即可在本文档的其余部分中找到具体的解决方案。
错误:“[Errno -2] 名称或服务未知”
平台: 任何
表示无法访问您尝试连接的远程主机
例如
2017-04-04 11:39:48,147 p=15299 u=fred | control socket path is /home/fred/.ansible/pc/ca5960d27a
2017-04-04 11:39:48,147 p=15299 u=fred | current working directory is /home/fred/git/ansible-inc/stable-2.3/test/integration
2017-04-04 11:39:48,147 p=15299 u=fred | using connection plugin network_cli
2017-04-04 11:39:48,340 p=15299 u=fred | connecting to host veos01 returned an error
2017-04-04 11:39:48,340 p=15299 u=fred | [Errno -2] Name or service not known
解决建议
如果您正在使用
provider:
选项,请确保其子选项host:
设置正确。如果您未使用
provider:
或顶级参数,请确保您的清单文件正确。
错误:“身份验证失败”
平台: 任何
如果传递给 ansible-connection
(通过 ansible
或 ansible-playbook
) 的凭据(用户名、密码或 ssh 密钥)无法用于连接到远程设备,则会发生此错误。
例如
<ios01> ESTABLISH CONNECTION FOR USER: cisco on PORT 22 TO ios01
<ios01> Authentication failed.
解决建议
如果您正在通过 password:
(直接或通过 provider:
) 或环境变量 ANSIBLE_NET_PASSWORD 指定凭据,则 paramiko
(Ansible 使用的 Python SSH 库) 可能正在使用 ssh 密钥,因此您指定的凭据将被忽略。要找出是否是这种情况,请禁用“查找密钥”。可以通过以下方式进行此操作
export ANSIBLE_PARAMIKO_LOOK_FOR_KEYS=False
要使此更改永久生效,请将以下内容添加到您的 ansible.cfg
文件中
[paramiko_connection]
look_for_keys = False
错误:“连接到主机 返回一个错误”或“错误的地址”
如果 SSH 指纹尚未添加到 Paramiko(Python SSH 库)的已知主机文件中,则可能会发生这种情况。
当将持久连接与 Paramiko 结合使用时,连接会在后台进程中运行。如果主机尚不具有有效的 SSH 密钥,则默认情况下,Ansible 将提示添加主机密钥。这将导致在后台进程中运行的连接失败。
例如
2017-04-04 12:06:03,486 p=17981 u=fred | using connection plugin network_cli
2017-04-04 12:06:04,680 p=17981 u=fred | connecting to host veos01 returned an error
2017-04-04 12:06:04,682 p=17981 u=fred | (14, 'Bad address')
2017-04-04 12:06:33,519 p=17981 u=fred | number of connection attempts exceeded, unable to connect to control socket
2017-04-04 12:06:33,520 p=17981 u=fred | persistent_connect_interval=1, persistent_connect_retries=30
解决建议
使用 ssh-keyscan
预先填充 known_hosts。您需要确保密钥正确。
ssh-keyscan veos01
或
您可以告诉 Ansible 自动接受密钥
环境变量方法
export ANSIBLE_PARAMIKO_HOST_KEY_AUTO_ADD=True
ansible-playbook ...
ansible.cfg
方法
ansible.cfg
[paramiko_connection]
host_key_auto_add = True
错误:“没有可用的身份验证方法”
例如
2017-04-04 12:19:05,670 p=18591 u=fred | creating new control socket for host veos01:None as user admin
2017-04-04 12:19:05,670 p=18591 u=fred | control socket path is /home/fred/.ansible/pc/ca5960d27a
2017-04-04 12:19:05,670 p=18591 u=fred | current working directory is /home/fred/git/ansible-inc/ansible-workspace-2/test/integration
2017-04-04 12:19:05,670 p=18591 u=fred | using connection plugin network_cli
2017-04-04 12:19:06,606 p=18591 u=fred | connecting to host veos01 returned an error
2017-04-04 12:19:06,606 p=18591 u=fred | No authentication methods available
2017-04-04 12:19:35,708 p=18591 u=fred | connect retry timeout expired, unable to connect to control socket
2017-04-04 12:19:35,709 p=18591 u=fred | persistent_connect_retry_timeout is 15 secs
解决建议
未提供密码或 SSH 密钥
清除持久连接
平台: 任何
在 Ansible 2.3 中,持久连接套接字存储在 ~/.ansible/pc
中,用于所有网络设备。当 Ansible playbook 运行时,指定详细输出时将显示持久套接字连接。
<switch> socket_path: /home/fred/.ansible/pc/f64ddfa760
要在持久连接超时之前(默认超时为 30 秒不活动),清除持久连接,只需删除套接字文件即可。
超时问题
持久连接空闲超时
默认情况下,ANSIBLE_PERSISTENT_CONNECT_TIMEOUT
设置为 30(秒)。如果此值太低,您可能会看到以下错误
2017-04-04 12:19:05,670 p=18591 u=fred | persistent connection idle timeout triggered, timeout value is 30 secs
解决建议
增加持久连接空闲超时值
export ANSIBLE_PERSISTENT_CONNECT_TIMEOUT=60
要使此更改永久生效,请将以下内容添加到您的 ansible.cfg
文件中
[persistent_connection]
connect_timeout = 60
命令超时
默认情况下,ANSIBLE_PERSISTENT_COMMAND_TIMEOUT
设置为 30(秒)。之前的 Ansible 版本默认将此值设置为 10 秒。如果此值太低,您可能会看到以下错误
2017-04-04 12:19:05,670 p=18591 u=fred | command timeout triggered, timeout value is 30 secs
解决建议
选项 1(全局命令超时设置):在配置文件中或通过设置环境变量增加命令超时值。
export ANSIBLE_PERSISTENT_COMMAND_TIMEOUT=60
要使此更改永久生效,请将以下内容添加到您的
ansible.cfg
文件中[persistent_connection] command_timeout = 60
选项 2(每个任务的命令超时设置):增加每个任务的命令超时。所有网络模块都支持可以在每个任务基础上设置的超时值。超时值控制命令在未返回的情况下任务失败之前的时间(以秒为单位)。
对于本地连接类型
解决建议
某些模块支持
timeout
选项,这与任务的timeout
关键字不同。- name: save running-config cisco.ios.ios_command: commands: copy running-config startup-config provider: "{{ cli }}" timeout: 30
解决建议
如果模块不直接支持
timeout
选项,则大多数网络连接插件可以使用ansible_command_timeout
变量启用类似的功能。- name: save running-config cisco.ios.ios_command: commands: copy running-config startup-config vars: ansible_command_timeout: 60
某些操作的完成时间超过默认的 30 秒。一个很好的例子是将 IOS 设备上当前正在运行的配置保存到启动配置。在这种情况下,将超时值从默认的 30 秒更改为 60 秒将防止任务在命令成功完成之前失败。
持久连接重试超时
默认情况下,ANSIBLE_PERSISTENT_CONNECT_RETRY_TIMEOUT
设置为 15(秒)。如果此值太低,您可能会看到以下错误
2017-04-04 12:19:35,708 p=18591 u=fred | connect retry timeout expired, unable to connect to control socket
2017-04-04 12:19:35,709 p=18591 u=fred | persistent_connect_retry_timeout is 15 secs
解决建议
增加持久连接空闲超时值。注意:此值应大于 SSH 超时值(配置文件 defaults 部分下的超时值),并且小于持久连接空闲超时值 (connect_timeout)。
export ANSIBLE_PERSISTENT_CONNECT_RETRY_TIMEOUT=30
要使此更改永久生效,请将以下内容添加到您的 ansible.cfg
文件中
[persistent_connection]
connect_retry_timeout = 30
Playbook 问题
本节详细介绍了由 Playbook 本身的问题引起的问题。
错误:“无法进入配置模式”
平台: Arista EOS 和 Cisco IOS
当您尝试在用户模式 shell 中运行需要特权模式的任务时,会发生这种情况。
例如
TASK [ios_system : configure name_servers] *****************************************************************************
task path:
fatal: [ios-csr1000v]: FAILED! => {
"changed": false,
"failed": true,
"msg": "unable to enter configuration mode",
}
解决建议
使用
connection: ansible.netcommon.network_cli
和become: true
代理问题
delegate_to vs ProxyCommand
为了使用堡垒机或中间跳转主机通过 cli
传输连接到网络设备,网络模块支持使用 ProxyCommand
。
要使用 ProxyCommand
,请在 Ansible 清单文件中配置代理设置以指定代理主机。
[nxos]
nxos01
nxos02
[nxos:vars]
ansible_ssh_common_args='-o ProxyCommand="ssh -W %h:%p -q bastion01"'
完成上述配置后,只需像往常一样构建和运行 playbook,无需进行任何额外的更改。网络模块现在将首先连接到 ansible_ssh_common_args
中指定的主机,即上例中的 bastion01
,从而连接到网络设备。
您还可以使用环境变量为所有主机设置代理目标。
export ANSIBLE_SSH_ARGS='-o ProxyCommand="ssh -W %h:%p -q bastion01"'
使用堡垒/跳转主机进行 netconf 连接
启用跳转主机设置
- 可以通过以下方式启用使用堡垒/跳转主机进行 netconf 连接:
将 Ansible 变量
ansible_netconf_ssh_config
设置为True
或自定义 ssh 配置文件路径将环境变量
ANSIBLE_NETCONF_SSH_CONFIG
设置为True
或自定义 ssh 配置文件路径在
netconf_connection
部分下设置ssh_config = 1
或ssh_config = <ssh-file-path>
如果配置变量设置为 1,则 proxycommand 和其他 ssh 变量将从默认 ssh 配置文件(~/.ssh/config)读取。
如果配置变量设置为文件路径,则 proxycommand 和其他 ssh 变量将从给定的自定义 ssh 文件路径读取
示例 ssh 配置文件(~/.ssh/config)
Host jumphost
HostName jumphost.domain.name.com
User jumphost-user
IdentityFile "/path/to/ssh-key.pem"
Port 22
# Note: Due to the way that Paramiko reads the SSH Config file,
# you need to specify the NETCONF port that the host uses.
# In other words, it does not automatically use ansible_port
# As a result you need either:
Host junos01
HostName junos01
ProxyCommand ssh -W %h:22 jumphost
# OR
Host junos01
HostName junos01
ProxyCommand ssh -W %h:830 jumphost
# Depending on the netconf port used.
示例 Ansible 清单文件
[junos]
junos01
[junos:vars]
ansible_connection=ansible.netcommon.netconf
ansible_network_os=junipernetworks.junos.junos
ansible_user=myuser
ansible_password=!vault...
注意
通过变量使用 ProxyCommand
进行密码验证
按照设计,SSH 不支持通过环境变量提供密码。这样做是为了防止机密信息泄露,例如在 ps
输出中。
我们建议尽可能使用 SSH 密钥,如果需要,可以使用 ssh-agent,而不是密码。
其他问题
使用 ansible.netcommon.network_cli
连接类型时出现间歇性故障
如果在 ansible.netcommon.network_cli
连接插件中正确匹配收到的命令提示符,则任务可能会间歇性失败,并出现截断的响应或错误消息 operation requires privilege escalation
。从 2.7.1 版本开始,添加了一个新的缓冲区读取计时器,以确保正确匹配提示,并在输出中发送完整响应。计时器的默认值为 0.2 秒,可以按任务进行调整,也可以全局设置为秒。
每个任务计时器设置示例
- name: gather ios facts
cisco.ios.ios_facts:
gather_subset: all
register: result
vars:
ansible_buffer_read_timeout: 2
要使其成为全局设置,请将以下内容添加到您的 ansible.cfg
文件中
[persistent_connection]
buffer_read_timeout = 2
可以通过将值设置为零来禁用在远程主机上执行的每个命令的此计时器延迟。
由于使用 ansible.netcommon.network_cli
连接类型时,命令响应中不匹配的错误正则表达式而导致的任务失败
在 Ansible 2.9 及更高版本中,添加了 ansible.netcommon.network_cli
连接插件配置选项,用于处理 stdout 和 stderr 正则表达式,以识别命令执行响应是正常响应还是错误响应。这些选项可以设置为组/主机变量或任务变量。
示例:对于不匹配的错误响应
- name: fetch logs from remote host
cisco.ios.ios_command:
commands:
- show logging
Playbook 运行输出
TASK [first fetch logs] ********************************************************
fatal: [ios01]: FAILED! => {
"changed": false,
"msg": "RF Name:\r\n\r\n <--nsip-->
\"IPSEC-3-REPLAY_ERROR: Test log\"\r\n*Aug 1 08:36:18.483: %SYS-7-USERLOG_DEBUG:
Message from tty578(user id: ansible): test\r\nan-ios-02#"}
解决建议
修改单个任务的错误正则表达式。
- name: fetch logs from remote host
cisco.ios.ios_command:
commands:
- show logging
vars:
ansible_terminal_stderr_re:
- pattern: 'connection timed out'
flags: 're.I'
终端插件正则表达式选项 ansible_terminal_stderr_re
和 ansible_terminal_stdout_re
具有 pattern
和 flags
作为键。flags
键的值应为 re.compile
python 方法接受的值。
由于网络速度较慢或远程目标主机较慢,使用 ansible.netcommon.network_cli
连接类型时出现间歇性故障
在 Ansible 2.9 及更高版本中,添加了 ansible.netcommon.network_cli
连接插件配置选项,用于控制连接到远程主机的尝试次数。默认的尝试次数为三次。在每次重试尝试之后,重试之间的延迟将以 2 的幂次方(以秒为单位)增加,直到尝试次数耗尽或触发 persistent_command_timeout
或 persistent_connect_timeout
计时器。
要使其成为全局设置,请将以下内容添加到您的 ansible.cfg
文件中
[persistent_connection]
network_cli_retries = 5