自宅サーバにLinux KVMを導入しようと急に思い立ったので、導入・設定方法から仮想マシンの起動までをまとめました。
…本当に大変でした。 しかも この記事で完結しません。
Linux KVMによる仮想化
Linuxには標準で KVM (Kernel-based Virtual Machine) と呼ばれるモジュールが搭載されています。これはLinuxカーネルをハイパーバイザ、つまり仮想化の基盤として動作させるためのものです(…という認識です)。KVMはDocker等とは異なり、CPUやメモリなどのハードウェアからエミュレーションを行うことで仮想化を実現します(ハイパーバイザ型)。このハードウェア (主にプロセッサの) エミュレーションを担っているのが QEMU です。QEMUを直接操作して仮想マシンを管理することも可能らしいのですが、多くは libvirt という仮想化APIを使用するようです。
こうやって一段落あたりの文章数が多い時は何を言っているかよくわかっていない時です。
つまり端的に言えば VirtualBoxやVMwareを使わずにLinuxの仮想マシンを起動させてみたくなったわけです。
導入環境
物理マシンのスペックは以下の通りです。
- 富士通 ESPRIMO D752/F
- CPU: Intel Core i5-3470 vPro @3.600GHz
- RAM: 4GB
- HDD: 250GB
- OS: Ubuntu Server 20.04 LTS
正直このスペックで仮想化(しかもハイパーバイザ)ってどうなのと言われそうなレベルです。まあ元が中古PCの再利用なので…
KVMの導入
今回はこのページを参考に導入していきます。
仮想化可能かを調べておく
まずは物理マシンが仮想化に対応しているかをチェック。
# egrep -c '(vmx|svm)' /proc/cpuinfo 4
kvm-ok
を実行し、KVM仮想環境が存在するかをチェックします。
# kvm-ok
INFO: /dev/kvm exists
KVM acceleration can be used
大丈夫そうです。
必要なパッケージをインストール
なんかもういつものパターンです。
今回は20.04なので、Cosmic (18.10) or later に該当。
sudo apt-get install qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils
先述した qemu、 libvirtがしっかりインストールされています。
ユーザをグループに追加する
libvirt
およびkvm
グループに追加する必要があるようです。
# groups
enchantcode adm cdrom sudo dip plugdev kvm lxd libvirt
なんか追加されてました。よくわかりませんが進めます。
インストールの確認
システムに正常にインストールされたかを確認します。
# virsh list --all
Id Name State
--------------------
大丈夫そうです。
GUIのインストール
virt-manager
のインストールは飛ばします。表示するディスプレイがないので…
VMのネットワークへのアクセス方法
KVMでは仮想マシンが外部ネットワークにアクセスするための方法を設定することができるようで…
- ユーザーモードネットワーク : デフォルト。VMはホストインターフェイスを介して外部ネットワークに接続します。外部からゲストOSは見えず、ホストOSが直接見えるようになります。
- ブリッジネットワーク : ホストOS上に仮想ネットワークインターフェイスを構成し、外部からはゲストOSが通常のホストのように見えるようになります。
…のふたつから選べるようになっています。
つまり、httpdを起動したり、SCPでファイルを送受信したりといった作業をゲストOSにやってもらうには ブリッジが必要ということになります。
個人的にはゲストOS上でどちらもやりたくなる気がするので、ここはひとつブリッジネットワークの構成にチャレンジしてみます。
構築前の注意
KVM/Networking - Community Help Wiki によると、
This works well, but does disable network manager so may not be best for desktops. これはうまく機能しますが、ネットワークマネージャを無効にするので、デスクトップには最適ではないかもしれません。(機械翻訳)
とのこと。 network manager あらため NetworkManager (パッケージ名: network-manager
) とは、ネットワーク接続が切り替わるときの処理を自動で管理してくれるソフトウェアのようです。
手元の Linux Mint にはインストールされていたのですが、今回の環境では導入されていませんでした。 Ubuntu-Serverだからかもしれません。
気兼ねなくブリッジを構成できることがわかったところで、早速ブリッジを…
おや?
# ip addr show virbr0 3: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000 link/ether XX:XX:XX:XX:XX:XX brd ff:ff:ff:ff:ff:ff inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0 valid_lft forever preferred_lft forever
見覚えのないネットワークインタフェースが追加されています。
# brctl show bridge name bridge id STP enabled interfaces virbr0 8000.5254009efdb6 yes virbr0-nic
どうやら、これがデフォルトで用意されている『NAT』のようです。
これを削除してしまっている記事もありますが、ここではそのままにしておきます。 (必要になった時に戻せないとかになると大変なので)
ブリッジネットワークの構築
公式ドキュメントでは /etc/network/interfaces
を触っていますが、今回はnetplanを使って設定してみます。
network: ethernets: (Ethernetインタフェース名): dhcp4: false dhcp6: false bridges: br0: interfaces: - (Ethernetインタフェース名) dhcp4: false addresses: - (固定するIPアドレス) gateway4: (ゲートウェイ) nameservers: addresses: - (DNSサーバ) search: [] parameters: stp: false dhcp6: false version: 2
正直これであっているのかは全くわかっていません。
netplanには一定時間入力がなかった場合にネットワークの設定を戻す try
というコマンドがあるのですが、どうやらブリッジの設定においては使えない模様。きびしい。
結局SSHが切れてはサーバを直接触るというループをN回やる羽目になりました。
仮想マシンの起動
ブリッジネットワークの設定が完了したようなので、いよいよ本題である 仮想マシンの起動 に挑戦します。
GUIが使えない
libvirtを用いたVMの起動について扱っている記事の多くは、virt-manager
によるGUIで設定を行なっています。
しかし今回のホストOSは Ubuntu Server なので、当然ながらXなど入っていません。ssh -X
も有効にははたらきません(たぶん)。
さらに先ほどディスプレイがないという理由でvirt-manager
のインストールを飛ばしてしまいました。セルフ縛りプレイ。
というわけで、ここではvirsh
やvirt-install
といったCLIコマンドをフル活用していきます。
ストレージプールの構成
まずはVMやディスクのイメージの配置場所(公式では Storage Poolまたは pool などと呼ばれています)を作ります。
この記事を参考に、
このようなディレクトリ構成を作り…
/var/kvm/ ├── images: ISOイメージ └── volumes: KVMボリューム
virshによりこれらのディレクトリをpoolとして定義します。
virsh pool-define-as default dir --target /var/kvm/volumes pool-define-as images dir --target /var/kvm/images pool-list --all
出力はこのようになりました。
Name State Autostart --------------------------------- default inactive no images inactive no
これらのpoolは現段階ではアクティブになっていませんので、システム起動時に自動でアクティブになるようにします。
virsh pool-autostart default pool-autostart images
poolの内部的な定義はXMLファイルであり、virsh上で pool-edit (pool名)
とすることでXMLファイルを直接編集することができます。
ちなみにpool-edit
の初回起動時はこんなふうにエディタ選択プロンプトが表示されます:
<---- easiest
の煽り性能が非常に優秀です。(私はnanoしか使えないのでnanoを選択しました。しっかりと煽られてゆくスタイル)
(ちなみに、実験過程で色々な場所にプールを作ってしまったせいで 私のサーバはもはやスパリゾートと化してしまいました。Tuxが悠々と泳いでいます。)
プールの設定が終了したらホストを再起動します。Tuxにもプールから上がってもらいます。
VMの起動
それではいよいよ本題、VMの起動にチャレンジしてみます。 起動するOSはUbuntu 20.04 Desktopとしました。
まずはISOを落とし…
virt-install
を叩きます。
sudo virt-install \ --name guest_ubuntudesktop \ --vcpus 2 \ --memory 2048 \ --disk size=10 \ --location /var/kvm/images/ubuntu-20.04.4-desktop-amd64.iso \ --os-variant ubuntu20.04 \ --network bridge:br0 \ --graphics none \ --extra-args "console=tty0 console=ttyS0"
location
にはISOファイルの場所を、extra-args
にはインストール時に使用するttyを指定しています。
インストールが始まり…
完了すると、いつものログイン画面が表示されます。
ここでログインを…
ログイン…
あれ アカウントなんていつ作った?
…どうやら、Ubuntu 20.04の初期ユーザ名はubuntu
のようです。どこに書いてあるんだそんなの…
root
やらuser
やらlinux
やらlinus
やら色々試した末にようやくたどりつきました。
『Ubuntu initial user name』とか『Ubuntu Live CD initial user』とか色々調べたのですが、Stack Overflowのページがヒットするばかりで 元情報にたどり着くことはできませんでした。 どなたか詳しい方教えてください…()
ネットワーク接続の確認
最後に、今回の目的でもあるネットワーク接続を確認します。
インタフェースを見ると…
# ip a 1: lo: <LOOPBACK,UP,LOWER_UP> ... ... 2: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> ... link/ether 52:54:00:17:55:05 brd ff:ff:ff:ff:ff:ff inet 192.168.11.24/24 brd 192.168.11.255 scope global dynamic noprefixroute enp1s0 ...
IPアドレスとして 192.168.11.24
が割り振られたようです。さっそくwgetしてみましょう。
# wget http://example.com --2022-03-07 08:41:08-- http://example.com/ Resolving example.com (example.com)... Connecting to example.com (example.com)... connected. HTTP request sent, awaiting response... 200 OK Length: 1256 (1.2K) [text/html] Saving to: ‘index.html’ index.html 100%[===================>] 1.23K --.-KB/s in 0s 2022-03-07 08:41:09 (98.1 MB/s) - ‘index.html’ saved [1256/1256] # cat index.html <!doctype html> <html> <head> <title>Example Domain</title> ...
しっかりと取得できているようです。
ルータからどう見えているかも確認してみます。
17:40:01 Sending ACK to 192.168.11.24 17:40:01 Received REQUEST 17:40:01 Sending OFFER of 192.168.11.24 17:39:59 Received DISCOVER
起動時にIPアドレスが振られ…
ホストとは別の ubuntu
という名称で認識されていました。
最後にhttpdを動かして、この記事を一旦終了とします。
# sudo apt update # sudo apt upgrade # sudo apt install apache2
…おや?
なんか upgrade
の過程で ちょっと経験したことのない勢いでエラーが流れていきます。当然処理も強制終了。
なんなんだ これは?
エラーメッセージを見ると…
cannot copy extracted data for 'XXX' to 'XXX': failed to write (No space left on device) No apport report written because the error message indicates a disk full error (機械翻訳) "XXX"の抽出データを"XXX"にコピーできません: 書き込みに失敗しました(デバイスにスペースが残っていません)。 エラーメッセージがディスクフルエラーを示しているため、アポートレポートは書き込まれません。
ディスクに空き領域がない!? なーに言ってんだこっちは250GBのストレージで
あっ
…はい。そりゃそうです。 一昔前のSDカードみたいな容量 でapt upgradeなんて 成功するはずがありません。
公式でも Ubuntuの動作要件として 25GBのストレージ容量 を要求しています。
というわけで仮想マシンから作り直しです。
sudo virt-install \ --name guest_ubuntudesktop \ --vcpus 2 \ --memory 2048 \ --disk size=40 \ --location /var/kvm/images/ubuntu-20.04.4-desktop-amd64.iso \ --os-variant ubuntu20.04 \ --network bridge:br0 \ --graphics none \ --extra-args "console=tty0 console=ttyS0"
aptを更新して、
sudo apt update sudo apt upgrade
また落ちた。なんで…!?
df
を叩いてみると…
# df -hT Filesystem Type Size Used Avail Use% Mounted on ... /cow overlay 989M 978M 12M 99% / ...
/
の行を見ると Use% 99%
となっています。確かにディスク容量はかなりギリギリに…
ん?Filesystemの /cow ってなんだ?
通常であれば、ここには /dev/sda1
のようなデバイス名が表示されるはず。/cow
とは…?
よく見ればtype
もおかしいです。ext4
ではなく overlay
…?
サイズは989MB、ちょうどVM実装RAMの半分くらい…
あっ
…これ Live CDじゃねえか!
失礼、Live CDですね
…はい。そりゃそうです。 LiveCDのインストール先は書き込み禁止の光学ディスク。ストレージはRAM上の一部を割り当てているだけなのです…
つまり、先程の操作は 40GBという広大な容量を持つ謎のCDを HDDのないPCに突っ込んで起動させている …という状況だったというわけです。文字に起こすとちょっと滑稽です。
Z
ちょっと長くなりすぎたので一旦切ります。
果たしてEnchanは無事VMを起動させることができたのか!?
つづく。
無事続きました: