Как стать автором
Обновить

Книга «Python для сетевых инженеров. Автоматизация сети, программирование и DevOps»

Время на прочтение13 мин
Количество просмотров27K
image Привет, Хаброжители!
Сети образуют основу для развертывания, поддержки и обслуживания приложений. Python — идеальный язык для сетевых инженеров, предлагающий инструменты, которые ранее были доступны только системным инженерам и разработчикам приложений. Прочитав эту книгу, вы из обычного сетевого инженера превратитесь в сетевого разработчика, подготовленного ко встрече с сетями следующего поколения.
Третье издание полностью переработано и обновлено для использования Python 3. Помимо новых глав, посвященных анализу сетевых данных с помощью стека ELK (Elasticsearch, Logstash, Kibana и Beats) и Azure Cloud Networking, в него включены сведения по использованию Ansible и фреймворков pyATS и Nornir. Кроме того, были обновлены примеры для лучшего понимания концепций и обеспечения совместимости.

Для кого эта книга
Эта книга идеально подойдет ИТ-специалистам и инженерам, которые занимаются администрированием сетевых устройств и хотят расширить свои знания о Python и других инструментах для решения сетевых проблем. Желательно иметь хотя бы базовое понимание сетевых технологий и Python.

Сетевой мониторинг с использованием Python: часть 1


Представьте, что вам позвонили в два часа ночи из центра управления сетью вашей компании. Вы подняли трубку и слышите следующее: «Здравствуйте, у нас возникла серьезная проблема, которая сказывается на работе наших промышленных сервисов. Мы подозреваем, что она может быть связана с сетью. Можете проверить?» Что бы вы ответили в такой неотложной ситуации? В большинстве случаев на ум приходит следующее: какие изменения вносились перед тем, как возникли проблемы? Вы, скорее всего, откроете систему мониторинга и проверите, какие метрики поменялись за последние пару часов. А еще лучше, если вы уже получили оповещение, что определенные показатели вышли за рамки нормального диапазона.

На страницах книги мы постоянно обсуждаем способы систематического внесения предсказуемых изменений в сетевую конфигурацию, чтобы обеспечить максимально беспроблемную работу сети. Однако сети далеко не статические — это, наверное, одна из самых изменчивых частей вашей инфраструктуры. Они по определению соединяют разные инфраструктурные компоненты, постоянно передавая трафик туда-сюда.

Сеть может перестать работать так, как мы того от нее ожидаем, по множеству причин: аппаратные сбои, ошибки в программном обеспечении, ошибки, допущенные людьми (несмотря на благие намерения), и многое другое. Вопрос не в том, пойдет ли что-то не так, а скорее — когда это случится и что именно при этом сломается. Мы всегда должны следить за работой нашей сети, и желательно получать уведомления в случае возникновения проблем.

В этой и следующей главах мы рассмотрим разные способы организации мониторинга сети. Многие инструменты, которые мы уже рассмотрели, можно объединять или напрямую использовать с помощью Python. Как и многие другие механизмы, о которых мы узнали, сетевой мониторинг состоит из двух частей.
Первое: нам нужно понять, какую информацию наше оборудование способно передавать. И второе: мы должны определить, какие полезные сведения мы можем из нее извлечь.

Начнем эту главу с обзора инструментов для эффективного мониторинга сети, таких как:

  • подготовка лаборатории;
  • протокол SNMP (Simple Network Management Protocol — простой протокол сетевого управления) и сопутствующие библиотеки для работы с ним в Python;
  • библиотеки визуализации для Python:
  • Matplotlib и примеры;
  • Pygal и примеры;
  • интеграция Python с MRTG и Cacti для визуализации сети.

Это далеко не полный список. На рынке сетевого мониторинга явно нет недостатка в коммерческих решениях. Но для простых задач, которые мы будем рассматривать, хорошо подойдут как коммерческие, так и открытые инструменты.

Подготовка лаборатории


Здесь наша лаборатория — как в главе 6, но с одним отличием: оба сетевых устройства будут работать под управлением IOSv (рис. 7.1).

image

Два хоста с Ubuntu будут генерировать сетевой трафик, чтобы мы могли получить ненулевые метрики.

SNMP


SNMP — это стандартный протокол администрирования устройств и сбора сведений о них. По моему опыту, большинство сетевых администраторов используют SNMP только в качестве механизма получения информации. Поскольку SNMP работает поверх протокола UDP, который не поддерживает постоянных соединений, и учитывая относительно слабую защиту в версиях 1 и 2, внесение изменений в конфигурацию устройств с помощью SNMP вызывает у операторов сетей некоторое беспокойство. В версии 3 появилась поддержка шифрования, а также новые концепции и терминология, но ее внедрение зависит от поставщика оборудования.

Протокол SNMP был представлен в 1988 году, описан в RFC 1065 и широко применяется в сетевом мониторинге. Работать с ним просто: диспетчер шлет устройству GET- и SET-запросы, а устройство, если на нем установлен SNMP-агент, возвращает в ответ информацию. Самый распространенный стандарт — SNMPv2c, описанный в RFC 1901 — RFC 1908. Для защиты в нем применяется простой механизм безопасности, разработанный сообществом. В нем также появились новые возможности, такие как получение массивов информации. На рис. 7.2 показан общий принцип работы SNMP.

image

Информация, хранящаяся на устройстве, структурирована в базе управляющей информации (Management Information Base, MIB). MIB использует иерархическое пространство имен с идентификатором объекта (Object Identifier, OID), представляющее сведения, которые можно прочитать и вернуть запрашивающей стороне. Говоря об извлечении информации с помощью SNMP, мы на самом деле имеем в виду использование управляющего хоста для выполнения запроса по определенному OID, который возвращает нужные нам данные. Производители устройств используют общие OID для своих систем и интерфейсов. Но некоторые OID могут предоставляться специально для отдельных предприятий.

Чтобы можно было извлекать полезную информацию, администратор сети должен приложить некоторые усилия для систематизации данных в формате OID. Иногда этот процесс оказывается утомительным и заключается в поиске отдельных идентификаторов. Например, вы можете обратиться к OID устройства и получить в ответ значение 10 000. Что это такое? Трафик, проходящий через интерфейс? Это биты или байты? А может, количество пакетов? Откуда мы знаем? Чтобы ответить на эти вопросы, нам нужно свериться либо со стандартом, либо с документацией производителя. Этот процесс можно упростить с помощью таких инструментов, как MIB Browser, который предоставляет метаданные для конкретного значения. Но, по моему опыту, создание системы мониторинга на основе SNMP иногда выглядит как игра в кошки-мышки, когда вы пытаетесь найти то самое недостающее значение.

Несколько основных аспектов SNMP, о которых стоит помнить.

  • Реализация во многом зависит от количества информации, которую способно предоставить устройство. А это, в свою очередь, зависит от того, как производитель относится к SNMP: как к неотъемлемой части системы или как к дополнительной возможности.
  • Обычно для возвращения значения SNMP-агенты отнимают процессорное время у управляющего уровня. Из-за этого протокол SNMP неэффективен на устройствах, к примеру, с большими BGP-таблицами; что еще хуже, его нецелесообразно использовать для частого извлечения данных.
  • Чтобы запросить данные, пользователь должен знать OID.

Поскольку протокол SNMP существует давно, я предполагаю, что вы уже с ним сталкивались. Приступим сразу к установке пакетов и нашему первому примеру с SNMP.

Подготовка


Для начала убедимся, что в нашей конфигурации есть управляющее устройство и агент с поддержкой SNMP. Пакет SNMP можно установить как на хостах (клиенте или сервере), так и на управляющем устройстве. Главное, чтобы диспетчер SNMP имел доступ к устройству и управляемое устройство принимало входящие соединения. В промышленных условиях установку следует делать только на управляющий хост, а SNMP-трафик должен быть разрешен только на управляющем уровне.

В этой лабораторной работе мы устанавливаем SNMP как на хост с Ubuntu в сети управления, так и на клиентский хост.
Организация внешнего доступа к хостам VIRL описывается в главе 6.

$ sudo apt-get update
$ sudo apt-get install snmp

Дальше нужно включить протокол SNMP и сконфигурировать его параметры на сетевых устройствах iosv-1 и iosv-2. Нам доступно много дополнительных параметров: контакт, местоположение, ID шасси и размер пакетов SNMP. Их список зависит от устройства, поэтому вам следует свериться с документацией своего поставщика. На устройствах IOSv мы настроим список доступа, чтобы принимать запросы только от нужных нам хостов, и привяжем этот список к неизменяемой строке сообщества SNMP. В примере в качестве этой строки будет использоваться слово secret, а список доступа будет называться permit_snmp:

!
ip access-list standard permit_snmp
permit 172.16.1.123 log
deny any log
!
snmp-server community secret RO permit_snmp
!

Строка сообщества SNMP играет роль пароля, разделяемого диспетчером и агентом; следовательно, ее необходимо включать в любой запрос, посылаемый устройству.

Как уже упоминалось в этой главе, поиск подходящего OID зачастую составляет значительную часть работы с SNMP. Для этого можно использовать Cisco IOS MIB Locator (http://tools.cisco.com/ITDIT/MIBS/servlet/index).

В качестве альтернативы мы можем пройтись по дереву SNMP для устройств Cisco, начиная с вершины: .1.3.6.1.4.1.9. Мы проведем обход, чтобы убедиться в корректной работе SNMP-агента и списка доступа:

iso.3.6.1.4.1.9.2.1.1.0 = STRING: "
Bootstrap program is IOSv
"
iso.3.6.1.4.1.9.2.1.2.0 = STRING: "reload"
iso.3.6.1.4.1.9.2.1.3.0 = STRING: "iosv-1"
iso.3.6.1.4.1.9.2.1.4.0 = STRING: "virl.info"
<опущено>

Сделаем наш запрос по OID более конкретным:

$ snmpwalk -v2c -c secret 172.16.1.189 .1.3.6.1.4.1.9.2.1.61.0
iso.3.6.1.4.1.9.2.1.61.0 = STRING: "cisco Systems, Inc.
170 West Tasman Dr.
San Jose, CA 95134-1706
U.S.A.
Ph +1-408-526-4000
Customer service 1-800-553-6387 or +1-408-526-7208
24HR Emergency 1-800-553-2447 or +1-408-526-7209
Email Address tac@cisco.com
World Wide Web www.cisco.com"

Что произойдет, если поменять в конце одну цифру, подставив 1 вместо 0? Вот что мы увидим:

$ snmpwalk -v2c -c secret 172.16.1.189 .1.3.6.1.4.1.9.2.1.61.1
iso.3.6.1.4.1.9.2.1.61.1 = No Such Instance currently exists at this OID

В отличие от API-вызовов этот вывод не предоставляет никакого сообщения или кода ошибки; он просто утверждает, что данный OID не существует. Иногда это может быть довольно неприятно.

Напоследок проверим список доступа, который должен отклонять нежелательные SNMP-запросы. Поскольку ключевое слово log в списке доступа указано как для разрешительных, так и для запретительных записей, запросы к устройствам сможет выполнять только хост 172.16.1.123:

*Sep 29 16:39:19.857: %SEC-6-IPACCESSLOGNP: list permit_snmp permitted 0
172.16.1.123 -> 0.0.0.0, 1 packet

Как видите, основная трудность конфигурации SNMP состоит в поиске подходящего OID. Некоторые OID определены в стандартизованных базах MIB-2, а другие входят в ту часть дерева, которая относится к конкретному предприятию. Эту информацию лучше всего искать в документации поставщика. В этом вам поможет ряд инструментов; например, вы можете ввести MIB (опять же предоставленные поставщиком) в MIB Browser и получить описание корпоративных OID. Существенную помощь в поиске идентификаторов объектов может оказать SNMP Object Navigator от Cisco (http://snmp.cloudapps.cisco.com/Support/SNMP/do/BrowseOID.do?local=en).

PySNMP


PySNMP — это кросс-платформенная реализация SNMP на чистом языке Python, разработанная Ильей Етингофом (https://github.com/etingof). Она инкапсулирует множество деталей протокола SNMP и поддерживает как Python 2, так и Python 3.
Для работы с PySNMP требуется пакет PyASN1. Вот что об этом написано в Википедии:
«ASN.1 — это стандарт и нотация описания правил и структур для представления, кодирования, передачи и декодирования данных в телекоммуникациях и компьютерных сетях».
PyASN1 — это удобная обертка вокруг ASN.1 для Python. Сначала установим этот пакет. Обратите внимание, что все действия выполняются в виртуальном окружении, поэтому здесь используется интерпретатор Python из виртуального окружения:

(venv) $ cd /tmp
(venv) $ git clone github.com/etingof/pyasn1.git
(venv) $ git checkout 0.2.3
(venv) $ python setup.py install # обратите внимание на путь venv
Установим пакет PySNMP:
(venv) $ cd /tmp
(venv) $ git clone github.com/etingof/pysnmp
(venv) $ cd pysnmp/
(venv) $ git checkout v4.3.10
(venv) $ python setup.py install # обратите внимание на путь venv

Мы используем более старую версию PySNMP, так как в версии 5.0.0 был удален модуль pysnmp.entity.rfc3413.oneliner (https://github.com/etingof/pysnmp/blob/a93241007b970c458a0233c16ae2ef82dc107290/CHANGES.txt). Если вы устанавливаете пакеты с помощью pip, то эти примеры, скорее всего, не будут работать.
Посмотрим, как с помощью PySNMP получить ту же контактную информацию компании Cisco, которую мы использовали в предыдущем примере. Это слегка отредактированный пример со страницы pysnmp.readthedocs.io/en/latest/faq response-values-mib-resolution.html. Сначала импортируем нужный нам модуль и создадим объект CommandGenerator:

>>> from pysnmp.entity.rfc3413.oneliner import cmdgen
>>> cmdGen = cmdgen.CommandGenerator()
>>> cisco_contact_info_oid = "1.3.6.1.4.1.9.2.1.61.0"

Мы можем выполнить SNMP-запрос с помощью метода getCmd. Ответ будет распакован в ряд переменных, из которых нас больше всего интересует varBinds с результатом запроса:

>>> errorIndication, errorStatus, errorIndex, varBinds = cmdGen.getCmd(
cmdgen.CommunityData('secret'),
cmdgen.UdpTransportTarget(('172.16.1.189', 161)),
cisco_contact_info_oid)
>>> for name, val in varBinds:
print('%s=%s' % (name.prettyPrint(), str(val)))
SNMPv2-SMI::enterprises.9.2.1.61.0=cisco Systems, Inc.
170 West Tasman Dr.
San Jose, CA 95134-1706
U.S.A.
Ph +1-408-526-4000
Customer service 1-800-553-6387 or +1-408-526-7208
24HR Emergency 1-800-553-2447 or +1-408-526-7209
Email Address tac@cisco.com
World Wide Web www.cisco.com
>>>

Обратите внимание: значения в ответе являются объектами PyASN1. Метод prettyPrint() может привести некоторые из них в удобочитаемый вид, но varBinds придется преобразовывать вручную. Мы превратили ее в строку.

Теперь на основе предыдущего интерактивного примера можно написать сценарий с проверкой ошибок. Назовем его pysnmp_1.py. И мы можем передать методу getCmd() сразу несколько OID:

#!/usr/bin/env/python3
from pysnmp.entity.rfc3413.oneliner import cmdgen
cmdGen = cmdgen.CommandGenerator()
system_up_time_oid = "1.3.6.1.2.1.1.3.0"
cisco_contact_info_oid = "1.3.6.1.4.1.9.2.1.61.0"
errorIndication, errorStatus, errorIndex, varBinds = cmdGen.getCmd(
cmdgen.CommunityData('secret'),
cmdgen.UdpTransportTarget(('172.16.1.189', 161)),
system_up_time_oid,
cisco_contact_info_oid
)
# Проверяем ошибки и выводим результаты
if errorIndication:
print(errorIndication)
else:
if errorStatus:
print('%s at %s' % (
errorStatus.prettyPrint(),
errorIndex and varBinds[int(errorIndex)-1] or '?'
)
)
else:
for name, val in varBinds:
print('%s = %s' % (name.prettyPrint(), str(val)))

Результаты будут распакованы, и мы получим значения двух OID:

$ python pysnmp_1.py
SNMPv2-MIB::sysUpTime.0 = 599083
SNMPv2-SMI::enterprises.9.2.1.61.0 = cisco Systems, Inc.
170 West Tasman Dr.
San Jose, CA 95134-1706
U.S.A.
Ph +1-408-526-4000
Customer service 1-800-553-6387 or +1-408-526-7208
24HR Emergency 1-800-553-2447 or +1-408-526-7209
Email Address tac@cisco.com
World Wide Web www.cisco.com

В следующем примере мы сохраним значения, полученные в ответ на запрос, для выполнения других действий с данными, таких как визуализация. Для вывода значений, относящихся к интерфейсам, воспользуемся ifEntry из MIB-2.

Вы можете найти ряд ресурсов с описанием дерева ifEntry; вот снимок страницы сайта Cisco SNMP Object Navigator, который мы использовали для ifEntry (рис. 7.3)

image

Выполним небольшую проверку, чтобы показать, какие OID имеют интерфейсы устройства:

$ snmpwalk -v2c -c secret 172.16.1.189 .1.3.6.1.2.1.2.2.1.2
iso.3.6.1.2.1.2.2.1.2.1 = STRING: "GigabitEthernet0/0"
iso.3.6.1.2.1.2.2.1.2.2 = STRING: "GigabitEthernet0/1"
iso.3.6.1.2.1.2.2.1.2.3 = STRING: "GigabitEthernet0/2"
iso.3.6.1.2.1.2.2.1.2.4 = STRING: "Null0"
iso.3.6.1.2.1.2.2.1.2.5 = STRING: "Loopback0"

Согласно документации, значения ifInOctets(10), ifInUcastPkts(11), ifOutOctets(16) и ifOutUcastPkts(17) можно отобразить в соответствующие значения OID. Например, в документации для CLI и MIB сказано, что пакеты, выходящие из GigabitEthernet0/0, имеют OID 1.3.6.1.2.1.2.2.1.17.1. Тот же процесс можно повторить и для остальных OID. Когда вы проверяете пакеты между CLI и SNMP, помните, что значения должны быть близкими, но не обязательно одинаковыми, так как между получением вывода в терминале и отправкой SNMP-запроса по каналу связи может пройти какой-то трафик:

iosv-1#sh int gig 0/0 | i packets
5 minute input rate 0 bits/sec, 0 packets/sec
5 minute output rate 0 bits/sec, 0 packets/sec
6872 packets input, 638813 bytes, 0 no buffer
4279 packets output, 393631 bytes, 0 underruns
$ snmpwalk -v2c -c secret 172.16.1.189 .1.3.6.1.2.1.2.2.1.17.1
iso.3.6.1.2.1.2.2.1.17.1 = Counter32: 4292

В промышленных условиях результаты, скорее всего, записываются в базу данных. Но поскольку это всего лишь пример, мы сохраним полученные значения в плоский файл. Напишем сценарий pysnmp_3.py для информационных запросов и определим в нем OID, которые нам нужно запрашивать:

system_name = '1.3.6.1.2.1.1.5.0'
# OID интерфейса
gig0_0_in_oct = '1.3.6.1.2.1.2.2.1.10.1'
gig0_0_in_uPackets = '1.3.6.1.2.1.2.2.1.11.1'
gig0_0_out_oct = '1.3.6.1.2.1.2.2.1.16.1'
gig0_0_out_uPackets = '1.3.6.1.2.1.2.2.1.17.1'

Эти значения будут использоваться в функции snmp_query(), которая принимает на вход host, community и oid:

def snmp_query(host, community, oid):
errorIndication, errorStatus, errorIndex, varBinds = cmdGen.getCmd(
cmdgen.CommunityData(community),
cmdgen.UdpTransportTarget((host, 161)),
oid
)

Все значения помещаются в словарь с разными ключами и записываются в файл с именем results.txt:

result = {}
result['Time'] = datetime.datetime.utcnow().isoformat()
result['hostname'] = snmp_query(host, community, system_name)
result['Gig0-0_In_Octet'] = snmp_query(host, community, gig0_0_in_oct)
result['Gig0-0_In_uPackets'] = snmp_query(host, community, gig0_0_in_
uPackets)
result['Gig0-0_Out_Octet'] = snmp_query(host, community, gig0_0_out_oct)
result['Gig0-0_Out_uPackets'] = snmp_query(host, community, gig0_0_
out_uPackets)
with open('/home/echou/Master_Python_Networking/Chapter7/results.txt',
'a') as f:
f.write(str(result))
f.write('\n')

В результате мы получим файл с пакетами, представленными в интерфейсе в момент запроса:

$ cat results.txt
{'Gig0-0_In_Octet': '3990616', 'Gig0-0_Out_uPackets': '60077', 'Gig0-
0_In_uPackets': '42229', 'Gig0-0_Out_Octet': '5228254', 'Time': '2017-03-
06T02:34:02.146245', 'hostname': 'iosv-1.virl.info'}
{'Gig0-0_Out_uPackets': '60095', 'hostname': 'iosv-1.virl.info', 'Gig0-0_
Out_Octet': '5229721', 'Time': '2017-03-06T02:35:02.072340', 'Gig0-0_In_
Octet': '3991754', 'Gig0-0_In_uPackets': '42242'}
<опущено>

Мы можем сделать этот сценарий выполняемым и запланировать его запуск раз в пять минут с помощью cron:

$ chmod +x pysnmp_3.py
# crontab configuration
*/5 * * * * /home/echou/Mastering_Python_Networking_third_edition/
Chapter07/pysnmp_3.py

Повторяю, что в промышленном окружении мы бы поместили информацию в базу данных. В реляционной БД уникальные идентификаторы можно использовать в качестве первичного ключа. В NoSQL первичным индексом (или ключом) может выступать время (так как оно никогда не повторяется), за которым следуют разные пары вида «ключ — значение».

Подождем, пока этот сценарий выполнится несколько раз, чтобы он записал нужные нам значения. Если вам не терпится, сократите интервал выполнения задания cron до 1 минуты. Когда в файле results.txt накопится достаточно данных для построения графика, можно переходить к следующему разделу, в котором вы увидите, как визуализировать данные с помощью Python.

Об авторе
Эрик Чоу — IT-технолог с более чем двадцатилетним опытом. Имел дело с крупнейшими сетями в индустрии, работая в Amazon, Azure и других компаниях из списка Fortune 500. Эрик страстно увлекается автоматизацией сетей и языком Python и помогает организациям в создании эффективных механизмов безопасности.

Более подробно с книгой можно ознакомиться на сайте издательства:

» Оглавление
» Отрывок

По факту оплаты бумажной версии книги на e-mail высылается электронная книга.

Для Хаброжителей скидка 30% по купону — Python
Теги:
Хабы:
Всего голосов 12: ↑12 и ↓0+12
Комментарии5

Публикации

Информация

Сайт
piter.com
Дата регистрации
Дата основания
Численность
201–500 человек
Местоположение
Россия