====== 複数のQEMU/KVMホストにまたがる仮想ネットワークをVXLANで構築 ======
{{tag>qemu-kvm libvirt vxlan centos7 rhel8-clone}}
目的: 複数のホストにまたがる仮想ネットワークを構築し、それぞれのホストで動くVMが相互に通信できるようにする。
- libvirtが作成するデフォルト仮想ネットワークのブリッジ''virbr0''はlibvirtが管理しているため、それとは別に手動でブリッジを作成する。
- 作成したブリッジをVXLANで相互に接続する。
- それぞれのホストでブリッジから仮想ネットワークを作成する。
- ブリッジ接続の仮想ネットワークはNATやDHCPサーバが自動的に構成されないので手動で追加する。
参考:
* [[https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/8/html/configuring_and_managing_networking/assembly_using-a-vxlan-to-create-a-virtual-layer-2-domain-for-vms_configuring-and-managing-networking|VXLAN を使用した仮想マシンの仮想レイヤー 2 ドメインの作成]]
* [[https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/8/html/configuring_and_managing_networking/configuring-a-gretap-tunnel-to-transfer-ethernet-frames-over-ipv4_configuring-ip-tunnels|IPv4 でイーサネットフレームを転送するための GRETAP トンネルの設定]]
===== 構成1 ホスト2台をユニキャストのVXLANで接続 =====
{{:articles:kvm-vxlan.png?nolink|}}
* ホストはCentOS 7.9/Rocky Linux 8.7で172.31.0.121(eth0)と172.31.0.122(eth0)の2台
* DHCP/DNSサーバはHost#1で実行
* NAT/ゲートウェイはHost#1、Host#2それぞれで作成、DHCPで公告するのはHost#1のbr0
* ''eth0''はmasqueradeでNATを構成するために''external''ゾーンに移動
* 仮想ネットワーク関連はfirewalldの''internal''ゾーンに作成する
* 仮想ネットワーク(''br0'')を作成する
* VXLANの接続先(''remote'')は対向のユニキャストアドレスを指定する
{{:articles:kvm-vxlan-zone.png?nolink|}}
==== (構成1) カーネルパラメータの設定 ====
libvirtがインストールされているならip_forwardの設定は不要なはず。
echo "net.ipv4.ip_forward = 1" > /etc/sysctl.d/ip_forward
echo 1 > /proc/sys/net/ipv4/ip_forward
==== (構成1) firewalldの設定 ====
まずは''external''ゾーンを''public''ゾーンと同等の設定にし、
VXLANを許可してからeth0を''public''から''external''に移す。
firewall-cmd --zone=external --add-service=dhcpv6-client
firewall-cmd --zone=external --add-port 4789/udp
firewall-cmd --set-default-zone=external
firewall-cmd --runtime-to-permanent
nmcli con mod eth0 connection.zone external
Host#1の''internal''ゾーンはDHCPとDNSを許可する。
firewall-cmd --zone=internal --add-service dhcp
firewall-cmd --zone=internal --add-service dhcpv6
firewall-cmd --zone=internal --add-service dns
firewall-cmd --runtime-to-permanent
設定の確認。
firewall-cmd --get-default-zone
firewall-cmd --get-active-zones
firewall-cmd --list-all-zones
==== (構成1) ブリッジの作成とVXLAN接続 ====
''internal''ゾーンにブリッジ''br0''とVXLANで接続する''vxlan10''を作成する。
CentOS 7では、''ipv6.method disabled''を''ipv6.method ignore''にすること。
=== Host#1 172.31.0.121 ===
nmcli con add type bridge con-name br0 ifname br0 ipv4.method static ip4 192.168.124.1/24 ipv6.method disabled connection.zone internal
nmcli con up br0
nmcli con add type vxlan slave-type bridge master br0 con-name br0-vxlan ifname vxlan10 id 10 remote 192.168.10.122 destination-port 4789 connection.zone internal
nmcli con up br0-vxlan
=== Host#2 172.31.0.122 ===
nmcli con add type bridge con-name br0 ifname br0 ipv4.method static ip4 192.168.124.2/24 ipv6.method disabled connection.zone internal
nmcli con up br0
nmcli con add type vxlan slave-type bridge master br0 con-name br0-vxlan ifname vxlan10 id 10 remote 192.168.10.121 destination-port 4789 connection.zone internal
nmcli con up br0-vxlan
=== 設定の確認 ===
PAGER= nmcli
ip link
bridge fdb
firewall-cmd --get-active-zone
==== (構成1) 仮想ネットワークの作成 ====
''br0''を使用する仮想ネットワーク''br0-vxlan''を作成。
cat < /tmp/network-br0-vxlan.xml
br0-vxlan
EOF
virsh net-define /tmp/network-br0-vxlan.xml
virsh net-autostart br0-vxlan
virsh net-start br0-vxlan
不要なファイルの削除と状態確認。
rm /tmp/network-br{0,1}-vxlan.xml
virsh net-list
==== (構成1) DNS/DHCPサーバの設定 - Host#1 ====
Rocky Linux 8の場合、必要なパッケージはlibvirtの依存関係でインストール済み。
CentOS 7の場合は追加でパッケージのインストールが必要。
yum install policycoreutils-python
''br0''で動く''dnsmasq''のサービスを作成する。
semanage fcontext --add -t dnsmasq_lease_t '/var/lib/dnsmasq-vxlan/dhcp\.leasefile'
semanage fcontext --add -t dnsmasq_etc_t '/var/lib/dnsmasq-vxlan(/.*)?'
mkdir /var/lib/dnsmasq-vxlan
cat < /var/lib/dnsmasq-vxlan/dnsmasq.conf
strict-order
pid-file=/var/run/dnsmasq-vxlan.pid
except-interface=lo
bind-dynamic
interface=br0
dhcp-range=192.168.124.16,192.168.124.254
dhcp-no-override
dhcp-authoritative
dhcp-lease-max=253
dhcp-leasefile=/var/lib/dnsmasq-vxlan/dhcp.leasefile
dhcp-hostsfile=/var/lib/dnsmasq-vxlan/dhcp.hostsfile
dhcp-optsfile=/var/lib/dnsmasq-vxlan/dhcp.optsfile
addn-hosts=/var/lib/dnsmasq-vxlan/addn.hosts
EOF
touch /var/lib/dnsmasq-vxlan/dhcp.leasefile
touch /var/lib/dnsmasq-vxlan/dhcp.hostsfile
touch /var/lib/dnsmasq-vxlan/addn.hosts
touch /var/lib/dnsmasq-vxlan/dhcp.optsfile
restorecon -rv /var/lib/dnsmasq-vxlan
cat < /etc/systemd/system/dnsmasq-vxlan.service
[Unit]
Description=DNS caching server for vxlan.
After=network.target
[Service]
ExecStart=/usr/sbin/dnsmasq -k --conf-file=/var/lib/dnsmasq-vxlan/dnsmasq.conf
[Install]
WantedBy=multi-user.target
EOF
systemctl enable dnsmasq-vxlan --now
systemctl status dnsmasq-vxlan
===== 構成2 ホスト3台をマルチキャストでVXLAN接続 =====
{{:articles:kvm-vxlan2.png?nolink|}}
* NAT/ゲートウェイはHost#1経由
* DHCP/DNSサーバをHost#1で実行
* 仮想ネットワークを2つ(''br0''と''br1'')作成
* 外部向けと内部向け(VXLAN)のネットワークを分ける
* VXLANの接続先(''remote'')にマルチキャストアドレスを指定
* VMとVXLAN関連の通信は全て''internal''ゾーンに移す
{{:articles:kvm-vxlan2-zone.png?nolink|}}
==== (構成2) NATの設定 - Host#1 ====
''external''ゾーンを''public''ゾーンと同等の設定にし、
''eth0''を''public''から''external''に移す。
firewall-cmd --zone=external --add-service=dhcpv6-client
firewall-cmd --set-default-zone=external
firewall-cmd --runtime-to-permanent
nmcli con mod eth0 connection.zone external
設定の確認。
firewall-cmd --get-default-zone
firewall-cmd --get-active-zones
firewall-cmd --list-all-zones
==== (構成2) ブリッジの作成とVXLAN接続 ====
VMとVXLAN関連の通信は全て''internal''ゾーンに移す。
firewall-cmd --zone=internal--add-port 4789/udp
firewall-cmd --runtime-to-permanent
nmcli con mod eth1 connection.zone internal
CentOS 7では、''ipv6.method disabled''を''ipv6.method ignore''にすること。
''br0''と''vxlan10''の作成。
nmcli con add type bridge con-name br0 ifname br0 ipv4.method disabled ipv6.method disabled connection.zone internal
nmcli con up br0
nmcli con add type vxlan slave-type bridge master br0 con-name br0-vxlan ifname vxlan10 id 10 remote 239.0.0.10 dev eth1 destination-port 4789 connection.zone internal
nmcli con up br0-vxlan
''br1''と''vxlan11''の作成。
nmcli con add type bridge con-name br1 ifname br1 ipv4.method disabled ipv6.method disabled connection.zone internal
nmcli con up br1
nmcli con add type vxlan slave-type bridge master br1 con-name br1-vxlan ifname vxlan11 id 11 remote 239.0.0.11 dev eth1 destination-port 4789 connection.zone internal
nmcli con up br1-vxlan
今後ともL2でループが発生しないならば、STPを停止して負荷を下げることも可能。
nmcli con mod br0 bridge.stp no
nmcli con up br0
設定の確認。
PAGER= nmcli
ip link
bridge fdb
firewall-cmd --get-active-zone
==== 注意: MTUの確認 ====
ホスト上の''ip link''でMTUを確認すること。
マルチキャストを使用すると、''br0''のMTUが1450になる。
eth1: mtu 1500
br0: mtu 1450
vxlan10: mtu 1450
ユニキャストなら1500のまま。
eth1: mtu 1500
br0: mtu 1500
vxlan10: mtu 1500
マルチキャストを使用する場合は特に、
作成したVMでネットワークデバイスのMTUを確認しホストに合わせること。
nmcli con mod eth0 802-3-ethernet.mtu 1450
nmcli con up eth0
VMより''br0''のMTUが小さいと大きいパケットが破棄されるため、
ホストからVMへのsshやVM-VM間のpingは成功するが、
VM-VM間のsshやpathtraceが失敗する。
==== (構成2) 仮想ネットワークの作成 ====
仮想ネットワーク''br0-vxlan''と''br1-vxlan''を作成。
cat < /tmp/network-br0-vxlan.xml
br0-vxlan
EOF
virsh net-define /tmp/network-br0-vxlan.xml
virsh net-autostart br0-vxlan
virsh net-start br0-vxlan
cat < /tmp/network-br1-vxlan.xml
br1-vxlan
EOF
virsh net-define /tmp/network-br1-vxlan.xml
virsh net-autostart br1-vxlan
virsh net-start br1-vxlan
不要なファイルの削除と状態確認。
rm /tmp/network-br{0,1}-vxlan.xml
virsh net-list
==== (構成2) DNS/DHCPサーバの設定 - Host#1 ====
Rocky Linux 8の場合、必要なパッケージはlibvirtの依存関係でインストール済み。
CentOS 7の場合は追加でパッケージのインストールが必要。
yum install policycoreutils-python
Host#1の''internal''ゾーンでDHCPとDNSを許可する。
firewall-cmd --zone=internal --add-service dhcp
firewall-cmd --zone=internal --add-service dhcpv6
firewall-cmd --zone=internal --add-service dns
firewall-cmd --runtime-to-permanent
''br0''と''br1''にIPv4のアドレスを設定。
nmcli con mod br0 ipv4.method static ip4 192.168.124.1/24
nmcli con up br0
nmcli con mod br1 ipv4.method static ip4 192.168.125.1/24
nmcli con up br1
''br0''と''br1''で動く''dnsmasq''のサービスを作成。
semanage fcontext --add -t dnsmasq_lease_t '/var/lib/dnsmasq-vxlan/dhcp\.leasefile'
semanage fcontext --add -t dnsmasq_etc_t '/var/lib/dnsmasq-vxlan(/.*)?'
mkdir /var/lib/dnsmasq-vxlan
cat < /var/lib/dnsmasq-vxlan/dnsmasq.conf
strict-order
pid-file=/var/run/dnsmasq-vxlan.pid
except-interface=lo
bind-dynamic
interface=br0
interface=br1
dhcp-range=tag:br0,192.168.124.16,192.168.124.254
dhcp-range=tag:br1,192.168.125.16,192.168.125.254
dhcp-no-override
dhcp-authoritative
dhcp-lease-max=253
dhcp-leasefile=/var/lib/dnsmasq-vxlan/dhcp.leasefile
dhcp-hostsfile=/var/lib/dnsmasq-vxlan/dhcp.hostsfile
dhcp-optsfile=/var/lib/dnsmasq-vxlan/dhcp.optsfile
addn-hosts=/var/lib/dnsmasq-vxlan/addn.hosts
EOF
touch /var/lib/dnsmasq-vxlan/dhcp.leasefile
touch /var/lib/dnsmasq-vxlan/dhcp.hostsfile
touch /var/lib/dnsmasq-vxlan/addn.hosts
touch /var/lib/dnsmasq-vxlan/dhcp.optsfile
restorecon -rv /var/lib/dnsmasq-vxlan
cat < /etc/systemd/system/dnsmasq-vxlan.service
[Unit]
Description=DNS caching server for vxlan.
After=network.target
[Service]
ExecStart=/usr/sbin/dnsmasq -k --conf-file=/var/lib/dnsmasq-vxlan/dnsmasq.conf
[Install]
WantedBy=multi-user.target
EOF
systemctl enable dnsmasq-vxlan --now
systemctl status dnsmasq-vxlan
==== (構成2) 仮想ネットワーク間の通信 - Host#1 ====
デフォルトでは仮想ネットワーク間(zone内のインタフェース間)の通信は遮断されている。
Rocky Linux 8以降は''firewall-cmd %%--%%zone=internal %%--%%add-forward''を実行すると、
仮想ネットワーク間(zone内のインタフェース間)で通信が疎通するようになる。
CentOS 7はzoneにforwardの設定がないため変更不可。
''trusted''ゾーンは全ての通信を許可するため、forward設定に関わらず仮想ネットワーク間の通信も遮断されない。
そのため、CentOS 7で仮想ネットワーク間の通信を許可したい場合は''internal''ゾーンではなく''trusted''ゾーンを使うことで実現できる。
===== ゲストOSのインストール =====
VMが接続する仮想ネットワークを''%%--%%network network=br0-vxlan''で指定してインストールする。
複数の仮想ネットワークに接続する場合は''%%--%%network''を複数指定する。
Rocky Linux 8以降ならゲストOSインストール時に仮想ネットワークに加えて仮想NICのMTUも指定可能。
仮想ネットワークのオプションに''mtu.size''を追加する(例: ''%%--%%network network=br0-vxlan,mtu.size=1450'')。
virt-install --name centos7 --memory 2048 --vcpus 1 --disk size=8 --network network=br0-vxlan --os-variant centos7.0 --location /var/lib/libvirt/images/CentOS-7-x86_64-Minimal-2009.iso --nographics --extra-args='console=ttyS0,115200n8'
===== 接続の確認 =====
* ''nmcli'' - DHCPの確認
* ''arping'' - ARPで疎通確認、同じL2セグメントなら成功する
* ''ping'' - ICMPで疎通確認
* ''tracepath'' - tracerouteの代替、UDPで大きいパケットの疎通確認
* ''ssh'' - SSH接続、TCPで大きいパケットの疎通確認
* ''curl'' - HTTP
* VMからVM
* ホストからVM
* VMからホスト
* VMから外部