人生は勉強ブログ

https://github.com/dooooooooinggggg

KVM/QEMU上の仮想マシンに対して,libvmiを使ってみる

環境

やっていくこと

  • libvmiとは
  • KVM/QEMUとは
  • VirtualBoxでNested Virtualizationはできない
  • 仮想化でない(USBブートした)Debianの上で,KVM/QEMUを動かす.
  • libvmiのサンプルプログラムを実行.

libvmiとは

libvmiとは,virtual machine introspectionの略である.

monitor the low-level details of a running virtual machine

このライブラリは,実行中の仮想マシンに対して,低いレイヤー,メモリの状態や,プロセスの状態などを監視することを実現するためのAPIを提供しているライブラリである.

サンプルコードも提供されており,これを実行することで,大雑把な動きを理解することができる.

対応している仮想化のプラットフォームは,KVM/QEMU及び,Xen

今回の記事では実際にこれを実行して結果を得られるところまで書く.

KVM/QEMUとは

もともと,この記事で扱っているテーマは,自分が今期やっていく研究の準備として行ったものである.今までは,VirtualBoxとDocker以外での仮想化をやったことがなかった.

KVM/QEMUという単語すら聞いたことない状態でのスタートだったため,まずはこれらの前提知識を調べるところから始まった.libvmiがどこでどのように動いているものなのかを大雑把に把握するためにも,KVM/QEMUについて簡単にまとめる.

KVMとは,Linuxカーネルに実装された仮想化の方法である.この機能を使うためにはいくつか条件がある.詳細については,後々解説する.

マシンの構成は,主にプロセッサ,メモリ,I/Oがあるが,KVMはこれらのうち,プロセッサの仮想化を担当している.

KVMは単体では動作せず,QEMUと組み合わせて使う.QEMUは,このアーキテクチャにおいては,メモリとI/Oを担当している.(QEMU自身でプロセッサの仮想化をすることもできるが,遅い)

単語の関係性として,仮想化の手段として,VirtualBoxと,KVM/QEMUQEMUは並列に考えることができる.その中で,今回はlibvmiを動かすために,KVM/QEMUという方法を選択するというだけ.

また,これらはVirtualBoxのように仮想マシンGUIで簡単に操作・管理できるソフトウェアが存在しない(正確に言えば普通にあるが,名前が違い,それらの関係性を把握するのも初見だと難しいので,下で解説)

virt-manager/virshとは

virt-managerとは,KVM/QEMUで起動している仮想マシンを操作・作成・管理などを行えるソフトウェアである.VirtualBoxは,KVM/QEMUのような,実際に仮想化を担当する部分と,virt-managerのようにそれらを管理する機能を一つのソフトウェアとしてまとめたものであると考えることができる.

virshは,あまりちゃんと使ってないのでうまく説明ができないが,これらの管理をシェルで実行できるようにしたもの,というイメージが正しそう.

関係性をシンプルにまとめた図として,以下のページの画像が非常に参考になる.

Virtual Machine Manager で VM を管理する」の「図 1. QEMU を使用した virt-manager スタックの概略図」

VirtualBoxでNested Virtualizationはできない

今回の環境は,仮想化されたLinuxではなく,USBブートしたLinux上としている.

これはKVMが動くかどうかに依存しており,結論からいうとVirtualBoxの上では,KVMは動作しない

引用になってしまうが,

  • 仮想化支援機能(Intel VTもしくはAMD-V)を搭載したプロセッサ
  • プロセッサの仮想化支援機能に対応したBIOSを持つマザーボード
  • ホストOS,ゲストOSを実行するために十分な容量のシステムメモリ
  • 64bit対応プロセッサを強く推奨(ディストリビューションによっては32bit非対応)
  • Intel EPT/AMD RVI搭載プロセッサの利用を強く推奨

これらのうち,Intel VTを搭載したプロセッサというのが,ハマるポイントになりうる.自分の調査不足かもしれないが,VirtualBoxで起動したマシンでは,プロセッサはこの機能を搭載していない(ように見える).

これをチェックする方法は以下.

cat /proc/cpuinfo | grep vmx
# flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf eagerfpu pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch epb invpcid_single kaiser tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid rdseed adx smap intel_pt xsaveopt dtherm ida arat pln pts
# etc...

このコマンドを叩いて,出力が得られれば,とりあえずKVMは動くという認識.

VirtualBox上のDebianでは出力を得られなかった,

よって,USBブートという選択をした.研究用だし壊れたら作り直せばいい

Debianの上で,KVM/QEMUを動かす.

では,実際にこれらを動かすために必要なツールを入れていく.

前提として必要なツール

sudo apt install make automake gcc git vim

KVM/QEMU

sudo apt install -y qemu-kvm libvirt0 virt-manager bridge-utils qemu-system-x86
sudo reboot
sudo gpasswd libvirt -a debian # debianというユーザー名

これが入ったら,qemuのバージョンを確認しておく.

qemu-x86_64 --version
# qemu-x86_64 version 2.8.1(Debian 1:2.8+dfsg-6+deb9u4)
# Copyright (c) 2003-2016 Fabrice Bellard and the QEMU Project developers

この結果が,2.8.0以上だった場合,libvmiをビルドする前に少しコードをいじる必要がある.

libvirt

参考:libvmiで仮想マシン内部のプロセス一覧を取得...できなかった

apt installでこける場合は,一旦そのパッケージはスルー.

sudo apt install libyajl-dev libnl-3-dev libnl-route-3-dev libdevmapper-dev libpciaccess-dev
wget http://libvirt.org/sources/libvirt-3.0.0.tar.xz
xz -d libvirt-3.0.0.tar.xz
tar xf libvirt-3.0.0.tar
cd libvirt-3.0.0
./configure
make
sudo make install
sudo systemctl start libvirtd
sudo systemctl enable libvirtd

libvmi

参考:libvmiで仮想マシン内部のプロセス一覧を取得...できなかった

apt installでこける場合は,一旦そのパッケージはスルー.

sudo apt install kvm libtool m4 check bison flex libglib2-dev
git clone https://github.com/libvmi/libvmi.git
cd libvmi

デバッグを有効にする.

vim libvmi/debug.h
// 56行目付近のコメントアウトを外す
#define VMI_DEBUG __VMI_DEBUG_ALL

また,qemuのバージョンが2.8.0以上だった場合は,以下を編集

vim libvmi/driver/kvm/kvm.c
// 1482行目付近
// before
if (major >= 2 && minor >= 8) {
// after
if (major >= 2 && minor > 8) {

完了したら,ビルド.

./autogen.sh
./configure --enable-xen=no
export CPATH='/usr/include/glib-2.0:/usr/lib/x86_64-linux-gnu/glib-2.0/include:glib-2.0'
make
sudo make install
which vmi-dump-memory
# /usr/local/bin/vmi-dump-memory

この表示が出ればインストールは成功.

ISO

参考:Debian 9: 仮想化のKVMをインストールする

起動するDebianのISOファイルを引っ張ってきて,任意の場所に配置する.

D=https://cdimage.debian.org/debian-cd/current/amd64/iso-cd
wget ${D}/debian-9.4.0-amd64-netinst.iso
sudo mkdir /var/lib/libvirt/iso
sudo mv debian-9.4.0-amd64-netinst.iso /var/lib/libvirt/iso/
sudo chown libvirt-qemu:libvirt /var/lib/libvirt/iso/debian-9.4.0-amd64-netinst.iso
virt-manager
# or
sudo virt-manager
# を実行すると,ソフトウェアが立ち上がる.

この記事に従って,先ほど作成した,/var/lib/libvirt/isoを表示されるディレクトリに追加し,マシンを作成していく.

自分の設定では,ストレージにあまり余裕がなかったので,以下の設定とした.

  • メモリ1024MB
  • コア数1
  • ストレージ14GB

これで作成を押すと,仮想マシンが作成できる.

libvmiのサンプルプログラムを実行

おそらくKVM/QEMUが立ち上がっていると思うので,以下のコマンドで確認し,実行する.

# ドメインを取得
sudo virsh list --all
#  Id    名前                         状態
# ----------------------------------------------------
#  3     debian9                        実行中
touch ~/memory_dump_1GB
sudo vmi-dump-memory debian9 ~/memory_dump_1GB # 時間がかかる

完了すると,およそ1GBのファイルができていると思うので,それを確認してみる

xxd ~/memory_dump_1GB

それっぽい文字列が大量に出てきたら,メモリダンプ成功.

結果

libvmiを動かすことができた.

参考文献