Я уверен, что многие из вас знакомы с той головной болью, которая возникает при создании Network Labs. Предположим, вы просто хотите протестировать некоторые функции BGP, возможно, изучить, как использовать Route Map с фильтрацией маршрутов BGP. Как правило, вы начинаете с создания лабораторной среды. Это включает в себя выбор платформы, такой как EVE-NG или Cisco CML, добавление кучи маршрутизаторов и подключение всего с помощью виртуальных кабелей.
Как только ваша настройка будет физически готова, начнется настоящее «веселье». Вы начинаете настройку каждого маршрутизатора, задаете IP-адреса интерфейсов, добавляете описания и настраиваете атрибуты BGP, такие как соседи и сетевые операторы. Если это звучит утомительно, то это потому, что так оно и есть! Я сам настраивал интерфейсы бесчисленное количество раз, и это никогда не становится менее болезненным. Вы когда-нибудь вводили неправильный IP-адрес, а затем тратили часы на устранение неполадок, почему вы не можете проверить связь со своим пиром? Если вы киваете в знак согласия, вы определенно не одиноки. Я уже умею настраивать интерфейс, просто не хочу делать это в 1000-й раз в этом году.
И как только вы задумываетесь о некоторой автоматизации или интеграции со сторонними инструментами (NMS, NCM и т. д.), вы сталкиваетесь с еще одним набором проблем. Настройка локальных учетных записей пользователей, настройка IP-адресов управления, создание ключей SSH — это все равно, что упасть в кроличью нору. К тому времени, когда вы закончите, вы будете слишком утомлены, чтобы даже вспомнить, с чего начали, чтобы экспериментировать с этими чертовыми картами маршрутов.
Я даже не хочу начинать с мультивендора. Допустим, вы закончили работу с Cisco и теперь хотите создать такую же лабораторию для Juniper. Вам придется делать это снова. Итак, как мы можем сделать этот процесс более простым и менее болезненным? Давайте погрузимся в это в этом посте.
💡
Изначально я почерпнул эту идею из этого замечательного поста в блоге, так что спасибо автору за создание такого подробного поста в блоге
Несколько вещей перед тем, как мы начнем
Прежде чем мы углубимся в детали, есть пара вещей, которые я хочу выделить.
Во-первых, важно понимать, что здесь нет универсального решения. Если вы только начинаете свой путь в мире сетевых технологий, вам может быть полезно настраивать интерфейсы и конфигурации BGP вручную. Это руководство лучше всего подходит для сетевых инженеров, которые уже хорошо понимают основы и хотят автоматизировать некоторые из наиболее утомительных задач.
Во-вторых, я предпочитаю управлять всем в коде. Вместо того, чтобы полагаться на топологические резервные копии и другие традиционные методы, я предпочитаю иметь кучу текстовых файлов в конце моих экспериментов (Lab-as-a-Code) Эти файлы можно легко сохранить в Git или поделиться ими с коллегами. Если мне когда-нибудь понадобится вернуться в ту же лабораторию, все, что мне нужно, — это эти текстовые файлы. Такой подход может сэкономить массу времени в будущем.
Containerlab, Nornir, Napalm и Jinja2
В этой настройке я собираюсь использовать четыре разных инструмента - Containerlab, Nornir, Napalm и Jinja2. Если вы не совсем знакомы ни с одним из этих инструментов, не стесняйтесь ознакомиться с подробными постами, которые я написал в каждом из своих блогов, чтобы быстро освежить в памяти.
Вот как все складывается воедино.
- Контейнерлаб - Мы начинаем с определения топологии нашей сети в файле YAML, который Containerlab использует для развертывания сети в виде контейнеров. Это делает создание и демонтаж лабораторий невероятно простыми и эффективными.
- Норнир - Для управления запасами и выполнения задач
- Напалм- Для управления конфигурацией мы используем Napalm. Он напрямую взаимодействует с сетевыми устройствами, отправляя конфигурации и извлекая информацию при необходимости.
- Джинджа2 - Фактические сетевые конфигурации динамически генерируются с использованием шаблонов Jinja2. Это означает, что мы можем определить шаблоны для конфигураций, такие как IP-адреса интерфейса и сведения о соседях BGP, которые затем заполняются конкретными значениями, хранящимися в файле hosts Nornir.
На первый взгляд это может показаться немного запутанным, но не волнуйтесь, как только мы начнем использовать эти инструменты, их преимущества и функциональность станут намного более очевидными.
Создание простой лаборатории BGP
Хорошо, давайте поговорим о создании нашей BGP-лаборатории. Предположим, что мы хотим настроить топологию BGP, которую вы видите на схеме, с четырьмя маршрутизаторами в четырех различных автономных системах (AS), каждый из которых имеет пиринг eBGP, как показано на рисунке.
В прошлом мы могли использовать такие инструменты, как EVE-NG или CML, чтобы вручную добавлять узлы и ссылки, но это именно то, чего мы пытаемся избежать. Вместо этого мы собираемся использовать подход «Лаборатория как код», что означает определение всего в структурированном, основанном на коде формате. Для развертывания этой топологии в Containerlab нам нужен только YAML-файл, описывающий настройку.
В этом примере я также собираюсь использовать Arista EOS, потому что вы можете скачать изображения с веб-сайта Arista (требуется создание учетной записи). Если вы работаете в Cisco, не волнуйтесь, синтаксис почти идентичен, и вы сможете следить за ним.
Структура каталога
Здесь представлена структура каталогов, в которой хранятся все необходимые файлы и папки.
.
├── clab
│ └── bgp.yaml
└── nornir_files
├── config_templates
│ └── config.j2
├── config.yaml
├── defaults.yaml
├── groups.yaml
├── hosts.yaml
└── render_configs.py
В нашей основной папке проекта мы организовали наши файлы в два основных каталога.
- clab - Этот каталог предназначен для конфигураций Containerlab. Он удерживает наши bgp.yaml , в котором описывается топология сети для Containerlab для развертывания нашей лабораторной среды.
- nornir_files - Этот каталог содержит все файлы, связанные с Nornir, нашим выбором для автоматизации.
- Тем nornir_files содержит следующееconfig_templates - Подкаталог, в котором находятся наши шаблоны Jinja2. Конкретно config.j2 Здесь хранится наш шаблон для конфигураций устройств.
config.yaml - Это конфигурационный файл Nornir, который сообщает Nornir, как выполнить инициализацию и какие плагины использовать.
defaults.yaml - Файл YAML с указанием значений по умолчанию для наших хостов, таких как имена пользователей и пароли.
groups.yaml - Содержит данные, специфичные для группы, которые могут быть унаследованы хостами в Nornir.
hosts.yaml - Этот важный файл содержит сведения о каждом сетевом устройстве, такие как имена хостов и роли.
render_configs.py— скрипт Python, использующий Nornir для рендеринга и развертывания конфигураций на устройствах.
Контейнерлаб
Ниже приведен общий обзор того, что может содержать файл YAML для нашей лаборатории BGP.
#bgp.yaml
name: bgp
mgmt: network: mgmt
ipv4-subnet: 192.168.100.0/24
topology: kinds: ceos: image: ceos:4.27.12M
nodes: eos-01: kind: ceos
mgmt-ipv4: 192.168.100.11
eos-02: kind: ceos
mgmt-ipv4: 192.168.100.12
eos-03: kind: ceos
mgmt-ipv4: 192.168.100.13
eos-04: kind: ceos
mgmt-ipv4: 192.168.100.14
links: - endpoints: ["eos-01:eth1", "eos-03:eth1"] - endpoints: ["eos-02:eth1", "eos-03:eth2"] - endpoints: ["eos-04:eth1", "eos-03:eth3"]
Не вдаваясь в детали файла, скажу, что мы определяем детали управляющей сети, типы узлов, которые мы будем использовать, и соединения между ними. Также указывается IP-адрес управления каждым узлом. С помощью всего одной команды мы можем запустить лабораторию в эксплуатацию.
sudo containerlab deploy --topo bgp.yaml
Если вам интересно узнать о внутренней работе Containerlab и вы хотите глубже погрузиться в то, как она работает, обязательно ознакомьтесь с другим моим постом в блоге, посвященным этой теме.
💡
Узлы Arista, созданные Containerlab, поставляются с предварительно настроенными учетными данными пользователя и включенным доступом по SSH. Таким образом, вам не нужно ничего делать вручную, чтобы начать работу
Норнир
В нашей лаборатории Nornir играет важную роль. Это позволяет нам управлять и автоматизировать конфигурации для наших сетевых устройств с помощью различных плагинов.
#config.yaml
--- inventory: plugin: SimpleInventory
options: host_file: 'hosts.yaml' group_file: 'groups.yaml' defaults_file: 'defaults.yaml'
runner: plugin: threaded
options: num_workers: 5
#groups.yaml
--- arista: connection_options: napalm: platform: eos
extras: optional_args: transport: ssh
#defaults.yaml
--- username: admin
password: admin
Этот hosts.yaml содержит сведения о каждом устройстве в нашей топологии, такие как IP-адрес управления (hostname), к которой он принадлежит (с указанием определенного набора характеристик и конфигураций, таких как тип устройства) и пользовательские данные. Под data, мы обозначим особенности конфигураций интерфейса и настроек BGP, таких как номера AS и соседние отношения.
#hosts.yaml
--- eos-01: hostname: 192.168.100.11
groups: - arista
data: interfaces: - name: eth1
description: eos-03 ip: 12.12.12.1 255.255.255.0
bgp: asn: 1000 neighbours: - ip: 12.12.12.2
asn: 200
eos-02: hostname: 192.168.100.12
groups: - arista
data: interfaces: - name: eth1
description: eos-03 ip: 12.12.13.1 255.255.255.0
bgp: asn: 100 neighbours: - ip: 12.12.13.2
asn: 200
eos-03: hostname: 192.168.100.13
groups: - arista
data: interfaces: - name: eth1
description: eos-01 ip: 12.12.12.2 255.255.255.0
- name: eth2
description: eos-02 ip: 12.12.13.2 255.255.255.0
- name: eth3
description: eos-03 ip: 12.12.14.2 255.255.255.0
bgp: asn: 200 neighbours: - ip: 12.12.12.1
asn: 1000 - ip: 12.12.13.1
asn: 100 - ip: 12.12.14.1
asn: 2000
eos-04: hostname: 192.168.100.14
groups: - arista
data: interfaces: - name: eth1
description: eos-03 ip: 12.12.14.1 255.255.255.0
bgp: asn: 2000 neighbours: - ip: 12.12.14.2
asn: 200
Короче говоря, мы имеем дело с простым, но мощным структурированным форматом данных, который Nornir использует для рендеринга конфигураций и управления состоянием каждого устройства. Определив здесь все, мы можем автоматизировать повторяющиеся задачи, такие как настройка интерфейсов и настройка BGP, что, как мы уже обсуждали ранее, может занять много времени, если выполнять его вручную.
Помните, что это всего лишь общий обзор. Если вам не терпится углубиться в суть Nornir, обязательно ознакомьтесь с моим подробным постом об этом.
Джинджа2
Jinja2 — это невероятно универсальный язык шаблонов, который мы используем для создания фактической конфигурации для наших устройств на основе данных, которые мы определили в файле hosts.yaml файл.
#config.j2
ip routing
!
{% for interface in interfaces%} interface {{ interface.name }} no switchport
description {{ interface.description }} ip address {{ interface.ip }} no shut
!
{% endfor %} router bgp {{ bgp.asn }} {% for neighbour in bgp.neighbours %} neighbor {{ neighbour.ip }} remote-as {{ neighbour.asn }} {% endfor %} !
end
- ip routing — команда для включения IP-маршрутизации на устройстве.
- Тем {% for interface in interfaces %} цикл перебирает каждый интерфейс, определенный в параметре interfaces Список hosts.yaml файл для устройства.
- Внутри петли мы используем {{ interface.name }}, {{ interface.description }}и {{ interface.ip }} , чтобы заменить эти заполнители фактическими значениями для каждого интерфейса.
- После настройки всех интерфейсов шаблон переходит к настройке BGP.
- router bgp {{ bgp.asn }} установка номера автономной системы BGP для маршрутизатора.
- Еще один цикл, {% for neighbour in bgp.neighbours %}, перебирает всех определенных соседей BGPneighbour и устанавливает соседские отношения с neighbor {{ neighbour.ip }} remote-as {{ neighbour.asn }} команда.
Здесь Jinja2 сопоставляет переменные и циклы в шаблоне с данными из метода hosts.yaml файл. Итак, для роутера типа eos-01, он заменит {{ interface.name }} с eth1, {{ interface.description }} с eos-03и так далее. В результате получается отрисованная конфигурация, готовая к отправке на устройство.
Напалм
Для отправки конфигураций мы используем Napalm, мощную библиотеку Python, которая взаимодействует с сетевыми устройствами. Хотя Netmiko также могла справиться с этой задачей, я остановил свой выбор на Napalm.
Чтобы начать работу с Napalm (с Nornir), нам сначала нужно установить nornir_napalm плагин. Кроме того, нам требуется nornir_jinja2 плагин для рендеринга наших шаблонов Jinja2.
pip install nornir_napalm
pip install nornir_jinja2
Вот скрипт Nornir, который использует плагины Napalm и Jinja2. У меня есть две функции (задачи). Первый из них отрисовывает необходимые конфигурации, а вторая задача отправляет отрисованную конфигурацию на каждое устройство.
#render_configs.py
from nornir import InitNornir
from nornir_napalm.plugins.tasks import napalm_configure
from nornir_utils.plugins.functions import print_result
from nornir_jinja2.plugins.tasks import template_file
def render_config(task): template = 'config.j2' result = task.run(task=template_file, template=template, path='config_templates/', **task.host) rendered_config = result[0].result
task.host['rendered_config'] = rendered_config
def napalm_send_config(task): host = task.host
config = host['rendered_config'] task.run(task=napalm_configure, configuration=config, dry_run=False)
nr = InitNornir(config_file='config.yaml') result = nr.run(task=render_config) result1 = nr.run(task=napalm_send_config)
print_result(result1)
Вот отрисованный конфиг для eos-01
render_config*******************************************************************
* eos-01 ** changed : False ****************************************************
vvvv render_config ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
---- template_file ** changed : False ------------------------------------------ INFO
ip routing
!
interface eth1
no switchport
description eos-03
ip address 12.12.12.1 255.255.255.0
no shut
!
interface Loopback1
no switchport
description test_network
ip address 100.100.1.1 255.255.255.0
no shut
!
router bgp 1000
neighbor 12.12.12.2 remote-as 200
network 100.100.1.0 mask 255.255.255.0
!
end
^^^^ END render_config ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
napalm_send_config************************************************************** * eos-01 ** changed : True ***************************************************** vvvv napalm_send_config ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
---- napalm_configure ** changed : True ---------------------------------------- INFO
@@ -22,12 +22,18 @@
transport ssh default
!
interface Ethernet1
+ description eos-03 + no switchport
+ ip address 12.12.12.1/24 !
interface Management0
ip address 192.168.100.11/24 !
-no ip routing
+ip routing
!
ip route 0.0.0.0/0 192.168.100.1 !
+router bgp 1000 + neighbor 12.12.12.2 remote-as 200 +!
end
^^^^ END napalm_send_config ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * eos-02 ** changed : True ***************************************************** vvvv napalm_send_config ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
---- napalm_configure ** changed : True ---------------------------------------- INFO
@@ -22,12 +22,18 @@
transport ssh default
!
interface Ethernet1
+ description eos-03 + no switchport
+ ip address 12.12.13.1/24 !
interface Management0
ip address 192.168.100.12/24 !
-no ip routing
+ip routing
!
ip route 0.0.0.0/0 192.168.100.1 !
+router bgp 100 + neighbor 12.12.13.2 remote-as 200 +!
end
^^^^ END napalm_send_config ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * eos-03 ** changed : True ***************************************************** vvvv napalm_send_config ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
---- napalm_configure ** changed : True ---------------------------------------- INFO
@@ -22,16 +22,30 @@
transport ssh default
!
interface Ethernet1
+ description eos-01 + no switchport
+ ip address 12.12.12.2/24 !
interface Ethernet2
+ description eos-02 + no switchport
+ ip address 12.12.13.2/24 !
interface Ethernet3
+ description eos-03 + no switchport
+ ip address 12.12.14.2/24 !
interface Management0
ip address 192.168.100.13/24 !
-no ip routing
+ip routing
!
ip route 0.0.0.0/0 192.168.100.1 !
+router bgp 200 + neighbor 12.12.12.1 remote-as 1000 + neighbor 12.12.13.1 remote-as 100 + neighbor 12.12.14.1 remote-as 2000 +!
end
^^^^ END napalm_send_config ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * eos-04 ** changed : True ***************************************************** vvvv napalm_send_config ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
---- napalm_configure ** changed : True ---------------------------------------- INFO
@@ -22,12 +22,18 @@
transport ssh default
!
interface Ethernet1
+ description eos-03 + no switchport
+ ip address 12.12.14.1/24 !
interface Management0
ip address 192.168.100.14/24 !
-no ip routing
+ip routing
!
ip route 0.0.0.0/0 192.168.100.1 !
+router bgp 2000 + neighbor 12.12.14.2 remote-as 200 +!
end
^^^^ END napalm_send_config ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Если я войду в систему на устройствах, я смогу проверить связь с IP-адресом однорангового узла, и сессия BGP должна быть установлена. Давайте проверим это на паре устройств.
eos-01#ping 12.12.12.2
PING 12.12.12.2 (12.12.12.2) 72(100) bytes of data.
80 bytes from 12.12.12.2: icmp_seq=1 ttl=64 time=0.099 ms
80 bytes from 12.12.12.2: icmp_seq=2 ttl=64 time=0.030 ms
80 bytes from 12.12.12.2: icmp_seq=3 ttl=64 time=0.017 ms
80 bytes from 12.12.12.2: icmp_seq=4 ttl=64 time=0.015 ms
80 bytes from 12.12.12.2: icmp_seq=5 ttl=64 time=0.005 ms
eos-01#show ip bgp summary
BGP summary information for VRF default
Router identifier 12.12.12.1, local AS number 1000
Neighbor Status Codes: m - Under maintenance
Neighbor V AS MsgRcvd MsgSent InQ OutQ Up/Down State PfxRcd PfxAcc
12.12.12.2 4 200 7 7 0 0 00:02:59 Estab 0 0
eos-01#show run | sec bgp
router bgp 1000
neighbor 12.12.12.2 remote-as 200
eos-04#show ip bgp summary
BGP summary information for VRF default
Router identifier 12.12.14.1, local AS number 2000
Neighbor Status Codes: m - Under maintenance
Neighbor V AS MsgRcvd MsgSent InQ OutQ Up/Down State PfxRcd PfxAcc
12.12.14.2 4 200 8 8 0 0 00:03:28 Estab 0 0
Добавление дополнительных конфигураций
Теперь предположим, что мы хотим добавить интерфейс Loopback в eos-01 и внедрять его маршрут в BGP без ручной настройки через CLI.
В hosts.yaml , мы добавили новый интерфейс в раздел interfaces Секция для eos-01. Мы также добавилиprefixes раздел в hosts.yaml для eos-01 , чтобы включить новую сеть в процесс BGP.
#hosts.yaml
--- eos-01: hostname: 192.168.100.11
groups: - arista
data: interfaces: - name: eth1
description: eos-03 ip: 12.12.12.1 255.255.255.0
- name: Loopback1 #new lines description: test_network
ip: 100.100.1.1 255.255.255.0
bgp: asn: 1000 neighbours: - ip: 12.12.12.2
asn: 200 prefixes: #new lines - ip: 100.100.1.0
mask: 255.255.255.0
<< TRUNCATED >>
Теперь давайте обсудим изменения в шаблоне Jinja2. мы изменили раздел BGP для обработки новых prefixes структура (сетевые операторы), которая теперь включает в себя отдельные ip и mask Поля. (Строки #17 - 21)
#config.j2
ip routing
!
{% for interface in interfaces%} interface {{ interface.name }} no switchport
description {{ interface.description }} ip address {{ interface.ip }} no shut
!
{% endfor %} router bgp {{ bgp.asn }} {% for neighbour in bgp.neighbours %} neighbor {{ neighbour.ip }} remote-as {{ neighbour.asn }} {% endfor %} {% if prefixes %} {% for prefix in prefixes %} network {{ prefix.ip }} mask {{ prefix.mask }} {% endfor %} {% endif %} !
end
С этими корректировками шаблон теперь считывает IP и маску отдельно для каждой записи в разделе prefixes и использует их для создания операторов сети BGP, которые будут использоваться для объявления этих сетей.
Обновив файл hosts.yaml и Jinja2 и перезапустив скрипт, мы эффективно добавляем конфигурацию интерфейса Loopback и связанную с ней рекламу маршрута в конфигурацию BGP, и все это автоматизированным, повторяемым и безошибочным способом. Вот вывод Nornir/Napalm при повторном запуске скрипта.
Тем + Знак указывает на строки конфигурации, добавляемые к устройству. Мы также видим, что в остальных 3 устройствах нет никаких изменений. Если я перейду на eos-04, я должен увидеть новый префикс в таблице BGP, который поступает из eos-01
eos-04#show ip bgp
BGP routing table information for VRF default
Network Next Hop Metric AIGP LocPref Weight Path
* > 100.100.1.0/24 12.12.14.2 0 - 100 0 200 1000 i
Куда мы идем дальше?
Теперь давайте представим, что вы все настроили, погрузились в некоторые конфигурации BGP, и все пошло немного наперекосяк, мы все были там, не так ли? Прелесть этого подхода заключается в простоте начать все сначала. Если вы ошибетесь, все, что нужно, чтобы вернуться к исходной точке, — это снести лабораторию и воссоздать ее, что займет всего несколько минут. В этом и заключается сила «Lab-as-a-Code».
А что, если вы хотите изменить ситуацию и работать с Juniper, а не с Arista? Никаких проблем. Все, что вам нужно сделать, это обновить файл топологии, чтобы заменить контейнер Arista на контейнер Juniper, создать новый шаблон Jinja2, который говорит на языке Junos, и отправить конфигурации.
Заключение
Надеюсь, вы нашли это пошаговое руководство простым и легким для понимания. Я избегал слишком глубокого погружения в каждую деталь, чтобы не нагружать вас большим постом в блоге.
Я хотел бы услышать ваше мнение по этому поводу. Если у вас есть комментарии, вопросы или отзывы, оставьте их в разделе комментариев. Я всегда стремлюсь совершенствоваться и делиться знаниями, которые могут сделать нашу жизнь в нетворкинге немного проще. Спасибо, что прочитали 🙃
Ссылки
https://juliopdx.com/2021/12/10/my-journey-and-experience-with-containerlab/