家にあるUbuntuPCでKVMを使ってVMを作成した。VMを外部ホストからsshで接続できるようにするため、ホストで作成したブリッジネットワークにVMを接続したが、色々と詰まったので全体の手順と一緒にまとめておく。

環境

ホストOS

Ubuntu 22.04.1 LTS

ゲストOS

Ubuntu 20.04.5 LTS

手順

UbuntuにKVMを入れる手順は省略(公式の手順を参照)

ブリッジを作成

こちらを参考にした。

デフォルトのネットワークを削除する

KVMをインストールすると、デフォルトでvirbr0というブリッジが作成されているはずである。
このブリッジはNATを使うことでVMが外のネットワークにアクセスできるようにしている。
これがあればホストとVMの間では通信ができるが、外部ホストからVMにアクセスすることはできない。今回は不要なので削除する。

KVM側ではdefaultという設定として記述されているのでこれを削除する。

$ virsh net-destroy default
$ virsh net-undefine default

netplanでブリッジを作成しNICを接続する

netplanを使う。/etc/netplan 配下のファイルで適当なものを修正するか新しく作成する。
ホストのNIC enxf8e43bb371e8 には静的に 192.168.0.130 を割り当てているのでこのアドレスを使う。

# /etc/netplan/99_config.yaml
network:
  version: 2
  ethernets:
    enxf8e43bb371e8:
      dhcp4: false
      dhcp6: false
  bridges:
    br0:
      interfaces: [enxf8e43bb371e8]
      addresses: [192.168.0.130/24]
      gateway4: 192.168.0.1
      nameservers:
        addresses: [192.168.0.1, 8.8.8.8]
      parameters:
        stp: false
      dhcp4: false
      dhcp6: false
$ sudo netplan apply

すると新しいブリッジ br0 が作成される。最初は enxf8e43bb371e8 についていたIPアドレスの記載が br0に移る。また enxf8e43bb371e8 の欄に master br0 と書いてあるので、ちゃんとNICがブリッジに接続されていることがわかる。

$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: enxf8e43bb371e8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel master br0 state UP group default qlen 1000
    link/ether f8:e4:3b:b3:71:e8 brd ff:ff:ff:ff:ff:ff

(skip)

16: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 72:e2:b6:e9:05:35 brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.130/24 brd 192.168.0.255 scope global noprefixroute br0
       valid_lft forever preferred_lft forever
    inet6 fe80::70e2:b6ff:fee9:535/64 scope link
       valid_lft forever preferred_lft forever

KVMにブリッジを認識させる。以下の host-bridge.xml を作成する。

<network>
  <name>host-bridge</name>
  <forward mode="bridge"/>
  <bridge name="br0"/>
</network>

KVMに登録する。

$ virsh net-define host-bridge.xml
$ virsh net-start host-bridge
$ virsh net-autostart host-bridge

正しく登録されていることを確認。

 $ virsh net-list --all
 Name          State    Autostart   Persistent
------------------------------------------------
 host-bridge   active   yes         yes

Bridge Netfilterを無効化する

2024年6月12日追記
ここでVMが外部ネットワークに繋がらない根本原因はiptablesでFORWARDをDENYしていたことが原因だった。 なのでFORWARDのデフォルトポリシーをACCEPTに変更することでも解決可能である。

ここで詰まった。この後VMを作成してもVMが外部のネットワークに繋がらない。
原因はBridge Netfilterがブリッジを介した通信を遮断しているせいだった。 こちらを参考にホストでBridge Netfilerを無効化する。

/etc/sysctl.conf に以下の行を追記。(環境によっては同様の設定が /etc/sysctl.conf/etc/sysctl.d/* にあるかもしれないので要確認)

net.bridge.bridge-nf-call-iptables = 0

以下を実行して更新。

$ sudo sysctl -p 

正しく更新されたことを確認。

$ sudo sysctl net.bridge.bridge-nf-call-iptables
net.bridge.bridge-nf-call-iptables = 0

VMを作成

Ubuntu20.04 でVMを作成する。メモリやコア数、ディスクサイズなどは適宜設定する。

$ virt-install \
  --name vm1 \
  --ram=2048 \
  --disk size=10 \
  --network network=host-bridge \
  --vcpus 1 \
  --os-type linux \
  --os-variant ubuntu20.04 \
  --graphics none \
  --location 'http://archive.ubuntu.com/ubuntu/dists/focal/main/installer-amd64/' \
  --extra-args "netcfg/disable_autoconfig=true console=ttyS0,115200n8 --- console=ttyS0,115200n8"

ここで要注意なのが --extra-argsconsole=ttyS0,115200n8 --- console=ttyS0,115200n8 である。
全ての設定をCLIのみで行う場合、後程 virsh console vm1 でVMに接続してsshなどの設定を行う必要があるが、コンソールにシリアル接続できるようにしておかないと何も動かなくなる。
詳しい話はこちら

また netcfg/disable_autoconfig=true はインストール時に自動でDHCPで動的にアドレスを指定しようとするのを防ぐ。必要かどうかは環境によるが、今回は静的にアドレスを指定したかったのでこうする。(参照)
ここで静的にアドレスを指定できないのかと調べたが、RHELでは指定できそうだがUbuntuでは見つからなかった。

Ubuntuインストール

ウィザードが出てくるので説明手順に従ってインストールする。

sshの設定をする

インストール完了後、そのままコンソールに接続してくれたならそれで良いが、そうでない場合は手動で接続する。

$ virsh console vm1

sshサーバーをインストールして、鍵を登録する。

$ sudo apt update
$ sudo apt install openssh-server

$ mkdir ~/.ssh
$ wget "https://github.com/hiroyaonoe.keys" -O ~/.ssh/authorized_keys

これでexitしてから、インストール時に指定したユーザー名とIPアドレス(DHCPの場合はよしなに調べる)を使えばssh接続できるはずである。

まとめ

ネットワーク周りの設定は難しい。特にBridge Netfilterの設定は解決に時間がかかったので役にたてばうれしい。
これで自宅のUbuntuPCにVMを立てる用意が整ったので、Kubernetesクラスタ立てるとかやってみたい。