KVMから始めるサーバー仮想化入門
エンジニアブログ第二回目となる今回は、サーバーの仮想化について紹介したいと思います。
仮想化とは
仮想化とは、簡単に言うと「物理的に無いものを有るように見せる」技術のことです。
一般的に広く使用されている仮想化技術は、CD/DVDドライブの仮想化ではないでしょうか。
CD/DVDドライブの無いPCで、仮想CD/DVDドライブを使ってisoファイルを再生したことがある人も多いと思います。
つまり、今回扱うサーバー仮想化とは「物理的に無いサーバーを有るように見せる」技術のことで、運用的には1台の物理サーバーの上で複数のOSを動かすことになります。
KVMとは
KVMとは、Kernel-based Virtual Machineの略のことで、Linuxカーネル 2.6.20 以降に標準搭載されている仮想化環境を利用するためのソフトウェアです。
ハイパーバイザType1型(KVMはホストOSに組み込まれているのでType2のホストOS型に分類されるという意見もある)で、ハードウェア側のエミュレーションはQEMUが担当しています。
開発元のQumranet社は、主要LinuxディストリビューションのRHELの開発元であるRed Hat社が2008年に買収しています。
KVM導入方法
1.ネットワーク(bridgeの設定)
特にネットワークの設定をせずにKVMをインストールすると、母艦の下のネットワーク(192.168.122.*)に、ゲストOSが入る感じになり、ゲストOSが母艦のネットワーク(192.168.5.*)に直接アクセスできなくなります。
イメージ的にはこんな感じになります。
これだと不便なので、bridgeを作ってゲストOSを母艦の192.168.5.*のネットワークに入れておきます。
イメージ的にはこんな感じになります。
設定手順
環境
母艦OS:CentOS 6.6 Minimal
※NetWorkManagerとかiptablesとかSELinuxは切っておきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
[user@localhost ~]$ ssh user@母艦 [user@母艦 ~]$ sudo vi /etc/sysconfig/network-scripts/ifcfg-br0 DEVICE=br0 TYPE=Bridge ONBOOT=yes IPADDR=192.168.5.50 //母艦のIPを決めて入れる NETWORK=192.168.5.0 //適宜変更 NETMASK=255.255.255.0 //適宜変更 NM_CONTROLLED=no BOOTPROTO=static [user@母艦 ~]$ sudo vi /etc/sysconfig/network-scripts/ifcfg-eth0 DEVICE=eth0 HWADDR=0B:A4:7C:02:B4:90 TYPE=Ethernet UUID=e66427c9-1802-4c56-80c2-8a442480e9a7 ONBOOT=yes NM_CONTROLLED=no BOOTPROTO=none BRIDGE=br0 [user@母艦 ~]$sudo service network restart |
2.KVMに必要なパッケージをインストール
1 |
[user@母艦 ~]$ sudo yum groupinstall Virtualization "Virtualization Platform" "Virtualization Client" |
3.ゲストOSインストール
母艦の上で動作するOSをインストールします。
基本はターミナルからvirt-installで進めるので、CUIベースでインストールすることになります。
GUIを使ってインストールすることも可能ですが、日本語パッケージやXウィンドウシステムなどを使用できるようにしておかないといけません。
CUIの場合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
[user@母艦 ~]$ wget http://ftp.tsukuba.wide.ad.jp/Linux/centos/6.8/isos/x86_64/CentOS-6.8-x86_64-minimal.iso /tmp/ [user@母艦 ~]$ sudo virt-install \ --name=centos6 \ --vcpus=1 \ --ram=1000 \ --autostart \ --disk=/var/lib/libvirt/images/centos6,format=qcow2,size=10,bus=virtio \ --network=bridge:br0 \ --arch=x86_64 \ --os-type=linux \ --os-variant=rhel6 \ --location /tmp/CentOS-6.8-x86_64-minimal.iso \ --graphics none,keymap=ja \ --extra-args='console=tty0 console=ttyS0,115200n8' |
各オプションの意味
–name virshコマンドやvirt−managerなど管理ツールで管理する仮想サーバーの名前
–vcpus 割り当てるCPUの数
–ram 割り当てるメモリ(MB)
–autostart 母艦が起動したらゲストも自動で起動する
–disk インストールしたOSのイメージファイルの場所、フォーマット、
サイズ(GB)、使用するDISKバスドライバ
–network ネットワークタイプ
–arch シミュレートする CPU アーキテクチャー
–os-type ゲストOSのOSタイプを指定
–os-variant ゲストOSの種類を指定
–location インストールメディアの場所
–graphics none,keymap=ja グラフィックスを使用しない,日本語キーボードタイプ
–extra-args インストール時にカーネルに渡すパラメータを指定(上の例はシリアルコンソール接続設定)
あとは画面(ターミナル)の表示に従ってキーボードのspaceとEnterとtabで進めていけばOKです。
コンソールを抜けたい時はcontrol+](Mac日本語キーボードの場合)
再接続したい場合は
1 2 |
[user@母艦 ~]$ sudo virsh list --all [user@母艦 ~]$ sudo virsh console Id番号 |
ゲストOSを再起動するとコンソールに繋がらなくなるので、インストール時に使用したシリアルコンソールのオプションなどを起動設定に追加しておきます。
1 2 3 4 5 6 7 8 9 10 |
[user@母艦 ~]$ cat /etc/grub.conf default=0 timeout=5 splashimage=(hd0,0)/grub/splash.xpm.gz hiddenmenu serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1 terminal --timeout=5 serial console title CentOS (2.6.88-888.8.3.el6.x86_64) root (hd0,0) kernel /vmlinuz-2.6.88-888.8.3.el6.x86_64 ro root=UUID=d303f45a-58c9-4b6e-adf4-27d10fa80bac rd_NO_LUKS LANG=en_US.UTF-8 rd_NO_MD SYSFONT=latarcyrheb-sun16 KEYBOARDTYPE=pc KEYTABLE=jp106 rd_NO_LVM crashkernel=auto rhgb quiet rd_NO_DM rhgb quiet console=tty0 console=ttyS0,115200n |
GUIの場合
ローカルPCがMacの場合はXQuartzを入れます。
https://www.xquartz.org/
ローカルPCがWinの場合は、sshクライアントソフトウェアのX転送を設定します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
[user@母艦 ~]$ sudo yum install xauth //踏み台サーバーなど、母艦にログインするまでに経由するサーバー全てに入れます。 [user@母艦 ~]$ echo $DISPLAY //こんな感じで$DISPLAYが割り当てられればOKです。 localhost:10.0 [user@母艦 ~]$ sudo yum groupinstall "Japanese Support" //GUIの文字化け対策に日本語パッケージを入れます。 [user@母艦 ~]$ sudo vi /etc/libvirt/libvirtd.conf //一般ユーザーでGUIが起動できない場合があるので設定します。 auth_unix_rw = "none" unix_sock_group = "libvirt" unix_sock_rw_perms = "0770" [user@母艦 ~]$ sudo groupadd libvirt [user@母艦 ~]$ sudo usermod -a -G libvirt GUIを起動したいユーザー名 [user@母艦 ~]$ sudo service libvirtd restart //一旦ローカルまでログアウトし、再度sshにX11転送オプションをつけてログイン(経由するサーバー全てで-Yオプションをつけてsshする) [user@localhost ~]$ ssh user@母艦 -Y [user@母艦 ~]$ virt-manager |
こんな感じのGUIが起動します。
あとはGUI左上の「新規」ボタンからOSを新規インストールします。
KVM運用方法
ゲストOSをコピーする
ネットワークの設定まで全く同じ状態でコピーされてしまうので、クローンOSはネットワーク設定がオリジナルと全く同じ状態で起動してしまいます。
オリジナルのOSが起動していればIPが割り振られないだけで済みますが、オリジナルが起動していない時は、オリジナルと同じIPが割り振られるので混乱や不具合の原因になるかも知れません。
コピー前にネットワークの設定を外した状態にして、コピー元のOSをシャットダウンするのがオススメです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
//オリジナルのネットワーク設定をコメントアウト [user@コピー元 ~]$ sudo vi /etc/sysconfig/network-scripts/ifcfg-eth0 //ファイル名は適宜変更してください。 DEVICE="eth0" HWADDR=52:54:40:17:98:04 BOOTPROTO="none" NM_CONTROLLED="no" ONBOOT="yes" TYPE="Ethernet" UUID="af7af043-b223-4bac-9f4a-85d325dee237" #IPADDR="192.168.5.55" #NETMASK="255.255.255.0" #NETWORK="192.168.5.0" #GATEWAY="192.168.5.254" //オリジナルをシャットダウン [user@コピー元 ~]$ sudo halt -p //次の項目の「コピー方法」の3つの手順のどれかでオリジナルOSをコピーします。 //クローンOSを起動する [user@母艦~]$ sudo virsh start クローンOS //コンソールからクローンOSにログインし、ネットワーク設定をします。 [user@母艦 ~]$ sudo virsh list --all [user@母艦 ~]$ sudo virsh console Id番号 [user@クローンOS~]$ sudo ifconfig -a eth1 Link encap:Ethernet HWaddr 52:44:40:14:98:00 BROADCAST MULTICAST MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:0 (0.0 b) TX bytes:0 (0.0 b) 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:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:0 (0.0 b) TX bytes:0 (0.0 b) //etc/sysconfig/network-scripts/ifcfg-eth0のHWADDRの部分を上記eth1のHWaddrのmacアドレスで置き換えます。 [user@クローンOS~]$ sed -i "s/$(cat /etc/sysconfig/network-scripts/ifcfg-eth0 |grep HW|cut -d "=" -f 2)/$(ifconfig -a|grep eth1 |awk '{print $NF}')/g" /etc/sysconfig/network-scripts/ifcfg-eth0 //被っていないIPアドレスを割り当てます。 [user@クローンOS~]$ sudo vi /etc/sysconfig/network-scripts/ifcfg-eth0 //udevの古いネットワーク設定を削除します。 [user@クローンOS~]$ sudo rm /etc/udev/rules.d/70-persistent-net.rules //OS再起動、もしくはドライバを再読み込みします。 [user@クローンOS~]$ sudo rmmod virtio_net [user@クローンOS~]$ sudo modprobe virtio_net //疎通確認できたらオリジナルを起動します。 //オリジナルのネットワーク設定を元に戻します。 |
コピー方法
virt-cloneを使う場合
1 2 3 4 5 6 |
//コピー元のOSがシャットダウンしているのを確認します [user@母艦 ~]$ sudo virsh list --all Id 名前 状態 ---------------------------------------------------- 19 ORIGINAL シャットオフ [user@母艦 ~]$ sudo virt-clone --original ORIGINAL --name CLONE --file /var/lib/libvirt/images/CLONE |
virt-managerを使う場合
対象のVirtualMachine(以降VM)を右クリックし、「クローン(C)…」を選択。 あとはGUIに従って入力していくだけです。
bashでなんとかする場合
対象のVMのOSイメージをコピーし、引っ越し先でimportするだけです。
1 2 3 4 5 6 7 8 9 10 11 12 |
[user@母艦 ~]$ sudo cp /var/lib/libvirt/images/ORIGINAL /var/lib/libvirt/images/CLONEImage [user@母艦 ~]$ sudo virt-install --connect qemu:///system \ --name CLONE \ --import \ --autostart \ --disk path=/var/lib/libvirt/images/CLONEImage,bus=virtio \ --ram 1000 \ --network bridge:br0,model=virtio \ --vcpus 2 \ --arch=x86_64 \ --os-type=linux \ --os-variant=rhel6 |
コピー時の注意点
上記「bashでなんとかする場合」では、OSイメージのファイル形式に気をつける必要があります。
不具合:コピー先のファイル容量が元ファイルの何倍にも膨れ上がる場合があります。
原因:コピー元のファイル形式がraw形式(KVMのデフォルト)の場合、raw形式がsparseファイルであることが原因です。
対策:回避するにはコピーコマンドにオプションをつけたり、圧縮するときにオプションつける必要があります。
1 |
[user@母艦 ~]$ sudo cp -p --sparse=always ORIGINAL CLONE |
以上で基本的な運用は可能になると思います。
あとがき
1台の物理サーバー上で複数のOSを動かすことは、リソースの有効活用といった観点からも必須になりつつあると思っています。
OSイメージをコピーして、お手軽にテスト環境を用意したり、負荷分散の台数を稼いだりバックアップが取れるのは、大変便利です。
VMwareやXen、VirtualBoxやDockerなど、仮想サーバーはKVMに限らず構築可能ですが、仮想サーバーを構築するならlinuxに標準採用されたKVMを是非一度は触れてもらいたいと思います。