Ubuntu 16.04 LTS で KVM を使った仮想サーバ ()

職場で教育用に使用する新しいLinux環境が欲しくなって、Ubuntu 16.04 LTS を使った仮想環境を自宅で試してみました。教育用にわざわざハードウェアを準備するのも困難な場合もあり、どこからでも ssh で接続さえすれば同じ環境が (こっそり) 使えます。 前回の Ubuntu 9.10の KVM で仮想サーバ から6年以上経過して、Linux の構成も Systemd を始めとして色々変更されています。


今回はホストは Ubuntu 16.04 LTS 64bit のデスクトップ版で qemu-kvm を使います。ゲストは Ubuntu 16.04 LTS 64bit のサーバ版を使用しました。 vnc のクライアントは、前回 は Windows でUltraVNC を使いましたが、 MacOSXの標準機能で行いました。


今回もKVM の使い方を理解するため、 libvirt を使わずコマンドラインから直接 kvmコマンドを使って仮想マシンをコントロールすることにします。


QEMU

QEMU 自身は色々なCPUを実行できるエミュレータで、CPU命令をソフトウェアでいちいち解釈実行する方法ではなく、動的にコンパイルするような方法を使ってかなり速いエミュレータとして有名でした。PCのハードウェア全体がソフトウェアで実現されていて、昔からOSの開発でも利用されていました。


KVM

Linuxカーネルのモジュールとしての KVM はintelVTやAMD-Dという機能を持つCPUを使って、仮想環境のOSの特権命令まで直接実行する仕組みです。CPUの仮想化支援機能(intelVTまたはAMD-V)にアクセスするためのインタフェース(/dev/kvm)を提供しています。カーネルモード、ユーザモードに加えて、ゲストモードという新しい動作モードが追加されます。CPUで仮想環境の命令を直接実行してしまうので、仮想環境といえども速度の低下は全くありません。ただし、ハードディスクやネットワークカードなどの周辺機器(IO)へのアクセスはトラップされて物理的なデバイスとのインターフェイスがソフトウェアで行われるため、速度は多少遅くなります。


仮想環境としての Linux KVMはこのCPU以外の周辺機器の仮想化を、昔から使われていて安定なQEMUを使うことでPC全体を仮想化(完全仮想化)しています。したがってKVMは仮想環境として、非常に新しい部分(CPUの持つ仮想マシンモニター機能)をシンプルな仕組みでカーネル内に持ち、古い部分(QEMUによるハードウェアエミュレーション)をユーザプロセス側で受け持つ形式でうまく融合したものとなっています。KVM は2007年2月以降のLinuxのカーネル(2.6.20以降)のソースにモジュール(バイナリになると250KB程度とコンパクト)として取り込まれています。GUIが必須ではないのでホスト側のリソース(メモリ、CPU負荷)が無駄にならないため、サーバとして利用するにはよい環境ではないかと思います。

仮想環境の構成

外部のネットワークから見た場合、ホスト1台とゲスト2台の合計3台のサーバが独立して稼働しているような構成とします。 物理的にIPアドレスを別々に持つ3台のサーバがスイッチングハブで接続されているのと同じ状態になります。この例ではゲストOSが2つですが、必要ならばいくつでも増やすことができます。


外部からは以下のように見えることを目指します。ゲストは同様にいくつでも増やせます。

  +------+     +-----------------------------------+
  | GW   +-----+         Switching HUB             |
  +------+     +----+-------------+-------------+--+
 172.18.21.1        |             |             |
               +----+-----+   +---+-----+   +---+-----+
               |   HOST   |   | GUEST   |   | GUEST   |
               +----------+   +---------+   +---------+
               172.18.21.80   172.18.21.90  172.18.21.91

ホストとしての64ビット Ubuntu 16.04LTS デスクトップ版のインストール

今回は仮想環境の入れ物(ホストOS)として 64ビット Ubuntuデスクトップ版(ubuntu-16.04-desktop-amd64.iso) をインストールしました。ゲストOSに64ビットを使う場合は64ビット版が必要です。KVMを使うため、BIOSの設定で intelVT または AMD-V を有効にしておきます。 実際のインストールは下のゲストのインストールとほぼ同じです。ホストのディスクのパーティションの構成は環境によって異なり、「Manual」を使うことになると思いますから割愛します。

KVM のインストール

今回も、libvirt を使わないで qemu-kvm を直接使って仮想環境を構築します。qemu-kvm と bridge-utils をインストールします。

jun@xerus:~$ sudo apt-get install qemu-kvm bridge-utils
sudo: unable to resolve host xerus
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following additional packages will be installed:
  cpu-checker msr-tools qemu-system-x86 seabios
Suggested packages:
  vde2 sgabios ovmf
The following NEW packages will be installed:
  bridge-utils cpu-checker msr-tools qemu-kvm qemu-system-x86 seabios
0 upgraded, 6 newly installed, 0 to remove and 1 not upgraded.
Need to get 28.6 kB/2921 kB of archives.
After this operation, 17.8 MB of additional disk space will be used.
Do you want to continue? [Y/n] y

ホスト側のネットワークの設定

物理的には1台のマシンをネットワーク的には独立した3台のサーバがスイッチングハブで接続されている状態に設定します。

  +------+     +-----------------------------------+
  | GW   +-----+         Switching HUB             |
  +------+     +----+-------------+-------------+--+
 172.18.21.1        |             |             |
               +----+-----+   +---+-----+   +---+-----+
               |   HOST   |   | GUEST   |   | GUEST   |
               +----------+   +---------+   +---------+
               172.18.21.80   172.18.21.90  172.18.21.91

ホストとなるマシンのネットワークカード(enp2s0)の内側にブリッジ(br0)があり、仮想マシンはtap デバイスを介してブリッジに接続します。

            +-----------------------------------------+
            |  Host : Ubuntu 16.04LTS amd64 desktop   |
            |                                         |
        +---+----+         +---------------+          |
        | enp2s0 +---------+ Switching HUB |          |
        +---+----+         |     br0       |          |
            |              +-+----------+--+          |
            |                |          |             |
            |         +------+-+      +-+------+      |
            |         | tap0   |      | tap1   |      |
            |         +---+----+      +---+----+      |
            |             |               |           |
            |         +---+----+      +---+----+      |
            |         |  KVM   |      |  KVM   |      |
            |         |  QEMU  |      |  QEMU  |      |
            |         +--------+      +--------+      |
            |         | Guest1 |      | Guest2 |      |
            |         | LINUX  |      | LINUX  |      |
            |         +--------+      +--------+      |
            +-----------------------------------------+

NetworkManager の削除

仮想マシンをホストと同じネットワークに接続するためにブリッジを作成します。 NetworkManager のアンインストールブリッジの設定は、ネットワークの設定ファイルを編集しますが、 NetworkManagerがジャマになるため削除します。

jun@xerus:~$ sudo apt-get remove network-manager
sudo: ホスト xerus の名前解決ができません
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています                
状態情報を読み取っています... 完了
以下のパッケージが自動でインストールされましたが、もう必要とされていません:
  plainbox-secure-policy python3-checkbox-support python3-guacamole
  python3-jinja2 python3-padme python3-plainbox python3-pyparsing
  python3-xlsxwriter
これを削除するには 'sudo apt autoremove' を利用してください。
以下のパッケージは「削除」されます:
  checkbox-converged checkbox-gui network-manager network-manager-gnome
  plainbox-provider-checkbox plainbox-provider-resource-generic ubuntu-desktop
アップグレード: 0 個、新規インストール: 0 個、削除: 7 個、保留: 1 個。
この操作後に 15.2 MB のディスク容量が解放されます。
続行しますか? [Y/n] y

ブリッジの生成

最初にホストのネットワークカード(NIC)を自分宛のEthernetフレーム以外も受け付けるプロミスキャスモード(promiscuous mode)に変更します。プロミスキャスモードにすることでEthernetフレームの宛先MACアドレスが自分と異なる場合でも読み込むことができるため、ブリッジとして動作できるようになります。

次にホスト内にブリッジを生成して、enp2s0をブリッジに繋ぎかえます。ブリッジとは Ethernet Bridge のことで、物理的には普通のスイッチングハブ(レイヤー2スイッチ)と考えることができます。 qemu-kvm をインストールすると自動的にインストールされる bridge-utils パッケージのコマンド 「brctl addbr ブリッジ名」で生成できます。

ブリッジを生成して、enp2s0を繋ぎかえる時にネットワークは一旦切断されるため、シェルスクリプトにしておけばリモートからでも連続してコマンドを実行できます。ブリッジにIPアドレスを設定するとホストも外部ネットワークに接続できます。ネットワークは一旦切断されるため、リモートからSSHで接続している場合は再接続する必要があります。

次に示す「bridge.sh」で上記の設定を一気に行います。最初にあるシェル変数のIPとGATEWAYの値は環境にあわせて変更してください。「sudo sh bridge.sh」で実行できます。 ホストの起動時に自動的にブリッジを生成する方法は後述します。

jun@xerus:~~$ cat bridge.sh
#!/bin/sh

IP=172.18.21.80                          # ホストのIPアドレス
GATEWAY=172.18.21.1                      # ルータのLAN側IPアドレス

echo "change IP address : $IP"
ifconfig enp2s0 0.0.0.0 promisc up       # プロミスキャスモードに設定
brctl addbr br0                          # ブリッジの作成
brctl addif br0 enp2s0                   # ブリッジにeth0を接続
ifconfig br0 up                          # ブリッジを起動
ifconfig br0 $IP netmask 255.255.255.0   # ブリッジにIP設定
route add default gw $GATEWAY            # ゲートウェイ設定

実行すると ifconfig の出力は以下のようになります。ブリッジのbr0にIPアドレスが設定され、enp2s0 はプロミスキャスモード(PROMISC)になっていることが確認できます。

jun@xerus:~$ ifconfig
br0       Link encap:Ethernet  HWaddr 00:1d:60:6d:ae:b4  
          inet addr:172.18.21.80  Bcast:172.18.21.255  Mask:255.255.255.0
          inet6 addr: fe80::21d:60ff:fe6d:aeb4/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:126698 errors:0 dropped:0 overruns:0 frame:0
          TX packets:70944 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:169672781 (169.6 MB)  TX bytes:10101020 (10.1 MB)

enp2s0    Link encap:Ethernet  HWaddr 00:1d:60:6d:ae:b4  
          inet6 addr: fe80::21d:60ff:fe6d:aeb4/64 Scope:Link
          UP BROADCAST RUNNING PROMISC MULTICAST  MTU:1500  Metric:1
          RX packets:128243 errors:0 dropped:0 overruns:0 frame:0
          TX packets:71192 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:171546528 (171.5 MB)  TX bytes:10128274 (10.1 MB)
          Interrupt:17 

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:285 errors:0 dropped:0 overruns:0 frame:0
          TX packets:285 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1 
          RX bytes:29238 (29.2 KB)  TX bytes:29238 (29.2 KB)

ホストの起動時に自動的にブリッジを生成するには /etc/network/interfaces を以下のように変更します。

# interfaces(5) file used by ifup(8) and ifdown(8)
auto lo
iface lo inet loopback

#auto enp2s0
#iface enp2s0 inet manual

auto br0
iface br0 inet static
  address 172.18.21.80
  netmask 255.255.255.0
  network 172.18.21.0
  broadcast 172.18.21.255
  gateway 172.18.21.1
  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

dns-nameservers 172.18.21.1

ホストを起動するとブリッジが有効になっていることが「ifconfig」で確認できます。


仮想ディスクイメージの作成

仮想マシンのハードディスクは仮想ディスクイメージというファイルとして準備する必要があります。仮想ディスクイメージは「qemu-img」コマンドを使って作成します。次の例は 8GB のディスクイメージを qcow2 フォーマットを使って、u1604.qcow2 というファイル名で作成します。ディスクイメージファイルもインストール用の ubuntu-16.04-server-amd64.iso もホストマシンの kvm1604 というフォルダに置いて作業をしています。

jun@xerus:~/kvm1604$ qemu-img create -f qcow2 u1604.qcow2 8G
Formatting 'u1604.qcow2', fmt=qcow2 size=8589934592 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16

qcow2 フォーマットは、使っている部分だけがファイルに記録されます。したがって実際に作成されるイメージは 8GB ではなく、次のように200KB程度のイメージファイルとなります。仮想ディスクに書き込むと徐々に大きくなり、ディスクイメージの作成時に指定したサイズまで大きくなります。

jun@xerus:~/kvm1604$ ls -lt
-rw-r--r--  1 jun  jun    197120 May  3 13:54 u1604.qcow2

ゲストOSとして64ビット Ubuntu 16.04LTS サーバ版のインストール

次のようにイメージファイルと同じフォルダに ubuntu-16.04-server-amd64.iso を置いて仮想マシンを起動してインストールを開始します。スクリーンショットが大きすぎますが、サイズの修正が大変なのでこのまま行きます m(_@_)m。

jun@xerus:~/kvm1604$ ls -lt
-rw-rw-r-- 1 jun jun 686817280 May  3 14:10 ubuntu-16.04-server-amd64.iso
-rw-r--r-- 1 jun jun    197120 May  3 13:54 u1604.qcow2

ゲストマシンの起動

MacOSXのVNCクライアントはパスワードを聞いてくるので、QEMUのVNCをパスワード付きで起動してQEMUモニタからパスワードを設定します。QEMUモニタを使うためにはオプションに「-monitor stdio」を付けて、QEMUモニタの入出力を標準入出力に設定して起動します。 次のように実行すると、QEMUモニタのプロンプト「 (qemu)」が表示されるので、VNC用のパスワードを「change vnc password」コマンドで設定します。

jun@xerus:~/kvm1604$ sudo kvm -hda u1604.qcow2 -cdrom ubuntu-16.04-server-amd64.iso -boot d -m 512 -vnc :0,password -monitor stdio
sudo: unable to resolve host xerus
QEMU 2.5.0 monitor - type 'help' for more information
(qemu) change vnc password
Password: ********
(qemu) 

Mac OS X 標準のVNCクライアントで接続

Macの Finderのメニューから [移動]->[サーバへ接続...(⌘K)]で起動できます。 ポート番号は kvm の起動時にVNCサーバとして指定したオプションの番号に5900を加えた値を指定します。「 -vnc :0」の場合は5900になります。

u160401.png


先ほど設定したVNC用のパスワードを入力します。

u160402.png


ゲストマシンの起動画面が表示されます。 最初にインストールに使用する言語の指定です。ここではデフォルトのEnglishのままでいきます。

u160403.png


Ubuntuを仮想ハードディスクにインストールするため、「Install Ubuntu Server」を選択します。

u160404.png


使う言語の指定です。サーバとして利用するのでコンソールが日本語を表示できない場合を考えてEnglishにしました。

u160405.png


国の指定です。日本を指定する場合は other / Asia / Japan とたどります。

u160406.png


u160407.png


u160408.png


言語と国の指定が一致していないので、locale を聞いてきます。ここでは「en_US.UTF-8」を選択します。

u16040.png


キーボードのレイアウトの指定です。日本語のキーボードは検出されないので、ここでは <No> を選択します。

u160410.png


Japaneseを選択します。

u160411.png


普通は「Japanese (OADG 109A)」です。

u160412.png


ホストの名前を設定します。適当に名前を決めてください。/etc/hostname と /etc/hosts というテキストファイルの内容を書き換えれば後から変更できます。

u160413.png


ユーザの名前を入力します。

u160414.png


アカウントに使うユーザ名を入力します。

u160415.png


パスワードを入力します。

u160416.png


確認のため、もう一度パスワードを入力します。

u160417.png


ホームディレクトリを暗号化する場合は <Yes> を選択します。普通は <No> で問題ありません。

u160418.png


タイムゾーンの確認です。 「Asia/Tokyo」で合っているので「Yes」を選択します。

u160419.png


Ubuntuをインストールするハードディスクの構成を選択します。仮想マシンの仮想ディスクイメージにインストールする場合は「use entire disk」としてディスク全体を使ってインストールしても問題ありません。

u160420.png


表示されたハードディスクが消去されるという警告です。間違いがなければエンターキーで次に進みます。

u160421.png


フォーマットされるパーティションの情報が表示されます。

u160422.png




インターネットへの接続がプロキシサーバを経由する場合はここで設定します。認証が必要な場合もユーザ名、パスワードをここで設定します。自宅で使う場合は何も設定しなくても大丈夫です。ここで設定しない場合でも、あとから以下の内容のテキストファイルを /etc/apt/apt.conf として置けば同じです。

Acquire::https::Proxy"https://ユーザ名:パスワード@プロキシIPアドレス:ポート番号";

u160423.png


システムのアップデートを自動で行うかどうかを指定します。

u160424.png


サーバをどういった目的で使うかが決まっていれば、ここでインストールするソフトウェアを指定できます。下の例は「データベースとしてPostgreSQLを使って、PHPでプログラムを作成、ApacheでWebサーバを動作させる。SSHで接続する。Windows機とファイルのやり取りもしたい。」といった場合の選択です。「LAMP Server」を選択すると MySQL もインストールされますが、不要ならば後から「apt-get remove mysql-common」を実行します。

u160425.png


u160426.png


インストールの終了です。

u160427.png


インストール後のディスクイメージのサイズを確認します。

jun@xerus:~/kvm1604$ ls -lt
-rw-r--r-- 1 jun jun 2170028032 May  3 15:35 u1604.qcow2

仮想ハードディスクからゲストOSの起動

仮想環境の場合は自動的に再起動されないので、「kvm -hda ディスクイメージ -boot c」として仮想ディスクイメージから起動します。ゲスト用のメモリは512MB(-m 512)、ゲストの出力が vnc の場合のコマンドです。

jun@xerus:~/kvm1604$ sudo kvm -hda u1604.qcow2 -boot c -m 512 -vnc :0,password -monitor stdio   
sudo: unable to resolve host xerus
QEMU 2.5.0 monitor - type 'help' for more information
(qemu) change inc password
Password: ********
(qemu) 

u160428.png


ネットワークカードの設定(-net)を省略するとホストがdhcpサーバ兼ルータとして働き、 ゲストのIPアドレスは以下の例のように 10.0.2.15 といったIPアドレスが自動的に設定されます。

u160429.png


ここでは起動の確認だけにします。各種の設定は後述します。

ゲストの動作確認とパッケージのインストール

ゲストの起動確認

jun@xerus:~/kvm1604$ sudo kvm -hda u1604.qcow2 -boot c -m 512 -nographic
Ubuntu 16.04 LTS u1604 ttyS0

u1604 login: jun
Password: 
Last login: Wed May  4 17:01:36 JST 2016 on tty1
Welcome to Ubuntu 16.04 LTS (GNU/Linux 4.4.0-21-generic x86_64)

 * Documentation:  https://help.ubuntu.com/

17 packages can be updated.
3 updates are security updates.

サーバ版は NetworkManager がインストールされていないことを確認します。

jun@u1604:~$ nmcli status
The program 'nmcli' is currently not installed. You can install it by typing:
sudo apt install network-manager

プログラミング用パッケージの追加

dhcp が存在するネットワークではこのままインターネットに接続できるので追加するパッケージをインストールしました。 プログラミングの教育用に使えるように設定しています。

jun@u1604:~$ sudo apt-get update
[sudo] password for jun: 
Hit:1 https://jp.archive.ubuntu.com/ubuntu/xenial InRelease
Get:2 https://jp.archive.ubuntu.com/ubuntu/xenial-updates InRelease [93.3 kB]
Hit:3 https://jp.archive.ubuntu.com/ubuntu/xenial-backports InRelease           
Get:4 https://security.ubuntu.com/ubuntu/xenial-security InRelease [92.2 kB]    
Get:5 https://jp.archive.ubuntu.com/ubuntu/xenial-updates/main amd64 Packages [36.9 kB]
Get:6 https://jp.archive.ubuntu.com/ubuntu/xenial-updates/main i386 Packages [36.8 kB]
Get:7 https://jp.archive.ubuntu.com/ubuntu/xenial-updates/main Translation-en [14.0 kB]
Get:8 https://jp.archive.ubuntu.com/ubuntu/xenial-updates/universe amd64 Packages [9,012 B]
Get:9 https://jp.archive.ubuntu.com/ubuntu/xenial-updates/universe i386 Packages [9,012 B]
Get:10 https://security.ubuntu.com/ubuntu/xenial-security/main amd64 Packages [27.7 kB]
Get:11 https://security.ubuntu.com/ubuntu/xenial-security/main i386 Packages [27.7 kB]
Get:12 https://security.ubuntu.com/ubuntu/xenial-security/main Translation-en [9,264 B]
Fetched 356 kB in 2s (148 kB/s)   
Reading package lists... Done
jun@u1604:~$ sudo apt-get upgrade
Reading package lists... Done
Building dependency tree       
Reading state information... Done
Calculating upgrade... Done
The following packages will be upgraded:
  bind9-host distro-info-data dnsutils language-selector-common libbind9-140
  libdns-export162 libdns162 libisc-export160 libisc160 libisccc140
  libisccfg140 liblwres141 libssl1.0.0 libtasn1-6 lxcfs openssl
  python3-distupgrade ubuntu-core-launcher ubuntu-release-upgrader-core
19 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
Need to get 4,204 kB of archives.
After this operation, 3,072 B of additional disk space will be used.
Do you want to continue? [Y/n]y

gcc, g++, binutils

jun@u1604:~$ sudo apt-get install build-essential
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following additional packages will be installed:
  binutils cpp cpp-5 dpkg-dev fakeroot g++ g++-5 gcc gcc-5
  libalgorithm-diff-perl libalgorithm-diff-xs-perl libalgorithm-merge-perl
  libasan2 libatomic1 libc-dev-bin libc6-dev libcc1-0 libcilkrts5 libdpkg-perl
  libfakeroot libfile-fcntllock-perl libgcc-5-dev libgomp1 libisl15 libitm1
  liblsan0 libmpc3 libmpx0 libquadmath0 libstdc++-5-dev libtsan0 libubsan0
  linux-libc-dev make manpages-dev
Suggested packages:
  binutils-doc cpp-doc gcc-5-locales debian-keyring g++-multilib
  g++-5-multilib gcc-5-doc libstdc++6-5-dbg gcc-multilib autoconf automake
  libtool flex bison gdb gcc-doc gcc-5-multilib libgcc1-dbg libgomp1-dbg
  libitm1-dbg libatomic1-dbg libasan2-dbg liblsan0-dbg libtsan0-dbg
  libubsan0-dbg libcilkrts5-dbg libmpx0-dbg libquadmath0-dbg glibc-doc
  libstdc++-5-doc make-doc
The following NEW packages will be installed:
  binutils build-essential cpp cpp-5 dpkg-dev fakeroot g++ g++-5 gcc gcc-5
  libalgorithm-diff-perl libalgorithm-diff-xs-perl libalgorithm-merge-perl
  libasan2 libatomic1 libc-dev-bin libc6-dev libcc1-0 libcilkrts5 libdpkg-perl
  libfakeroot libfile-fcntllock-perl libgcc-5-dev libgomp1 libisl15 libitm1
  liblsan0 libmpc3 libmpx0 libquadmath0 libstdc++-5-dev libtsan0 libubsan0
  linux-libc-dev make manpages-dev
0 upgraded, 36 newly installed, 0 to remove and 0 not upgraded.
Need to get 38.5 MB of archives.
After this operation, 143 MB of additional disk space will be used.
Do you want to continue? [Y/n] y

Java8

jun@u1604:~$ sudo apt-get install openjdk-8-jdk
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following additional packages will be installed:
  ca-certificates-java dbus-x11 fontconfig fontconfig-config fonts-dejavu-core
  fonts-dejavu-extra gconf-service gconf-service-backend gconf2 gconf2-common
  hicolor-icon-theme java-common libasound2 libasound2-data libasyncns0
  libatk1.0-0 libatk1.0-data libavahi-glib1 libbonobo2-0 libbonobo2-common
  libcairo2 libcanberra0 libdatrie1 libdrm-amdgpu1 libdrm-intel1
  libdrm-nouveau2 libdrm-radeon1 libflac8 libfontconfig1 libgconf-2-4
  libgdk-pixbuf2.0-0 libgdk-pixbuf2.0-common libgif7 libgl1-mesa-dri
  libgl1-mesa-glx libglapi-mesa libgnome-2-0 libgnome2-common libgnomevfs2-0
  libgnomevfs2-common libgraphite2-3 libgtk2.0-0 libgtk2.0-bin
  libgtk2.0-common libharfbuzz0b libice-dev libice6 libjbig0 libjpeg-turbo8
  libjpeg8 liblcms2-2 libllvm3.8 libltdl7 libnspr4 libnss3 libnss3-nssdb
  libogg0 liborbit-2-0 libpango-1.0-0 libpangocairo-1.0-0 libpangoft2-1.0-0
  libpciaccess0 libpcsclite1 libpixman-1-0 libpthread-stubs0-dev libpulse0
  libsm-dev libsm6 libsndfile1 libthai-data libthai0 libtiff5
  libtxc-dxtn-s2tc0 libvorbis0a libvorbisenc2 libvorbisfile3 libx11-dev
  libx11-doc libx11-xcb1 libxau-dev libxcb-dri2-0 libxcb-dri3-0 libxcb-glx0
  libxcb-present0 libxcb-render0 libxcb-shm0 libxcb-sync1 libxcb1-dev
  libxcomposite1 libxcursor1 libxdamage1 libxdmcp-dev libxfixes3 libxi6
  libxinerama1 libxrandr2 libxrender1 libxshmfence1 libxt-dev libxt6 libxtst6
  libxxf86vm1 openjdk-8-jdk-headless openjdk-8-jre openjdk-8-jre-headless
  sound-theme-freedesktop x11-common x11proto-core-dev x11proto-input-dev
  x11proto-kb-dev xorg-sgml-doctools xtrans-dev
Suggested packages:
  gconf-defaults-service default-jre libasound2-plugins alsa-utils
  libbonobo2-bin libcanberra-gtk0 libcanberra-pulse desktop-base
  libgnomevfs2-bin libgnomevfs2-extra gamin | fam gnome-mime-data
  librsvg2-common gvfs libice-doc liblcms2-utils pcscd pulseaudio libsm-doc
  libxcb-doc libxt-doc openjdk-8-demo openjdk-8-source visualvm
  icedtea-8-plugin openjdk-8-jre-jamvm libnss-mdns fonts-ipafont-gothic
  fonts-ipafont-mincho ttf-wqy-microhei | ttf-wqy-zenhei fonts-indic
The following NEW packages will be installed:
  ca-certificates-java dbus-x11 fontconfig fontconfig-config fonts-dejavu-core
  fonts-dejavu-extra gconf-service gconf-service-backend gconf2 gconf2-common
  hicolor-icon-theme java-common libasound2 libasound2-data libasyncns0
  libatk1.0-0 libatk1.0-data libavahi-glib1 libbonobo2-0 libbonobo2-common
  libcairo2 libcanberra0 libdatrie1 libdrm-amdgpu1 libdrm-intel1
  libdrm-nouveau2 libdrm-radeon1 libflac8 libfontconfig1 libgconf-2-4
  libgdk-pixbuf2.0-0 libgdk-pixbuf2.0-common libgif7 libgl1-mesa-dri
  libgl1-mesa-glx libglapi-mesa libgnome-2-0 libgnome2-common libgnomevfs2-0
  libgnomevfs2-common libgraphite2-3 libgtk2.0-0 libgtk2.0-bin
  libgtk2.0-common libharfbuzz0b libice-dev libice6 libjbig0 libjpeg-turbo8
  libjpeg8 liblcms2-2 libllvm3.8 libltdl7 libnspr4 libnss3 libnss3-nssdb
  libogg0 liborbit-2-0 libpango-1.0-0 libpangocairo-1.0-0 libpangoft2-1.0-0
  libpciaccess0 libpcsclite1 libpixman-1-0 libpthread-stubs0-dev libpulse0
  libsm-dev libsm6 libsndfile1 libthai-data libthai0 libtiff5
  libtxc-dxtn-s2tc0 libvorbis0a libvorbisenc2 libvorbisfile3 libx11-dev
  libx11-doc libx11-xcb1 libxau-dev libxcb-dri2-0 libxcb-dri3-0 libxcb-glx0
  libxcb-present0 libxcb-render0 libxcb-shm0 libxcb-sync1 libxcb1-dev
  libxcomposite1 libxcursor1 libxdamage1 libxdmcp-dev libxfixes3 libxi6
  libxinerama1 libxrandr2 libxrender1 libxshmfence1 libxt-dev libxt6 libxtst6
  libxxf86vm1 openjdk-8-jdk openjdk-8-jdk-headless openjdk-8-jre
  openjdk-8-jre-headless sound-theme-freedesktop x11-common x11proto-core-dev
  x11proto-input-dev x11proto-kb-dev xorg-sgml-doctools xtrans-dev
0 upgraded, 113 newly installed, 0 to remove and 0 not upgraded.
Need to get 65.6 MB of archives.
After this operation, 357 MB of additional disk space will be used.
Do you want to continue? [Y/n] y

apache2

jun@u1604:~$ sudo apt-get install apache2
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following additional packages will be installed:
  apache2-bin apache2-data apache2-utils libapr1 libaprutil1
  libaprutil1-dbd-sqlite3 libaprutil1-ldap liblua5.1-0
Suggested packages:
  www-browser apache2-doc apache2-suexec-pristine | apache2-suexec-custom
The following NEW packages will be installed:
  apache2 apache2-bin apache2-data apache2-utils libapr1 libaprutil1
  libaprutil1-dbd-sqlite3 libaprutil1-ldap liblua5.1-0
0 upgraded, 9 newly installed, 0 to remove and 0 not upgraded.
Need to get 1,532 kB of archives.
After this operation, 6,350 kB of additional disk space will be used.
Do you want to continue? [Y/n] y

ユーザホームディレクトリ/public_html にページを置くことができるように userdir モジュールを有効にします。cgi や SSI の準備もしておきます。

jun@u1604:~$ sudo a2enmod userdir
Enabling module userdir.
To activate the new configuration, you need to run:
  service apache2 restart

jun@u1604:~$ sudo a2enmod cgid
Enabling module cgid.
To activate the new configuration, you need to run:
  service apache2 restart

jun@u1604:~$ sudo a2enmod include
Considering dependency mime for include:
Module mime already enabled
Enabling module include.
To activate the new configuration, you need to run:
  service apache2 restart

jun@u1604:~$ sudo service apache2 restart

/etc/apache2/mods-available/userdir.conf も編集しておきます。

<IfModule mod_userdir.c>
        UserDir public_html
        UserDir disabled root

        <Directory /home/*/public_html>
                AllowOverride FileInfo AuthConfig Limit Indexes Options
                Options MultiViews Indexes SymLinksIfOwnerMatch Includes
                <Limit GET POST OPTIONS>
                        Require all granted
                </Limit>
                <LimitExcept GET POST OPTIONS>
                        Require all denied
                </LimitExcept>
        </Directory>
</IfModule>

php

jun@u1604:~$ sudo apt-get install php
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following additional packages will be installed:
  php-common php7.0 php7.0-cli php7.0-common php7.0-fpm php7.0-json
  php7.0-opcache php7.0-readline
Suggested packages:
  php-pear
The following NEW packages will be installed:
  php php-common php7.0 php7.0-cli php7.0-common php7.0-fpm php7.0-json
  php7.0-opcache php7.0-readline
0 upgraded, 9 newly installed, 0 to remove and 0 not upgraded.
Need to get 3,164 kB of archives.
After this operation, 13.7 MB of additional disk space will be used.
Do you want to continue? [Y/n] y

Node.js

jun@u1604:~$ sudo apt-get install nodejs
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following additional packages will be installed:
  libuv1
The following NEW packages will be installed:
  libuv1 nodejs
0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded.
Need to get 3,219 kB of archives.
After this operation, 13.4 MB of additional disk space will be used.
Do you want to continue? [Y/n] y

Lua

jun@u1604:~$ sudo apt-get install luajit
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following additional packages will be installed:
  libluajit-5.1-common
The following NEW packages will be installed:
  libluajit-5.1-common luajit
0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded.
Need to get 241 kB of archives.
After this operation, 632 kB of additional disk space will be used.
Do you want to continue? [Y/n] y

Gauche (scheme)

jun@u1604:~$ sudo apt-get install gauche
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following additional packages will be installed:
  libgauche-0.9-0 slib
Suggested packages:
  r5rs-doc gauche-doc gauche-zlib gauche-gdbm
The following NEW packages will be installed:
  gauche libgauche-0.9-0 slib
0 upgraded, 3 newly installed, 0 to remove and 0 not upgraded.
Need to get 2,325 kB of archives.
After this operation, 16.7 MB of additional disk space will be used.
Do you want to continue? [Y/n] y

Ruby

jun@u1604:~$ sudo apt-get install ruby
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following additional packages will be installed:
  fonts-lato javascript-common libjs-jquery libruby2.3 libyaml-0-2 rake
  ruby-did-you-mean ruby-minitest ruby-net-telnet ruby-power-assert
  ruby-test-unit ruby2.3 rubygems-integration unzip zip
Suggested packages:
  ri ruby-dev bundler
The following NEW packages will be installed:
  fonts-lato javascript-common libjs-jquery libruby2.3 libyaml-0-2 rake ruby
  ruby-did-you-mean ruby-minitest ruby-net-telnet ruby-power-assert
  ruby-test-unit ruby2.3 rubygems-integration unzip zip
0 upgraded, 16 newly installed, 0 to remove and 0 not upgraded.
Need to get 6,413 kB of archives.
After this operation, 28.8 MB of additional disk space will be used.
Do you want to continue? [Y/n] y

Emacs (NoX)

jun@u1604:~$ sudo apt-get install emacs-nox
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following additional packages will be installed:
  emacs24-bin-common emacs24-common emacs24-common-non-dfsg emacs24-el
  emacs24-nox emacsen-common liblockfile-bin liblockfile1
The following NEW packages will be installed:
  emacs-nox emacs24-bin-common emacs24-common emacs24-common-non-dfsg
  emacs24-el emacs24-nox emacsen-common liblockfile-bin liblockfile1
0 upgraded, 9 newly installed, 0 to remove and 0 not upgraded.
Need to get 35.7 MB of archives.
After this operation, 103 MB of additional disk space will be used.
Do you want to continue? [Y/n] y

samba の設定

Windows からファイルを共有できるようにします。

jun@u1604:~$ sudo vi /etc/samba/smb.conf 

各行の先頭の数値は行番号です。入力の必要はありません。

193 [homes]
194    comment = Home Directories
195    browseable = yes
196 
197 # By default, the home directories are exported read-only. Change the
198 # next parameter to 'no' if you want to be able to write to them.
199    read only = no
200 
201 # File creation mask is set to 0700 for security reasons. If you want to
202 # create files with group=rw permissions, set next parameter to 0775.
203    create mask = 0755
204 
205 # Directory creation mask is set to 0700 for security reasons. If you want to
206 # create dirs. with group=rw permissions, set next parameter to 0775.
207    directory mask = 0755

Ubuntu のユーザを追加します。ここではアカウント名を「user_name」とした例です。

jun@u1604:~$ sudo adduser user_name

新しいアカウントに管理者権限を追加するには以下のコマンドを実行して、アカウントを sudo グループに追加します。

jun@u1604:~$ sudo gpasswd -a user_name sudo

samba にアカウントを追加します。

jun@u1604:~$ sudo pdbedit -a user_name
new password:xxxxxxxx
retype new password:xxxxxxxx

RvtlWiki のインストール

rvtl64 と RvtlWiki をインストールしてWikiを使えるようにします。最初に rvtl64をダウンロードしてインストールします。

jun@u1604:~$ curl -O https://www.mztn.org/rvtl/rvtl-amd64_4.01.tar.gz
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  197k  100  197k    0     0  1640k      0 --:--:-- --:--:-- --:--:-- 1642k
jun@u1604:~$ tar zxf rvtl-amd64_4.01.tar.gz
jun@u1604:~$ cd rvtl-amd64/
jun@u1604:~/rvtl-amd64$ sudo cp rvtl64 /usr/bin
jun@u1604:~/rvtl-amd64$ cd /usr/bin
jun@u1604:/usr/bin$ sudo ln -s rvtl64 rvtlw

RvtlWiki は github の最新版を持ってきます。

jun@u1604:~$ git clone https://github.com/jun-mizutani/rvtlwiki.git
Cloning into 'rvtlwiki'...
remote: Counting objects: 54, done.
remote: Total 54 (delta 0), reused 0 (delta 0), pack-reused 54
Unpacking objects: 100% (54/54), done.
Checking connectivity... done.

ここでは /home/jun/public_html/rvtlwiki というフォルダにインストールします。フォルダを作って、コピーして、パーミッションを調整しているだけです。

jun@u1604:~$ mkdir public_html
jun@u1604:~$ cd public_html
jun@u1604:~/public_html$ mkdir rvtlwiki

git clone で持ってきたファイルのうち、rvtlwiki64 以下のファイルをコピーします。

jun@u1604:~/public_html$ cp -a ../rvtlwiki/rvtlwiki64/* rvtlwiki
jun@u1604:~/public_html$ cp -a ../rvtlwiki/rvtlwiki64/.htaccess rvtlwiki

httpd から rvtlwiki/pages へ書き込めるようにパーミッションを変更します。

jun@u1604:~/public_html$ chmod 777 rvtlwiki/pages
jun@u1604:~/public_html$ chmod 666 rvtlwiki/pages/*

日本語 man ページ

日本語のマニュアルが利用できるように日本語のロケールをインストールします。

jun@u1604:~$ sudo apt-get install language-pack-ja
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following additional packages will be installed:
  language-pack-ja-base
The following NEW packages will be installed:
  language-pack-ja language-pack-ja-base
0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded.
Need to get 1,768 kB of archives.
After this operation, 8,278 kB of additional disk space will be used.
Do you want to continue? [Y/n] y
略

マニュアルページの日本語版をインストールします。

jun@u1604:~$ sudo apt-get install manpages-ja manpages-ja-dev
[sudo] password for jun: 
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following NEW packages will be installed:
  manpages-ja manpages-ja-dev
0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded.
Need to get 5,840 kB of archives.
After this operation, 7,932 kB of additional disk space will be used.
略

システムのロケールを英語のまま変更しないで、日本語のman ページを表示するには、次のように LANG を一時的に変更して、man コマンドを実行します。

jun@u1604:~$ LANG=ja_JP.UTF-8 man grep
GREP(1)                     General Commands Manual                 GREP(1)

名前
       grep, egrep, fgrep - パターンにマッチする行を表示する

書式
       grep [OPTIONS] PATTERN [FILE...]
       grep [OPTIONS] [-e PATTERN | -f FILE] [FILE...]

説明
       grep は FILE で名前を指定されたファイル (ファイルが指定されていない場合
       や、 ファイル名の代わりに 1 個のマイナス記号 (-) が指定されている場合は
       標準入力) を検索して、与えられた PATTERN にマッチする部分を含む行を探し
       ます。 デフォルトでは、 grep はマッチした行を表示します。

       さらに、2 つの兄弟プログラム egrep と fgrep が利用可能です。  egrep は
       grep -E  と同じです。 fgrep は grep -F と同じです。 egrep や fgrep を直
       接その名前で呼び出すのは、お勧めできません。   それが可能になっているの
       は、こうしたコマンドの存在を前提とする 昔のアプリケーションが、プログラ
       ムを修正しないでも 動くようにするためなのです。

ディスクイメージの縮小

qcow2形式のディスクイメージは使っている部分だけを記録する形式ですが、使っているうちに大きくなってきます。イメージ中の未使用の部分を削除するには qemu-img の件肝機能を使います。以下のように qcow2 から qcow2 への変換を行うことで、イメージが再構築されて小さくすることができます。

jun@xerus:~/kvm1604$ qemu-img convert -O qcow2 u1604.qcow2 u1604.qcow2.new
jun@xerus:~/kvm1604$ ls -lt
-rw-r--r-- 1 jun jun 3354722304  5月  5 18:03 u1604.qcow2
-rw-r--r-- 1 jun jun 3238920192  5月  5 18:07 u1604.qcow2.new

カーネルのシリアル出力設定

カーネルのコンソール出力をシリアルに出力するように変更するため、grub を修正します。/etc/default/grub を変更した後、「update-grub」を実行します。

jun@u91064s:/etc/init$ sudo vi /etc/default/grub
# If you change this file, run 'update-grub' afterwards to update
# /boot/grub/grub.cfg.

GRUB_DEFAULT=0
GRUB_HIDDEN_TIMEOUT=0
GRUB_HIDDEN_TIMEOUT_QUIET=true
GRUB_TIMEOUT="10"
GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian`
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"
GRUB_CMDLINE_LINUX="console=tty0 console=ttyS0,115200n8"

# Uncomment to disable graphical terminal (grub-pc only)
#GRUB_TERMINAL=console

# The resolution used on graphical terminal
# note that you can use only modes which your graphic card supports via VBE
# you can see them in real GRUB with the command `vbeinfo'
#GRUB_GFXMODE=640x480

# Uncomment if you don't want GRUB to pass "root=UUID=xxx" parameter to Linux
#GRUB_DISABLE_LINUX_UUID=true

# Uncomment to disable generation of recovery mode menu entrys
#GRUB_DISABLE_LINUX_RECOVERY="true"

Ubuntu 16.04LTS は Systemd を使っているため、inittab がありません。/etc/systemd/system/serial-getty@ttyS0.service を作成して、シリアル回線でログインできるようにします。

/lib/systemd/system/serial-getty@.service を /etc/systemd/system/serial-getty@ttyS0.service としてコピーします。

# cp /lib/systemd/system/serial-getty@.service /etc/systemd/system/serial-getty@ttyS0.service

/etc/systemd/system/serial-getty@ttyS0.service を編集します。

以下のように1行を変更します。

jun@u1604:~$ sudo vi /etc/systemd/system/serial-getty@ttyS0.service 
#  This file is part of systemd.
#
#  systemd is free software; you can redistribute it and/or modify it
#  under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation; either version 2.1 of the License, or
#  (at your option) any later version.

[Unit]
Description=Serial Getty on %I
Documentation=man:agetty(8) man:systemd-getty-generator(8)
Documentation=https://0pointer.de/blog/projects/serial-console.html
BindsTo=dev-%i.device
After=dev-%i.device systemd-user-sessions.service plymouth-quit-wait.service
After=rc-local.service

# If additional gettys are spawned during boot then we should make
# sure that this is synchronized before getty.target, even though
# getty.target didn't actually pull it in.
Before=getty.target
IgnoreOnIsolate=yes

[Service]
#ExecStart=-/sbin/agetty --keep-baud 115200,38400,9600 %I $TERM
ExecStart=-/sbin/agetty -L ttyS0 115200 vt100
Type=idle
Restart=always
UtmpIdentifier=%I
TTYPath=/dev/%I
TTYReset=yes
TTYVHangup=yes
KillMode=process
IgnoreSIGPIPE=no
SendSIGHUP=yes

[Install]
WantedBy=getty.target

serial-getty@ttyS0.service のシンボリックリンクを /etc/systemd/system/getty.target.wants/ に作成します。

$ 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

以上で、kvm を起動した端末上でゲストにログインできるようになります。

複数のゲストマシンの同時起動

ゲストOSを複数起動するためには、ゲストのディスクイメージを別々に用意して起動します。1つのディスクイメージを複数の仮想マシンで共有することはできません。同じ環境のゲストを使う場合でもイメージをコピーする必要があります。今回はサーバとして使用するのでゲストマシンごとにMACアドレス、IPアドレス、ホスト名を別の値を設定する必要があります。

ゲストのネットワークの設定は、ゲストOS側の /etc/rc.local で設定するようにしています。ネットワークカードのデバイス名とMACアドレスを ifconfig から取得して、MACアドレスの最終オクテットをIPアドレスの第4オクテットとして設定し、ホスト名もその値を使うようなスクリプトにしています。 ゲストを起動するためのKVMコマンドのオプションでMACアドレスを指定することで、IPアドレスとホスト名を自動で設定します。

例えば 172.18.21.90 を設定する場合は90の16進数である「5A」をMACアドレスの最終桁に設定します。 ホスト名は「Guest90」のように設定されます。IPアドレスの 172.18.21 の部分は /etc/rc.local の IP24 の行を変更して下さい。ゲイトウェイアドレスは 172.18.21.1 に設定されますが、変更する場合は GW の行を変更して下さい。

まず、/etc/network/interfaces のDHCP の設定を変更します。

jun@u1604:~$ cat /etc/network/interfaces
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

source /etc/network/interfaces.d/*

# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
#auto ens3
#iface ens3 inet dhcp

dns-nameservers 172.18.21.1

/etc/rc.local のスクリプトを修正します。

jun@u1604:~$ cat /etc/rc.local
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.

IP24=172.18.21

GW=.1

NIC=`ifconfig -a|awk '$1 ~ /^ens/ {print $1,$5}'`
HW=`echo $NIC | awk 'BEGIN{FS=":"} {print $6}'`
DEV=`echo $NIC | awk '{print $1}'`
IP=$IP24.$((0x$HW))
echo $DEV
echo "ip address :" $IP
echo "broadcast  :" $IP24.255
echo "gateway    :" $IP24$GW
ifconfig $DEV $IP netmask 255.255.255.0 broadcast $IP24.255
route add default gw $IP24$GW
hostname Guest$((0x$HW))
echo 127.0.0.1  localhost >/etc/hosts
echo $IP  $(hostname) >> /etc/hosts

exit 0

/etc/rc.local を以上のように書き換えて、「sudo chmod +x /etc/rc.local」を実行して実行可能に設定します。

ゲスト1の起動

ゲストを起動するためのKVMコマンドのオプションはMACアドレス(macaddr=52:54:00:12:34:90)とTAPデバイスの名称の指定(ifname=tap0)を行います。MACアドレスの最終オクテットはIPアドレスの第4オクテットとして設定されます。

sudo kvm -m 512 -boot c -nographic \
    -drive file=u1604.qcow2,if=virtio,boot=on \
    -net nic,macaddr=52:54:00:12:34:5A,model=virtio \
    -net tap,ifname=tap0,script=/etc/qemu-ifup

Ubuntu 16.04 LTS Guest90 ttyS0

Guest90 login: jun
Password: 
Last login: Thu May  5 18:00:18 JST 2016 on ttyS0
Welcome to Ubuntu 16.04 LTS (GNU/Linux 4.4.0-21-generic x86_64)

 * Documentation:  https://help.ubuntu.com/

0 packages can be updated.
0 updates are security updates.


jun@Guest90:~$ ifconfig
ens3      Link encap:Ethernet  HWaddr 52:54:00:12:34:5a  
          inet addr:172.18.21.90  Bcast:172.18.21.255  Mask:255.255.255.0
          inet6 addr: fe80::5054:ff:fe12:345a/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:130 errors:0 dropped:0 overruns:0 frame:0
          TX packets:31 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:11803 (11.8 KB)  TX bytes:3255 (3.2 KB)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:549 errors:0 dropped:0 overruns:0 frame:0
          TX packets:549 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1 
          RX bytes:58629 (58.6 KB)  TX bytes:58629 (58.6 KB)

jun@Guest90:~$ 

ゲスト2の起動

ゲスト2を起動するにはゲスト1の仮想ディスクイメージファイル(u1604.qcow2)をコピーしてファイル名を変更します。ここでは u1604.qcow2 としました。MACアドレス(macaddr=52:54:00:12:34:5B)とTAPデバイスの名称(ifname=tap1)の指定がゲスト1 と別の値を指定しています。

sudo kvm -m 512 -boot c -nographic \
    -drive file=u1604B.qcow2,if=virtio \
    -net nic,macaddr=52:54:00:12:34:5B,model=virtio \
    -net tap,ifname=tap1,script=/etc/qemu-ifup

次のようにコピーしただけの仮想ディスクイメージファイルを使って、ゲスト1と別のIPアドレス、別のホスト名、別のMACアドレスでゲスト2が起動することを確認できます。


Ubuntu 16.04 LTS Guest91 ttyS0

Guest91 login: jun
Password: 
Last login: Thu May  5 18:00:18 JST 2016 on ttyS0
Welcome to Ubuntu 16.04 LTS (GNU/Linux 4.4.0-21-generic x86_64)

 * Documentation:  https://help.ubuntu.com/

0 packages can be updated.
0 updates are security updates.


jun@Guest91:~$ ifconfig
ens3      Link encap:Ethernet  HWaddr 52:54:00:12:34:5b  
          inet addr:172.18.21.91  Bcast:172.18.21.255  Mask:255.255.255.0
          inet6 addr: fe80::5054:ff:fe12:345b/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:81 errors:0 dropped:0 overruns:0 frame:0
          TX packets:26 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:8152 (8.1 KB)  TX bytes:2705 (2.7 KB)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:381 errors:0 dropped:0 overruns:0 frame:0
          TX packets:381 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1 
          RX bytes:44341 (44.3 KB)  TX bytes:44341 (44.3 KB)

jun@Guest91:~$ 

ホスト側で確認

ゲストを2台起動する前後のホスト側のネットワークの状態です。eth0 以外にも br0、tap0、tap1 が動作していることがわかります。

jun@xerus:~$ ifconfig
br0       Link encap:Ethernet  HWaddr 00:1d:60:6d:ae:b4  
          inet addr:172.18.21.80  Bcast:172.18.21.255  Mask:255.255.255.0
          inet6 addr: fe80::21d:60ff:fe6d:aeb4/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:21558 errors:0 dropped:0 overruns:0 frame:0
          TX packets:16150 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:1581526 (1.5 MB)  TX bytes:7807608 (7.8 MB)

enp2s0    Link encap:Ethernet  HWaddr 00:1d:60:6d:ae:b4  
          inet6 addr: fe80::21d:60ff:fe6d:aeb4/64 Scope:Link
          UP BROADCAST RUNNING PROMISC MULTICAST  MTU:1500  Metric:1
          RX packets:53864 errors:0 dropped:0 overruns:0 frame:0
          TX packets:32897 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:48977992 (48.9 MB)  TX bytes:8960455 (8.9 MB)
          Interrupt:17 

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:170 errors:0 dropped:0 overruns:0 frame:0
          TX packets:170 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1 
          RX bytes:12438 (12.4 KB)  TX bytes:12438 (12.4 KB)

2台起動後。

jun@xerus:~$ ifconfig
br0       Link encap:Ethernet  HWaddr 00:1d:60:6d:ae:b4  
          inet addr:172.18.21.80  Bcast:172.18.21.255  Mask:255.255.255.0
          inet6 addr: fe80::21d:60ff:fe6d:aeb4/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:24484 errors:0 dropped:0 overruns:0 frame:0
          TX packets:16491 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:1885016 (1.8 MB)  TX bytes:7953235 (7.9 MB)

enp2s0    Link encap:Ethernet  HWaddr 00:1d:60:6d:ae:b4  
          inet6 addr: fe80::21d:60ff:fe6d:aeb4/64 Scope:Link
          UP BROADCAST RUNNING PROMISC MULTICAST  MTU:1500  Metric:1
          RX packets:56726 errors:0 dropped:0 overruns:0 frame:0
          TX packets:33345 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:49312628 (49.3 MB)  TX bytes:9118943 (9.1 MB)
          Interrupt:17 

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:170 errors:0 dropped:0 overruns:0 frame:0
          TX packets:170 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1 
          RX bytes:12438 (12.4 KB)  TX bytes:12438 (12.4 KB)

tap0      Link encap:Ethernet  HWaddr 36:18:21:a3:96:c4  
          inet6 addr: fe80::3418:21ff:fea3:96c4/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:53 errors:0 dropped:0 overruns:0 frame:0
          TX packets:2517 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:500 
          RX bytes:6377 (6.3 KB)  TX bytes:306963 (306.9 KB)

tap1      Link encap:Ethernet  HWaddr fa:49:a0:ef:67:79  
          inet6 addr: fe80::f849:a0ff:feef:6779/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:53 errors:0 dropped:0 overruns:0 frame:0
          TX packets:2423 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:500 
          RX bytes:6377 (6.3 KB)  TX bytes:296429 (296.4 KB)

ゲストOSをサーバとして使う

ここまでコンソールで kvm コマンドを実行することでゲストOSを起動し、そのまま端末上でゲストにログインできるようになりました。 ゲストで実行する Linux をサーバとして使用する場合は、常にコンソール出力を表示する必要はなく、ホストのバックグラウンドプロセス(デーモン)として動作すれば十分です。


ここでは仮想マシン上のゲストOSをホストと独立してサーバとして利用します。デスクトップでLinuxを使う場合と異なり、ネットワークさえつながっていればキーボードも画面もほとんど必要ありません。ホストの起動時に自動的にゲストもサーバとして起動し、メンテナンス等で必要なときだけコンソール経由でアクセスできれば理想的です。「ゲストOSはホストのバックグラウンドプロセスとして黙ってサーバとしての動作を続け、必要なときだけコンソールを表示する。」という動作をカーネルのコンソール出力をシリアル端末に切り替えて、コンソールの接続、切断を screen コマンドを利用して実現します。



以上の機能が実現できます。

screen のインストール

screen はホスト側で使うので、ホストマシン上でインストールします。

jun@xerus:~/kvm1604$ sudo apt install screen
sudo: ホスト xerus の名前解決ができません
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています                
状態情報を読み取っています... 完了
提案パッケージ:
  iselect | screenie | byobu
以下のパッケージが新たにインストールされます:
  screen
アップグレード: 0 個、新規インストール: 1 個、削除: 0 個、保留: 0 個。
560 kB のアーカイブを取得する必要があります。
この操作後に追加で 972 kB のディスク容量が消費されます。
略

screenから使う

screen コマンドは端末の出力を物理的な端末と切り離したり、再接続したりすることができるコマンドです。 以下のコマンドを入力して1番目のゲストを起動します。「screen -S Guest90」の行は、screen のセッション(ウィンドウの集合)にGuest90という名前を付けるオプションです。ゲストOSで動作させるサーバの名前などをセッション名として指定すると再接続する場合に識別しやすくなります。

jun@xerus:~/kvm1604$ screen -S Guest90
jun@xerus:~/kvm1604$ sudo kvm -m 512 -boot c -nographic \
    -drive file=u1604.qcow2,if=virtio \
    -net nic,macaddr=52:54:00:12:34:5A,model=virtio \
    -net tap,ifname=tap0,script=/etc/qemu-ifup

ゲストのLinuxが起動して、ログインプロンプトが表示されるまで私の環境で 10 秒程度の時間がかかります。kvmコマンドの応答と考えるとちょっと長く感じますが、サーバが10秒で起動すると考えると非常に速いです。

Ubuntu 16.04 LTS Guest90 ttyS0

Guest90 login: jun
Password: 
Last login: Thu May  5 18:16:14 JST 2016 on ttyS0
Welcome to Ubuntu 16.04 LTS (GNU/Linux 4.4.0-21-generic x86_64)

 * Documentation:  https://help.ubuntu.com/

0 packages can be updated.
0 updates are security updates.


jun@Guest90:~$ 

screenの機能で切断(デタッチ)、接続(アタッチ)ができることを確認するため、Guest90で「top」を起動しておきます。

top - 23:50:46 up 2 min,  1 user,  load average: 0.01, 0.14, 0.14
Tasks: 130 total,   1 running, 129 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.0 us,  0.3 sy,  0.0 ni, 99.7 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :   500192 total,   211920 free,    53092 used,   235180 buff/cache
KiB Swap:   522236 total,   522236 free,        0 used.   396236 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND     
 1237 jun       20   0   41788   3748   3160 R  0.3  0.7   0:02.94 top         
    1 root      20   0   38004   5988   3912 S  0.0  1.2   0:02.17 systemd
    2 root      20   0       0      0      0 S  0.0  0.0   0:00.00 kthreadd
    3 root      20   0       0      0      0 S  0.0  0.0   0:00.02 ksoftirqd/0
    5 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 kworker/0:0H
    6 root      20   0       0      0      0 S  0.0  0.0   0:00.04 kworker/u2:0
    7 root      20   0       0      0      0 S  0.0  0.0   0:00.07 rcu_sched
    8 root      20   0       0      0      0 S  0.0  0.0   0:00.00 rcu_bh
    9 root      rt   0       0      0      0 S  0.0  0.0   0:00.00 migration/0
   10 root      rt   0       0      0      0 S  0.0  0.0   0:00.00 watchdog/0
   11 root      20   0       0      0      0 S  0.0  0.0   0:00.00 kdevtmpfs
   12 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 netns
   13 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 perf
   14 root      20   0       0      0      0 S  0.0  0.0   0:00.00 khungtaskd
   15 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 writeback
   16 root      25   5       0      0      0 S  0.0  0.0   0:00.00 ksmd
   17 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 crypto

ctrl-A d を入力してホストに戻ります。次に以下のコマンドを入力して2番目のゲストを起動します。セッション名は「Guest91」と指定します。イメージファイル、MACアドレス、tap1 の部分が前のGuest90と異なっていることに注意して下さい。

jun@xerus:~/kvm1604$ screen -S Guest91
jun@xerus:~/kvm1604$ sudo kvm -m 512 -boot c -nographic \
    -drive file=u1604B.qcow2,if=virtio \
    -net nic,macaddr=52:54:00:12:34:5B,model=virtio \
    -net tap,ifname=tap1,script=/etc/qemu-ifup

2つ目の仮想マシンも10秒程度で起動します。

Ubuntu 16.04 LTS Guest91 ttyS0

Guest91 login: jun
Password: 
Last login: Thu May  5 18:16:32 JST 2016 on ttyS0
Welcome to Ubuntu 16.04 LTS (GNU/Linux 4.4.0-21-generic x86_64)

 * Documentation:  https://help.ubuntu.com/

0 packages can be updated.
0 updates are security updates.


jun@Guest91:~$ 

Guest90と同様にGuest91でも「top」を起動しておきます。

top - 23:55:22 up 3 min,  1 user,  load average: 0.15, 0.37, 0.19
Tasks: 136 total,   1 running, 135 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.0 us,  1.0 sy,  0.0 ni, 97.0 id,  2.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :   500192 total,   212128 free,    53096 used,   234968 buff/cache
KiB Swap:   522236 total,   522236 free,        0 used.   396288 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND     
 1249 jun       20   0   41788   3700   3108 R  1.0  0.7   0:00.07 top         
    1 root      20   0   38144   6132   3920 S  0.0  1.2   0:02.38 systemd     
    2 root      20   0       0      0      0 S  0.0  0.0   0:00.00 kthreadd    
    3 root      20   0       0      0      0 S  0.0  0.0   0:00.02 ksoftirqd/0 
    4 root      20   0       0      0      0 S  0.0  0.0   0:00.00 kworker/0:0 
    5 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 kworker/0:0H
    6 root      20   0       0      0      0 S  0.0  0.0   0:00.02 kworker/u2:0
    7 root      20   0       0      0      0 S  0.0  0.0   0:00.05 rcu_sched   
    8 root      20   0       0      0      0 S  0.0  0.0   0:00.00 rcu_bh      
    9 root      rt   0       0      0      0 S  0.0  0.0   0:00.00 migration/0 
   10 root      rt   0       0      0      0 S  0.0  0.0   0:00.00 watchdog/0  
   11 root      20   0       0      0      0 S  0.0  0.0   0:00.00 kdevtmpfs   
   12 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 netns       
   13 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 perf        
   14 root      20   0       0      0      0 S  0.0  0.0   0:00.00 khungtaskd  
   15 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 writeback   
   16 root      25   5       0      0      0 S  0.0  0.0   0:00.00 ksmd        

ctrl-A d を入力してGuest91の画面を切り離し、端末をホストのシェルに切り替えます。ネットワーク越しにSSHで端末を使っている場合に「exit」でシェルを終了して切断しても、ゲストは動作したまま残ります。後日「screen -r セッション名」で元の画面に戻ることができます。


必要な作業が終われば、ctrl-A d を入力してホストに戻ります。ここでログオフして端末を閉じても、screen で動作しているセッションの一覧は「screen -ls」で次のように表示されます。

jun@xerus:~$ screen -ls
There are screens on:
	7302.Guest91	(2016年05月05日 23時51分40秒)	(Detached)
	7166.Guest90	(2016年05月05日 23時47分43秒)	(Detached)
2 Sockets in /var/run/screen/S-jun.

「screen -r Guest90」で最初のゲストの画面を、「screen -r Guest91」で2番目に起動したLinuxのコンソール画面を表示して通常に操作することができます。

                                             +-----------------+
                                             |  ゲスト 0       |
                            +---------+      |                 |
    +-----------------+     | screen  |      |  コンソール画面 |
    | ホスト端末画面  |     | session +------+                 |
    |                 | <---| Guest90 |      |                 |
    |                 |     +---------+      +-----------------+
    |                 |
    |                 |                      +-----------------+
    |                 |     +---------+      |  ゲスト 1       |
    |                 | <---| screen  |      |                 |
    +-----------------+     | session +------+  コンソール画面 |
                            | Guest91 |      |                 |
                            +---------+      |                 |
                                             +-----------------+

このようにゲストのコンソールは screen コマンドのセッションとして残すことができ、必要なときにはいつでも、どこからでもゲストのコンソールを操作することができるようになります。

jun@host:~$ cat start-g0.sh
#!/bin/sh

kvm -m 512 -boot c -nographic -serial stdio -localtime \
    -drive file=u91064s.qcow2,if=virtio,boot=on \
    -net nic,macaddr=52:54:00:12:34:00,model=virtio \
    -net tap,ifname=tap0,script=/etc/qemu-ifup
jun@host:~$ cat start-g1.sh
#!/bin/sh

kvm -m 512 -boot c -nographic -serial stdio -localtime \
    -drive file=u91064sB.qcow2,if=virtio,boot=on \
    -net nic,macaddr=52:54:00:12:34:01,model=virtio \
    -net tap,ifname=tap1,script=/etc/qemu-ifup

screenをスクリプト内で使用

Guest90を screen 内で起動してデタッチするスクリプトです。
jun@xerus:~/kvm1604$ cat start90.sh
#!/bin/sh

screen -S Guest90 -d -m kvm -m 512 -boot c -nographic \
    -localtime -drive file=u1604.qcow2,if=virtio \
    -net nic,macaddr=52:54:00:12:34:5A,model=virtio \
    -net tap,ifname=tap0,script=/etc/qemu-ifup
Guest91を screen 内で起動してデタッチするスクリプトです。
jun@xerus:~/kvm1604$ cat start91.sh
#!/bin/sh

screen -S Guest91 -d -m kvm -m 512 -boot c -nographic \
    -localtime -drive file=u1604B.qcow2,if=virtio \
    -net nic,macaddr=52:54:00:12:34:5B,model=virtio \
    -net tap,ifname=tap1,script=/etc/qemu-ifup

実行権限を与えておきます。

jun@xerus:~/kvm1604$ chmod +x start90.sh 
jun@xerus:~/kvm1604$ chmod +x start91.sh 

実行結果

ホスト側から上記のスクリプトを実行します。

jun@xerus:~/kvm1604$ sudo ./start90.sh
jun@xerus:~/kvm1604$ sudo ./start91.sh 

Guest90とGuest91というセッション名でscreenからkvmが起動していることが確認できます。

jun@xerus:~/kvm1604$ screen -ls
There are screens on:
	7302.Guest91	(05/05/16 23:51:40)	(Detached)
	7166.Guest90	(05/05/16 23:47:43)	(Detached)
2 Sockets in /var/run/screen/S-jun.

接続する場合は 「sudo screen -r Guest90」とします。

jun@xerus:~$ sudo screen -r Guest90
Ubuntu 16.04 LTS Guest90 ttyS0                                                                                               
                                                                                                                             
Guest90 login:                                                                                                               
jun@xerus:~$ sudo screen -r Guest90
Ubuntu 16.04 LTS Guest90 ttyS0                                                                                               
                                                                                                                             
Guest90 login:                                                                                                               

このページの目次