February 2008 Archives
Какая, казалось бы, хорошая идея, сделать так, чтобы крэш роутера не прерывал трафик, идущий через него. Достоинств куча: упрощается сеть - не надо ставить вторую коробку; можно обойтись одним только link protection и забить на node protecion, если с питанием все хорошо; можно сэкономить немножко денег - опять же за счет дублирующей коробки, за счет rack space, за счет операционных расходов на конфигурацию и мониторинг второй коробки; можно улучшить доступность для single-homed подключений. В общем, это должно быть круто.
Собственно, этому ничего не мешает - у современного роутера control plane и forwarding plane раздельны. Поэтому, если control plane упал по софтверной ошибке или по отказу процессорного модуля, forwarding plane вполне может продолжать бег, как та курица с отрубленной головой. А тем временем запасной процессорный модуль, обнаружив такое безобразие, переговорит с соседними роутерами, восстановит состояние протоколов, возьмет контроль над безголовым forwarding plane и все продолжится в нормальном режиме. Такая конструкция называется NSF/SSO (Non-Stop Forwarding/Stateful Switchover) и graceful restart.
Все ли хорошо в этой схеме? Нет.
Весь этот NSF/SSO основан на трех предположениях:
Неужто нам никогда не будет счастья? Может быть и будет. Следующий кандидат - NSR, Non-Stop Routing. Идея в том, что оба RP, и активный, и запасной, всегда несут полное состояние. И при отказе одного, второй тут же подхватывает управление. Т.е. ситуации "курица, бегущая без головы" не возникает. Не рвутся и не восстанавливаются протокольные adjacency; запасной RP, став активным, может сразу проверить целостность FIB, а то и тупо-линейно сформировать его заново; не надо детектировать раздельные отказы - ящик либо сдох, либо жив во всех своих частях (наверное жив, тут тоже могут быть нюансы), не надо надеяться на безглючность реализации graceful restart соседом. Реализации NSR в природе существуют. Я, правда, еще их подробно не испытывал. Наверное, испытав, опять буду ругаться. Но есть хотя бы надежда.
А что делать сегодня? Ставить две коробки. Да, деньги. Да, rack space. Да, сложность сети. Но если действительно нужна отказоустойчивость, то другого выхода нет. Ну а можно сыграть в оптимиста и забить на недостатки NSF, только надо четко понимать, где здесь выигрыш, а где проигрыш.
Собственно, этому ничего не мешает - у современного роутера control plane и forwarding plane раздельны. Поэтому, если control plane упал по софтверной ошибке или по отказу процессорного модуля, forwarding plane вполне может продолжать бег, как та курица с отрубленной головой. А тем временем запасной процессорный модуль, обнаружив такое безобразие, переговорит с соседними роутерами, восстановит состояние протоколов, возьмет контроль над безголовым forwarding plane и все продолжится в нормальном режиме. Такая конструкция называется NSF/SSO (Non-Stop Forwarding/Stateful Switchover) и graceful restart.
Все ли хорошо в этой схеме? Нет.
Весь этот NSF/SSO основан на трех предположениях:
- При падении процессорного модуля forwarding plane остался в целости и сохранности.
- Соседи падающего роутера могут достоверно понять, что с ним случилось: отказал control plane, forwarding plane или весь ящик целиком?
- В процессе восстановления состояния протоколов по информации от соседей не произойдет временного разрушения forwarding.
- Целостность FIB. Если был железный отказ RP, кто сказал, что этот отказ произошел не во время FIB update? Если нам не повезло, и отказ случился именно в такой неудобный момент, то FIB может оказаться в неконсистентном состоянии. Масштаб этой неконсистентности зависит от организации FIB. Может быть, кривым останется один маршрут - это более вероятно при табличной организации FIB на основе TCAM, а может, от всего FIB'а остались одни ошметки - такое совсем не исключено, если для FIB используется какая-нибудь сложная структура данных.
Т.е. для надежной работы NSF необходимы транзакционные FIB updates. В принципе, это сделать можно, но довольно сложно. FIB оптимизируется в первую очередь под задачу быстрого lookup - это самое главное, во-вторых под компактность в случае non-TCAM-based FIB - быстрая память, в которой приходится держать FIB, дорога, в-третьих под быстрые updates - это тоже немаловажно. Требование транзакционности неизбежно вступит в противоречие с этими тремя целями.
Можно обеспечить более слабую версию транзакционности FIB update. Если на линейной карте есть свой управляющий процессор (а он таки есть), то можно проводить транзакцию FIB update с ним, а не непосредственно с FIB, а тот уже сам разберется. Т.е. получится гарантия целостности FIB относительно отказа RP, но не относительно отказа CPU линейной карты. Этого, в принципе, достаточно.
Если же это падение по софтверной ошибке, то тут all bets are off. Если дело дошло до какого-нибудь SIGSEGV в монолитном IOS'е, то кто в здравом рассудке поручится, что перед этим падающий RP не превратил FIB в кровавое месиво? Тут надо падать с грохотом, с погашением лазеров и загружаться из cold state. Да, перерыв будет долгим, но зато конечным. Товарищи вендоры, не допускайте падения своих продуктов по такой симптоматике! А ежели такое, недайбоже, случилось, плюйте на всякий NSF и уходите на жесткий ребут всей коробки целиком. - Отличение соседями сбоев forwarding plane от сбоев control plane. Вся логика работы NSF основана на том, что соседи падающего роутера знают заранее: не надо пугаться, если с соседом что случилось, он еще может воспрянуть к жизни, а пока можно слать ему трафик. Однако оптимальная реакция соседа на отказ роутера, конечно же, зависит от вида отказа. Например, если с той стороны в линк не светят, то нет никакого смысла слать туда пакеты, надо быстренько перекинуть трафик в другом направлении.
В общем случае логика должны быть такова: если у соседа отказал control plane, то ничего не предпринимаем, а когда тот начнет восстанавливать состояние, поможем, а если оказал forwarding plane, то разворачиваем трафик в другую сторону как можно быстрее. Другой способ действий чреват очень медленным восстановлением от сбоя. Проблема в том, что отличить отказ control plane от отказа forwarding plane бывает трудно.
Для детектирования отказа control plane существуют протокольные hello/keepalives. Они должны быть достаточно медленными в случае NSF - надо, чтобы восстанавливающийся роутер успел начать восстановление до развала adjacencies. Масштаб - секунды, десятки секунд. Это, очевидно, неприемлемо для случаев отказа forwarding элементов, ибо в этом случае надо действовать быстро.
Есть замечательное изобретение - протокол BFD, которое по идее должно обеспечить нам именно обнаружение сбоев в forwarding plane, причем обнаружение достаточно быстрое. Спасает ли наc BFD?
Для того, чтобы BFD мог детектировать сбои forwarding plane, он должен работать исключительно на этом самом forwarding plane независимо от control plane. Ок, я не буду произносить все те слова, которые у меня накопились в адрес бывшего энтерпрайзного свитча, которые злые и циничные люди попытались превратить в сервис-провайдеский роутер. Все и так всё знают и понимают. Настоящие же роутеры могут исполнить BFD прямо с линейной карты. Это хорошо, но не покрывает все нужные случаи. Речь о наложенных топологиях, которые не совпадают с физическими. Пусть у нас есть протокольное соседство по pseudowire. Этот PW может выходить из нашей коробки сейчас через интерфейс на одном модуле, а через секунду через интерфейс на другом. Или, что еще хуже, входить через один, в выходить через другой. Где именно должен исполняться BFD, контролирующий adjacency через этот PW? Или вот взять multihop BFD для контроля далекого iBGP'шного next-hop - та же самая ситуация.
Таким образом, общего решения задачи отличения сбоев forwarding plane от сбоев control plane не существует. - Непрекращение forwarding'а в процессе самого восстановления. Нас ведь интересует не просто восстановление чего-то там в сети. Нас интересует восстановление сервиса, за который клиент платит деньги. Возьмем, к примеру, какой-нибудь простецкий VPLS с autodiscovery. Что должно восстановиться, чтобы он продолжил функционировать? IS-IS (ну или OSPF), как IGP, раз. RSVP, как протокол сигнализации TE-туннелей, два. BGP, как средство autodiscovery, три. Targeted LDP, как средство сигнализации наших псевдопроводов, четыре. Совсем не мало.
Вся эта банда протоколов рестартует [почти] независимо, сходится в произвольном порядке, апдейтит forwarding'овые таблицы кто во что горазд, взаимодействует друг с другом - например малейшая неаккуратность в восстановлении BGP'шных VPLS autodiscovery префиксов совершенно очевидным образом разрушит LDP-сигнализацию pseudowires, которым повезло выжить при отказе активного RP. Вся эта конструкция процессе сходимости может находиться в самых интересных промежуточных состояниях и целостность forwarding'а в этих промежуточных состояниях ой как не гарантируется. Известно лишь одно: рано или поздно оно сойдется и все станет хорошо, но, для того, чтобы NSF был действительно Non-Stop, этой гарантии "рано или поздно" мало.
Роутер, стартующий из холодного состояния, тоже подвержен подобным проблемам, но для более или менее удовлетворительного решения этих проблем есть всякие механизмы типа LDP-IGP synch, overload bit при старте и т.д., суть которых сводится к заявлению "я еще не готов к работе, не надо слать через меня трафик". Очевидно, что это не годится для случая NSF.
Изменение такого положения вещей потребует, пожалуй, полной переработки механики работы протоколов с тем, чтобы они больше знали о внутреннем состоянии друг-друга и избегали странных промежуточных поз. Очень большая работа. И я совсем не уверен в том, что это вообще возможно.
Неужто нам никогда не будет счастья? Может быть и будет. Следующий кандидат - NSR, Non-Stop Routing. Идея в том, что оба RP, и активный, и запасной, всегда несут полное состояние. И при отказе одного, второй тут же подхватывает управление. Т.е. ситуации "курица, бегущая без головы" не возникает. Не рвутся и не восстанавливаются протокольные adjacency; запасной RP, став активным, может сразу проверить целостность FIB, а то и тупо-линейно сформировать его заново; не надо детектировать раздельные отказы - ящик либо сдох, либо жив во всех своих частях (наверное жив, тут тоже могут быть нюансы), не надо надеяться на безглючность реализации graceful restart соседом. Реализации NSR в природе существуют. Я, правда, еще их подробно не испытывал. Наверное, испытав, опять буду ругаться. Но есть хотя бы надежда.
А что делать сегодня? Ставить две коробки. Да, деньги. Да, rack space. Да, сложность сети. Но если действительно нужна отказоустойчивость, то другого выхода нет. Ну а можно сыграть в оптимиста и забить на недостатки NSF, только надо четко понимать, где здесь выигрыш, а где проигрыш.