Балансування двох провайдерів на основі 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 дозволяє штучно подовжити значення атрибуту для деяких маршрутів.
Спробуємо застосувати цей метод в нашій мережі. Для цього створимо на CRS два 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 сусідів 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 сусідів 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. Але в нашому прикладі таке неможливо. Наші клієнтські мережі не можна агрегувати в один або два префікса. Звичайно, в мережі прикладі підібрані спеціально, але, саме, зіткнення з такою ситуацією на практиці підштовхнуло мене до написання замітки.
Embedded Event Manager
Ми вирішили проблему балансування вхідного трафіку. Залишилося домогтися резервування. Загальний шлях вирішення зрозумілий: у разі падіння одного з бенкетів міняти фільтр вихідних анонсів на те, бенкеті, що ще "живий". Це можна було б реалізувати «зовні», змінюючи налаштування нашого пограниченого маршрутизатора скриптом по 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 сусідів 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 сусідів 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 сусідів 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. Конфігурації всіх пристроїв з рассматриваемго прикладу можна скачати за адресою.
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.