web-dev-qa-db-ja.com

複数、異なるVLANトランクからKVMゲスト(Linux)

私はある種の障害を建築上の課題に突き当たりました。私はKVM-を実行しているサーバーを持っています-これはいくつかのゲスト、仮想化されたファイアウォールなどを実行しているもの、単純なWebサーバーを備えています。

  • Webサーバーには、タグなしの単一のVLANインターフェースが必要です
  • ファイアウォールにはタグ付きのVLANトランクが必要です

通常、これは簡単です。_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インターフェースを割り当てることができます)

5
choco-loo

長い解決策...

だから私はさまざまな概念をいじくり回していて、実行可能な解決策を作ったと思います。基本的に、eth0が属するメインブリッジトランク(bt)があります。次に、ファイアウォールごとにVMに独自のブリッジがあります。

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

この時点で、ファイアウォールVMからのタグ付きトラフィックは、トラフィックが入るための独自のブリッジに入ります。

次に、タグ付きトラフィックを必要とする各インターフェイスに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を結合して、メインブリッジとVMブリッジ間のタグなし通信を可能にします。

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

これにより、ファイアウォールVMへのインターフェイスのトランクが可能になり、必要な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-guests/

6
choco-loo