Linux VRF and Namespaces: различия между версиями

Материал из noname.com.ua
Перейти к навигацииПерейти к поиску
Строка 90: Строка 90:
   
 
* Сложно делать Route Leaking (когда нужно часть или весь трафик пускать между VRF). Понадобится "виртуальный патчкорд" <code>veth</code> между VRF. Сделать конечно можно, масштабируемость только очень сомнительная.
 
* Сложно делать Route Leaking (когда нужно часть или весь трафик пускать между VRF). Понадобится "виртуальный патчкорд" <code>veth</code> между VRF. Сделать конечно можно, масштабируемость только очень сомнительная.
* Слишком полная изоляция:
+
* Слишком полная изоляция
 
* VRF решает задачу изоляции FIB (при этом не стоит путать FIB и таблицу маршрутизации, FIB содержит лучшие маршруты, тогда как таблица маршрутизации - все маршруты, в том числе полученные от протоколов динамической маршрутизации но не используемые прямо в данный момент как неоптимальные)
 
* Пример ниже - о том что бы посмотреть списки интерфейсов нужно сначала сделать <PRE>ip netns</PRE> а потом смотреть отдельно по каждому неймспейсу
 
* В целом - управление сетью с netns вместо vrf становится слишком сложный - тот же процесс lldp должен будет запустить столько своих экземпляров сколько есть VRF и это же касается BGPв, и (кроме того что нужно будет написать сои расширения для всех демонов) еще и требует "пропихивания"в апстрим.
  +
  +
{{#spoiler:show=Оригинал|
 
<PRE>
 
<PRE>
 
Network namespaces were designed to provide a complete isolation of the entire network stack — devices, network addresses, neighbor and routing tables, protocol ports and sockets.
 
Network namespaces were designed to provide a complete isolation of the entire network stack — devices, network addresses, neighbor and routing tables, protocol ports and sockets.
Строка 96: Строка 101:
 
</PRE>
 
</PRE>
   
* VRF решает задачу изоляции FIB (при этом не стоит путать FIB и таблицу маршрутизации, FIB содержит лучшие маршруты, тогда как таблица маршрутизации - все маршруты, в том числе полученные от протоколов динамической маршрутизации но не используемые прямо в данный момент как неоптимальные)
 
 
<PRE>
 
<PRE>
 
VRF on the other hand is a network layer feature and as such should really only impact FIB lookups.
 
VRF on the other hand is a network layer feature and as such should really only impact FIB lookups.
Строка 102: Строка 106:
 
</PRE>
 
</PRE>
   
  +
* Пример ниже - о том что бы посмотреть списки интерфейсов нужно сначала сделать <PRE>ip netns</PRE> а потом смотреть отдельно по каждому неймспейсу
 
* В целом - управление сетью с netns вместо vrf становится слишком сложный - тот же процесс lldp должен будет запустить столько своих экземпляров сколько есть VRF и это же касается BGPв, и (кроме того что нужно будет написать сои расширения для всех демонов) еще и требует "пропихивания"в апстрим.
 
 
<PRE>
 
<PRE>
 
Let’s walk through a few a simple examples to highlight what I mean about impact on the software architecture and operational model of a network namespace as VRF.
 
Let’s walk through a few a simple examples to highlight what I mean about impact on the software architecture and operational model of a network namespace as VRF.
Строка 109: Строка 112:
 
Because a process in Linux is limited to a single network namespace, it will only see network devices, addresses, routes, even networking related data under /proc and /sys local to that namespace. For example, if you run ‘ip link list’ to list network devices, it will only show the devices in the namespace in which it is run. This command is just listing network interfaces, not transmitting packets via the network layer or using network layer sockets. Yet, using a namespace as a VRF impacts the view of all network resources by all processes.
 
Because a process in Linux is limited to a single network namespace, it will only see network devices, addresses, routes, even networking related data under /proc and /sys local to that namespace. For example, if you run ‘ip link list’ to list network devices, it will only show the devices in the namespace in which it is run. This command is just listing network interfaces, not transmitting packets via the network layer or using network layer sockets. Yet, using a namespace as a VRF impacts the view of all network resources by all processes.
 
</PRE>
 
</PRE>
  +
 
<PRE>
 
<PRE>
 
A NOS is more than just routing protocols and programming hardware. You need supporting programs such as lldpd for verifying network connectivity, system monitoring tools such as snmpd, tcollector and collectd and debugging tools like ‘netstat’, ‘ip’, ‘ss’. Using a namespace as a VRF has an adverse impact on all of them. An lldpd instance can only use the network devices in the namespace in which lldpd runs. Therefore, if you use a network namespace for a VRF, you have to run a separate instance of lldpd for each VRF. Deploying N-VRFs means starting N-instances of lldpd. VRF is a layer 3 feature, yet the network namespace choice means users have to run multiple instances of L2 applications.
 
A NOS is more than just routing protocols and programming hardware. You need supporting programs such as lldpd for verifying network connectivity, system monitoring tools such as snmpd, tcollector and collectd and debugging tools like ‘netstat’, ‘ip’, ‘ss’. Using a namespace as a VRF has an adverse impact on all of them. An lldpd instance can only use the network devices in the namespace in which lldpd runs. Therefore, if you use a network namespace for a VRF, you have to run a separate instance of lldpd for each VRF. Deploying N-VRFs means starting N-instances of lldpd. VRF is a layer 3 feature, yet the network namespace choice means users have to run multiple instances of L2 applications.
 
</PRE>
 
</PRE>
  +
 
<PRE>
 
<PRE>
 
That limitation applies to system monitoring applications such as snmpd, tcollector and collectd as well. For these tools to list and provide data about the networking configuration, statistics or sockets in a VRF they need a separate instance per VRF. N-VRFs means N-instances of the applications with an additional complication of how the data from the instances are aggregated and made available via the management interface.
 
That limitation applies to system monitoring applications such as snmpd, tcollector and collectd as well. For these tools to list and provide data about the networking configuration, statistics or sockets in a VRF they need a separate instance per VRF. N-VRFs means N-instances of the applications with an additional complication of how the data from the instances are aggregated and made available via the management interface.
 
</PRE>
 
</PRE>
  +
 
<PRE>
 
<PRE>
 
And these examples are just infrastructure for a network OS. How a VRF is implemented is expected to impact network layer routing protocols such as quagga/bgp. Modifying them to handle the implementation of a VRF is required. But even here the choice is either running N-versions of bgpd or modifying bgpd to open a listen socket for each VRF which means N-listen sockets. As N scales into the 100’s or 1000’s this is wasted resources spinning up all of these processes or opening listen sockets for each VRF.
 
And these examples are just infrastructure for a network OS. How a VRF is implemented is expected to impact network layer routing protocols such as quagga/bgp. Modifying them to handle the implementation of a VRF is required. But even here the choice is either running N-versions of bgpd or modifying bgpd to open a listen socket for each VRF which means N-listen sockets. As N scales into the 100’s or 1000’s this is wasted resources spinning up all of these processes or opening listen sockets for each VRF.
 
</PRE>
 
</PRE>
  +
 
<PRE>
 
<PRE>
 
Yes, you could modify each of the code bases to be namespace aware. For example, as a VRF (network namespaces) is created and destroyed the applications either open socket local to the namespace, spawn a thread for the namespace or just add it to a list of namespaces to poll. But there are practical limitations with this approach – for example the need to modify each code base and work with each of the communities to get those changes accepted. In addition, it still does not resolve the N-VRF scalability issue as there is still 1 socket or 1 thread per VRF or the complexity of switching in and out namespaces. Furthermore, what if a network namespace is created for something other than a VRF? For example, a container is created to run an application in isolation, or you want to create a virtual switch with a subset of network devices AND within the virtual switch you want to deploy VRFs? Now you need a mechanism to discriminate which namespaces are VRFs. This option gets complicated quick.
 
Yes, you could modify each of the code bases to be namespace aware. For example, as a VRF (network namespaces) is created and destroyed the applications either open socket local to the namespace, spawn a thread for the namespace or just add it to a list of namespaces to poll. But there are practical limitations with this approach – for example the need to modify each code base and work with each of the communities to get those changes accepted. In addition, it still does not resolve the N-VRF scalability issue as there is still 1 socket or 1 thread per VRF or the complexity of switching in and out namespaces. Furthermore, what if a network namespace is created for something other than a VRF? For example, a container is created to run an application in isolation, or you want to create a virtual switch with a subset of network devices AND within the virtual switch you want to deploy VRFs? Now you need a mechanism to discriminate which namespaces are VRFs. This option gets complicated quick.
 
</PRE>
 
</PRE>
  +
 
<PRE>
 
<PRE>
 
And then there is consideration of how the VRF implementation maps to hardware for offload of packet forwarding.
 
And then there is consideration of how the VRF implementation maps to hardware for offload of packet forwarding.
 
</PRE>
 
</PRE>
  +
 
<PRE>
 
<PRE>
 
I could go on, but hopefully you get my point: The devil is in the details. Many people and many companies have tried using network namespaces for VRFs, and it has proven time and time again to be a square peg for a round hole. You can make it fit with enough sweat and tears, but it really is forcing a design that was not meant to be. Network namespaces are great for containers where you want strict isolation in the networking stack. Namespaces are also a great way to create virtual switches, carving up a single physical switch into multiple smaller and distinct logical switches. But network namespaces are a horrible solution when you just want layer 3 isolation.
 
I could go on, but hopefully you get my point: The devil is in the details. Many people and many companies have tried using network namespaces for VRFs, and it has proven time and time again to be a square peg for a round hole. You can make it fit with enough sweat and tears, but it really is forcing a design that was not meant to be. Network namespaces are great for containers where you want strict isolation in the networking stack. Namespaces are also a great way to create virtual switches, carving up a single physical switch into multiple smaller and distinct logical switches. But network namespaces are a horrible solution when you just want layer 3 isolation.
 
</PRE>
 
</PRE>
  +
}}
   
 
=<code>ip link add vrf-1</code>=
 
=<code>ip link add vrf-1</code>=

Версия 17:10, 30 апреля 2025

Network Namespaces или VRF

Эта статья задумывается как полуперевод-полукомпиляция и возможно с добавлением собственного опыта

Зачем нужен VRF

VRF это способ "виртуализировать" сеть, и иметь несколько полностью или частично независимых экземпляров сетевого стека.
Пример для банального небольшого провайдера на картинке:
VRF 1.png
Что тут нарисовано

  • Есть 2 группу клиентов
    • Беспроводные (картинка с 2 антенами это точка доступа). Им нужно строго ограничивать скорость - гонять через выделенный роутер который делает шейпинг. Если их не шейпить, то один клиент сможет занять всю полосу в эфире, остальные на той же базовой станции работать не смогут.
    • Проводные, включены на скорости порта. Гонять их трафик через шейпер не только безсмысленно но и вредно - шейпер плохо работает на скоростях выше 50Мбит

Icon-caution.gif

Вместо шейпера тут может быть например файрволл для гостевой сети, суть от этого не меняется

  • Роутер/L3 свитч куда включены эти клиенты
  • Шейпер, пограничный роутер и "интернет" добавлены для наглядности


(тут я не касаюсь L3VPN и вообще VPN ни в каком виде)

Задача описанная выше решается просто на любом более-менее современном L3 коммутаторе

  • Для каждой группы клиентов создается свой VRF, своя таблица маршрутизации со своим шлюзом
  • Так как шлюзы в разных VRF разные то часть клиентов можно направить через шейпер а другую часть мимо
  • На Cisco при желании можно сделать маршрутизацию между VRF - Route Leaking что б клиенты из разных VRF могли общаться друг с другом (в случае интернет-провайдера это сделать можно, в случае с гостевой сетью конечно не желательно)

Это все было банально и все это все и так знают (VRF без MPLS в Cisco называют VRF-Lite)

Вопрос как это все сделать используя Linux

VRF в Linux

Прежде чем говорить о VRF перечислим проблемы которые решает VRF

  • Изоляция на уровне L3 - разные VRF имеют независимые таблицы маршрутизации

Icon-caution.gif

C некоторой натяжкой можно считать VRF реализацией Policy Routing

В Linux есть три способа получить разные таблицы маршрутизации для разных групп source адресов

ip rule

Первый, самый старый способ - использовать несколько таблиц маршрутизации
Насколько я помню он был "всегда" :) (пишут что с 99 года, те раньше чем я познакомился с Linux)
Для этого требуется создать табличку маршрутизации (прописывать в /etc/iproute2/rt_tables ну или зависит от дистрибутива если хочется именования)

echo «123 testtable» >> /etc/iproute2/rt_tables
ip route add default via 192.168.22.254 table testtable

Создаем правило, отправляющее нужные пакеты в нужную таблицу:

ip rule add from 192.168.1.20 table testtable 

Или даже вот так

ip rule add iif eth1 table testtable

Недостатки ip rule

Это самый неудобный способ, и он не решает следующие проблемы

  • Пересечение диапазонов IP адресов. Этой проблемы нет в примере, так как адреса клиентов одинаковые, но при желании делать L3VPN она обязательно возникнет
  • Сложность управление и нагромождение ip rule и как следствие линейный поиск по списку с соответвующим падением производительности
  • Проблемы с выбором исходящего интерфейса для локального софта

В целом для относительно небольших и не сложных конфигураций это решение можно применять и оно работает.

ip netns

Примерно с 2009 года для изоляции сети в Linux используют Network Namespaces

  • Полная изоляция (в том числе можно иметь дублирование адресов в разных VRF)
  • Гироко применяется, и более-менее документировано
  • Используют всякие Докеры, Кубернетесы и прочие контейнеры


Подробно описывать я это все конечно не буду (документации просто полно), остановлючь не недостатках

Недостатки ip netns

Я просто оставлю цитаты со своими комментариями: Network Namespace as a VRF? Just say No

  • Сложно делать Route Leaking (когда нужно часть или весь трафик пускать между VRF). Понадобится "виртуальный патчкорд" veth между VRF. Сделать конечно можно, масштабируемость только очень сомнительная.
  • Слишком полная изоляция
  • VRF решает задачу изоляции FIB (при этом не стоит путать FIB и таблицу маршрутизации, FIB содержит лучшие маршруты, тогда как таблица маршрутизации - все маршруты, в том числе полученные от протоколов динамической маршрутизации но не используемые прямо в данный момент как неоптимальные)
  • Пример ниже - о том что бы посмотреть списки интерфейсов нужно сначала сделать
    ip  netns
    а потом смотреть отдельно по каждому неймспейсу
  • В целом - управление сетью с netns вместо vrf становится слишком сложный - тот же процесс lldp должен будет запустить столько своих экземпляров сколько есть VRF и это же касается BGPв, и (кроме того что нужно будет написать сои расширения для всех демонов) еще и требует "пропихивания"в апстрим.

ip link add vrf-1

Тут все относительно несложно

Приведу тестовую схему

Ссылки