Балансировка двух провайдеров на основе BGP и EEM

Статья рассматривает способ управления BPG-анонсами на маршрутизаторах Cisco, c операционной системой IOS XE, с помощью Cisco Embedded Event Manager (EEM) для балансировки входящего трафика и резервирования uplink от нескольких вышестоящих провайдеров.



Введение


Часто в сети небольшого провайдера можно встретить ситуацию, когда uplink представляет собой BGP-присоединение к двум или более операторам. Причем, второй провайдер используется не в качестве резерва, а вместе и одновременно с первым. Кроме того, ситуация осложняется тем, что каналы эти могут быть не симметричны по скорости. Например, при общей потребности uplink в 2 Gbps покупается два канала у двух разных провайдеров: 1500 Mbps и 500 Mbps. Протокол BGP, в этом случае замечательно решает задачу резервирования. Конечно, полноценного резерва тут нет. Очевидно, что нельзя зарезервировать два гигабита пятьюстами мегабитами без деградации сервиса для абонентов, однако, полного отказа услуги не произойдет. А если отказ произойдет не в ЧНН (часы наибольшей нагрузки), то сервис может не пострадать вовсе.


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


Рассмотрим, в качестве примера, следующую схему:


Схема сети


«Наша» AS65000 подключена в двум провайдерам: ISP #1 (AS65001) и ISP #2 (AS65002) по каналам шириной 1,5 Gbps и 500 Mbps, соответственно. Абоненты в нашей сети находятся за тремя локальными маршрутизаторами R7, R8 и R9 и используют, соответственно, три подсети:


  • 172.16.7.0/24
  • 172.16.8.0/24
  • 172.16.9.0/24

В качестве «ресурсов глобальной сети Интернет» выступают три маршрутизатора:


  • R5 (AS65050, 10.0.5.0/24) – имеет присоединение к обоим провайдерам;
  • R10 (AS65100, 10.0.10.0/24) – присоединен только к ISP#1;
  • R11 (AS65110, 10.0.11.0/24) – присоединен только к ISP#2.

Провайдеры имеют между собой пиринговый стык (между R12 и R13).


В отличии от клиентского присоединения, загрузка которого прямо связано с выручкой провайдера, пиринговый стык может не приносить провайдеру непосредственный доход, а то и вовсе, быть расходным. Поэтому нормальной практикой является увеличение BPG Local Preference для клиентских присоединений, и его уменьшение для пиров. На нашей схеме значения local preference обозначены красными маркерами: на пиринге у обоих провайдеров стоит значение 100 (по умолчанию), а на соединениях с нами, как с клиентом, увеличенное 120. Такой вариант позволяет провайдеру, при получении одинакового BPG-маршрута от клиента и другого провайдера, явным образом отдавать предпочтение клиентскому присоединению. Одновременно, именно это и является одной из причин трудностей с балансировкой uplink стандартными средствами BGP.


Бадансировка


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


  • 1500 Mbps через ISP#1;
  • 500 Mbps через ISP#2.

Эмпирическим путем устанавливаем два диапазона IP-адресов, которые «потребляют» трафик в требуемой нам пропорции. Для простоты ситуации (принцип метода от этого не меняется) допустим, что абоненты за маршрутизаторами R7 и R8 потребляют примерно три четверти общего входящего трафика, а оставшаяся четверть приходится на абонентов маршрутизатора R9. В таком случае, использую BGP анонсы, мы должны добиться что бы трафик для сетей 172.16.7.0/24 и 172.16.8.0/24 шел через ISP#1, а для сети 172.16.9.0/24 – через ISP#2.


Сформируем два префикс-листа и рассмотрим методы, которыми мы можем разделить трафик для них по каналам:


ip prefix-list isp-1-out seq 5 permit 172.16.7.0/24
ip prefix-list isp-1-out seq 10 permit 172.16.8.0/24

ip prefix-list isp-2-out seq 5 permit 172.16.9.0/24

AS-PATH Prepend


В качестве стандартного решения такой задачи протокол BGP предлагает механизм AS-PATH Prepend. Суть его в том, что при выборе лучшего маршрута из нескольких возможных, протокол BGP использует значение атрибута AS-PATH, где последовательно перечислены номера всех автономных систем, через которые прошел BGP-анонс. Маршрут с кратчайшим AS-PATH является предпочтительным. Метод AS-PATH prepend позволяет искусственно удлинить значение атрибута для некоторых маршрутов.


Попробуем применить этот метод в нашей сети. Для этого создадим на CSR два route-map и используем их:


route-map isp-1-out permit 10
 match ip address prefix-list isp-1-out
route-map isp-1-out permit 20
 match ip address prefix-list isp-2-out
 set as-path prepend 65000 65000 65000

route-map isp-2-out permit 10
 match ip address prefix-list isp-1-out
 set as-path prepend 65000 65000 65000
route-map isp-2-out permit 20
 match ip address prefix-list isp-2-out

router bgp 65000
 address-family ipv4
  neighbor 192.168.101.1 route-map isp-1-out out
  neighbor 192.168.103.3 route-map isp-2-out out

Теперь в сторону ISP#1 префикс 172.16.9.0/24 будет анонсироваться с AS-PATH, удлиненным на три номера AS65000, а в сторону ISP#2 тоже самое будет делаться для префиксов 172.16.7.0/24 и 172.16.8.0/24.


Теперь, в идеале, трафик для каждой группы префиксов должен поступать через своего провайдера, а в случае падения одного из uplink, начнет работать анонс с prepend. Например, при падении ISP#2 трафик для 172.16.9.0/24 не прервется, так как весь мир все равно «видит» этот префикс через ISP#1, хоть с удлиненным AS-PATH.


Этот способ сработал бы, но тут в игру вмешиваются различные local preferences, которые провайдеры используют для клиентов и пиринга. Так как, при выборе маршрута атрибут LOCAL PREFERENCE имеет больший приоритет, чем AS-PATH, внутри каждого провайдера наш prepend не будет играть роли и трафик всегда будет направляться через клиентский канал. В нашей сети этот метод сработает только для AS65050, так как она присоединена в обоим провайдерам.


Посмотрим подробней.


Действительно, на R5 все хорошо:


R5#sh ip bgp
...
 *   172.16.7.0/24  192.168.45.4  0 65002 65000 65000 65000 65000 ?
 *>                 192.168.25.2  0 65001 65000 ?
 *   172.16.8.0/24  192.168.45.4  0 65002 65000 65000 65000 65000 ?
 *>                 192.168.25.2  0 65001 65000 ?
 *>  172.16.9.0/24  192.168.45.4  0 65002 65000 ?
 *                  192.168.25.2  0 65001 65000 65000 65000 65000 ?
R5#sh ip route
...
      172.16.0.0/24 is subnetted, 3 subnets
B        172.16.7.0 [20/0] via 192.168.25.2, 1d00h
B        172.16.8.0 [20/0] via 192.168.25.2, 1d00h
B        172.16.9.0 [20/0] via 192.168.45.4, 1d00h

R5#traceroute 172.16.7.1 source 10.0.5.1
...
  1 192.168.25.2 0 msec 0 msec 1 msec
  2 192.168.12.1 0 msec 1 msec 0 msec
  3 192.168.101.100 3 msec 3 msec 3 msec
  4 192.168.107.7 2 msec *  2 msec

R5#traceroute 172.16.9.1 source 10.0.5.1
...
  1 192.168.45.4 1 msec 0 msec 1 msec
  2 192.168.34.3 0 msec 1 msec 0 msec
  3 192.168.103.100 3 msec 3 msec 3 msec
  4 192.168.109.9 2 msec *  3 msec

На основе атрибута AS-PATH для каждой группы префиксов выбран оптимальный маршрут через своего провайдера, что подтверждает трассировка.


Но вот на R11 (AS65110) все не так радужно.


R11#traceroute 172.16.7.1 source 10.0.11.1
...
  1 192.168.114.4 0 msec 1 msec 4 msec
  2 192.168.34.3 1 msec 0 msec 0 msec
  3 192.168.103.100 3 msec 3 msec 3 msec
  4 192.168.107.7 2 msec *  2 msec

R11#traceroute 172.16.9.1 source 10.0.11.1
...
  1 192.168.114.4 0 msec 1 msec 0 msec
  2 192.168.34.3 0 msec 0 msec 0 msec
  3 192.168.103.100 3 msec 2 msec 3 msec
  4 192.168.109.9 2 msec *  2 msec

Трафик до обоих хостов идет к нам через один и тот же пятисотмегабитный стык.


Причина как раз в local preference. Смотрим на R13 провайдера ISP#2:


R13>sh ip bgp
 ...
 *   172.16.7.0/24  192.168.200.12           0 65001 65000 ?
 *>i                192.168.103.100  0  120  0 65000 65000 65000 65000 ?
 *   172.16.8.0/24  192.168.200.12           0 65001 65000 ?
 *>i                192.168.103.100  0  120  0 65000 65000 65000 65000 ?
 *   172.16.9.0/24  192.168.200.12           0 65001 65000 65000 65000 65000 ?
 *>i                192.168.103.100  0  120  0 65000 ?

R13#sh ip route
...
      172.16.0.0/24 is subnetted, 3 subnets
B        172.16.7.0 [200/0] via 192.168.103.100, 1d00h
B        172.16.8.0 [200/0] via 192.168.103.100, 1d00h
B        172.16.9.0 [200/0] via 192.168.103.100, 1d00h

На маршрутизаторе все BGP-анонсы наших сетей в двух экземплярах:


  • полученные через клиентское присоединение (next-hop 192.168.103.100);
  • полученные через пиринг (next-hop 192.168.200.12).

Но, несмотря на длинный AS-PATH, для префиксов 172.16.7.0/24 и 172.16.8.0/24 best-маршрут – маршрут с local preference 120 через клиента, т.е. через нас, а не через пиринг. Получается, что ISP#2 направит весь трафик наших абонентов через канал 500Mbps. И, если за этим провайдером окажется дата-центр какого-нибудь крупного контент-провайдера (например VK.com), то это приведет к перегрузке на канале и проблемам с сервисом.


Получается, что стандартный AS-PATH prepend нам не поможет.


Исключение анонсов


Другой способ разделить трафик – просто исключить из BGP-анонсов в сторону оператора те префиксы, трафик на которые мы не хотим получать через этого провайдера.


Попробуем.


Вместо route-map настроим для каждого соседа фильтрующий prefix-list.


router bgp 65000
 address-family ipv4
  neighbor 192.168.101.1 prefix-list isp-1-out out
  neighbor 192.168.103.3 prefix-list isp-2-out out

Теперь в сторону каждого провайдера анонсируются только те маршруты, которые должны получать трафик через этот стык:


CSR#sh ip bgp neighbors 192.168.101.1 advertised-routes
...
     Network          Next Hop    Metric LocPrf Weight Path
 *>  172.16.7.0/24    192.168.107.7    0         32768 ?
 *>  172.16.8.0/24    192.168.108.8    0         32768 ?

Total number of prefixes 2

CSR#sh ip bgp neighbors 192.168.103.3 advertised-routes
...
     Network          Next Hop    Metric LocPrf Weight Path
 *>  172.16.9.0/24    192.168.109.9    0         32768 ?

Total number of prefixes 1

При таком подходе оператор выстраивает свою таблицу маршрутизации именно так, как нам надо:


R13>sh ip route
...
      172.16.0.0/24 is subnetted, 3 subnets
B        172.16.7.0 [20/0] via 192.168.200.12, 00:04:53
B        172.16.8.0 [20/0] via 192.168.200.12, 00:04:53
B        172.16.9.0 [200/0] via 192.168.103.100, 00:05:13

Теперь трассировки с R11 идут через разных провайдеров:


R11#traceroute 172.16.7.1 source 10.0.11.1
...
  1 192.168.114.4 4 msec 4 msec 4 msec
  2 192.168.134.13 1 msec 0 msec 1 msec
  3 192.168.200.12 0 msec 1 msec 0 msec
  4 192.168.121.1 0 msec 1 msec 1 msec
  5 192.168.101.100 2 msec 4 msec 3 msec
  6 192.168.107.7 2 msec *  2 msec

R11#traceroute 172.16.9.1 source 10.0.11.1
...
  1 192.168.114.4 0 msec 4 msec 0 msec
  2 192.168.34.3 0 msec 1 msec 0 msec
  3 192.168.103.100 3 msec 3 msec 3 msec
  4 192.168.109.9 2 msec *  2 msec

Однако, тут возникает проблема с резервированием. Действительно, при падении ISP#2 абоненты из сети 172.16.9.0/24 лишаются сервиса, так как весь мир больше «не видит» маршрута к ним. Обычно, это можно решить анонсированием агрегирования префикса для резерва. Например, если бы мы располагали диапазоном адресов от 172.16.6.0 до 172.16.9.255, то мы могли бы дополнительно анонсировать обоим провайдерам укрупненные подсети 172.16.6.0/23 и 172.16.8.0/23, которые включают в себя наши префиксы. Тогда, при падении одного из провайдеров и исчезновении в Интернете «специфик» маршрутов /24, все равно оставались бы /23, и сервис работал бы у всех абонентов даже на одном uplink. Но в нашем примере такое невозможно. Наши клиентские сети нельзя агрегировать в один или два префикса. Конечно, сети в примере подобраны специально, но, именно, столкновение с такой ситуацией на практике подтолкнуло меня к написанию заметки.


Резервирование


Мы решили проблему балансировки входящего трафика. Осталось добиться резервирования. Общий путь решения поняетн: в случае падения одного из пиров менять фильтр исходящих анонсов на том, пире, что еще "жив". Это можно было бы реализовать «снаружи», меняя настройки нашего пограниченого маршрутизатора скриптом по SSH или SNMP. Однако, цель заметки – сделать все встроенными средствами Cisco.


BGP Conditional Advertisement


Один из вариантов управления BGP-анонсами в зависимости от состояния BGP-соседства — Conditional Advertisement, которое позволяет анонсировать в сторону соседа те или иные префиксы, в зависимости от наличия или отсутствия в таблице BGP "контрольных" префиксов.


Префиксы, которые нужно анонсировать или, наоборот, убрать из анонса определяются специальным route-map: advertise-map, который может быть в режиме withdraw (префиксы, соответствующие route-map исключаются из анонса) или advertise (префиксы участвуют в анонсе). "Контрольные" префиксы определяются отдельным condition-map, который может быть объявлен как exist-map или non-exist-map. В первом случае префиксы из advertise-map анонсируются, только если в таблице BGP есть префиксы, соотвествующие exist-map. В случае non-exist-map — наоброт: если non-exist-map возвращет пустой список префиксов, то префиксы advertise-map анонсируются, а если нет, то исключаются из анонса.


В нашем случае подходит вариант с non-exist-map. Конфигурация route-map тут имеет несколько особенностей:


  1. route-map должен содержать только permit-секции;
  2. в каждой секции в условиях match должен обязательно содержаться prefix-list (нельзя фильтровать только по as-path или community);
  3. prefix-list должен быть "точного соответствия", т.е. без параметров le или ge;
  4. фильтрация по next-hop или interface не поддерживается.

Значить нам нужен контрольный префикс. Можно выбрать что-то из того, что нам анонсируют провайдеры (или даже сообщить им, что вы используете conditional advertisement и попросить добавить в анонс префикс, на который можно ориентироваться). Но в большинстве случаев (если среди ваших клиентов нет других провайдеров) вы, вместо full-view, получите от своего вышестоящего провайдера default-префикс 0.0.0.0/0. Его мы и будем использовать в качестве контрольного. А что бы отличить default одного провайдера от другого добавим в non-exist-map фильтр по AS-PATH.


Создадим prefix-list и два as-path ACL:


ip prefix-list default seq 5 permit 0.0.0.0/0

ip as-path access-list 1 permit ^65001.*
ip as-path access-list 2 permit ^65002.*

Добавим два condition-map, каждый из которых будет возвращать непустой список, только если соединение с соответствующим ISP установлено:


route-map isp-1-is-alive permit 10
 match ip address prefix-list default
 match as-path 1

route-map isp-2-is-alive permit 10
 match ip address prefix-list default
 match as-path 2

Создадим два route-map, который будут advertise-map для соотвествубщих пиров:


route-map isp-1-adv permit 10
 match ip address prefix-list isp-2-out

route-map isp-2-adv permit 10
 match ip address prefix-list isp-1-out

Еще один route-map будем использовать для фильтрации всех исходящих анонсов:


route-map full-out permit 10
 match ip address prefix-list isp-1-out isp-2-out

Теперь применим их в конфигурации BGP-соседей:


router bgp 65000
 address-family ipv4
  neighbor 192.168.101.1 advertise-map isp-1-adv non-exist-map isp-2-is-alive
  neighbor 192.168.101.1 route-map full-out out
  neighbor 192.168.103.3 advertise-map isp-2-adv non-exist-map isp-1-is-alive
  neighbor 192.168.103.3 route-map full-out out

Рассмотрим подробней конфигурацию neighbor 192.168.103.3:


  1. префиксы для анонса выбираются по route-map full-out;
  2. дополнительно проверяется non-exist-map isp-1-is-alive:
    • если isp-1-is-alive вернул НЕпустой список, до advertise-map isp-1-adv присваивается статус withdraw и его префиксы исключаются из анонса;
    • если isp-1-is-alive вернул пустой список, до advertise-map isp-1-adv присваивается статус advertise и его префиксы анонсируются.

Посмотрим, что получилось. Изначально "контрольные" префиксы для обоих non-exist-map есть в таблице BGP и соответствующие advertise-map находятся в статусе withdraw:


CSR#sh ip bgp neighbors 192.168.101.1 | i Condition
  Condition-map isp-2-is-alive, Advertise-map isp-1-adv, status: Withdraw

CSR#sh ip bgp neighbors 192.168.103.3 | i Condition
  Condition-map isp-1-is-alive, Advertise-map isp-2-adv, status: Withdraw

Так как оба провайдера "живы", то в сторону каждого из них анонсируются только часть префиксов:


CSR#sh ip bgp neighbors 192.168.101.1 advertised-routes
...
     Network          Next Hop            Metric LocPrf Weight Path
 *>  172.16.7.0/24    192.168.107.7            0         32768 i
 *>  172.16.8.0/24    192.168.108.8            0         32768 i

Total number of prefixes 2

CSR#sh ip bgp neighbors 192.168.103.3 advertised-routes
...
     Network          Next Hop            Metric LocPrf Weight Path
 *>  172.16.9.0/24    192.168.109.9            0         32768 i

Total number of prefixes 1

В случае отключения BGP-соседства c ISP#1 из таблицы BGP исчезают префиксы для route-map isp-1-is-alive и advertise-map isp-2-adv для ISP#2 переходит в статус advertise:


CSR#sh ip bgp neighbors 192.168.103.3 | i Condition
  Condition-map isp-1-is-alive, Advertise-map isp-2-adv, status: Advertise

Теперь префиксы по route-map isp-2-adv не исключаются из анонса и в сторону ISP#2 анонсируется полный набор префиксов:


CSR#sh ip bgp neighbors 192.168.103.3 advertised-routes
...
     Network          Next Hop            Metric LocPrf Weight Path
 *>  172.16.7.0/24    192.168.107.7            0         32768 i
 *>  172.16.8.0/24    192.168.108.8            0         32768 i
 *>  172.16.9.0/24    192.168.109.9            0         32768 i

Total number of prefixes 3

При восстановлении BGP-соседства статус меняется advertise-map обратно на withdraw, и префиксы вновь распределяются по провайдерам для балансировки.


Еще один вариант использования Conditional Advertismement, это локализация проблемы на стороне провадйера или даже выше его зоны ответственности. В случае нашей тестовой схемы можно представить, что в AS65110 находится дацацентр крупного контент-провайдера, доступ к которому критичен для наших абонентов. В случае падения пиринговой связанности между двумя провайдерами, часть абонентов, чьи префиксы анонсируются только в сторону ISP#1 лишатся доступа в AS65110. При этом соединение с провайдером есть, префиксы и default от него есть, но сервис абонентов страдает. В этом случае мы можем использовать конфигурацию, аналогичную описанной выше, только в качестве "контрольного" префикса использовать адреса критично важных для нас ресурсов в AS65110.


Cisco Embedded Event Manager


Описанный дальше метод, учитывая возможности BGP Conditional Advertismement, выглядит немного искусственным для решения такой простой задачи. Причина этого в том, что в первоначальной версии статьи он был единственным, так как рассказ о Cisco EEM и был целью написания заметки. При этом проблема балансировки была выбрана как наиболее простой и понятный вариант иллюстрации. Однако позже, в комментариях, мне справедливо указали, что описывать проблему управления BGP-анонсами не упомянув инструмент, который именно для этого и предназначен не очень корректно. Так в статье появился параграф про BGP Conditional Advertisment, на фоне которого применение Cisco EEM кажется громоздким и избыточным. Однако это очень мощный инструмент, имеющий колоссальное поле применения, так что познакомиться с ним все же стоит.


Мы решили проблему балансировки входящего трафика. Осталось добиться резервирования. Общий путь решения понятен: в случае падения одного из пиров менять фильтр исходящих анонсов на том, пире, что еще "жив". Это можно было бы реализовать «снаружи», меняя настройки нашего пограниченого маршрутизатора скриптом по SSH или SNMP. Однако, цель заметки – сделать все встроенными средствами Cisco.


Тут нам пригодиться механизм Cisco Embedded Event Manager (EEM). Это очень гибкий механизм управления маршрутизатором и траблшутинга проблем на сети, возможности которого выходят далеко за пределы описываемой задачи. Нам от него требуется его умение отловить возникновение определённого события (падение или восстановление BGP-соседства) и выполнить заданный набор команд.


Для начала создадим префикс-лист, который включает в себя все наши префиксы.


ip prefix-list full-out seq 5 permit 172.16.7.0/24
ip prefix-list full-out seq 10 permit 172.16.8.0/24
ip prefix-list full-out seq 15 permit 172.16.9.0/24

Теперь сконфигурируем EEM-аплет, который будет запускаться при возникновении в логе записи об изменении статуса BGP-соседства (определяем регулярным выражением). Аплет:


  1. парсит сообщение в логе и определяет:
    • router-id BGP-соседа, который спровоцировал сообщение,
    • его статус;
  2. в зависимости от IP-адреса и статуса применяет для другого BGP-соседа тот или иной префикс-лист;
  3. «мягко» сбрасывает анонсы в сторону второго соседа, что бы ускорить распространение маршрутной информации и применение сделанных изменений.

Конфигурация аплета:


event manager applet isp
 event syslog pattern "neighbor 192.168.10[13].[13] (Up|Down|reset)"
 action 01.0 regexp "(192.168.10[13].[13])" "$_syslog_msg" _match _ip
 action 02.0 if $_ip eq "192.168.101.1"
 action 03.0  set _name "ISP #1"
 action 04.0  set _target_ip "192.168.103.3"
 action 05.0  set _list "isp-2-out"
 action 06.0 elseif $_ip eq "192.168.103.3"
 action 07.0  set _name "ISP #2"
 action 08.0  set _target_ip "192.168.101.1"
 action 09.0  set _list "isp-1-out"
 action 10.0 else
 action 11.0  exit
 action 12.0 end
 action 13.0 regexp "(Up|Down|reset)" "$_syslog_msg" _match _state
 action 14.0 if $_state eq "Up"
 action 15.0  set _status "UP"
 action 16.0 else
 action 17.0  set _status "DOWN"
 action 18.0  set _list "full-list"
 action 19.0 end
 action 20.0 syslog priority warnings msg "$_name now is $_status !"
 action 21.0 syslog priority warnings msg "Applying prefix list '$_list' to the neighbor $_target_ip"
 action 22.0 cli command "enable"
 action 23.0 cli command "configure terminal"
 action 24.0 cli command "router bgp 65000"
 action 25.0 cli command "address-family ipv4" 
 action 26.0 cli command "neighbor $_target_ip prefix-list $_list out"
 action 27.0 cli command "end"
 action 28.0 syslog priority warnings msg "Soft clear BGP session $_target_ip"
 action 29.0 cli command "clear ip bgp $_target_ip soft out"

Изначально обе BGP-сессии у нас активны и анонсы выглядят следующим образом:


CSR#show ip bgp summary
...
Neighbor        V           AS MsgRcvd MsgSent   TblVer  InQ OutQ Up/Down  State/PfxRcd
192.168.101.1   4        65001       8       5        7    0    0 00:00:19        3
192.168.103.3   4        65002       8       5        7    0    0 00:00:24        3

CSR#show ip bgp neighbors 192.168.101.1 advertised-routes
...
     Network          Next Hop            Metric LocPrf Weight Path
 *>  172.16.7.0/24    192.168.107.7            0         32768 ?
 *>  172.16.8.0/24    192.168.108.8            0         32768 ?

Total number of prefixes 2

CSR#show ip bgp neighbors 192.168.103.3 advertised-routes
...
     Network          Next Hop            Metric LocPrf Weight Path
 *>  172.16.9.0/24    192.168.109.9            0         32768 ?

Total number of prefixes 1

На сети ISP#2 наши анонсы выглядят следующим образом:


R13>show ip bgp
...
 Network          Next Hop            Metric LocPrf Weight Path
 *>  172.16.7.0/24    192.168.200.12                     0 65001 65000 ?
 *>  172.16.8.0/24    192.168.200.12                     0 65001 65000 ?
 *>i 172.16.9.0/24    192.168.103.100      0    120      0 65000 ?

Трассировки с R11 идут в нашу сеть так, как нам нужно:


R11#traceroute 172.16.7.1 source 10.0.11.1
Type escape sequence to abort.
Tracing the route to 172.16.7.1
VRF info: (vrf in name/id, vrf out name/id)
  1 192.168.114.4 0 msec 1 msec 0 msec
  2 192.168.134.13 0 msec 0 msec 1 msec
  3 192.168.200.12 0 msec 0 msec 1 msec
  4 192.168.121.1 1 msec 1 msec 1 msec
  5 192.168.101.100 3 msec 3 msec 3 msec
  6 192.168.107.7 2 msec *  3 msec

R11#traceroute 172.16.9.1 source 10.0.11.1
Type escape sequence to abort.
Tracing the route to 172.16.9.1
VRF info: (vrf in name/id, vrf out name/id)
  1 192.168.114.4 1 msec 0 msec 1 msec
  2 192.168.34.3 0 msec 1 msec 0 msec
  3 192.168.103.100 3 msec 3 msec 3 msec
  4 192.168.109.9 2 msec *  2 msec

Теперь попробуем отключить пир с ISP#1 со стороны провайдера. В результате одна из BGP-сессий на нашем бордере переходит в IDLE:


CSR#show ip bgp summary
...
Neighbor        V           AS MsgRcvd MsgSent   TblVer  InQ OutQ Up/Down  State/PfxRcd
192.168.101.1   4        65001       0       0        1    0    0 00:00:10 Idle
192.168.103.3   4        65002      26      26        9    0    0 00:16:31        3

В логе мы при этом видим, что как только возникло событие %BGP-5-NBR_RESET: Neighbor 192.168.101.1 reset (Peer closed the session) сработал наш аплет и изменил префикс-лист:


*Jul 20 09:00:58.208: %BGP-5-NBR_RESET: Neighbor 192.168.101.1 reset (Peer closed the session)
*Jul 20 09:00:58.208: %BGP-5-ADJCHANGE: neighbor 192.168.101.1 Down Peer closed the session
*Jul 20 09:00:58.214: %HA_EM-4-LOG: isp: ISP #1 now is DOWN !
*Jul 20 09:00:58.214: %HA_EM-4-LOG: isp: Applying prefix list 'full-list' to the neighbor 192.168.103.3
*Jul 20 09:00:58.778: %SYS-5-CONFIG_I: Configured from console by  on vty0 (EEM:isp)
*Jul 20 09:00:58.879: %HA_EM-4-LOG: isp: Soft clear BGP session 192.168.103.3

Посмотрим, что теперь мы анонсируем в сторону ISP#2:


CSR#show ip bgp neighbors 192.168.103.3 advertised-routes
...
     Network          Next Hop         Metric LocPrf Weight Path
 *>  172.16.7.0/24    192.168.107.7         0         32768 ?
 *>  172.16.8.0/24    192.168.108.8         0         32768 ?
 *>  172.16.9.0/24    192.168.109.9         0         32768 ?
Total number of prefixes 3

Т.е. теперь мы анонсируем через ISP#2 все наши префиксы. Вот как это теперь выглядит на R13:


R13>show ip bgp
...
     Network          Next Hop          Metric LocPrf Weight Path
 *>i 172.16.7.0/24    192.168.103.100        0    120      0 65000 ?
 *>i 172.16.8.0/24    192.168.103.100        0    120      0 65000 ?
 *>i 172.16.9.0/24    192.168.103.100        0    120      0 65000 ?

А все трассировки в нашу сеть идут через одного провайдера.


При восстановлении BGP-сессии с IPS#1 аплет снова вернет префикс-лист для ISP#2 в исходное положение.


Заключение


Целью статьи было кратко рассмотреть применение Cisco EEM для управления входящим трафиком при балансировке нескольких аплинков, и, надеюсь, это удалось. Конечно, данный способ едва ли возможно назвать оптимальным. Скорее, это решение «в лоб». Однако, он работает и обеспечивает определенную степень отказоустойчивости. Для написания заметки вся схема собиралась в UNELAB на образах Cisco IOL и Cisco CSRv1000. Конфигурации всех устройств из рассматриваемго примера можно скачать по ссылке.

Поделиться публикацией
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама
Комментарии 18
  • 0
    Есть еще один очень простой, но очень действенный способ борьбы с localpref:
    В оба аплинка анонсится агрегированный префикс, в качестве резерва, и в каждый аплинк дополнительно — соответствующий аплинку more-specific префикс. Таким образом, трафик практически всегда будет литься на more-specific анонс, а в случае падения — на оставшийся агрегированный.
    Заодно исчезают игры с ивентами и прочими лишними сервисами, работает даже на самом простом софте/железе.
    Единственное, что надо иметь более чем /24
    • 0
      Это не «еще один» способ. Я бы сказал, что это ОСНОВНОЙ способ и я упомянул его в статье, но наверное надо было описать его подробней. Вот только он, действительно, не работает при неудачной конфигурации подсетей, когда их нельзя сагрегировать.
      • 0
        Это да. Распишите, пожалуйста, подробнее. Статьи на хабре часто используются как готовый мануал на все случаи жизни :)
        С другой стороны, основной способ из статьи, проверяющий состояние bgp neigbor, я считаю далеко не самым надежным в ситуации, когда у аплинка сессия с вами есть, а вот выше — уже проблемы. Хотя, конечно, последняя миля обычно более подвержена проблемам, чем ядро оператора.
        С цисками я практически не работал, но, кажется, у них есть возможность проверять наличие/отсутствие во входящих анонсах конкретного префикса, и в зависимости от этого что-то делать? Такой вариант намного надежнее. Правда, работает только при получении FW (или хотя бы локальный ix + дефолт — распространенная схема для приземления bgp на L3 коммутатор с нерезиновой forwarding table).
        • +1
          Метод проверки наличия определённых префиксов и анонс маршрутов на основе наличия/отсутствия оных на Cisco есть — BGP Conditional Advertisement. Поэтому EEM не требуется.

          Ещё один вариант влияния на маршрутизацию у вышестоящих провайдеров — BGP community.

          • 0
            В отличии от conditional/more-specific/eem, комьюнити, все-таки, совсем не универсальный метод т.к. опирается на возможности конкретного оператора. Хотя и, пожалуй, самый гибкий и многофункциональный. Он, скорее, идет в дополнение к остальным методам.

            Далеко не у всех есть даже backup community с выставлением минимального localpref, обычно ограничиваются препендами на различные направления.
            • 0
              Conditional Advertisment — однозначно да. Надо описать. То что про него с заметке ни слова — косяк.

              Community — в идеальном мире идеальных провайдеров. В реальности все весьма печально и гибкостью политика многих операторов не отличается.
    • 0
      Почему сделано так
       action 14.0 if $_state eq "Up"
       action 15.0  set _status "UP"
       action 16.0 else
       action 17.0  set _status "DOWN"
       action 18.0  set _list "full-list"
       action 19.0 end
       action 20.0 syslog priority warnings msg "$_name now is $_status !"
      

      А не так:

       action 14.0 if $_state eq "DOWN"
       action 18.0  set _list "full-list"
       action 19.0 end
       action 20.0 syslog priority warnings msg "$_name now is $_state !"
      


      Есть какие то ньюансы работы с переменными или просто для красоты?
      • +1
        Для красоты. Из регулярного выражения _state может быть и «Down» и «reset». Приводим в сообщении к «DOWN». Унифицированное сообщение в syslog, что бы упростить жизнь дежурной смене, например.
      • 0
        Возможно, я невнимательно прочитал, но ведь в таком решении при падении пирингового линка между ISP, пропадет связность части подсетей с ресурсами, доступными только через одного ISP?
        • 0
          Как правило, провайдеры имеют несколько стыков между собой или с пиринговыми площадками. На схеме, поэтому, сделан пир межу ними. Так что связанность не пропадает.
          • 0
            Я имел ввиду конкретно ваш пример. При использовании решения с EEM, которое вы описали, при пропадании линка между ISP апплет не сработает, т.к. оба пира для AS65000 будут живы, но при этом у ISP1 не будет информации о сети 172.16.9/24, а у ISP2 о двух других сетях. Соответсвенно 9-я подсеть не достучится до AS65100, а 7 и 8 до AS65110…
            Вы правы, в большинстве случаев есть несколько стыков, но было бы интересно почитать про реализацию апплета, который бы предусматривал возможность возникновения таких ситуаций. Например, каким-то образом фиксировать пропадание анонсов с NH R1 и предпоследней AS 65002 в AS-PATH (для ISP1) и NH на R3 и предпоследняя AS 65001 для ISP2…
            К сожалению, не знаком с ЕЕМ, поэтому не в курсе его возможностей. Но тема интересная, спасибо.
            • 0
              На EEM такое наверное можно сделать, но сложно. Для этого есть BGP Conditional Advertisment, который, конечно, надо описать в заметке (и на что мне уже указали выше). Там как раз можно написать route-map с анализом префиксов, next-hop для них и as-path, в зависимости от результата которого будут меняться анонсы. Конечно, для этого надо иметь от провайдера контрольный префикс. Т.е. вариант «берем только default» не прокатит. Возможно даже нужен full view.
              • 0
                Думаю, Default route вполне достаточен для реализации BGP Conditional Advertisment во многих инсталляциях. Конечно, предварительно стоит попробовать прояснить, кто в сети провайдера его инжектирует, чтобы понять его «качество».
                • 0
                  default-route имеет смысл только на PE, если есть несколько full-view. В ядре оно не нужно: все, что есть в FW — пророутится куда надо, остальное — unreachable.
                  На цисках/кваггах даже есть neighbor xxx default-originate, такой дефолт в принципе существует только в виде абстрактоного BGP-анонса.
                  Хотя, наверное, технически правильнее организовать aggregate 0/0 с правильной политикой и именно его редистрибьютить (нет фул-вью — нет дефолта), но я не сталкивался с таким, обычно не заморачиваются и с раздают default-originate или static 0/0.
        • 0
          Как правило, провайдеры имеют несколько стыков между собой или с пиринговыми площадками. На схеме, поэтому, сделан пир межу ними. Так что связанность не пропадает.
          • +1
            Можно переделать сценарий EEM и выполнять переконфигурацию не по событию «появления записи в логе», а по событию «трэк определенного хоста (или набора хостов) в интернете». Это немного упрощает сценарий, и к тому же страхует от ситуации, когда проблема возникает на сети провайдера, а последняя миля в порядке.
            • 0
              Можно. Но в этом случае нужно брать от провайдеров не только default, но и какие-то «контрольные» префиксы. А вот их адекватный выбор (что бы по ним можно было увидеть проблему у провайдера) задачка не типовая и сильно завязана на топологию провайдера.

            Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.