自宅では長らく VMware ESXi を使用してきて、大変良かったのだが、ホストが Linux だと何かと楽だろうと考えたりしていたり、DS77U5 への移行のタイミングでホスト側に直接 Docker で入れられるものは直接入れたくなったりしたのもあり、新たに libvirtd を検証開始。意外とすんなり入って中の状態も分かりやすい感じにはなったが、(主に libvirtd に直接関係ない)よくわからないところに罠があったのでメモ。
なおこの前に OpenStack を試そうとしたが、 conjure-up が半端に色々ラップしたまま失敗してどうなっているのかさっぱりわからない状態になったのを見て OpenStack は諦めた。
まずは、 Ubuntu 18.04: 仮想化のKVMをインストールする – Narrow Escape にしたがってパッケージを入れた。ただし、 libguestfs-tools は要らなそうだったので、今のところ入れていない。なお、 /var/lib/libvirt に色々保存するようだったので、通常必要ない操作だがインストール前にこのディレクトリを実際に保存したいパーティションにシンボリックリンクとして指定した。
$ sudo apt install -y qemu-kvm libvirt0 libvirt-bin virt-manager
また、
$ sudo gpasswd libvirt -a `whoami`
続いて、ブリッジネットワークを構成する。いつの間にか(多分 LTS だと 18.04 から?) /etc/network/interfaces がもぬけの殻になっていて、 netplan に移行したから /etc/netplan/ を見ろと言っているので、 /etc/netplan/01-netcfg.yaml を編集した。なおこのファイルの名前は、環境によっては 50-cloud-init.yaml などになるようだ。
なお、ブリッジ側の MAC アドレスは起動するたびにランダムに変わるようで、 DHCP で固定の IP アドレスを配るのに問題があるので、固定した。IP アドレスを static でホスト側で指定するなら不要と思われる。また、 VM で検証しているときはホスト側の仮想スイッチでプロミスキャスモードを禁止しているために通信がうまく行えない罠にはまっていた。
あと、 macvcap でホストの LAN に直接刺せそうな選択肢があるが、これはブリッジではなく NIC をその VM で占有する時に使うもののようなので、 VM とホスト両方、あるいは複数 VM で使うときはブリッジ構成は必要なようだ。
# This file describes the network interfaces available on your system # For more information, see netplan(5). network: version: 2 renderer: networkd ethernets: enp1s0: dhcp4: no bridges: br0: macaddress: XX:XX:XX:XX:XX:XX dhcp4: yes interfaces: [enp1s0]
これで
$ sudo netplan generate $ sudo netplan apply
などとするとブリッジが構成できたが、古いものが消えなかったりして微妙にこのファイルの定義とずれていくようなので、素直に
$ sudo reboot
するのがよさそう。
これでブリッジが構成されるので、
$ sudo brctl show bridge name bridge id STP enabled interfaces br0 XXXX.XXXXXXXXXXXX no enp1s0 vnet0 docker0 XXXX.XXXXXXXXXXXX no vethXXXXXXX vethXXXXXXX virbr0 XXXX.XXXXXXXXXXXX yes virbr0-nic
みたいな感じで brctl でブリッジが見え、 ifconfig でも DHCP から降ってきた IP アドレスが見れるようになった。
なお、 vnet0 というのが、 libvirtd でブリッジに接続したときに VM と紐づけて作る tap インターフェイスのようだ。なので、この状態で enp1s0, br0, vnet0 は同じ L2 として自由に疎通できそうだが、実際には br0 をまたいだパケットがやりとりされない現象に悩んだ。tcpdump を見ても、 enp1s0 から流れてきたパケットは br0 には流れているが vnet0 には流れず、 vnet0 から流しているはずの DHCP discover も br0 には流れているが enp1s0 には流れなかった。
結局、 networking – why linux bridge doesn’t work – Super User を見て、 iptables が L2 に干渉してくるのか疑問に思いながらも試してみたところ、echo 0 > /proc/sys/net/bridge/bridge-nf-call-iptables によって実際に解決した。よくわかっていないが、どうやら自分のホストに来てしまった時点で L2 な転送でも iptables を通ってしまうようだ。
なのであとは /etc/sysctl.conf 相当のファイルに
net.bridge.bridge-nf-call-iptables = 0
という内容を書くことになるが、ここにも罠があった。
まず、 Ubuntu 18.04 だと /etc/sysctl.d といういかにもディレクトリがあり、 /etc/sysctl.d/README にはご丁寧に
After making any changes, please run “service procps start” (or, from
a Debian package maintainer script “invoke-rc.d procps start”).
とまで書いてあったのだが、なぜか動かなかったので、結局昔ながらのやり方で /etc/sysctl.conf に書き込むことにした。
しかし、これでは sysctl -p /etc/sysctl.conf や invoke-rc.d procps start では反映されるものの、再起動するとなぜか 1 に戻ってしまう。該当範囲は不明だが、少なくとも Ubuntu 18.04 では procps のサービス起動(sysctl.conf 読み込みを実施する)をネットワークが有効になる前に実施してしまうので、ネットワーク関係の設定はここに書いても無視されてしまうようだ: Ubuntu 18.04 で ipv6 を無効にする | 雑廉堂の雑記帳
少なくとも net.bridge.bridge-nf-call-iptables は /etc/rc.local でもうまくいかなかった。そのためネットワーク関係のあれこれが起動しているであろう net if の post-up にねじこみたかったが、FAQ | netplan.io によるとそのようなものはまだないようで、代わりに networkd-dispatcher で設定するよう勧められている。幸い、手元の Ubuntu 18.04 では OS インストール時に networkd-dispatcher がインストールされていたようだったので、次のようなファイルを作成することで、再起動しても sysctl.conf が読み込まれて、ブリッジなら iptables を無視してパケットが行き来できるようになった。
$ cat /usr/lib/networkd-dispatcher/routable.d/99sysctlworkaround #!/bin/sh /etc/init.d/procps restart exit 0 $ ls -al /usr/lib/networkd-dispatcher/routable.d/99sysctlworkaround -rwxr-xr-x 1 root root 46 Jul 6 20:57 /usr/lib/networkd-dispatcher/routable.d/99sysctlworkaround
これでようやく、 libvirtd に br0 を認識させて、直接 enp1s0 に出ていけるようになった。
MAC アドレスは中からも外からもホストの vnet0 としても、ここに表示されたものになるようだ。ESXi ではマシンを一回立ち上げるまで MAC アドレスがわからないが、 libvirtd + virt-mangaer では最初に起動する前から表示されるので、インストール前に DHCP/DNS に登録できるのは便利。
(2019/7/23 追記)UEFI ベースの VM を移植するに、 UEFI/OVMF – Ubuntu Wiki にあるように apt install ovmf して UEFI 用のファームウェアをダウンロードする必要があった。また、他のところで使っていた UEFI ベースの VM イメージを取り込む際、 BIOS メニューに入る前(Tiano core ロゴ)に F2 を連打してメニューから efi ファイルを直接選択して起動し起動後に grub-install して起動すべきファイルを認識させる必要があった。
ピンバック: 【Ubuntu 18.04】単一NICに複数IPを割り当てる【netplan】 | 志功索悟のブログ