[[PageOutline]] = KVMメモ = このページは、kvmをlibvirt(virsh)で使いたい人向けのメモです。簡単に使いたい人は、virt-managerを使ってください。 == 準備 == === Fedora/CentOS === kvmを利用するのに、libvirtを利用します。libvirtをインストールしておきます。virt-managerをインストールすると必要なパッケージが一通り入って便利です。また、kvmで仮想マシンを実行するのに必要なqemu-kvmもインストールしておきます。 {{{ # yum install virt-manager # yum install qemu-kvm }}} 次に、kvmのモジュールをカーネルにロードします。AMDの場合は、kvm_intelの代わりにkvm_amdを使ってください。 {{{ # modprobe kvm # modprobe kvm_intel }}} libvirtを利用するには、libvirtdの起動が必要です。libvirtdを起動しておきます。 {{{ # /etc/init.d/libvirtd start }}} その他、下記のパッケージを入れておくとよいかもしれません。 {{{ # yum install virt-top # yum install qemu-kvm-tools }}} CentOS6.4を利用する場合、下記のフォルダにあるqemu-kvm-rhev(RHEV用のパッケージ)を利用するとよいです。スナップショットなどの標準のqemuでは利用できない機能が利用できます。 * http://www.dreyou.org/ovirt/vdsm32/Packages/ === Ubuntu === {{{ # apt-get install qemu-kvm virt-manager # apt-get install virt-top }}} Ubuntu 12.04 LTSのqemu/libvirtの最新パッケージは、Ubuntu Cloud Archiveにあります。 /etc/apt/source.listに下記のapt-lineを追加してqemu/libvirt-binパッケージをインストールしてください。 {{{ deb http://ubuntu-cloud.archive.canonical.com/ubuntu precise-updates/havana main }}} == virshを利用したKVM仮想マシンの作り方 == === イメージ作成 === {{{ # qemu-img create -f raw ubuntu.img 10G }}} === libvirt XMLファイルの作成方法 === 下記のXMLを適当に編集。特に、 * name(他の仮想マシンとユニークな名前になるように) * memory(メモリ容量) * vcpu(CPUの数) * diskとcdromのsource file * acpiを有効にしないと、virshからshutdownコマンドでシャットダウンできない。 * mac addressを他と被らないように 辺りに注意しておく。下記は、Fedora13の例。 {{{ UbuntuVM 524288 524288 1 hvm /usr/bin/qemu-kvm }}} Ubuntuの場合は、typeタグのmachineをpcなどにする。 {{{ ... hvm ... }}} === virshに登録して起動 === {{{ # virsh (virsh実行。以下、virshのコンソールで実行) virsh # define virt-kvm.xml }}} defineで仮想マシンを定義したXMLを登録すると、/etc/libvirt/qemuディレクトリにDomain名のファイルで定義ファイルが作られる。 {{{ # ls /etc/libvirt/qemu UbuntuVM.xml networks }}} 起動と起動状態の確認は、次の通りです。 {{{ virsh # start UbuntuVM virsh # list Id 名前 状態 ---------------------------------- 1 UbuntuVM 実行中 }}} VNCクライアントのスクリーン1で接続可能(!vnc://localhost:1)です。vncのポートなどは、次の行で設定します。 {{{ }}} デフォルトでは、仮想マシンを起動したホスト以外からのVNCクライアントの接続を受け付けないようになっています。'''ホストマシンとは別のマシンからvncで接続するには、/etc/libvirt/qemu.confに次の設定を追加します'''。 {{{ vnc_listen = "0.0.0.0" }}} '''Windowsでvncを利用する場合カーソルがずれます'''。inputデバイスの設定を次のように変更してください。 {{{ }}} 停止はshutdownを使います。 {{{ virsh # shutdown UbuntuVM }}} '''acpiが有効になっていないと、virshからのシャットダウンを受け付けない'''ので注意してください。また、linuxの場合、acpidをインストール/起動しておく必要があります。ubuntu serverの場合デフォルトではインストールされないので、 {{{ # apt-get install acpid }}} としてacpidをインストールします。 ハイバネートとレジューム {{{ virsh # save UbuntuVM UbuntuVM.mem virsh # restore UbuntuVM UbuntuVM.mem }}} == Windows利用時に注意 == === libvirt xmlを記述するときの注意 === * clock offsetをlocaltimeにしないと時間がずれます。 * acpiを有効にしないと、Windows7以降でインストールできません。 * inputデバイスをtabletにしないと、VNCで接続したときにカーソルの動きが変になります。 === Windowsゲストドライバ === Windowsゲストドライバを利用すると、ネットワークI/OやディスクI/Oが速くなります。 ゲストドライバの取得とインストール方法は下記のURLを参照。 * [http://www.linux-kvm.org/page/WindowsGuestDrivers Windows guest drivers] == ネットワーク接続 == === ルーティングして接続 === 仮想マシンのIPアドレスから、ホストOSのNICにルーティングして接続します。 * ゲスト側のネットワークを適当設定(例えば192.168.100.2,GWを192.168.100.1)。ネットワークセグメントはホストと別にする。 * ホスト側のネットワークを設定する。 {{{ # ifconfig vnet0 192.168.100.1 netmask 255.255.255.0 }}} IPフォワードの設定をしていなければ、IPフォワードの設定を行う。 {{{ # echo 1 > /proc/sys/net/ipv4/ip_forward }}} 図で説明すると、上記の設定で次のようなネットワークが構築できる。 {{{ eth0:10.9.123.3 +--------------+ +---------------+ +--+-+ +-+---+ +--+-+ | LAN---|eth0| ホストOS |vnet0|-----|eth0| 仮想マシン | +--+-+ +-+---+ +--+-+ | +--------------+ +---------------+ vnet0:192.168.100.1 eth0:192.168.100.2 }}} == NATによるLAN上のIPからの接続 == プライベートIPをeth0に割り振り、NATで接続します。 {{{ eth0:10.8.99.6,10.8.99.7(NATで192.168.100.2に接続) +--------------+ +---------------+ +--+-+ +-+---+ +--+-+ | LAN---|eth0| ホストOS |vnet0|-----|eth0| 仮想マシン | +--+-+ +-+---+ +--+-+ | +--------------+ +---------------+ vnet0:192.168.100.1 eth0:192.168.100.2 }}} * eth0に10.8.99.6でアクセスするとホストOSに接続。 * eth0に10.8.99.7でアクセスすると仮想マシン(192.168.100.2)に接続。 するように設定してみる。普通にeth0に10.8.99.6を設定しておく。 次に10.8.99.7へのアクセスを192.168.100.2に転送するNAT用のnat.iptファイルを用意する。 {{{ *nat :PREROUTING ACCEPT [5318:237514] :POSTROUTING ACCEPT [162:9112] :OUTPUT ACCEPT [14132:847744] -A PREROUTING -d 10.8.99.7 -j DNAT --to-destination 192.168.100.2 -A POSTROUTING -d 192.168.100.0/255.255.255.0 -j MASQUERADE -A POSTROUTING -s 192.168.100.2 -j SNAT --to-source 10.8.99.7 -A OUTPUT -d 10.8.99.7 -j DNAT --to-destination 192.168.100.2 COMMIT }}} NATを読み込む。 {{{ # cat nat.ipt | iptables-restore }}} eth0に10.8.99.7を割り振らないとLAN上のマシンからアクセスできないので、ipコマンドでNICにIPを割り振っておきます。 {{{ # ip addr add 10.8.99.7 dev eth0 }}} === ブリッジによるホストのNICと同じセグメントへの設定 === ホストIPアドレスが192.168.1.5で、仮想マシンのIPアドレスを192.168.1.6のようにホストのNICと同じセグメントのネットワークに仮想マシンを所属させたい場合は、ブリッジを利用します。 {{{ virbr0:192.168.1.5 +--------------+ +---------------+ | +-virbr0+ + | | |+-+---+| +--+-+ | | ホストOS ||vnet0||-----|eth0| 仮想マシン | | |+-+---+| +--+-+ | | | + | | | | |+-+---+| | | | ||eth0 || | | | |+-+--++| | | | +-----|-+ | | +--------------+ | +---------------+ | eth0:192.168.1.6 LAN }}} ※ブリッジを使うのでvnet0とeth0にはIPは振りません。 まず、/etc/network/interfacesに次のように記述し、ブリッジを有効にする。 {{{ auto virbr0 iface virbr0 inet static address 192.168.1.5 netmask 255.255.255.0 network 192.168.1.0 broadcast 192.168.1.255 gateway 192.168.1.1 bridge_ports eth0 }}} eth0を無効にし、ブリッジを有効にする。 {{{ # ifdown eth0 # ifup virbr0 }}} libvirt.xmlのinterface定義にブリッジに含めるように定義 {{{ }}} 仮想マシンを起動すると、ブリッジに含まれた形で起動してくる。 {{{ # brctl show bridge name bridge id STP enabled interfaces virbr0 8000.0016d32ff458 no eth0 vnet0 }}} 下記のようにすると、interfacesに書くことなくテストすることができる。 {{{ # brctl addbr virbr0 # brctl addif virbr0 eth0 # ifconfig virbr0 192.168.1.5 netmask 255.255.255.0 }}} あとは、仮想マシン側のeth0でifconfigでIPアドレスを指定するなどすればok。 === ポートフォワードによる仮想マシンIPを利用したルートコンソールの接続 === 仮想マシンのIPでVNCに接続すると、ブレードサーバのOAのようにルートコンソールが取得できると嬉しくありませんか? ポートフォワードを使うと実現することができます。 例えば、ゲストOSの5900番(VNCのデフォルトポート)をホストOS上の仮想マシンのコンソールのポートに転送するようにすれば、VNCで仮想マシンに接続するとルートコンソールが取れるようになります。 {{{ *nat :PREROUTING ACCEPT [5318:237514] :POSTROUTING ACCEPT [162:9112] :OUTPUT ACCEPT [14132:847744] -A PREROUTING -d 10.8.99.7 -p tcp --dport 5900 -j DNAT --to-destination 10.8.99.6:5900 -A PREROUTING -d 10.8.99.7 -j DNAT --to-destination 192.168.100.2 -A POSTROUTING -d ! 192.168.100.0/255.255.255.0 -j MASQUERADE -A POSTROUTING -s 192.168.100.2 -j SNAT --to-source 10.8.99.7 -A OUTPUT -d 10.8.99.7 -j DNAT --to-destination 192.168.100.2 COMMIT }}} === DHCPでIPを付与 === DHCPでIPを付与するようにするには、/var/lib/libvirt/network/default.xmlを次のように編集します。 {{{ default 631f86c8-5469-468a-a361-3a91d4b99a35 }}} 上記のネットワーク設定ファイルを再設定して、ネットワークを再起動(net-destroy,net-start)します。 {{{ virsh # net-define /var/lib/libvirt/network/default.xml ネットワーク default が /var/lib/libvirt/network/default.xml から定義されました virsh # net-destroy default ネットワーク default は停止されました virsh # net-start default ネットワーク default が起動されました }}} == メモリバルーンニング == メモリバルーニングは、仮想マシンのメモリを動的に増減させます。setmemコマンドで、メモリを変更できます。 ==== ゲスト {{{ $ free total used free shared buffers cached Mem: 485656 229632 256024 0 49528 81960 -/+ buffers/cache: 98144 387512 Swap: 524284 58200 466084 }}} この状態で、ホスト上で下記のコマンドを実行してみます。 ==== ホスト {{{ # virsh setmem DOMNAME 1000000 }}} ゲスト上でfreeを実行すると、メモリが増えているのが分かります。 ==== ゲスト {{{ $ free total used free shared buffers cached Mem: 973656 229792 743864 0 49532 81984 -/+ buffers/cache: 98276 875380 Swap: 524284 58200 466084 }}} メモリを減らすこともできます。 == libvirtから仮想マシンへのルートログイン == libvirtでは、仮想マシンの実際に利用しているメモリなど、細かい情報が取れません。シリアルコンソールでルートログインできるように設定しておくと、ホストOSから状態の監視に使えます。 ※言うまでもないことですが、仮想マシンのユーザがルートコンソールを管理者に取られるのが嫌な場合は、この方法は利用しないでください。 まず、libvirtのXMLファイルを定義して、ゲストのシリアルコンソールを有効にします。 {{{ ... }}} === ゲスト側の設定 ==== grub.cfgを設定 /boot/grub/grub.cfgに下記のようにシリアルコンソールの設定(console...115200n8を追加) {{{ linux /boot/vmlinuz-3.2.0-40-generic \ root=UUID=187b5cde-ed09-4d02-93c3-9c2fc162a97d ro quiet\ console=tty0 console=ttyS0,115200n8 }}} ==== パスワードなしでシリアルログインできるように設定 mingettyをインストール {{{ # apt-get install mingetty }}} /etc/init/ttyS0.confに下記のように設定 {{{ start on stopped rc RUNLEVEL=[2345] and ( not-container or container CONTAINER=lxc or container CONTAINER=lxc-libvirt) stop on runlevel [!2345] respawn exec /sbin/mingetty --autologin root ttyS0 }}} === ホスト側から接続 ゲストを再起動すると、ホスト側から {{{ $ virsh DOMAINNAME console }}} でルートログインできる。 == ネットワーク帯域制限 == ネットワークインタフェース定義の部分で、bandwidthを定義すれば、帯域制限をかけることができる。単位はaverage/peakはkbyte/s。burstはkbyte。 {{{ ... }}} Ubuntuだと、kernel 3.5.0にしないと動作しない。RHEL6などでは多分利用できない。 == QMP == KVM(というかqemu)には、ハイパーバイザからVMのイベントや情報を取得するQMP(Qemu Messaging Protocol)が提供されています。QMPを利用することにより、様々な情報を取得することができます。下記は利用例です。 {{{ # virsh qemu-monitor-command DOMNAME '{"execute":"query-blockstats"}' |python -mjson.tool { "id": "libvirt-27", "return": [ { "device": "drive-virtio-disk0", "parent": { "stats": { "flush_operations": 0, "flush_total_time_ns": 0, "rd_bytes": 0, "rd_operations": 0, "rd_total_time_ns": 0, "wr_bytes": 0, "wr_highest_offset": 3860278784, "wr_operations": 0, "wr_total_time_ns": 0 } }, "stats": { "flush_operations": 0, "flush_total_time_ns": 0, "rd_bytes": 163434496, "rd_operations": 9976, "rd_total_time_ns": 8262845363, "wr_bytes": 13394944, "wr_highest_offset": 10235260416, "wr_operations": 1439, "wr_total_time_ns": 147967748900 } }, { "device": "drive-ide0-1-0", "parent": { "stats": { "flush_operations": 0, "flush_total_time_ns": 0, "rd_bytes": 0, "rd_operations": 0, "rd_total_time_ns": 0, "wr_bytes": 0, "wr_highest_offset": 0, "wr_operations": 0, "wr_total_time_ns": 0 } }, "stats": { "flush_operations": 0, "flush_total_time_ns": 0, "rd_bytes": 49218, "rd_operations": 15, "rd_total_time_ns": 1671233, "wr_bytes": 0, "wr_highest_offset": 0, "wr_operations": 0, "wr_total_time_ns": 0 } } ] } }}} QMPについては、あまりドキュメントが整備されていません。QMPの詳細は、下記のスキーマに記載されています * http://git.qemu-project.org/?p=qemu.git;a=blob;f=qapi-schema.json;hb=HEAD == ログメッセージの出力 == libvirtdのデバッグログを出力するには、/etc/libvirt/libvirtd.confに下記の記述を追加し、libvirtdを再起動する。 {{{ log_level = 1 log_outputs="1:file:/var/log/libvirt/libvirtd.log" }}} == リソース取得 == 下記のvirt-xxxコマンドにより、CPU、メモリ、ディスクのリソースを取得することができます。 ||コマンド||説明|| ||virt-top||仮想マシンのCPU使用率、メモリの使用率を表示|| ||virt-df||仮想マシンのディスクの使用量を表示(Ubuntuではlibguestfs-toolsパッケージを利用)|| ||virt-dmesg|| ??? || == KVMのもうちょっと高度な使い方 == そのうち書く予定 * リソースの取得方法 * iscsiのDISKから起動 * ライブマイグレーション * block migration * pythonからの操作