enchanのメモ書き

計算機とフリルとラブライブ!

Ubuntu Server 20.04 LTSにLinux KVMを導入する (1)

自宅サーバに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の導入

今回はこのページを参考に導入していきます。

help.ubuntu.com

仮想化可能かを調べておく

まずは物理マシンが仮想化に対応しているかをチェック。

# 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

先述した qemulibvirtがしっかりインストールされています。

ユーザをグループに追加する

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のインストールを飛ばしてしまいました。セルフ縛りプレイ。

というわけで、ここではvirshvirt-installといったCLIコマンドをフル活用していきます。

ストレージプールの構成

まずはVMやディスクのイメージの配置場所(公式では Storage Poolまたは pool などと呼ばれています)を作ります。
この記事を参考に、

endy-tech.hatenablog.jp

このようなディレクトリ構成を作り…

/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を落とし…

ftp.jaist.ac.jp

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を起動させることができたのか!?

つづく。


無事続きました:

enchan1207.hatenablog.com