Назад | Перейти на главную страницу

Несколько разных каналов VLAN для гостей KVM (Linux)

Я наткнулся на своего рода преграду с архитектурной проблемой. У меня есть сервер под управлением KVM, на котором будет несколько гостей, некоторые из которых будут использовать виртуализированные брандмауэры, а другие - просто веб-серверы.

Обычно это было бы просто, просто добавьте мост с помощью eth0 в нем добавляем несколько VLAN на мост (vmbr0.1 и т. д.) - затем выделите интерфейс с немаркированной VLAN для каждого гостя (или их множества).

                             firewall1 (vlan 1,2,3,4)
switch ===== eth0  vmbr0     firewall2 (vlan 1,2,5,6)
                   (eth0)    server1 (vlan 7)
                             server2 (vlan 8)
     vlan trunk
 (1,2,3,4,5,6,7,8)     

Теперь это отлично работает, если у вас есть только несколько интерфейсов, которые вам нужно передать гостю. Но что происходит, когда вам нужно поместить 500 VLAN в брандмауэр. Это непрактично.

Так что я не могу понять, как создать номерные магистрали (с общими VLAN и разными VLAN) и выделить их гостю.

Ближайшее решение, которое я нашел до сих пор, - создать VLAN на главном мосту, а затем для серверов просто выделить из него одну VLAN.

Затем для брандмауэров создайте мост для каждого, только с гостевым tap интерфейс в нем, затем создайте немаркированный vlan интерфейс для соответствующего моста и добавьте его в основной vmbr0 мост.

Единственная проблема с этим состоит в том, что трафик, выходящий из немаркированного интерфейса, конечно, немаркирован.

Можно ли пометить трафик, выходящий из интерфейса?

-

В противном случае, как можно получить разные магистрали для гостей KVM, которые могут иметь общие VLAN и разные VLAN (но никогда ВСЕ vlan) - и иметь возможность назначать отдельные нетегированные интерфейсы vlan

Долгое решение ...

Итак, я экспериментировал с разными концепциями и думаю, что нашел работоспособное решение. В основном это основной мостовой ствол (bt) который eth0 принадлежит. Тогда для каждой виртуальной машины межсетевого экрана есть свой мост.

bridge name     bridge id               STP enabled     interfaces
bt              8000.002618895a72       no              eth0
bt-fw1          8000.000000000000       no              tap100i0
bt-fw2          8000.000000000000       no              tap101i0

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

Затем я создал VLAN для каждого интерфейса, которому нужен тегированный трафик, и соответствующую VLAN на главном мосту для немаркированного трафика.

Например. VLAN 1, 4000-4005

bt-fw1.1       | 1  | bt-fw1
bt-fw1.4000    | 4000  | bt-fw1
bt-fw1.4001    | 4001  | bt-fw1
bt-fw1.4002    | 4002  | bt-fw1
bt-fw1.4003    | 4003  | bt-fw1
bt-fw1.4004    | 4004  | bt-fw1
bt-fw1.4005    | 4005  | bt-fw1
bt-fw2.1       | 1  | bt-fw2
bt-fw2.4000    | 4000  | bt-fw2
bt-fw2.4001    | 4001  | bt-fw2
bt-fw2.4002    | 4002  | bt-fw2
bt-fw2.4003    | 4003  | bt-fw2
bt-fw2.4004    | 4004  | bt-fw2
bt-fw2.4005    | 4005  | bt-fw2
bt.1           | 1  | bt
bt.4000        | 4000  | bt
bt.4001        | 4001  | bt
bt.4002        | 4002  | bt
bt.4003        | 4003  | bt
bt.4004        | 4004  | bt
bt.4005        | 4005  | bt

Затем для каждой VLAN создается мост, который объединяет все соответствующие VLAN от каждого интерфейса, чтобы обеспечить немаркированную связь между основным мостом и мостами виртуальных машин.

bt.v1                   8000.2a8c73ad057d       no      bt-fw1.1
                                                        bt-fw2.1
                                                        bt.1
bt.v4000                8000.2a8c73ad057d       no      bt-fw1.4000
                                                        bt-fw2.4000
                                                        bt.4000
bt.v4001                8000.2a8c73ad057d       no      bt-fw1.4001
                                                        bt-fw2.4001
                                                        bt.4001
bt.v4002                8000.2a8c73ad057d       no      bt-fw1.4002
                                                        bt-fw2.4002
                                                        bt.4002
bt.v4003                8000.2a8c73ad057d       no      bt-fw1.4003
                                                        bt-fw2.4003
                                                        bt.4003
bt.v4004                8000.2a8c73ad057d       no      bt-fw1.4004
                                                        bt-fw2.4004
                                                        bt.4004
bt.v4005                8000.2a8c73ad057d       no      bt-fw1.4005
                                                        bt-fw2.4005
                                                        bt.4005

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

Любые будущие гости, которым нужна только одна немаркированная VLAN, могут быть просто добавлены в соответствующий bt.X мост.

Добавить IP-интерфейсы хоста так же просто, как добавить IP-адрес в соответствующий мост VLAN.

Например.

ip addr add 192.168.100.1/24 dev bt.v4005

Вспомогательный сценарий

Как мой /etc/network/interfaces файл может быстро стать огромным, я написал небольшой сценарий, который допускает минимальную настройку - но с тем же желаемым конечным результатом.

в /etc/network/interfaces файл, который он содержит

# bridge bt-c0-fw1 vlan 1 4000-4005 interfaces tap100i0
# bridge bt-c0-fw2 vlan 1 4000-4005 interfaces tap101i0
# bridge bt vlan 1 4000-4005 interfaces eth0
# bridge-vlan bt vlan 1 4000-4005 interfaces bt-fw1 bt-fw2 bt

auto eth0
iface eth0 inet manual
  post-up /scripts/build-bridges.sh || /bin/true

Затем в сценарии пост-ап, /scripts/build-bridges.sh

#!/bin/bash

CONFIG="/etc/network/interfaces"
DEFINERS="vlan|interfaces"
DEBUG=0

# Tear down all interfaces
modprobe -r 8021q
modprobe 8021q

brctl show | awk 'NR>1{print $1}' | while read BRIDGE; do
  ifconfig "$BRIDGE" down
  brctl delbr "$BRIDGE"
done

function run()
{
  if [ $DEBUG -eq 1 ]; then
    echo "$@"
  else
    eval "$@"
  fi
}

function get_vars()
{
  DATA=( $(echo "$2" | grep -Eoh "$1.+?" | sed -E "s/^$1 //g;s/($DEFINERS).+//g") )
  for VAL in ${DATA[@]}; do
    echo $VAL | grep -qE "[0-9]+-[0-9]+"
    if [ $? -eq 0 ]; then
      LOWER=$(echo $VAL | cut -f1 -d"-")
      UPPER=$(echo $VAL | cut -f2 -d"-")
      for i in $(seq $LOWER $UPPER); do
        echo $i
      done
    else
      echo $VAL
    fi
  done
}

# Build bridges
while read LINE; do
  BRIDGE=$(get_vars bridge "$LINE")
  if [[ ! "$BRIDGE" == "" ]]; then
    run brctl addbr $BRIDGE
    run ifconfig $BRIDGE up
    for INTERFACE in $(get_vars interfaces "$LINE"); do
      ifconfig $INTERFACE >/dev/null 2>&1
      if [ $? -eq 0 ]; then
        run brctl addif $BRIDGE $INTERFACE
      fi
    done
    run ifconfig $BRIDGE up
    for VLAN in $(get_vars vlan "$LINE"); do
      run vconfig add $BRIDGE $VLAN 2>&1 | grep -vE "(VLAN 1 does not work|consider another number)"
      run ifconfig $BRIDGE.$VLAN up
    done
  fi
done < <(grep -E "^# bridge " $CONFIG)

# Build vlan bridges
while read LINE; do
  BRIDGE=$(get_vars "bridge-vlan" "$LINE")
  for VLAN in $(get_vars " vlan" "$LINE"); do
    run brctl addbr $BRIDGE.v$VLAN
    run ifconfig $BRIDGE.v$VLAN up
    for INTERFACE in $(get_vars interfaces "$LINE"); do
      ifconfig $INTERFACE.$VLAN >/dev/null 2>&1
      if [ $? -eq 0 ]; then
        run brctl addif $BRIDGE.v$VLAN $INTERFACE.$VLAN
      fi
    done
  done
done < <(grep -E "^# bridge-vlan " $CONFIG)

exit 0

Я надеюсь, что это поможет кому-то другому, я потратил ДНИ на чтение и тестирование, и это кажется наиболее элегантным и простым в управлении решением.

Здесь тоже есть хорошее чтение http://blog.davidvassallo.me/2012/05/05/kvm-brctl-in-linux-bringing-vlans-to-the-gests/