Ubuntu Server 16.04.2 LTSにKVM環境の構築

作成日:2017/03/20
最終更新日:2020/07/05

Ubuntu Server 16.04.2 LTSにKVM環境の構築

作成日:2017/03/20
最終更新日:2020/07/05

概要

XenよりもKVMの方が利用可能なOSに制限がなさそうなことが理解ってきました。 4月から再び半分学生に戻ることになったので、これを機にサーバーを再構築します。 サーバー環境の変遷は以下のとおりです。

  1. PC実機数台構成
  2. FreeBSD jailによる仮想化
  3. VirtualBoxによる仮想化
  4. Xenによる仮想化
  5. KVMによる仮想化 ←今ここ

HOSTの設定

Ubuntu Server 16.04.2 LTSのインストール

HOSTとなる端末のOSはUbuntu Server 16.04.2 LTSを用います。 サーバー機のDVDマルチドライブでインストールメディアを読み込まなかったので、 USBメモリからブートすることにしました。

以下のコマンドでインストールメディアを用意します。 なお、/dev/sdbは環境によって変わるので注意が必要です。

コマンド1. インストールメディアの作成
cd ~/
sudo dd if=./ubuntu-16.04.2-server-amd64.iso of=/dev/sdb bs=4096

OpenSSHのインストール

aptで追加します。

コマンド2. OpenSSHのインストール
sudo apt-get install openssh-server
sudo service ssh start

固定アドレスの設定

Ubuntu serverをインストールすると、標準状態ではDHCPで動的にIPアドレスを取得する設定になります。サーバー機として使用する場合には静的にIPアドレスを指定し、固定するほうが使い勝手が良いので設定を変更します。

/etc/network/interfaces を変更します。設定変更前に元のファイルを複製しておきます。 今回設定変更するインタフェースはenp2s0になります。

コマンド3. /etc/network/interfacesの変更
sudo cp /etc/network/interfaces /etc/network/interfaces.org
sudo vi /etc/network/interfaces

例えば、以下のように書き換えます。

ソース1. /etc/network/interfacesの変更内容
auto enp2s0
iface enp2s0 inet static
address IPアドレス
network ネットワークアドレス
netmask サブネットマスク
broadcast ブロードキャストアドレス
gateway ゲートウェイのIPアドレス

設定を変更したら以下のコマンドでIPアドレスの変更を適用します。

コマンド4. 設定の反映
sudo service networking restart

※DHCPからstaticに変更したとき、上記のコマンドで切り替わらず再起動によって変更されました。

ifconfigで設定変更を確認します。

コマンド5. 設定の確認
user@HOST:~$ ifconfig enp2s0
enp2s0    Link encap:Ethernet  HWaddr QQ:QQ:QQ:QQ:QQ:QQ  
          inet addr:XXX.XXX.XXX.XXX  Bcast:YYY.YYY.YYY.YYY  Mask:ZZZ.ZZZ.ZZZ.ZZZ
          inet6 addr: fe80::TTTT:TTTT:TTTT:TTTT/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:1315 errors:0 dropped:0 overruns:0 frame:0
          TX packets:915 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:122176 (122.1 KB)  TX bytes:156504 (156.5 KB)
user@HOST:~$ 

IPアドレスを静的に指定した場合にはDNSサーバーも静的に設定します。 /etc/resolvconf/resolv.conf.d/baseを編集します。

コマンド6. /etc/resolvconf/resolv.conf.d/baseの変更
sudo cp /etc/resolvconf/resolv.conf.d/base /etc/resolvconf/resolv.conf.d/base.org
sudo vi /etc/resolvconf/resolv.conf.d/base

/etc/resolvconf/resolv.conf.d/baseの中身は空のはずなので以下の様に記述します。

ソース2. /etc/resolvconf/resolv.conf.d/baseの変更内容
nameserver DNSサーバーのIPアドレス

設定を変更したら以下のコマンドでDNSサーバーの変更を適用します。

コマンド7. 設定の反映
sudo service networking restart

DNSサーバーの設定ファイルを確認し設定が変更されたか確認します。

コマンド8. 設定の確認
user@HOST:~$ cat /etc/resolv.conf
# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
#     DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
nameserver XXX.XXX.XXX.XXX
user@HOST:~$ 

※DHCPからstaticに変更したとき、上記のコマンドで切り替わらず再起動によって変更されました。

KVMの導入

KVMとは

KVMはLinux Kernel自体をハイパーバイザとする仕組みです。 正式名称を「Kernel-based Virtual Machine」といいます。

KVMはCPUの仮想化支援機能(Intel VT-xやAMD-V)を必要とし、 完全仮想化によりOSの仮想化環境を提供します。

KVMの導入

Ubuntu 16.04 LTS で KVM を使った仮想サーバ (2016-05-06)を参考に導入します。

コマンド9. KVMのインストール
sudo apt-get install qemu-kvm bridge-utils

HOSTをのNICをブリッジに変更

HOSTのNICをプロミスキャスモードに変更し、自分宛てのEthernetフレームも受信可能にします。 そしてブリッジインタフェースであるbr0を追加し、enp2s0をブリッジに収容します。 各GUESTはここにtapインタフェース経由で接続する形になります。

/etc/network/interfaces を変更します。設定変更前に元のファイルを複製しておきます。 今回設定変更するインタフェースはenp2s0になります。

コマンド10. NICのブリッジ化
sudo vi /etc/network/interfaces

例えば、以下のように書き換えます。

ソース3. 設定変更例
# The primary network interface
#auto enp2s0
#iface enp2s0 inet static
# The bridge network instarface
auto br0
iface br0 inet static
  address IPアドレス
  network ネットワークアドレス
  netmask サブネットマスク
  broadcast ブロードキャストアドレス
  gateway ゲートウェイのIPアドレス
  pre-up ifconfig enp2s0 down
  pre-up ifconfig enp2s0 0.0.0.0 promisc up
  pre-up brctl addbr br0
  pre-up brctl addif br0 enp2s0
  pre-up ifconfig enp2s0 up
  post-down ifconfig enp2s0 down
  post-down brctl delif br0 enp2s0

上記の設定変更をしたら、一回再起動します。

仮想HDDの作成

仮想HDDファイルを作成します。 Web上の記事を探すと、KVMではQCOW2形式を使うのが一般的なようです。 それに習い、QCOW2形式で作成します。

コマンド11. HDDファイルの作成
qemu-img create -f qcow2 UbuntuServer-16.04.2LTS.qcow2 10G

GUEST用OSのインストールメディアの用意

GUEST用のインストールメディアのイメージをHOSTにダウンロードします。 Ubuntu Serverにはデフォルトでcurlが入っているので、これを用いると良いでしょう。

今回はUbuntu ServerをGUESTにインストールすることにしますので、ubuntu-16.04.2-server-amd64.isoをダウンロードしておきます。

GUESTの起動

サーバー機にインストールしているのでGUESTのコンソールへはVNCでアクセスすることにします。 対してクライアントとしてはUbuntuにはRemminaというVNCクライアントが入っているのでこれを使用します。

以下のコマンドを実行してGUESTを起動します。

コマンド12. GUESTの起動
sudo kvm -hda ./UbuntuServer-16.04.2LTS.qcow2 \
-vnc :0 \
-boot d \
-net nic,macaddr=52:54:00:00:00:01,model=virtio \
-net tap,ifname=tap0,script=/etc/qemu-ifup \
-m 512 \
-cdrom ./ubuntu-16.04.2-server-amd64.iso

GUESTのVNCを有効にするにはvncオプションを使用します。 この:0はポート番号を示します。 実際にはこの値に5900を加えたものを使用します。

コマンド13. VNCのポート指定例
-vnc :0

GUESTをHOSTにブリッジ接続します。 nicの方で実際にGUESTから見えるNICを指定します。 tapの方でHOST側の設定をします。

コマンド14. NICの指定例
-net nic,macaddr=52:54:00:00:00:01,model=virtio
-net tap,ifname=tap0,script=/etc/qemu-ifup

GUESTを実行するとHOST側のプロンプトは専有されます。 VNC経由でインストールを継続します。

なお、GUESTを終了するとHOSTのプロンプトが返ってきます。 このとき、poweroffコマンドなどでGUESTを終了しないと、 HOST側は固まったままになります。

GUESTの設定

GUESTのNICに割り当てる仮想MACアドレスからIPアドレスなどを自動生成するようにします。 まずは、/etc/network/interfacesのThe primary network interfaceを以下のように変更します。

ソース4. DHCPの無効化
# The primary network interface
#auto ens3
#iface ens3 inet dhcp

DNSの設定も前述のように編集します。

次に/etc/rc.localを編集します。 たとえば以下のようなscriptにします。

ここで、Gatewayは192.168.xxx.254であるとします。 なお、仮想MACアドレスの第5オクテットをxxx、第6オクテットをホスト部にします。

また、IPアドレス \t ホスト名を列挙したファイルを/etc/hostlistとし、ここからホスト名を自動決定するようにします。なお \t はタブです。

ソース5. IPアドレスの自動設定スクリプト
#!/bin/sh
IP_HD=192.168
GW=254
NIC=`ifconfig -a| awk '$1 ~ /^ens/ {print $1,$5}'`
NW=`echo $NIC | awk 'BEGIN{FS=":"} {print $5}'`
HW=`echo $NIC | awk 'BEGIN{FS=":"} {print $6}'`
DEV=`echo $NIC | awk '{print $1}'`
IP=$IP_HD.$((0x$NW)).$((0x$HW))
HN=`cat /etc/hostlist | grep $IP | head -1 | awk '{print $2}'`
IP_NW=$IP_HD.$((0x$NW)).0
IP_GW=$IP_HD.$((0x$NW)).$GW
IP_BC=$IP_HD.$((0x$NW)).255
echo $DEV
echo "ip address :" $IP "\t("$HN")"
echo "broadcast  :" $IP_BC
echo "gateway    :" $IP_GW
ifconfig $DEV $IP netmask 255.255.255.0 broadcast $IP_BC
route add default gw $IP_GW
hostname $HN
echo 127.0.0.1  localhost >/etc/hosts
echo $IP  $HN >> /etc/hosts
exit 0

あとは、/etc/rc.localに実行権を与え、systemctlに登録します。

コマンド15. rc.localの実行設定
sudo chmod 755 /etc/rc.local
sudo systemctl enable rc-local.service

これで、再起動するとIPアドレスやホスト名が仮想MACアドレスに応じて生成されます。

GUESTのシリアルコンソール対応

GUESTにシリアルコンソール経由でアクセスできるようにします。 この対応を行うことで、HOSTからGUESTにアクセスできるようになります。

まず、grubをシリアルに出力するように変更します。 /etc/default/grub を次のように変更後、「update-grub」を実行します。

ソース6. Grubのシリアルコンソール対応
#GRUB_CMDLINE_LINUX_DEFAULT=""
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"
#GRUB_CMDLINE_LINUX=""
GRUB_CMDLINE_LINUX="console=tty0 console=ttyS0,115200n8"

次に、/etc/systemd/system/serial-getty@ttyS0.serviceを作成します。 /lib/systemd/system/serial-getty@.serviceを元に作成します。

コマンド16. 設定のコピー
sudo cp /lib/systemd/system/serial-getty@.service /etc/systemd/system/serial-getty@ttyS0.service

/etc/systemd/system/serial-getty@ttyS0.serviceを編集し、ExecStartをシリアルコンソールで起動するように修正します。

ソース7. 設定の編集
  #ExecStart=-/sbin/agetty --keep-baud 115200,38400,9600 %I $TERM
  ExecStart=-/sbin/agetty -L ttyS0 115200 vt100

/etc/systemd/system/getty.target.wants/以下にシンボリックリンクを生成します。 その後、systemctlを再初期化しロードします。

コマンド17. シリアルインタフェースの有効化
sudo ln -s /etc/systemd/system/serial-getty@ttyS0.service /etc/systemd/system/getty.target.wants/
sudo systemctl daemon-reload
sudo systemctl start serial-getty@ttyS0.service

HOSTで次のコマンドを実行すると、プロンプトがGUESTのものに変化します。

コマンド18. GUESTの起動
sudo kvm -hda ./UbuntuServer-16.04.2LTS.qcow2 \
-nographic \
-boot c \
-net nic,macaddr=52:54:00:00:00:01,model=virtio \
-net tap,ifname=tap0,script=/etc/qemu-ifup \
-m 512

GUESTの起動scriptの作成

HOSTでGUESTを自動起動するための仕組みを生成します。 具体的にはscreenを用いて構成します。 このとき、各GUESTようの仮想HDDは/home/GUESTNAMEにあるものとします。 script名はstart_guest.shとします。

ソース8. GUEST起動スクリプト
#!/bin/sh
/usr/bin/screen -S GUESTNAME -d -m \
/usr/bin/kvm -hda /home/GUESTNAME/UbuntuServer-16.04.2LTS.qcow2 \
-m 512 \
-boot c \
-nographic \
-net nic,macaddr=52:54:00:00:00:01,model=virtio \
-net tap,ifname=tap0,script=/etc/qemu-ifup

このscriptをsudoで実行するとGUESTがscreen上に生成されます。

コマンド19. GUESTの起動例
sudo ./start_guest.sh
sudo screen -ls
There is a screen on:
	4577.GUESTNAME	(03/20/2017 02:54:27 PM)	(Detached)
1 Socket in /var/run/screen/S-root.

GUESTのコンソールにアクセスしたいときは以下のコマンドを実行します。

コマンド20. screenの復帰
sudo screen -r GUESTNAME

GUESTをHOSTの起動時に自動実行したい場合はstart_guest.shをcronに登録します。

コマンド21. Cronへの登録
sudo crontab -e
@reboot /home/USERNAME/start_guest.sh