Linux KVM初期設定まとめ(on ubuntu 22.04)
ここではubuntu 22.04上でKVMを用いた仮想環境を構築する方法を紹介します。KVMはubuntuなどのレポジトリで標準で提供されている仮想環境です。無料でVMwareのように多数の仮想コンピュータを運用する事ができます。
筆者の研究機関では基幹サーバ類で負荷があまり高くないものを全てKVM仮想マシンで置き換え、高性能ラックマウントサーバ一台あたり10-20台の仮想マシンをホスティングさせていますが、非常に安定して稼働しています。
今回はホストとなるコンピュータがVLANを用いた複数のネットワークに物理的に接続されている環境での設定を行います。これにより、ホストを事業所内部のプライベートネットワークに置きつつ、任意の仮想マシンをサーバとして外部に提供するといった運用が可能になります。
環境
今回設定したホストはNICを6(enp129s0f0, enp129s0f1, enp65s0f0, enp65s0f1, enp65s0f2, enp65s0f3)そのうちenp129s0f0(10Gbps NIC)がスイッチに繋がっています。スイッチのポートはtag-VLANにより、VLAN-ID 100, 200, および300が割り当てられており、そのうちVLAN-ID=100がグローバルIPアドレス、200と300がローカルIPアドレスを持つセグメントです。都合上、100にはDHCPサーバは稼働していませんが、200と300 では稼働しています。
仮想マシンのイメージ用にはHDD4台から成るRAIDをZFSを用いて構築します。
パッケージのインストール
以下のように必要なパッケージをインストールします。
> sudo apt-get install virt-manager bridge-utils
X環境があればこの時点でvirt-manager
というコマンドを実行すればGUIが起動しそこから仮想マシンの生成・起動等が行えます。こういう感じのGUIが開きます。
ですが、今はまだそれをせずにまずはネットワークの設定をまず行いますので、このウィンドウは閉じます。
尚、私の利用法の場合、Windows上のcygwinのXを用いていますが、それだとvirt-manager
起動時に警告が出ます。それをなくすには以下のようにします。
> sudo apt-get install libgl1-mesa-glx
念のためリブートしましょう。
> sudo /sbin/shutdown -r now
ホストマシンのNICを仮想マシンが使えるようにブリッジを設定
まず現状確認。
> brctl show
bridge name bridge id STP enabled interfaces
virbr0 8000.5254000760a9 yes virbr0-nic
> virsh net-list
Name State Autostart Persistent
--------------------------------------------
default active yes yes
ここで現れたvirbr0はNATを行うもののようであり、今回は仮想マシンをホストマシンと等格に扱ってネットに繋ぎたいので使いません。このままでも良いですが後で混乱しそうなので消してしまいます。
> virsh net-destroy default
> virsh net-undefine default
これでこのようにきれいになります。
> virsh net-list
Name State Autostart Persistent
----------------------------------------
> brctl show
>
次にブリッジを作ります。ホストのメインのNICを調べます。
> ip addr
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: enp65s0f0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc mq state DOWN group default qlen 1000
link/ether 3c:ec:ef:4a:4a:70 brd ff:ff:ff:ff:ff:ff
3: enp65s0f1: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc mq state DOWN group default qlen 1000
link/ether 3c:ec:ef:4a:4a:71 brd ff:ff:ff:ff:ff:ff
4: enp65s0f2: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc mq state DOWN group default qlen 1000
link/ether 3c:ec:ef:4a:4a:72 brd ff:ff:ff:ff:ff:ff
5: enp65s0f3: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc mq state DOWN group default qlen 1000
link/ether 3c:ec:ef:4a:4a:73 brd ff:ff:ff:ff:ff:ff
6: enp129s0f0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether a0:36:9f:20:30:40 brd ff:ff:ff:ff:ff:ff
inet 10.25.5.70/16 brd 10.25.255.255 scope global dynamic enp129s0f0
valid_lft 3210sec preferred_lft 3210sec
inet6 fe80::a236:9fff:fe20:3040/64 scope link
valid_lft forever preferred_lft forever
7: enp129s0f1: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc mq state DOWN group default qlen 1000
link/ether a0:36:9f:20:30:42 brd ff:ff:ff:ff:ff:ff
この場合外部に物理的に接続されているのは enp129s0f0 (10 Gbps NIC)であるとわかります。ubuntuのネットワーク設定は/etc/netplanにあるので、そこにある(おそらくOSインストール時に自動生成された)のオリジナルの設定ファイルを別名でセーブ・不活性化し、新たなconfigを作ります。
> cd /etc/netplan
> mv 00-installer-config.yaml 00-installer-config.yaml.org
> cp 00-installer-config.yaml.org 00-gauss.yaml
次に00-gauss.yamlの中身を以下のようにします。
network:
ethernets:
enp129s0f0:
dhcp4: no
enp129s0f1:
dhcp4: no
enp65s0f0:
dhcp4: no
enp65s0f1:
dhcp4: no
enp65s0f2:
dhcp4: no
enp65s0f3:
dhcp4: no
vlans:
vlan100:
id: 100
link: enp129s0f0
dhcp4: no
vlan200:
id: 200
link: enp129s0f0
dhcp4: no
vlan300:
id: 300
link: enp129s0f0
dhcp4: no
bridges:
br100:
interfaces: [vlan100]
dhcp4: no
accept-ra: no
dhcp6: no
parameters:
stp: false
br200:
interfaces: [vlan200]
dhcp4: yes
accept-ra: no
dhcp6: no
parameters:
stp: false
br300:
interfaces: [vlan300]
dhcp4: no
accept-ra: no
dhcp6: no
parameters:
stp: false
version: 2
ethernetsセクションでは、すべての物理インターフェースには何もIPドレスを割り当てないようにしています。vlansセクションで、enp129s0f0に三つのVLANインターフェースを割り当てています。例えばvlan100というインターフェースにパケットを送ると、VLAN-ID=100というタグがついてイーサネットに流れていきます。VLANインターフェースそのものにもここではまだIPアドレスは割り当てていません。最後にbridgesセクションで、ブリッジ(ネットワークスイッチのようなもので、そこに参加するインターフェース間でパケットを通してくれるもの)を作成しています。例えばbr200というブリッジインターフェースはvlan200に繋がります。br200自体にアドレスを最後に割り振っています。この場合はDHCPサーバから取得しています。vlan100, vlan300にはIPアドレスを割り振りません。すなわち、このホストはプライベートネット用VLAN-ID=200を通してのみ通信することができます。
ではそれ以外のブリッジbr100, br300は何に使うかというと、仮想マシン専用です。つまり、次に解説するようにvirt-manager
上でNICを選ぶ際のブリッジを上記のbr100, br200, br300 から適宜選べば目的のVLANにブリッジされ、任意のネットワークに出現できるというわけです。
尚、物理インターフェースがたくさんあるのだからtag-VLAN使わずにそれぞれ別個のVLANに接続したらいちいちvlansセクションはいらないのでは、という指摘がありそうですが、その通りです。ただそれをするとこの場合イーサネットスイッチの10Gbpsポートが3倍必要になってしまいます。それだけです。サーバ台数×VLAN数のポートが準備できればtag-VLANは使う必要ありませんし、その方がパフォーマンスも高いでしょう。
ネットワーク設定は以上で終わりです。勿論、netplan try
と netplan apply
を忘れずにして、リブートもするよよいでしょう。
zfs RAIDへの仮想マシンのフォルダの再配置
このまま早速仮想マシン生成にはいってもいいのですが、OSインストール時に特に何も指定していなければ、仮想マシンの関連ファイルは/var/lib/libvirtにすべて入ることになります。そしてディスクイメージは/var/lib/libvirt/imagesに置かれます。場合によってはとても大きなイメージになります。さらに、/varのあるファイルシステムがただのSSD(筆者の場合512GBのSSD)だったりすると、それが壊れてしまったら全ての仮想マシンのイメージが失われます。
そこで、筆者の環境では仮想マシンのイメージ用に4台のHDDを用意し、ZFSを用いてRAIDZ2を構築することにしました。RAIDZ2であれば4台中2台が壊れてもまだデータを保持できます。さらに、ZFSではスナップショット機能があるので、これを用いて定期的に仮想マシンイメージのスナップショットを取ることもできます(それについては別記事を執筆予定)。ZFSのパフォーマンスに関しては、いまのところ不満はありません。どなたかご存じの方、ご教示ください。
ZFSを利用するには以下のように準備します。
sudo apt-get install zfsutils-linux
4台のHDDのデバイスファイルは /dev/sda, /dev/sdb, /dev/sdc, /dev/sdd です。わからない方はあらかじめ/dev/の中を眺めて調べておいてください。それらすべてに空のgptパーティションテーブルを作成します。sdaの場合はこうです。
> sudo parted /dev/sda
(parted) mklabel gpt
(parted) q
>
空かどうか怪しい場合は必ずmklabelの前にpコマンドで確認しましょう。
RAIDZ2 poolを作成します。
> sudo zpool create zpool1 raidz2 sda sdb sdc sdd
pool名は好みが分かれるところでしょう。
ZFS poolはそのままファイルシステムとしても使えますが、ほかにも作りたくなると構成が美しくなくなるので、仮想マシンデータ用ファイルシステムを作成します。
> sudo zfs create zpool1/vmdata
> sudo zfs set mountpoint=/vmdata zpool1/vmdata
> sudo zfs set mountpoint=none zpool1
そしてlibvirt(kvmのディレクトリ)を移動し、リンクをはります。
> sudo cd /var/lib
> sudo mv libvirt /vmdata/
> sudo ln -s /vmdata/libvirt .
これ以外にも/var全体をZFSに移動するとか、いろいろ考え方はあると思います。あとはお好みでどうぞ。
仮想マシンの生成
今書いています。しばしお待ちを。
Discussion