[CentOS 7][KVM] 仮想マシンをホストと同じネットワークへ接続する方法2選＋1選追加

仮想マシンを外部ネットワークへ接続させる方法はいくつかあるみたいです。

<dl>
<dt>NATモード</dt>
<dd>初期状態だとこのモードです。仮想マシンはIPマスカレードされてホストのIPアドレスとして外へ出ていきます。外から仮想マシンへはアクセスするときは、一工夫必要になります。</dd>
<dt>Routedモード</dt>
<dd>ホストがルータとして動作します。仮想マシンは自身のIPアドレスで外へ出ていきます。外から仮想マシンへアクセスするときは、なんらかのルーティングが必要になります。</dd>
<dt>ブリッジ</dt>
<dd>libvirtの外側で設定されたブリッジデバイスに仮想マシンを接続します。</dd>
<dt>ダイレクト-ブリッジ</dt>
<dd>
macvtapのbridgeモードを利用して直接ホストネットワークへ接続します。
@takehironet さんに教えてもらいました。Thanks :smile: 
同一ホスト上の仮想マシン同士でやりとりする場合は、両方とも同じモードである必要があります。</dd>
<dt>ダイレクト-プライベート</dt>
<dd>macvtapのprivateモードを利用して直接ホストネットワークへ接続します。</dd>
<dt>ダイレクト-vepa</dt>
<dd>macvtapのvepaモードを利用して直接ホストネットワークへ接続します。vepa(Virtual Ethernet Port Aggregator)が使えるスイッチがないと使えません。</dd>
<dt>ダイレクト-パススルー</dt>
<dd>macvtapを利用して直接ホストネットワークへ接続します。物理インターフェースは一度に一つの仮装インターフェースからしか使えません。物理インターフェースに空きがないときはエラーが記録されます。</dd>
<dt>ホストデバイス</dt>
<dd>PCIネットワークデバイスを仮想マシンへ直接割り当てます。</dd>
</dl>


ここではブリッジとダイレクト-プライベート、そしてダイレクト-ブリッジを試してみます。


# やり方その1「ブリッジ」接続するときの作業手順

ここでは、物理デバイス名は「ens32」です。

## (ステップ1)  ブリッジコネクションを作成

「br0」というインターフェースに対してブリッジコネクションを作成します。

```
# nmcli con add type bridge ifname br0
Connection 'bridge-br0' (2ef66f6a-4079-4d07-9c1a-e9fdeecca8bd) successfully added.
```

こんなんできました。

```
# nmcli con show
NAME        UUID                                  TYPE            DEVICE
vnet0       66568803-1d59-4dcf-b241-ff6cab294715  generic         vnet0
ens32       461d3edc-1e6e-4334-b8dc-1ff3d691c03e  802-3-ethernet  ens32
virbr0-nic  8d33a0ef-019a-4ce1-a8e8-71dc0c9bbe1e  generic         virbr0-nic
virbr0      4094d785-3de6-4acc-86bb-64cafc4d3deb  bridge          virbr0
bridge-br0  2ef66f6a-4079-4d07-9c1a-e9fdeecca8bd  bridge          br0
```

```
# nmcli dev
DEVICE      TYPE      STATE                                  CONNECTION
virbr0      bridge    connected                              virbr0
ens32       ethernet  connected                              ens32
virbr0-nic  tap       connected                              virbr0-nic
vnet0       tap       connected                              vnet0
br0         bridge    connecting (getting IP configuration)  bridge-br0
lo          loopback  unmanaged                              --
```

## (ステップ2) ブリッジスレーブコネクションを作成

「bridge-br0」コネクションをマスターとして、「ens32」インターフェースをスレーブとするコネクションを作成します。

```
# nmcli con add type bridge-slave ifname ens32 master bridge-br0
Connection 'bridge-slave-ens32' (59ea6a01-af71-4f55-8433-eb7c49117578) successfully added.
```

こんなんできました。

```
# nmcli con
NAME                UUID                                  TYPE            DEVICE
bridge-slave-ens32  59ea6a01-af71-4f55-8433-eb7c49117578  802-3-ethernet  --    
vnet0               66568803-1d59-4dcf-b241-ff6cab294715  generic         vnet0 
ens32               461d3edc-1e6e-4334-b8dc-1ff3d691c03e  802-3-ethernet  ens32 
virbr0-nic          8d33a0ef-019a-4ce1-a8e8-71dc0c9bbe1e  generic         virbr0-nic
virbr0              4094d785-3de6-4acc-86bb-64cafc4d3deb  bridge          virbr0
bridge-br0          2ef66f6a-4079-4d07-9c1a-e9fdeecca8bd  bridge          br0
```

```
# nmcli dev
DEVICE      TYPE      STATE                                  CONNECTION
virbr0      bridge    connected                              virbr0
ens32       ethernet  connected                              ens32
virbr0-nic  tap       connected                              virbr0-nic
vnet0       tap       connected                              vnet0
br0         bridge    connecting (getting IP configuration)  bridge-br0
lo          loopback  unmanaged                              --
```

## (ステップ3) 既存コネクションを削除して再起動

ネットワーク接続が切れてしまうので、すかさず再起動してます。

```
# nmcli con delete ens32 && reboot
Connection 'ens32' (461d3edc-1e6e-4334-b8dc-1ff3d691c03e) successfully deleted.
```

うまくいけばこんな結果に。

```
# nmcli con
NAME                UUID                                  TYPE            DEVICE
virbr0              89597488-c27c-4038-aeb9-ab426c19cfbe  bridge          virbr0
bridge-br0          2ef66f6a-4079-4d07-9c1a-e9fdeecca8bd  bridge          br0   
bridge-slave-ens32  59ea6a01-af71-4f55-8433-eb7c49117578  802-3-ethernet  ens32 
virbr0-nic          9125d953-43f0-44c1-90a1-91db218a27b5  generic         virbr0-nic
```

```
# nmcli dev
DEVICE      TYPE      STATE      CONNECTION
br0         bridge    connected  bridge-br0
virbr0      bridge    connected  virbr0
ens32       ethernet  connected  bridge-slave-ens32
virbr0-nic  tap       connected  virbr0-nic
lo          loopback  unmanaged  --
```

```
# ip addr show br0
3: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
    link/ether 10:78:d2:e3:56:12 brd ff:ff:ff:ff:ff:ff
    inet 172.27.51.121/24 brd 172.27.51.255 scope global dynamic br0
       valid_lft 690988sec preferred_lft 690988sec
    inet6 fe80::1278:d2ff:fee3:5612/64 scope link
       valid_lft forever preferred_lft forever
```

## (ステップ4) libvirtのネットワーク設定を作成

こんな内容のXMLファイルを作成します。

```xml:host-bridge.xml
<network>
  <name>host-bridge</name>
  <forward mode="bridge" />
  <bridge name="br0"/>
</network>
```

XMLの書式についてはこちら → http://libvirt.org/formatnetwork.html

`virsh`コマンドで読み込みます。

```
# virsh net-define --file host-bridge.xml
Network host-bridge defined from host-bridge.xml
```

自動開始するようにします。

```
# virsh net-autostart host-bridge
Network host-bridge marked as autostarted
```

こんなんできました。

```
# virsh net-list --all
 Name                 State      Autostart     Persistent
----------------------------------------------------------
 default              active     yes           yes
 host-bridge          inactive   yes           yes
```


## (ステップ5) 既存仮想マシンのネットワーク接続を変更

`<interface type='network'>`要素中身を変更します。

```xml:変更前
      <source network='default'/>
```

```xml:変更後
      <source network='host-bridge'/>
```

# やり方その2「プライベート」接続するときの作業手順



## (ステップ1) macvtapリンクを作成

```
# ip link add link ens32 name macvtap0 type macvtap mode private
```

状態がDOWNになっているので上げます。

```
# ip link set macvtap0 up
```

こんなんできました。

```
23: macvtap0@ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN mode DEFAULT qlen 500
    link/ether 7e:f3:46:9c:f0:c1 brd ff:ff:ff:ff:ff:ff
```

## (ステップ2) libvirtのネットワーク設定を作成

こんな内容のXMLファイルを作成します。

```xml:net-private.xml
<network>
  <name>vtap</name>
  <forward mode="private">
    <interface dev="macvtap0" />
  </forward>
</network>
```

`virsh`コマンドで読み込みます。

```
# virsh net-define --file net-private.xml
Network vtap defined from net-private.xml
```

自動開始するようにします。

```
# virsh net-autostart vtap
Network vtap marked as autostarted
```

こんなんできました。

```
# virsh net-list --all
 Name                 State      Autostart     Persistent
----------------------------------------------------------
 default              active     yes           yes
 vtap                 inactive   yes           yes
```


## (ステップ3) 既存仮想マシンのネットワーク接続を変更

`<interface type='network'>`要素の中身を変更します。

```xml:変更前
      <source network='default'/>
```

```xml:変更後
      <source network='vtap'/>
```

## 落穂拾（えない）

この方法だとホスト-VM間の通信ができません。VMにホストと通信するための別NICを追加する等の解決策があります。

作成したmacvtap0は再起動すると消えてしまいます。永続化の方法模索中。。。

# やり方その3 「ダイレクト-ブリッジ」接続するときの作業手順

ここでは、物理デバイス名は「ens32」です。

## 既存仮想マシンのネットワーク接続を変更

`<interface type='network'>`要素の中身を変更します。

```xml:変更前
      <source network='default'/>
```

```xml:変更後
      <source dev='ens32' mode='bridge'/>
```

## 新規インストール時にvirt-installで指定する場合

ネットワークのオプションを次のようにします。

```
--network type=direct,source=ens32,source_mode=bridge
```

source_modeを指定しないと、デフォルトのvepaになります。


# 参考情報

 - [Fedora Networking Guide - Network Bridging - Using NetworkManager Command line tool](https://docs.fedoraproject.org/en-US/Fedora/21/html/Networking_Guide/sec-Network_Bridging_sec-Using_the_NetworkManager_Command_Line_Tool_nmcli.html)
 - [libvirt: Network XML Format](http://libvirt.org/formatnetwork.html)