CentOSのKVMで使う仮想ネットワークについて調べてみた

# はじめに
CentOSのKVMで使う仮想ネットワークについて調べてみました

# まとめ
* 仮想マシンをネットワークに接続するにはvirbr0またはbr0の仮想ブリッジを作成する必要がある
* 仮想ブリッジとは仮想スイッチ
* 仮想ブリッジの種類は2種類。virbr0とbr0
  - vibr0よりはbr0がよく使われていて、その場合vibr0は削除することが多い
* ip aで見えるvnetXとは
  - Tapデバイスのこと。**ブリッジ(仮想スイッチ)のポートのようなイメージ**
* 仮想ブリッジと物理NICの接続
  - ifcfg-eth0ファイルを編集することでbr0仮想ブリッジとeth0を接続する

# 仮想ネットワークの概要
KVMではホストLinuxの仮想ブリッジ機能を利用して仮想ネットワークを構成します。
仮想ブリッジは，ホストLinux上に仮想的なL2スイッチを構成する機能です。
複数の仮想ブリッジを構成することも可能です。

イメージ

```
【仮想マシン】【仮想マシン】
////////////　 ////////////　
  プロセス　　　  プロセス
     ↓　　　　　　   ↓
  仮想NIC         仮想NIC
////////////　 ////////////　　　　
   ↓　　　　　　     ↓
//////////////////////////////////////////////////　【ホストLinux】
   ↓                ↓
TAPデバイス　　  TAPデバイス   
   ↓　　　　　　     ↓
###########仮想ブリッジ#############　virbr0/br0 **仮想的なL2スイッチ**
　　　　   　 ↓  iptables (virbr0) or ブリッジ接続 (br0)
          物理NIC(eth0)
//////////////////////////////////////////////////
```

**仮想マシンをネットワークに接続するにはvirbr0またはbr0の仮想ブリッジを作成する必要がある**



# 仮想ブリッジとは？
https://gihyo.jp/admin/serial/01/ibm_kvm/0003#:~:targetText=%E4%BB%8A%E5%9B%9E%E3%81%AFKVM%E3%81%AE%E4%BB%AE%E6%83%B3,%E3%81%99%E3%82%8B%E3%81%93%E3%81%A8%E3%82%82%E5%8F%AF%E8%83%BD%E3%81%A7%E3%81%99%E3%80%82

* 仮想ブリッジは，ホストLinux上に**仮想的なL2スイッチを構成する機能**
* ホストOSのネットワークをブリッジ化するとは？
  - 仮想マシンとホストLinuxのネットワークを共有すること
  - ホストOSをインストールしたとき、そのネットワークインターフェースはeth0になっています
  - これをホストOSとゲストOSで共有するために、仮想的なブリッジをホストOSに作ってeth0を接続する方法に切り替えます。



## virbr0、br0とは？
* 仮想ブリッジの名前
* [違い](https://www.checksite.jp/kvm-br-conf/)

## virbr0とは？
* virbr0 とは仮想環境でNAT 変換の役割を行う仮想ブリッジ
* KVM仮想環境を構築する場合に標準で導入

http://tooljp.com/linux/Redhat7/faqRedhat7/html/what-is-virbr.html
https://www.orangetakam.com/blog/?p=1034

### vibr0の構成	
* 仮想ブリッジから物理NICにiptablesで向けている
* iptablesのNAT（IPマスカレード）機能を利用
* 仮想ブリッジに対してIPアドレスをアサインして，仮想マシンのゲストOSでは，これをデフォルトゲートウェイに指定
* このゲートウェイに到達したパケットについては，送信元IPアドレスを物理NICのIPアドレスに変換して外部ネットワークに送出
* 仮想ブリッジに接続された仮想マシン全体は，外部のネットワークとは独立したプライベート・ネットワークを構成
* 仮想マシンから外部のサーバに接続することは可能ですが，仮想マシン上のサーバ・アプリケーションに外部から接続することはできません
* vibr0はlibvirtdサービスが管理しており，virt-managerから追加／削除などの管理作業する
* ホストLinux上で稼働するdnsmasqプロセスにより，DHCPサーバとDNSサーバの機能が提供されます。ゲストOSのIPアドレスをDHCPで自動設定することが可能です。また，外部ネットワークとの接続に必要なiptablesの設定は，libvirtdサービスが起動したタイミングで自動的に行われます。

イメージ

```
【仮想マシン】【仮想マシン】
////////////　 ////////////　
 プロセス　　　   プロセス
   ↓　　　　　　    ↓
 仮想NIC         仮想NIC
////////////　 ////////////　　　　
   ↓　　　　　　   ↓
//////////////////////////////////////////////////　【ホストLinux】
   ↓              ↓
TAPデバイス　　TAPデバイス   
   ↓　　　　　　   ↓
###########仮想ブリッジ#############　virbr0 **仮想的なL2スイッチ**
　　　　   　 ↓  iptables (virbr0) 
          物理NIC(eth0)
//////////////////////////////////////////////////
```

https://gihyo.jp/admin/serial/01/ibm_kvm/0003#:~:targetText=%E4%BB%8A%E5%9B%9E%E3%81%AFKVM%E3%81%AE%E4%BB%AE%E6%83%B3,%E3%81%99%E3%82%8B%E3%81%93%E3%81%A8%E3%82%82%E5%8F%AF%E8%83%BD%E3%81%A7%E3%81%99%E3%80%82

## br0とは?
* vibr0と同じく仮想マシンをネットワークに接続するための仮想スイッチ
* 標準では作成されていない
* vibr0よりはbr0がよく使われている

## ホストLinuxの物理NICを仮想ブリッジに接続する構成
* ホストLinuxのネットワーク設定ファイルを直接に編集する必要

### イメージ

```
【仮想マシン】【仮想マシン】
////////////　 ////////////　
 プロセス　　　 プロセス
   ↓　　　　　　  ↓
 仮想NIC         仮想NIC
////////////　 ////////////　　　　
   ↓　　　　　　   ↓
//////////////////////////////////////////////////　【ホストLinux】
   ↓              ↓
TAPデバイス　　 TAPデバイス   
   ↓　　　　　　   ↓
###########仮想ブリッジ#############　br0 **仮想的なL2スイッチ**
　　　　   　　|  接続 
          物理NIC(eth0)
//////////////////////////////////////////////////
```

### br0ブリッジの作成

#### nmcliで作成
https://enakai00.hatenablog.com/entry/20141121/1416551748

```
# nmcli con add type bridge ifname br0
# nmcli con modify bridge-br0 bridge.stp no
# nmcli con modify bridge-br0 ipv4.method manual ipv4.address "192.168.199.100/24" ipv4.gateway "192.168.199.254"
```

KVMホストの物理ポートenp0s25をブリッジに接続します。

```
# nmcli con add type bridge-slave ifname enp0s25 master bridge-br0
```

ゲストOSをブリッジに接続する
仮想マシンのGUIから設定


#### 手動で作成
ifcfg-br0を作成

```
$ cat /etc/sysconfig/network-scripts/ifcfg-br0
TYPE="Bridge"　　　　### 
BOOTPROTO="dhcp"
DEFROUTE="yes"
PEERDNS="yes"
PEERROUTES="yes"
IPV4_FAILURE_FATAL="no"
IPV6INIT="yes"
IPV6_AUTOCONF="yes"
IPV6_DEFROUTE="yes"
IPV6_PEERDNS="yes"
IPV6_PEERROUTES="yes"
IPV6_FAILURE_FATAL="no"
NAME="br0"
DEVICE="br0"
ONBOOT="yes"
```

### br0仮想ブリッジとeth0を接続する
ifcfg-eth0の設定

```
$ cat /etc/sysconfig/network-scripts/ifcfg-eth0
TYPE="Ethernet"
HWADDR="52:54:00:xx:xx:xx"
NAME="eth0"
DEVICE="eth0"
ONBOOT="yes"
BRIDGE="br0"
```

# TAPデバイスとは？
https://ja.wikipedia.org/wiki/TUN/TAP

* TUN/TAPは仮想ネットワークデバイス及びそのデバイスドライバの実装およびデバイス名
* TAP(Terminal Access Point) は、イーサネットデバイスをシミュレートし、データリンク層を操作できる。
* TUN(TUNnel) はネットワーク層をシミュレートし、IPパケットなどを操作できる


OSがTUN/TAPデバイスに送ったパケットは、そのデバイスに接続しているユーザープログラムに送信される。
また、ユーザープログラムからTUN/TAPデバイスに送られたパケットは、TUN/TAPデバイスはそれらのパケットをOSのプロトコルスタックに渡すので、
OS側からはあたかも外部からパケットを受け取ったように見える。
用途としては、たとえばTAPはブリッジに使われ、TUNはルーティングに使われる。

**ブリッジ(仮想スイッチ)のポートのようなイメージ**

OSがTUN/TAPデバイスに送ったパケットは、そのデバイスに接続しているユーザープログラムに送信される。

自分で投げたデータがそのまま自分のOSに届くような動作をするデバイスなのですね。
デバイスとしてそういう動作をするものを用意しておくと、プロセスから見ると便利な場面が多々あるという事かな。

TAPはL2で動作する仮想デバイス。
例えば、仮想ブリッジはL2だけで動作するものなので作成した時のポートにはTAPデバイスを追加していく。

TUNはL3で動作する仮想デバイス。
L3つまりIP層で動作する。なのでRubyの例の様なトンネルデバイスを作成する場合に利用する。



## vnetX (X = 1, 2, …)
https://www.virment.com/kvm-configuration/

* 仮想マシンとホストマシンが通信するために使用するTAPデバイスです
* ホストLINUX側からみたTAPデバイス



## virbrY (Y = 1, 2, …)
https://www.virment.com/kvm-configuration/

* 仮想スイッチです。仮想ネットワークの作成順に連番が振られていきます
* KVMをインストールした時点では、virbr0がデフォルトで作成されています