Ansible один из двух (наряду с SaltStack) наиболее популярных программных комплексов третьей волны, которые позволяют удалённо управлять конфигурациями. Тем не менее, в сегменте сетевого оборудования лидирует наш сегодняшний герой (если о ПО можно так сказать). В первую очередь это вызвано тем, что Ansible не поставит перед пользователем задачи устанавливать агент на хостинги, требующие от него управления. Тем паче ежели Ваш аппарат взаимодействует с ними через CLI, то Ansible это то, что доктор прописал.
Одним выстрелом три "электронных зайца"
Вообще, прежде чем знакомить уважаемых читателей со сценарием работы в данном программном комплексе, позвольте перечислить несколько его достоинств:
- Ansible позволяет параллельно подключать по SSH к устройствам (пользователь может сам определить их число).
- Ansible может передавать задачи на подключённые машины.
- Ansible способен разбивать машины, входящих в систему, на подгруппы и передавать специальных задачи для каждой подгруппы.
Конечно, указаны не все достоинства Ansible. Просто в данных 3 пунктах, как мне кажется, отражена основная суть работы в данной среде. Выполняя эти три задачи, система автоматически освобождает Вас от головной боли по делегированию задач и функций в компании. Время деньги, как говорится.
Сценарии
Ну и переходим к основному блюду нашего материала - сценариям (playbook). Они состоят из двух частей набора команд для выполнения (play) и конкретных команд (task). Они выполняются друг за другом.
Все записи данных осуществляются с помощью YAMLа. К несомненным плюсам его использования следует отнести то, что он гораздо лучше воспринимается людьми, нежели тот же самый JSON. Ежели Вы больше привыкли Вы к Python, то тут у Вас не возникнет проблем с адаптацией, так как синтаксис у них схожий.
А вот так происходит процесс написания сценария (комментарии даны построчно к выводу):
- Имя сценария обязательный элемент для любого сценария;
- Сценарий применяется к машинам в подгруппе cisco-routers;
- Выключение режима сбора событий в конкретной машине (если не выключить данный режим, то система потратит много времени на решение ненужных задач);
- В разделе task указывается список команд для каждого конкретного случая;
После чего происходит выполнение команды:
PLAY [Run show commands on routers] *************************************************** TASK [run sh ip int br] *************************************************************** changed: [192.168.100.1] changed: [192.168.100.3] changed: [192.168.100.2] TASK [run sh ip route] **************************************************************** changed: [192.168.100.1] changed: [192.168.100.3] changed: [192.168.100.2] PLAY [Run show commands on switches] ************************************************** TASK [run sh int status] ************************************************************** changed: [192.168.100.100] TASK [run sh vlans] ******************************************************************* changed: [192.168.100.100] PLAY RECAP **************************************************************************** 192.168.100.1 : ok=2 changed=2 unreachable=0 failed=0 192.168.100.100 : ok=2 changed=2 unreachable=0 failed=0 192.168.100.2 : ok=2 changed=2 unreachable=0 failed=0 192.168.100.3 : ok=2 changed=2 unreachable=0 failed=0
И запускаем проверку выполнения команд:
SSH password: PLAY [Run show commands on routers] *************************************************** TASK [run s hip int br] *************************************************************** Changed: [192.168.100.1] => {“changed”: true, “rc”: 0, “stderr”: “Shared connection To 192.168.100.1 closed. ”, “stdout”: “ Interface IP-Address OK? Method Status Protocol Ethernet0/0 192. 168.100.1 YES NVRAM up up Ethernet0/1 192.168.200.1 YES NVRAM up up Loopback0 10.1.1.1 YES manual up up ”, “stdout_lines “: [“”, “Interface IP-Address OK? Method Status Protocol”, “Ethernet0/0 192.168.100.1 YES NVRAM up up “, “Ethernet0/1 192.168.200.1 YES NVRAM up up “, “Loopaback0 10.1.1.1 YES manual up up “]}
А что внутри?
А теперь поговорим о начинке сценария. Основу составляют переменные. Это могут быть данные о машине, выводы команд, а также их можно вводить вручную.
Главное не забывать правила написания имён. Их всего два:
- имена всегда должны состоять из букв, цифр и нижнего подчёркивания;
- имена всегда должны начинаться с буквы.
Переменные могут быть определены разными способами:
Инвентарным файлом
[cisco-routers] 192.168.100.1 192.168.100.2 192.168.100.3 [cisco-switches] 192.168.100.100 [cisco-routers:vars] ntp_server=192.168.255.100 log_server=10.255.100.1
PLAYBOOKом
-name: Run show commands on router: hosts: cisco-routers gather_facts: false vars: ntp_server: 192.168.255.100 log_server: 10.255.100.1 tasks: -name: run sh ip int br raw: s hip int br | ex unass -name: run s hip route raw: sh ip route
Специальными файлами, созданными для групп:
[cisco-routers] 192.168.100.1 192.168.100.2 192.168.100.3 [cisco-switches] 192.168.100.100
Или группами каталогов
|– group_vars _ | |– all.yml | | |–cisco-routers.yml | Каталог с переменными для групп устройств | |–cisco-switches.yml _| | |–host vars _ | |–192.168.100.1 | | |–192.168.100.2 | | |–192.168.100.3 | Каталог с переменными для устройств | |–192.168.100.100 _| | |–myhosts | Инвертарный файл
Команда register позволяет сохранять результаты выполнений модулей в переменные. После чего переменная может быть использована в шаблонах, принятиях решений о выполнении заданного сценария.
--- - name: Run show commands on routers hosts: cisco-routers gather_facts: false tasks: -name: run s hip int br raw: s hip int br | ex unass register: sh_ip_int_br_result ---
debug отображает информацию в стандартном потоке вывода в виде произвольной строки, переменной или фактах о машине.
--- - name: Run show commands on routers hosts: cisco-routers gather_facts: false tasks: -name: run s hip int br raw: sh ip int br | ex unass register: sh_ip_int_br_result -name: Debug registered var debug: var=sh_ip_int_br_result.stdout_lines
После чего результатом работы станет следующее:
SSH password: PLAY [Run show commands on routers] *************************************************** TASK [run sh ip int br] *************************************************************** changed: [192.168.100.1] changed: [192.168.100.2] changed: [192.168.100.3] TASK [Debug registered var] *********************************************************** ok: [192.168.100.1] => { “sh_ip_int_br_result.stdout_lines”: [ “”, “Interface IP-Address OK? Method Status Protocol”, “Ethernet0/0 192.168.100.1 YES NVRAM up up “, “Ethernet0/1 192.168.200.1 YES NVRAM up up “, “Loopback0 10.1.1.1 YES manual up up “ ] } ok: [192.168.100.2] => { “sh_ip_int_br_result.stdout_lines”: [ “”, “Interface IP-Address OK? Method Status Protocol”, “Ethernet0/0 192.168.100.1 YES NVRAM up up “, “Ethernet0/2 192.168.200.1 YES NVRAM administratively down down “, “Loopback0 10.1.1.1 YES manual up up “ ] } ok: [192.168.100.3] => { “sh_ip_int_br_result.stdout_lines”: [ “”, “Interface IP-Address OK? Method Status Protocol”, “Ethernet0/0 192.168.100.3 YES NVRAM up up “, “Ethernet0/2 192.168.200.1 YES NVRAM administratively down down “, “Loopback0 10.1.1.1 YES manual up up “, “Loopback10 10.255.3.3 YES manual up up “ ] } PLAY RECAP **************************************************************************** 192.168.100.1 : ok=2 changed=1 unreachable=0 failed=0 192.168.100.2 : ok=2 changed=1 unreachable=0 failed=0 192.168.100.3 : ok=2 changed=1 unreachable=0 failed=0
Вместо заключения
Можно ещё долго приводить примеры работы в системе, но ещё один факт так сказать "вишенка на торте". К плюсам Ansible следует отнести и то, что заданную команду система может выполнять практически до бесконечности. Пока не наступит требуемый результат трансформации не прекратятся. Пользователю можно не беспокоиться - программа сама всё сделает за Вас, а Вы можете заниматься другими делами.