KVMでUbuntuとWindows10を共存させることにした

もう20年近くUbuntuで生活して来たわけですが、ついにWindowsとの共存を考えるに至りました。

Ubuntuデスクトップ上でWin10を動作させる。KVM+QEMUで。

というのも、マイナンバーカードを使って公的認証サービス(便利!)を利用する際にはどうしてもWindows前提の利用者クライアントソフト(クソアプリ)を使わないといけないのです。WineではICカードリーダーを認識せず挫折。

もうひとつ理由があって、最近のUbuntuは知らない間に魔改造されすぎ。

昔の知識が使えなくなったり似たようなツールをたくさん作りすぎて知識が分散してしまいもう手に負えない。この調子だとUbuntu捨てるかも。

Ubuntuメインか。Windowsメインか。

もうWindowsでいいかな

アプリはWindowsでもLinuxでも同じものが使えるし。むしろドライバ系がちゃんと用意されているWindowsは魅力。

UbuntuでもプリンタやUSBカメラは汎用ドライバでだいたい動くけど、Canon専用紙とかWindows or Mac向けのツールでできるような細かい設定(余白の設定とか)はできない。

そしてWLS2(Windows Subsystem for Linux 2)の出来栄えがかなり良いらしく、アプリケーションとしてUbuntu 20.04が起動できるらしい。Dockerの開発ができるのは嬉しい。

内部的にはHyper-vを使って準仮想化してるので、Windowsの干渉を受けずにUbuntuがそのまま動作するイメージ。ただGUIは使えずコンソール1画面ぽい。

https://docs.microsoft.com/ja-jp/windows/wsl/tutorials/wsl-containers

やっぱりUbuntuメインかなぁ

マルウェアの恐怖を感じながら使うのはちょっとね。Windows 10のパッチが当たるとUbuntuが動かなくなったりしそうだし。

案の定、問題が起きてました。累積パッチを当てるとWSL2が破壊されるとのこと(ワラ)

https://japan.zdnet.com/article/35159439/

あとはまあ、やっぱり開発がね。

アプリ開発もさることながら、ちょっとした作業を自動化するのにbashからperlやらpythonやら呼び出してちょいちょいってできるのがUNIX系の魅力なので。

WindowsのBatとかpowershellとかもうね、精神衛生的に無理。

昨今のUbuntu界隈はもうついていけないのでそのうち離脱するとして、Windowsに行くかと言うとまあそれも微妙。CentOSかDebianかなぁ。

今回作った環境

KVMでWindows 10を浮かべました。まあそれだけです。Windowsが必要になった時だけ呼び出す感じで。

KVMでWindows10を動作させる

KVMはVT-xを使えるようにしたカーネルの機能。通常はCPU→OS→仮想CPU→仮想OS→アプリという順番でアプリが動作するためオーバーヘッドが大きい。そこで、インテルはCPU→仮想CPU→仮想OSという動作ができるようにOS層をすっ飛ばすAPIを作りました。これがVT-x。

OS層をすっとばすにはVT-xに直接接続できる機能がLinux Kernel内に必要。これがKVM。最近のLinux Kernelは最初からKVMが取り込まれている。

QEMUは仮想マシンを動かすエミュレータ。ぶっちゃけKVMがなくてもQEMUだけで仮想化はできる。でも前述のとおりめっちゃ遅い。そこでできたのがqemu-kvm。OSをすっ飛ばしてKVM経由でCPUを直接使えるようにカスタマイズされたQEMUと思えばいいです。

Ubuntuで仮想マシンを作る前に

KVMやらQEMUやらの前にLinuxのネットワーク構成とツールのお話しをしましょう。というかこれを理解しないとあとでわけがわからなくなります。

LinuxのNIC設定のおさらい

NICの設定方法が変わってきた歴史

古典的なUNIX

NICの設定は/etc/rc.config.d/netconfに記載していました。IPアドレスやルーティングテーブル、デフォルトゲートウェイなどはここに記載しておけば、OS起動時にinitから起動されたnetプロセスが設定を読み込んでよろしくやってくれるのでした。

RedHat Linuxは設定をNICごとに分ける方針へ

その後init.dの仕組みが少しかわり、デフォルトGWの設定は/etc/sysconfig/networkへ、NICごとの設定は/etc/sysconfig/network-script/ifcfg-ethx へと移行しました。Red Hat Linux系はこの方式を採用しています。

設定ファイルはNICごとにバラバラになってしまいましたが、OS起動時にnetworkプロセスが設定を読み込むというnetに近い動作をしていました.

しかしRedHat 7以降はsystemctlというシステム管理コマンド経由でnetworkプロセスに設定を読み込ませるという動きに変わっています。

Debianは設定ファイルは1つにするものの制御方式を変更

Debian系のOSは/etc/network/interfacesへと移行しました。考え方はnetconfのように1つのファイルに複数のNICの設定を記載しておくものですが、ifupやifdownというネットワーク設定用の専用コマンドが読み込む定義ファイルとして使われるようになりました。

Ubuntuは18.04移行、netplanという方法を採用しています。

netplanは/etc/netplan/xxx.yamlにNICの設定を記載します。この記載方法はやや特殊でphtyonの様に段落でスタンザを記載します。その後 netplan generateコマンドを実行して/run/systemdの下にあれやこれや設定ファイルを作るという仕組みです。

そしてネットワークの起動はsystemctlに似たserviceというサービス制御コマンドから行います。ややこしい。

更にわかりにくことに、Ubuntu 20.10では以下のとおり”ネットワークの設定はNetwork Managerにおまかせします"という設定になっています。

Network Managerには賛否ありますが、とりあえず設定ファイルがどれかわからなくなってしまうのはシステム移行時にとても困るはずです。

Let NetworkManager manage all devices on this system
 network:
   version: 2
   renderer: NetworkManager

Linuxのネットワーク系コマンドのおさらい

よく使われるネットワーク系コマンド

今も現役 net-tools

UNIXのネットワーク系コマンドと言えばnet-toolsでした。ifconfigやarp、routeコマンドはよく知られている強力なコマンドです。ありがたいことにnet-toolsは今でも現役で使うことができます。

使いやすくなったiproute2

net-toolsに続いて出てきたのがiproute2というツールです。こちらはnet-toolsの軽量版といったところです。

iproute2はifconfig を "ip a"、arpを"ip n"、routeを"ip r"の様に"ip x"というコマンドに統一しようという意図が見えます。

ただ、iproute2は機能が少なく、net-toolsを置き換えるほどの勢いはありません。通常の構築ならiproute2、ネットワークのテストやセキュリティ系の技術を身につけるならnet-toolsの様に棲み分けがあります。

オペレーションの統一なるか Network Manager

現在、Network Managerというツールが普及し始めています。内部的にnet-toolsやiproute2のコマンドをコールしています。

Network Managerの設定ファイルはどこに保存されるかわかりません。ディストリビューションや環境に依存します。逆に言うと環境が違っても同じコマンド(nmcli)で運用できます。

Linuxのネットワークオペレーションを統一してくれるかもしれませんが、設定ファイルがどこにあるかわからないのは気持ちが悪い。

その他の*ctl系コマンド達

nmcliの他にブリッジ(後述)に特化したbrctr、TUN/TAP(後述)に特化したtunctl等の*ctlも使われるようになりました。*ctlでできることはnmcliでもできますが、*ctlはより少ないオプションで同じ機能を提供しています。

疑似ネットワークのおさらい

NICの性能向上と仮想化の進歩により、疑似ネットワークが作られるようになりました。

古典的には1つのNICに複数のIPアドレスを割り当てるIPエイリアスがありましたが、現在は仮想HUBとして使う"ブリッジ"やブリッジに接続できる仮想ネットワークデバイスであるTUN/TAPが使える様になりました。

疑似ネットワークの構成

疑似ネットワークの構成は以下のとおりです。virbr0とかはまだ出てきません。

仮想ブリッジ

仮想的に作られたHUBです。HUBでありながらIPアドレスを持つことができるためブリッジと呼ばれています。

仮想ブリッジを作っただけでは内部ネットワークでしか利用できません。外部と通信する際は物理NICに接続する必要があります。

ブリッジの作成と物理NICへの接続はnmcliかbrctlでできます。通常、ブリッジ名はbr0から順に最後の1桁を追番にします。

TAPデバイス

正式にはTUN/TAPデバイスと呼ばれます。仮想ネットワークインタフェースなのですが、少し変わった特性を持っています。

ブリッジに接続するとブリッジからはHUBのポートとして見えます。一方、仮想マシンに接続すると仮想マシンからはNICに見えます。

この特性を利用して、ブリッジと仮想マシンの両方に接続することで仮想LANを構成できます。

TAPデバイスはifconfigかtunctlで作成できます。おそらくnmcliでも作成できるはずです。

TAPデバイスとブリッジはnmcliかbrctlで接続できますが、仮想マシンとの接続は仮想マシンを管理しているqemuが行います。(後述)

ブリッジやTAPを作ってみる

$ brctl addbr br0 ← ブリッジ作成
$ brctl addif br0 eths25 ← ブリッジと物理NICを接続
$ tunctl -t vnet0 ←TUN/TAPデバイスを作成
$ brctl addif vnet0 br0 ←TUN/TAPデバイスをブリッジに接続
$ nmcli device ←確認
DEVICE           TYPE      STATE            CONNECTION      
lo               loopback  管理無し         --     
eths25           ethernet  接続済み         有線接続 1      
br0              bridge    接続済み (外部)  br0 ←ブリッジができてる       
vnet0            tun       管理無し         --  ← TUN/TAPができてる
$ brctl show ←確認
bridge name	bridge id		STP enabled	interfaces
br0   		8000.5254008a9192	yes		eths25 ← br0と物理NICが接続
                                   	                vnet0 ←br0とTUN/TAPが接続

上記の例ではbr0(bridge)とvnet0(tun)が作成でき、br0とNIC,TUN/TAPが接続されていることがわかります。

仮想マシンを作るとどうなるか

やっと仮想マシンの話にたどり着きました。今まで長々と話してきたのにはわけがあります。

仮想マシンを作るにはvirshというコマンドを使うのですが、このvirshコマンドは裏でいろんなことをします。

virshはKVMだけでなくVMwareやXen等も同じコマンドで管理できる便利なツールです。virshはCLIツールですが、virt-managerというGUIツールもあります。

virshやvirt-managerといった仮想マシン管理ツールはlibvirtというライブラリを使用しています。このライブラリを使えば誰でもvirshのような仮想マシンを管理するツールを開発できます。

https://ja.wikipedia.org/wiki/Libvirt

あまりにいろんなことを勝手にやるので、使っていくうちにどこまでがOSの設定なのかわからなくなり、知らない間にQEMU環境を壊しかねません。

そうならないように、先にOSの機能を説明したのでした。

というわけでvirshを使用した場合の疑似ネットワークです。

virshを使った場合の疑似ネットワーク

DHCPが追加されている

前述のOSだけの疑似ネットワークと比べて大きく違っている点は、DHCPとNATが追加されていることです。

virshやvirt-managerを導入すると自動的にブリッジがvirbr0という名称で作成され、libvirtが提供しているDHCPサーバと接続されます。

ちなみにこのDHCPサーバはdnsmasqというプロセス名で起動しており、設定ファイルは/var/lib/libvirt/dnsmasq/default.confにあります。

$ sudo cat /var/lib/libvirt/dnsmasq/default.conf
strict-order
user=libvirt-dnsmasq
pid-file=/run/libvirt/network/default.pid
except-interface=lo
bind-dynamic
interface=virbr0 ← virbr0に接続
dhcp-range=192.168.122.2,192.168.122.254,255.255.255.0 ← dhcpレンジの割当て
dhcp-no-override
dhcp-authoritative
dhcp-lease-max=253
dhcp-hostsfile=/var/lib/libvirt/dnsmasq/default.hostsfile
addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts

NATが設定されている。ということは...

virber0にはIPアドレスが割り当てられ、iptablesにNATの設定が追加されています。

ということは... そうです。仮想マシンから見てvirbr0のIPアドレスはデフォルトGWに見えるんです。

TUN/TAPデバイスはありません

TUN/TAPデバイスは仮想マシンを起動したタイミングで自動的に作成され、停止とともに削除されます。これらの制御はvirshやvirt-managerが行います。

最後に仮想ネットワークについて

virshを導入すると、疑似ネットワークにはない新しい概念、「仮想ネットワーク」が作成されます。

仮想ネットワークはブリッジ、DHCP、NATをすべてひとまとめにした概念で、最初はdefaultというネットワーク名が割り当てられます。

このネットワークはあとで追加できます。

$ virsh net-list
 Name      State    Autostart   Persistent
--------------------------------------------
 default   active   yes         yes
$ virsh net-info default
Name:           default
UUID:           0059aa64-3fa8-4ddc-afa7-6ec756219701
Active:         yes
Persistent:     yes
Autostart:      yes
Bridge:         virbr0
$ virsh net-dumpxml  default  | grep "ip address"
ip address='192.168.122.1' netmask='255.255.255.0'
$ virsh net-dumpxml  default  | grep "forward mode"
forward mode='nat'
$ virsh net-dumpxml  default  | grep "range"
range start='192.168.122.2' end='192.168.122.254'
$ virsh net-dhcp-leases default
 Expiry Time   MAC address   Protocol   IP address   Hostname   Client ID or DUID
-----------------------------------------------------------------------------------
仮想マシンが起動するとここに割り当て済IPアドレスが表示される

上記の例ではdefaultという名称のネットワークにはvirbr0というブリッジがあり、192.168.122.1というIPアドレスが設定されています。

また、NAT機能とDHCP機能を持っており、DHCPレンジは192.168.122.2〜254であることがわかります。

おさらいはここまで

以上、Linuxのネットワーク関連のおさらいとvirshが作る疑似ネットワークのお話しでした。

長かった。しかもここまでの話は全く知らなくてもvirshやvirt-managerを使えば簡単に仮想マシンを作れちゃいます。

では引き続き仮想マシンを作ってWindows 10をインストールします。

仮想マシンを作る

疲れたから後日

Windows 10をインストールする。

疲れたから後日

利用者クライアントソフトをインストールする

疲れたから後日


コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です