本記事ではKVM仮想化技術を体系的に紹介し、発展の歴史、デプロイ方法、仮想マシン管理、ネットワークモードの構成、コマンドラインによる自動インストールをカバーします。すべてのコマンドはCentOS/RHEL環境で検証済みです。
I. KVMの発展の歴史#
KVM(Kernel-based Virtual Machine)は、今日のクラウドコンピューティング分野における主流の仮想化技術です。その発展の脈絡を理解することで、業界がなぜ最終的にKVMを選択したのかを理解できます。
仮想化技術は大きく二つのカテゴリに分けられます:クローズドソース仮想化(例:VMware、Microsoft Hyper-V)とオープンソース仮想化(例:Xen、KVM)。
初期のオープンソース仮想化の代表はXenでした。AWSとAlibaba Cloudは初期にどちらもXen方式を採用していました。CitrixのXenServerおよびデスクトップクラウド製品FusionAccess(Citrix XenDesktopに対応)もXenをベースにしていました。HuaweiのFusionComputeも6.3バージョン以前はXenを使用していました。
主なマイルストーンは以下の通りです:
- 2008年:Red HatがKVMを買収し、RHEL 5.4で正式にKVMをリリースしました(RHEL 5.0にはXenが搭載されていました)。
- 2010年:OpenStackプロジェクトが誕生しました。Red HatはIBM、Dell、VMware、Cisco、HPなどと共にKVMオープンソースコミュニティを支援し、オープンソースソフトウェア財団の下でエコシステムを構築しました。同時期にCitrixはCloudStackコミュニティを推進していました。
- 2014年:RHEL 5.11がリリースされました(RHEL 5.xシリーズのライフサイクル終了、7年間の技術サポート提供、KVMへの無料アップグレードが可能)。
- 2017年前後:AWSがKVMベースのNitroプラットフォームインスタンスを発表し、Alibaba Cloudおよび世界中の多くのベンダーがKVMを全面的に採用しました。
今日、主要なクラウドサービスプロバイダーの仮想化基盤は基本的にKVMです。HuaweiのFusionCompute 6.3もXenからKVMに切り替えました。2019年にIBMが約340億ドルでRed Hatを買収し、Ansible、GlusterFS、CephなどのRed Hatエコシステムプロジェクトがその傘下に入りました。これはこの技術路線の価値をさらに裏付けるものです。
II. KVMとは#
KVMはKernel-based Virtual Machineの略です。その核心的な特徴は以下の通りです:
- カーネルのアップグレードが不要:システム自体のカーネルを直接再利用し、各仮想マシンは一つのプロセスとして実行されます。
- 軽量な仮想化プラットフォーム:従来の方式に比べてより軽量で効率的です。
- 統合管理:Xen/KVM仮想化プラットフォームはどちらも統合管理プラットフォームとコマンドラインツールを提供しています。
III. KVMのデプロイ#
1. KVM必要パッケージのインストール#
前提条件:物理マシンのBIOSで仮想化サポートVT-xを有効にします(ほとんどのコンピュータではデフォルトで有効)。VMware内でネストしてインストールする場合は、VMwareの設定でもVT-xサポートを有効にする必要があります。
推奨リソース構成:CPU 4コア、メモリ4GB。
1
2
|
[root@cloud ~]# yum -y groupinstall "Virtualization*"
[root@cloud ~]# systemctl restart libvirtd.service
|
2. グラフィカルな仮想マシンインストール#
本実習ではグラフィカルツールvirt-managerを使用して仮想マシンを作成・インストールします。
注意:グラフィカルウィザードの操作手順は本記事ではスクリーンショットで示しません。本文はコマンドライン操作を主とし、グラフィカルインターフェースは指示に従ってクリックすれば完了します。また、「ホストマシン」とはKVM仮想マシンを実行するマシンを指します。本実習はVMware内でネスト仮想化を行うため、ここでのホストマシンは物理マシンではなくVMware仮想マシンです。
まずシステムインストールイメージを準備します:/isosディレクトリを作成し、CentOS 8.4のISOファイルをコピーします。
1
|
[root@cloud ~]# mkdir /isos
|
グラフィカル管理インターフェースを起動します:
1
|
[root@cloud ~]# virt-manager
|
インターフェースで新規仮想マシンの作成をクリックし、/isosに配置したISOをインストールソースとして選択し、ウィザードに従ってCPU、メモリ、ディスクを構成すればインストールが完了します。インストールされた仮想マシンのディスクファイルはデフォルトで/var/lib/libvirt/images/ディレクトリにserver1.qcow2のような名前で保存されます:
1
2
3
|
[root@cloud ~]# cd /var/lib/libvirt/images/
[root@cloud images]# ls
server1.qcow2
|
3. ディスクの作成#
前のステップのグラフィカルインストール時にvirt-managerが自動的にディスクを作成します。ここでは手動作成の方法を紹介します。これは後でクラウドイメージの作成や仮想マシンへのディスク追加で使用します。qemu-imgを使用してqcow2形式のディスクを作成します:
1
|
[root@cloud ~]# qemu-img create -f qcow2 -o preallocation=metadata /var/lib/libvirt/images/server1.qcow2 10g
|
ヒント:この方法でクラウドイメージを作成する場合、容量が小さいほど作成速度が速くなります。イメージを最小化する方法を研究することをお勧めします。通常、システムディスクは高い性能を要求しません。本当の性能のボトルネックはデータディスクにあります。
4. ブリッジモードの作成(アップリンク付き仮想スイッチ)#
ネットワーク構成ディレクトリに移動し、既存のネットワークインターフェースをベースにブリッジ構成をコピーします:
1
2
|
[root@cloud ~]# cd /etc/sysconfig/network-scripts/
[root@cloud network-scripts]# cp ifcfg-ens33 ifcfg-br0
|
ブリッジインターフェースifcfg-br0の編集:
1
|
[root@cloud network-scripts]# cat ifcfg-br0
|
1
2
3
4
5
6
7
8
|
TYPE=Bridge
NAME=br0
DEVICE=br0
ONBOOT=yes
IPADDR=192.168.8.99
PREFIX=24
GATEWAY=192.168.8.254
DNS1=192.168.8.254
|
物理インターフェースifcfg-ens33をbr0にブリッジするよう編集:
1
|
[root@cloud network-scripts]# cat ifcfg-ens33
|
1
2
3
4
5
|
TYPE=Ethernet
NAME=ens33
DEVICE=ens33
ONBOOT=yes
BRIDGE=br0
|
ネットワーク構成を再読み込みし、接続を再起動します:
1
2
3
|
[root@cloud ~]# nmcli connection reload
[root@cloud ~]# nmcli connection down ens33 ; nmcli connection up ens33
[root@cloud ~]# nmcli connection down br0 ; nmcli connection up br0
|

5. クラウドイメージの作成#
要件:カスタムクラウドマシンイメージを作成します。
KVM仮想マシンのデプロイ完了後、仮想マシンに入って必要なソフトウェアをインストールします:
- ローカルyumリポジトリの構成
- 必要なパッケージのインストール:
1
|
# yum -y install net-tools vim-enhanced bash-completion cloud-init
|
/etc/cloud/cloud.cfg構成ファイルを編集し、実際の要件に応じてパラメータを調整
/etc/ssh/ssh_host*を削除
init 0でシャットダウン
最後にイメージを圧縮します:
1
|
[root@cloud images]# qemu-img convert -c -O qcow2 /var/lib/libvirt/images/server1.qcow2 /isos/server1.qcow2
|
IV. KVMの管理#
virsh対話型インターフェースに入ります:
主な仮想マシン管理コマンドは以下の通りです。
すべての仮想マシンの一覧表示:
1
2
3
4
|
[root@cloud ~]# virsh list --all
Id Name State
-------------------------
- server1 shut off
|
仮想マシンの起動 / シャットダウン / 強制終了 / 再起動:
1
2
3
4
|
[root@cloud ~]# virsh start server1
[root@cloud ~]# virsh shutdown server1
[root@cloud ~]# virsh destroy server1
[root@cloud ~]# virsh reboot server1
|
6. 仮想マシンコンソールインターフェースへのアクセス#
KVM仮想マシンに入り、仮想マシンに仮想コンソールを追加することで、ホストマシンからコンソール方式で仮想マシンにアクセスできます。
仮想マシン内でgrub構成を編集:
1
|
[root@VM1 ~]# vim /etc/default/grub
|
GRUB_CMDLINE_LINUXの末尾にconsole=ttyS0を追加:
1
|
GRUB_CMDLINE_LINUX="crashkernel=auto resume=UUID=94e88e69-fad6-4d1f-99cf-0ba83cc793b5 rhgb quiet console=ttyS0"
|
grub構成を再生成し再起動:
1
2
|
[root@VM1 ~]# grub2-mkconfig -o /boot/grub2/grub.cfg
[root@VM1 ~]# reboot
|
ホストマシンからコンソールに接続:
1
|
[root@cloud ~]# virsh console server1
|
コンソールを終了するショートカットキーはCtrl + ]です。
7. 構成による仮想マシンへのディスク追加#
(1) ディスクファイルの作成:
1
|
[root@cloud images]# qemu-img create -f qcow2 -o preallocation=metadata /var/lib/libvirt/images/disk2.qcow2 5g
|
(2) 構成ファイルでディスクを追加:
1
|
[root@cloud ~]# vim /etc/libvirt/qemu/server1.xml
|
構成に以下のdiskセクションを追加:
1
2
3
4
5
6
|
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='/var/lib/libvirt/images/disk2.qcow2'/>
<target dev='vdb' bus='virtio'/>
<address type='pci' domain='0x0000' bus='0x07' slot='0x00' function='0x0'/>
</disk>
|
サービスを再起動し仮想マシンを起動:
1
2
3
|
[root@cloud ~]# systemctl restart libvirtd.service
[root@cloud ~]# virsh start server1
[root@cloud ~]# virsh console server1
|
KVM仮想マシン内でディスクを確認:
1
2
3
|
[root@localhost ~]# fdisk -l
/dev/vda
/dev/vdb
|
比較:Xen仮想化ではディスクデバイス名は/dev/xvda、/dev/xvdbです。
8. KVM仮想マシンの迅速な作成#
既存の仮想マシンのXML構成をコピーして迅速に作成:
1
2
3
4
|
[root@cloud qemu]# cp server1.xml server2.xml
[root@cloud qemu]# uuidgen
f3ccabc3-ca4c-41f2-8d6f-e99077c24eeb
[root@cloud qemu]# vim server2.xml
|
name、uuid、ディスクパス、MACアドレスなどの主要パラメータを変更:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
<domain type='kvm'>
<name>server2</name>
<uuid>f3ccabc3-ca4c-41f2-8d6f-e99077c24eeb</uuid>
<metadata>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='/isos/server1.qcow2'/>
<target dev='vda' bus='virtio'/>
<address type='pci' domain='0x0000' bus='0x04' slot='0x00' function='0x0'/>
</disk>
<interface type='bridge'>
<mac address='52:54:00:96:f6:a2'/>
<source bridge='br0'/>
<model type='virtio'/>
<address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/>
</interface>
|
サービスを再起動し新しい仮想マシンを起動:
1
2
3
|
[root@cloud ~]# systemctl restart libvirtd.service
[root@cloud ~]# virsh start server2
[root@cloud ~]# virsh list --all
|
V. KVMネットワーク構成#
KVMには一般的に3つのネットワークモードがあります:NATモード、ホストオンリーモード(Host-Only)、ブリッジモード。
1. NATモード#
iptablesのアドレスマスカレードでNATを実現します:
1
|
# iptables -t nat -A POSTROUTING -s 192.168.122.0/24 ! -d 192.168.122.0/24 -j MASQUERADE
|
またはSNATでソースアドレスを指定:
1
|
# iptables -t nat -A POSTROUTING -s 192.168.122.0/24 ! -d 192.168.122.0/24 -j SNAT --to-source 192.168.8.99
|

NATルールの確認:
1
|
[root@cloud ~]# iptables -t nat -nL
|
デフォルトのネットワーク構成ファイルは/etc/libvirt/qemu/networksにあります:
1
2
3
|
[root@cloud networks]# pwd
/etc/libvirt/qemu/networks
[root@cloud networks]# vim default.xml
|
2. ホストオンリーモード#
ホストオンリーモードでは、仮想マシンはホストマシンとのみ通信でき、外部ネットワークにはアクセスできません。

3. KVM仮想マシンからのインターネットアクセスの有効化#
(1) VMwareホストマシンにインターネットアクセス可能なネットワークインターフェースを追加します。
(2) ホストマシンのOSに入り、デュアルブリッジを構成します。
ifcfg-br0(内部ネットワークブリッジ):
1
2
3
4
5
6
|
TYPE=Bridge
NAME=br0
DEVICE=br0
ONBOOT=yes
IPADDR=192.168.8.99
PREFIX=24
|
ifcfg-br1(外部ネットワークブリッジ、DHCP):
1
2
3
4
5
|
TYPE=Bridge
NAME=br1
DEVICE=br1
ONBOOT=yes
BOOTPROTO=dhcp
|
ifcfg-ens33をbr0にブリッジ:
1
2
3
4
5
|
TYPE=Ethernet
NAME=ens33
DEVICE=ens33
ONBOOT=yes
BRIDGE=br0
|
ifcfg-ens37をbr1にブリッジ:
1
2
3
4
5
|
TYPE=Ethernet
NAME=ens37
DEVICE=ens37
ONBOOT=yes
BRIDGE=br1
|
サービスを再起動し仮想マシンをシャットダウン:
1
2
3
4
5
|
[root@cloud ~]# systemctl restart libvirtd.service
[root@cloud ~]# virsh shutdown server1
Domain server1 is being shutdown
[root@cloud ~]# virsh shutdown server2
Domain server2 is being shutdown
|
KVM内のserver1仮想マシンのネットワークインターフェースをbr1にブリッジするよう変更し、VM1内でIP取得方式をDHCPに変更:
1
2
3
4
5
6
7
8
9
10
11
|
[root@VM1 ~]# nmcli connection modify enp1s0 ipv4.method auto autoconnect yes
[root@VM1 ~]# nmcli connection down enp1s0 ; nmcli connection up enp1s0
[root@VM1 ~]# ifconfig
enp1s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.31.158 netmask 255.255.255.0 broadcast 192.168.31.255
inet6 fe80::5054:ff:fe96:f6a1 prefixlen 64 scopeid 0x20<link>
ether 52:54:00:96:f6:a1 txqueuelen 1000 (Ethernet)
RX packets 1253 bytes 279527 (272.9 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 119 bytes 17932 (17.5 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
|
外部ネットワーク接続のテスト:
1
2
3
4
5
|
[root@VM1 ~]# ping www.baidu.com
PING www.a.shifen.com (183.2.172.17) 56(84) bytes of data.
64 bytes from 183.2.172.17 (183.2.172.17): icmp_seq=1 ttl=52 time=23.6 ms
64 bytes from 183.2.172.17 (183.2.172.17): icmp_seq=2 ttl=52 time=24.3 ms
64 bytes from 183.2.172.17 (183.2.172.17): icmp_seq=3 ttl=52 time=23.5 ms
|
VI. コマンドラインによるKVM仮想マシンのインストール#
kickstart自動インストールスクリプトを活用することで、無人での仮想マシンの一括インストールが可能です。
1. ディスクの作成#
1
|
[root@cloud images]# qemu-img create -f qcow2 -o preallocation=metadata /var/lib/libvirt/images/server3.qcow2 10g
|
2. 自動インストール#
virt-installでインストールソースとkickstartファイルを指定:
1
2
3
4
5
|
[root@cloud ~]# virt-install -n server3 --memory 2048 --vcpu 2 \
--disk /var/lib/libvirt/images/server3.qcow2 \
--network bridge=br1 \
-l http://192.168.31.96/pub \
-x inst.ks=http://192.168.31.96/ks/ks01.cfg --vnc
|
kickstart構成ファイルks01.cfgの例:
1
|
# vim /var/www/html/ks/ks01.cfg
|
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
|
#version=RHEL8
# Use text install for fully unattended
text
repo --name="AppStream" --baseurl=http://192.168.0.107/pub/AppStream
repo --name="BaseOS" --baseurl=http://192.168.0.107/pub/BaseOS
reboot
%packages
@^minimal-environment
kexec-tools
%end
# Keyboard layouts
keyboard --xlayouts='us'
# System language
lang en_US.UTF-8
# Network information
network --bootproto=dhcp --activate --hostname=server3 --onboot=yes
# Use network installation media
url --url=http://192.168.0.107/pub/BaseOS
# Run the Setup Agent on first boot
firstboot --disable
ignoredisk --only-use=vda
clearpart --all --initlabel
autopart
# System timezone
timezone Asia/Shanghai --utc
# Root password
rootpw --iscrypted $6$c31XqEglO8ECIli0$enF8T.LW3OknT.178Vb9m2HHYD6dqRdKF2QZia5.G5Tv/zMD//04S2h61oBOKihJZwPIUmWxLc7oXuWtkHQy10
user --name=admin --password=$6$Ey847S5bcqYg8ktk$sd4BJeFF01IFsGOaFwRoqXoYuZ5H1RV3bLC6n6gQGa1tNAjplFDhTnm3Cjw2pgwltIE.xr27X7E/ro4gF2JSG1 --iscrypted --gecos="admin"
%addon com_redhat_kdump --enable --reserve-mb='auto'
%end
%anaconda
pwpolicy root --minlen=6 --minquality=1 --notstrict --nochanges --notempty
pwpolicy user --minlen=6 --minquality=1 --notstrict --nochanges --emptyok
pwpolicy luks --minlen=6 --minquality=1 --notstrict --nochanges --notempty
%end
|
注意:上記のインストールソースアドレス(192.168.0.107)、ホスト名(server3)、およびrootpw、userの後のパスワードハッシュは例です。実際の使用時はご自身の環境のアドレスと生成したパスワード暗号文に置き換えてください。