Руководство по отладке и устранению неполадок сети
Введение
Начиная с версии Ansible 2.1, вы можете использовать знакомые модели Ansible для создания playbooks и разработки модулей для управления разнородными сетевыми устройствами. Ansible поддерживает множество сетевых устройств с использованием как CLI по SSH, так и API (при наличии) в качестве транспортных средств.
В этом разделе описывается, как отлаживать и устранять неполадки сетевых модулей в Ansible 2.3.
Как устранять неполадки
Этот раздел посвящен устранению проблем с сетевыми модулями.
Ошибки обычно делятся на следующие категории:
| Проблемы с аутентификацией: | |
|---|---|
| |
| Проблемы с таймаутами: |
|
| Проблемы с playbook: | |
| |
Предупреждение
unable to open shell
Сообщение unable to open shell появилось в Ansible 2.3 и означает, что демону ansible-connection не удалось успешно связаться с удаленным сетевым устройством. Обычно это указывает на проблему с аутентификацией. Более подробная информация в разделе «Проблемы с аутентификацией и подключением» в этом документе.
Включение журналов сети и чтение файла журнала
Платформы: Любые
Ansible 2.3 имеет улучшенные журналы для диагностики и устранения проблем с сетевыми модулями Ansible.
Поскольку журналы очень подробные, они отключены по умолчанию. Их можно включить с помощью опций ANSIBLE_LOG_PATH и ANSIBLE_DEBUG на ansible-controller, то есть на машине, выполняющей 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-controller:
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— это PID (ID процесса) процессаansible-connection -
u=fred— это пользовательrunning, а не удаленный пользователь, от имени которого вы пытаетесь подключиться -
creating 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— время, затраченное на получение оболочки на удаленном устройстве
Поскольку файлы журналов содержат много информации, вы можете использовать grep для поиска определенной информации. Например, после того как вы определили pid из строки creating new control socket for host, вы можете искать другие записи журнала подключения:
grep "p=28990" $ANSIBLE_LOG_PATH
Изоляция ошибки
Платформы: Любые
Как и при любой попытке отладки, важно максимально упростить тестовый случай.
В Ansible это можно сделать, убедившись, что вы работаете только с одним удаленным устройством:
- Используя
ansible-playbook --limit switch1.example.net... - Используя команду ad-hoc
ansible
ad-hoc относится к запуску Ansible для выполнения некоторых быстрых команд с помощью /usr/bin/ansible, а не языка оркестрации, который является /usr/bin/ansible-playbook. В этом случае мы можем гарантировать подключение, попытавшись выполнить одну команду на удаленном устройстве:
ansible -m eos_command -a 'commands=?' -i inventory switch1.example.net -e 'ansible_connection=local' -u admin -k
В приведенном выше примере мы:
- подключаемся к
switch1.example.net, указанному в файле инвентаризацииinventory - используем модуль
eos_command - выполняем команду
? - подключаемся с именем пользователя
admin - указываем Ansible запросить пароль ssh, указав
-k
Если ключи 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 4*v for connection level verbosity ansible -m eos_command -a 'commands=?' -i inventory switch1.example.net -e 'ansible_connection=local' -u admin -k
Затем просмотрите файл журнала и найдите соответствующее сообщение об ошибке в остальной части документа.
Категория «проблема с путем сокета»
Платформы: Любые
Сообщения socket_path does not exist or cannot be found и unable to connect to socket новые в Ansible 2.5. Эти сообщения указывают на то, что сокет, используемый для связи с удаленным сетевым устройством, недоступен или не существует.
Например:
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 does not exist or cannot be found\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\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 10 secs
или
2017-04-04 12:19:05,670 p=18591 u=fred | persistent connection idle timeout triggered, timeout value is 30 secs
Следуйте инструкциям, описанным в проблемах с таймаутами
Категория «невозможно открыть оболочку»
Платформы: Любые
Сообщение unable to open shell появилось в Ansible 2.3. Это означает, что демону ansible-connection не удалось успешно связаться с удаленным сетевым устройством. Это обычно указывает на проблему с аутентификацией. Это сообщение «общий случай», поэтому необходимо включить :ref:logging`a_note_about_logging` для нахождения базовых проблем.
Например:
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:ни верхнего уровня, убедитесь, что ваш файл инвентаризации корректен.
Ошибка: «Аутентификация не удалась»
Платформы: Любые
Возникает, если учетные данные (имя пользователя, пароли или ключи ssh), переданные в ansible-connection (через ansible или ansible-playbook), не могут быть использованы для подключения к удаленному устройству.
Например:
<ios01> ESTABLISH CONNECTION FOR USER: cisco on PORT 22 TO ios01 <ios01> Authentication failed.
Рекомендации по решению:
Если вы указываете учетные данные через password: (прямо или через provider:) или переменную окружения ANSIBLE_NET_PASSWORD, возможно, paramiko (библиотека Python SSH, используемая Ansible) использует ключи ssh, и поэтому указанные вами учетные данные игнорируются. Чтобы выяснить, так ли это, отключите поиск ключей. Это можно сделать так:
export ANSIBLE_PARAMIKO_LOOK_FOR_KEYS=False
Чтобы сделать это постоянным изменением, добавьте следующее в ваш файл ansible.cfg:
[paramiko_connection] look_for_keys = False
Ошибка: «подключение к хосту <hostname> вернуло ошибку» или «Неверный адрес»
Это может произойти, если отпечаток 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 для предварительной подготовки файла известных хостов. Вам нужно убедиться, что ключи корректны.
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 секунд бездействия), просто удалите файл сокета.
Проблемы с таймаутами
Таймауты
Время ожидания бездействия постоянного подключения:
Например:
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
Таймаут команды: Например:
2017-04-04 12:19:05,670 p=18591 u=fred | command timeout triggered, timeout value is 10 secs
Рекомендации по решению:
Вариант 1: Увеличение значения таймаута команды в файле конфигурации или путем установки переменной окружения. Примечание: Это значение должно быть меньше, чем время ожидания бездействия постоянного подключения, т.е. connect_timeout
export ANSIBLE_PERSISTENT_COMMAND_TIMEOUT=30
Чтобы сделать это постоянным изменением, добавьте следующее в ваш файл ansible.cfg:
[persistent_connection] command_timeout = 30
Вариант 2: Увеличение таймаута команды на уровне задачи. Все сетевые модули поддерживают значение таймаута, которое может быть установлено для каждой задачи. Значение таймаута контролирует время в секундах, прежде чем задача завершится неудачно, если команда не вернула результат.
Например:
Рекомендации по решению:
- name: save running-config
ios_command:
commands: copy running-config startup-config
provider: "{{ cli }}"
timeout: 30
Некоторые операции занимают больше времени, чем стандартные 10 секунд. Хороший пример — сохранение текущей конфигурации IOS-устройств в стартовую конфигурацию. В этом случае изменение значения таймаута со стандартных 10 секунд до 30 секунд предотвратит сбой задачи до успешного завершения команды. Примечание: это значение должно быть меньше таймаута простоя постоянного подключения, т.е. connect_timeout
Таймаут подключения постоянного сокета: например:
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 (значение таймаута в разделе «Значения по умолчанию» в файле конфигурации) и меньше значения таймаута простоя постоянного подключения (connect_timeout).
export ANSIBLE_PERSISTENT_CONNECT_RETRY_TIMEOUT=30
Чтобы внести это изменение в постоянный режим, добавьте следующее в ваш ansible.cfg файл:
[persistent_connection] connect_retry_timeout = 30
Проблемы с Playbook
В этом разделе описаны проблемы, вызванные проблемами с самим Playbook.
Ошибка: «указано неверное подключение, ожидалось connection=local, получено ssh»
Платформы: Любые
Модули сети требуют, чтобы подключение было установлено на local. Любое другое значение подключения приведет к сбою playbook. Ansible теперь обнаружит это условие и вернет сообщение об ошибке:
fatal: [nxos01]: FAILED! => {
"changed": false,
"failed": true,
"msg": "invalid connection specified, expected connection=local, got ssh"
}
Для решения этой проблемы установите значение connection на local с помощью одного из следующих методов:
- Установите для play значение
connection: local - Установите для задачи значение
connection: local - Запустите ansible-playbook с параметром
-c local
Ошибка: «Невозможно войти в режим конфигурации»
Платформы: eos и ios
Это происходит, когда вы пытаетесь выполнить задачу, требующую привилегированного режима в оболочке пользователя.
Например:
TASK [ios_system : configure name_servers] *****************************************************************************
task path:
fatal: [ios-csr1000v]: FAILED! => {
"changed": false,
"failed": true,
"msg": "unable to enter configuration mode",
}
Рекомендации по решению:
Добавьте authorize: yes к задаче. Например:
- name: configure hostname
ios_system:
provider:
hostname: foo
authorize: yes
register: result
Если для входа в привилегированный режим требуется пароль, это можно указать с помощью auth_pass; если auth_pass не задано, вместо него будет использоваться переменная окружения ANSIBLE_NET_AUTHORIZE
Добавьте authorize: yes в задачу. Например:
- name: configure hostname
ios_system:
provider:
hostname: foo
authorize: yes
auth_pass: "{{ mypasswordvar }}"
register: result
Проблемы с прокси
delegate_to vs ProxyCommand
Новая система подключения для модулей сети в Ansible 2.3, использующая транспорт cli, больше не поддерживает использование директивы delegate_to. Для использования бастиона или промежуточного хоста перехода для подключения к сетевым устройствам через транспорт 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
Примечание
Использование ProxyCommand с паролями через переменные
По умолчанию SSH не поддерживает предоставление паролей через переменные среды. Это сделано для предотвращения утечки секретов, например, в выводе ps
Мы рекомендуем использовать ключи SSH и, при необходимости, ssh-agent вместо паролей, где это возможно.
© 2012–2018 Michael DeHaan
© 2018–2019 Red Hat, Inc.
Licensed under the GNU General Public License version 3.
https://docs.ansible.com/ansible/2.5/network/user_guide/network_debug_troubleshooting.html