
Telnet is a obviously a very insecure protocol, completely insecure in fact, and we strongly want to discourage usage. We would likely refuse the pull request, to be honest — it is just asking for a world of hurt should MITM possibilities arise.— Michael DeHaan, создатель Ansible
Абсолютно согласен. Эм, а как мне быть, когда у меня 20 тысяч legacy свитчей, которые перезагружаются/зависают из-за подключения по SSH, а часть оборудования его вообще не поддерживает?
Прошу под кат.
Особенности Ansible
SSH
В данный момент (релиз 2.3.0) в Ansible используется 3 вида соединений:
- SSH
- Local
- Docker
На самом деле SSH состоит из 2 типов и отличается использованием транспорта – ssh и paramiko. Последний использовался по умолчанию до версии Ansible 1.3, современные дистрибутивы используют параметр smart (т.е. OpenSSH), значительно ускоряя работу SSH с помощью мультиплексирования (функция Control Master). Для совместимости с legacy оборудованием лучше использовать paramiko, устанавливая ключ
–c paramiko при работе с модулями/плейбуками.Важно: при аутентификации по паролю, а не по ключам вместо ssh используется sshpass.
Если необходимо, установите пакет.
sudo apt-get install sshpassДля RHEL-based систем нужно включить EPEL
yum --enablerepo=epel install sshpassДля SSH есть прекрасный модуль raw, отправляющий одну команду требуемому количеству хостов и отображающий вывод со всех хостов. Для Telnet нам придется воспользоваться playbook, имеющим схожий функционал.
Telnet
Для работы с Telnet мы вынуждены использовать тип соединения local. Это означает, что команды playbook будут исполняться непосредственно на хосте Ansible (на удаленных свитчах вряд ли установлен Python, хех).
Для этого устанавливаем:
sudo apt-get install telnetили
yum install telnetЕще понадобится pexpect, который доступен через менеджер дополнений pip. Pip устанавливается вместе с Ansible, поэтому достаточно выполнить:
pip install pexpectПодготовка окружения завершена.
Настройка inventory
Воспользуемся стандартным файлом /etc/ansible/hosts
[test_cluster]
192.168.0.[10:25]Итак, наши коммутаторы входят в сущность test_cluster, имеют IP-адреса со 192.168.0.10 по 192.168.0.25. Предполагается, что на них настроен единый аккаунт с правами администратора, разрешен доступ по telnet.
Создаем наш playbook в формате .yml
---
- hosts: test_cluster
  gather_facts: false
  connection: local
  tasks:
  - name: telnet,login and execute command
    ignore_errors: true
    expect:
      command: telnet "{{ inventory_hostname }}"
      responses:
        (?i)username: "admin"
        (?i)password: "12345"
        (?i)#: "{{COMMAND}}\r\nlogout\r\nexit\r\nquit"
      echo: yes
    register: telnet_output
  - name: Debug output
    debug: var=telnet_output.stdout_linesИдем по порядку:
hosts: test_clusterХосты, к которым выполняется подключение
gather_facts: falseНормально не работает с сетевым оборудованием, нужно отключить
connection: localPexpect есть только на хосте Ansible.
tasks:Начинаем работу с модулями
ignore_errors: trueНеизвестно, что будет в выводе – из-за ограниченного функционала модуля expect может получиться результат FAILED. Рекомендуется отключить.
command: telnet "{{ inventory_hostname }}"Исполняется на хосте Ansible, происходит подключение ко всем удаленным хостам.
responses:(?i) означает, что игнорируется регистр. До
: мы указываем, что ожидаем, после – чем отвечаем.# — проверяем, что аутентификация успешна, мы находимся в привилегированном режиме; отвечаем комбинацией переменной команды с выходом из терминала (logout/exit/quit)Работа с expect предполагает доскональное знание CLI удаленного хоста, наличие навыков обращения с регулярными выражениями python. Например, добавление строки
#: "save" будет бессмысленно, т.к. сопоставление будет происходить только по первому условию #: "{{COMMAND}}\r\nlogout\r\nexit\r\nquit"register: telnet_outputСобираем вывод, помещаем в переменную telnet_output.
Debug возвращает нам вывод в удобном виде.Запускаем playbook c нужной командой:
ansible-playbook raw_telnet.yml  -e '{"COMMAND":"show stp"}'Результат выполнения:
        "Command: show stp",
        "",
        "",
        "",
        "STP Bridge Global Settings",
        "",
        "---------------------------",
        "",
        "STP Status        : Enabled",
        "",
        "STP Version       : RSTP",
        "",
        "Max Age           : 20     ",
        "",
        "Hello Time        : 2      ",
        "",
        "Forward Delay     : 15     ",
        "",
        "Max Hops          : 20     ",
        "",
        "TX Hold Count     : 3      ",
        "",
        "Forwarding BPDU   : Enabled",При желании практически все можно заменить переменными и не править playbook вообще. Конечно, хранить пароли в открытом виде тоже небезопасно, для этого в Ansible существуют Vaults.
Cсылки:
> Оригинальная документация
> Основы Ansible
> Ansible+сети
Комментарии (9)
 - Amet1312.05.2017 13:34+2- Мне вот интересно, те кто до сих пор используют apt-get вместо apt, просто привыкли набирать apt-get, не знают про это сокращение или же сохраняют в своих мануалах для совместимости со старыми версиями Debian/Ubuntu?  - Gaernebjorn12.05.2017 15:04+1- apt-get есть всегда и пример точно сработает, а apt — появился в убунте16.04, то бишь год назад. 7х дебианов еще полно, потому, что "не надо трогать" :) А статья про админство, где, зачастую, лучше постарше, но постабильнее  - Envek12.05.2017 22:30- В 14.04 тоже есть, но умеет значительно меньше, чем в 16.04. Но CLI глазу приятный и на четыре клавиши нажимать меньше в самых типовых сценариях — это решает, использую всегда, когда вспоминаю :-) 
 
  - Eivind12.05.2017 16:32+1- На текущем Debian для apt не работает bash-completion из коробки, так что «сокращиние» выходит весьма сомнительным. 
 - selivanov_pavel12.05.2017 16:43+1- Заинтересовался и потыкал палочкой этот apt. - --no-install-recommendsне умеет,- --print-urisне умеет,- showpkgне умеет. apt-get + apt-cache умеют гораздо больше, не вижу смысла использовать ещё и apt. Ну и как сказал Gaernebjorn, систем на precise, trusty и старых релизах дебиан ещё много.
 - VolCh15.05.2017 08:57- Если не изменяет память, то apt предназначен прежде всего для работы ручками из терминала, а для скриптов рекомендуется apt-get, apt-cache и т. д. 
 
 - nick_volynkin12.05.2017 19:17+1- Читал все эти - apt-get install sshpassи- pip install pexpectи думал, что можно же роль написать...
 - Картинка великолепная, очень подходит к статье. Если кто-то ещё не видел источник, то вот: 
 - telnet towel.blinkenlights.nl
 - AlexGluck21.05.2017 02:33- Я вот пытаюсь понять, при динамическом inventory файле как люди не раздражаются ограничиваться json выводом? 
 Я костыле-писатель, формирую файл баш-скриптом и всегда указываю- ansible-playbook example.yml -i `inventory.sh`
 Как обходить дупликацию хостов находящихся в разных сущностях, и нужно ли это делать?
 
 И что-то до меня никак не доходит, как засунуть в сущность В все хосты, кроме тех что в сущности А, пробовал так:
 - host4 host5 host6 [groupA] host1 host2 host3 [groupB] all:!groupA [groupC] host7 host8 host9
 
           
 
dmitry_ch
Супер, спасибо!