KVM仮想マシンを操作します。 仮想マシンのクローン作成

クローン



KVMに基づく仮想化に関する一連の記事の続き。 以前の記事では、ツール 、ホストマシンのセットアップ、および仮想マシンの作成について説明しました 。 今日は、仮想マシンイメージの作成とクローン作成について説明します。







この問題に関する調査により、憂鬱な結果が得られました。ネットワーク内の仮想マシンのイメージの作成に関する情報を見つけることは非常に難しく、品質と完全性に違いはありません。



最小限のシステムで仮想マシンのイメージを取得するには、その中のいくつかのファイルを変更するだけで正常に機能するシステムを取得できますが、Debianの場合は若干の難点があります。



既存のシステムに基づいて新しい仮想マシンを作成するには、次の変更を行う必要があります。







libguestfsライブラリは、私にとって素晴らしい発見であることが判明しました。これにより、対話的に、およびプリコンパイルされたスクリプトに従って、ディスクの管理と仮想マシンファイルの管理が可能になります。



このライブラリは、悪名高いRed Hat社のRichard Jonesによって作成されました。 MSファミリーからゲストオペレーティングシステムをインストールする際に、ファイルシステム(ext2から始まり、WindowsでNTFS、FreeBSDでUFS-一般に、カーネルが動作可能なすべてのファイルシステム)、システムイメージ、LVMパーティションで作業できます。 Windows-レジストリを編集します(hivexライブラリを使用)。 一般に、ユーティリティは非常に機能が豊富で非常に柔軟です。 そして最も重要なことは、それを使用するために管理(ルート)権限を必要としないことです。



画像を探索する





それでは、仕事に取り掛かりましょう。



ゲストシステムのイメージを操作する主なツールはguestfishです。



インタラクティブモードでいくつかの操作を行ってみましょう。



$ guestfish

><fs> add-drive debian_5_i386.img

><fs> run

><fs> list-filesystems

/dev/vda1: ext3

><fs> mount-vfs rw ext3 /dev/vda1 /

><fs> cat /etc/fstab

# /etc/fstab: static file system information.

#

# <file system> <mount point> <type> <options> <dump> <pass>

proc /proc proc defaults 0 0

/dev/vda1 / ext3 errors=remount-ro 0 1

/dev/hdc /media/cdrom0 udf,iso9660 user,noauto 0 0









これは非常にクールです-必要なすべての操作は、非インタラクティブモードで実行できます(プリコンパイルされたシナリオに従って)。 システム内のホスト、ホスト名、インターフェースファイルを編集するスクリプトの例を示します。



$ guestfish <<EOF

add-drive debian_guest.img

run

mount-vfs rw ext3 /dev/vda1 /

upload -<<END /etc/hosts

127.0.0.1 localhost.localdomain localhost debian_guest.local debian_guest

10.10.10.100 debian_guest.local

END

upload -<<END /etc/resolv.conf

nameserver 8.8.8.8

END

upload -<<END /etc/hostname

debian_guest.local

END

upload -<<END /etc/network/interfaces

auto lo

iface lo inet loopback

allow-hotplug eth0

iface eth0 inet static

address 10.10.10.100

gateway 10.10.10.10

netmask 255.255.255.0

network 10.10.10.0

broadcast 10.10.10.255

END

EOF









このコンテキストでは、 heredocを使用すると非常に便利でした。



(ところで、ライブラリについて質問がある場合、著者自身がirc.freenode.netのIRCチャネル#libguestfsで非常に迅速に回答します。とにかく、この男は非常に興味深いです。)



安全な地獄





名前が示すように、私はかなり長い間この問題に悩まされていました。Debian/ Ubuntuでは、削除されたときの自動キー再生成はまったくありません。 私が使用しようとした他のシステムでは、これで問題ありませんが、debベースのオペレーティングシステムではこれは問題です。



私はこれが好きでした:



$ guestfish

><fs> add-drive debian_guest.img

><fs> run

><fs> mount-vfs rw ext3 /dev/vda1 /

><fs> download /etc/init.d/ssh /home/username/debian_5_etc_init_ssh









次の変更が行われました。



--- /home/username/debian_5_etc_init_ssh 2012-12-21 00:00:00.000000000 +0000

+++ /home/username/debian_5_etc_init_ssh_fixed 2012-12-21 00:00:00.000000000 +0000

@@ -32,6 +32,10 @@

([ "$previous" ] && [ "$runlevel" ]) || [ "$runlevel" = S ]

}



+check_ssh_host_key() {

+ if [ ! -e /etc/ssh/ssh_host_key ] ; then

+ echo "Generating Hostkey..."

+ /usr/bin/ssh-keygen -t rsa1 -f /etc/ssh/ssh_host_key -N '' || return 1

+ fi

+ if [ ! -e /etc/ssh/ssh_host_dsa_key ] ; then

+ echo "Generating DSA-Hostkey..."

+ /usr/bin/ssh-keygen -d -f /etc/ssh/ssh_host_dsa_key -N '' || return 1

+ fi

+ if [ ! -e /etc/ssh/ssh_host_rsa_key ] ; then

+ echo "Generating RSA-Hostkey..."

+ /usr/bin/ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key -N '' || return 1

+ fi

+}

+

check_for_no_start() {

# forget it if we're trying to start, and /etc/ssh/sshd_not_to_be_run exists

if [ -e /etc/ssh/sshd_not_to_be_run ]; then

@@ -75,6 +79,7 @@



case "$1" in

start)

+ check_ssh_host_key

check_privsep_dir

check_for_no_start

check_dev_null

@@ -106,6 +111,7 @@

;;



restart)

+ check_ssh_host_key

check_privsep_dir

check_config

log_daemon_msg "Restarting OpenBSD Secure Shell server" "sshd"









注意、パッチは機能していません。必要な変更の例として示されています。



また、Debian / Ubuntuの2つのバージョンについて、すでに変更されたsshファイルを使用して同様のファイルを作成しました。 その後、単純に仮想マシンにダウンロードできます。



><fs> upload /home/username/debian_5_etc_init_ssh_fixed /etc/init.d/ssh







キーを削除して、自動的に生成されるようにします。



><fs> glob rm /etc/ssh_host_*_key*







マスクによる削除は機能しません。 このメソッドはAPIに実装されていないため、globプレフィックスを使用すると、マスクをファイルのリストに展開できます。



FreeBSDとCentOSの場合、キーを単に削除するだけで十分で、起動時に生成されます。



ユーザー識別





まず、Linux / FreeBSDでのユーザー情報の保存方法を説明する価値があります。 少し退屈になりますが、まだ何をしているかを理解する必要があります。 少なくとも、シャドウファイルに関する情報だけで十分です。



ユーザー認証に必要なものはすべて、ファイル/ etc / passwdおよび/ etc / shadow(FreeBSDの/etc/master.passwd)に保存されています。



/ etc / passwdファイルの構造を考慮してください



root:x:0:0:root:/root:/bin/bash







wikiからフィールドを使用する順序を引用します。







構造/ etc / shadowを考慮してください



root:$1$APv1HQOB$HJQhYFq9JSnhusQ.1Ql10.:14977:0:99999:7:::







再びwikiから







特に2番目のフィールド(パスワードハッシュ)を変更する必要があります。 次の3つの部分に分けることができます。







ハッシュはコマンドによって生成されます:



$ mkpasswd --method=md5 --salt="APv1HQOB" "$password"

$1$APv1HQOB$HJQhYFq9JSnhusQ.1Ql10.








ファイル/ etc / shadowで置き換える必要があります。



8文字の長さのランダムなパスワードとソルトを生成し、出力し、ハッシュを生成し、目的のファイルに置き換える小さなスクリプトを作成しました。



#!/bin/bash

tempfile=`mktemp`

shadow="/etc/shadow"

salt=`pwdgen`

passwd=`pwdgen`

hash=`pwhash $salt $password`

hash_esc=`escape_hash $hash `

pwdgen() {

charspool=('a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 'u' 'v' 'w' 'x' 'y' 'z' '0' '1' '2' '3' '4' '5' '6' '7' '8' '9' '0' 'A' 'B' 'C' 'D' 'E' 'F' 'G' 'H' 'I' 'J' 'K' 'L' 'M' 'N' 'O' 'P' 'Q' 'R' 'S' 'T' 'U' 'V' 'W' 'X' 'Y' 'Z');

len=${#charspool[*]}

for c in $(seq 8); do

echo -n ${charspool[$((RANDOM % len))]}

done

}



pwhash(){

salt=$1

password=$2

hash=`mkpasswd --method=md5 --salt=$salt $password`

echo $hash

}



# , sed $

escape_hash() {

echo $1 | sed -e 's/\//\\\//g' -e 's/\$/\\\$/g'

}



guestfish <<EOF

add-drive debian_guest.img

run

mount-vfs rw ext3 /dev/vda1 /

download /etc/shadow $tempfile

! sed 's/^root:[^:]\+:/root:$hash_esc:/' $tempfile > $tempfile.new

upload $tempfile.new $shadow

EOF









お気づきかもしれませんが、スクリプト内で外部コマンドを使用し、最初のセクションの内容をスクリプトで受け取ったハッシュに置き換えました。 これには外部演算子「 使用されます。guestfishを使用するプロセスを中断せずにいくつかの小さな操作を実行する必要がある場合は非常に便利ですguestfishの起動にはまだ時間がかかるため)。



マスターイメージの準備





イメージは定期的に更新する必要があるため(イメージの重要な更新またはバグ修正の場合)、必要な操作を実行するマスターイメージを準備する必要があります。 展開のために、個別のスクリプトを使用してこれらのイメージを準備します。



画像から削除する必要があるもの:



  1. ログを消去
  2. システムにとどまる痕跡を削除する
  3. ダウンロードしたパッケージを削除します(DebianとUbuntuに関連します。それらはゴミです)
  4. ネットワークカードの設定でファイルを削除します
  5. キーを削除します。




その後、ファイルシステムのサイズを縮小し、パーティションを縮小し、イメージから余分な部分を削除する必要があります。



必要なアクションの最初の部分を実行する小さなコードを添付します。



guestfish <<EOF

add-drive debian_guest.img

run

mount-vfs rw ext3 /dev/vda1 /

upload /home/username/debian_5_etc_init_ssh_fixed /etc/init.d/ssh

-glob rm /etc/ssh/ssh_host_*

-glob rm /etc/udev/rules.d/70-persistent-net.rules

-glob rm /root/*

-glob rm /root/.*

-glob rm /var/log/*

-glob rm /var/cache/apt/archives/*deb







Eof



コマンドの前にある「-」フラグは、いずれかのコマンドが-1を返す場合に終了しないことを意味します。 これは、ファイルがなくても他のコマンドの実行が中断されないように、意図的に行われます。 したがって、さまざまなディストリビューション用にこのスクリプトをカスタマイズする必要はありませんが、可能です。



それでは、画像の縮小を始めましょう。



$ guestfish <<EOF

add-drive add-drive ${images}/${os}_${version}_${arch}.img

run

e2fsck-f /dev/vda1

resize2fs-M /dev/vda1

tune2fs /dev/vda1 | grep "Block count:" | sed -e 's/Block\ count:\ //g' -e 's/$/*4+2144/g' | bc > /tmp/block_count

EOF

$ foo=`cat /tmp/block_count`

$ guestfish <<EOF

allocate debian_guest_minimal.img ${foo}k

EOF









番号2144は、ブートローダーとパーティションテーブルのサイズです。



要するに、これの本質は次のとおりです。ファイルシステムを最小サイズに圧縮し、占有し始めた量(最小ブロック数)を計算し、ブロックサイズが4 KBであるため4を掛けてから、取得した値のイメージを作成します。



その後、 libguestfsユーティリティパッケージvirt-resizeユーティリティを使用して、結果のファイルシステムを新しい小さなイメージに転送する必要があります。



$ virt-resize --shrink /dev/vda1 debian_guestl.img debian_guest_minimal.img







このメソッドの制限についてすぐに議論する必要があります。これは、resize2fsが動作するのはext2-4ファイルシステムのみです。 非標準のものについては、必要な機能を簡単に完成させることができます(ただし、前述したように 、libguestfsのアセンブルは非常に困難です)。 サンプルについては、 resize2fs-Mを実装するための私のパッチを見ることができます。



残念ながら、FreeBSDでは、すべてがはるかに複雑であり、仮想マシンの構成に別のディスクを追加してマウントする以外、問題の解決策はありません。



もちろん、オプションで、結果の画像をxzでパックする必要があります(これは長い時間ですが、結果には価値があります)。



$ xz -9 debian_guest.img

$ ls -lsha debian_guest.img.xz

107M -rw-r--r-- 1 username username 107M Dec 21 00:00 debian_guest.img.xz









イメージ展開





そのため、仮想マシンのイメージを取得しましたが、イメージは既製の作業システムではありません。 動作するシステムを取得するには、いくつかの操作を実行する必要があります。



  1. イメージをディスクに割り当てる
  2. ブートローダーとパーティションテーブルをコピーする
  3. テンプレートから仮想マシンイメージに情報を転送する
  4. ファイルシステムを展開する
  5. ルートパスワードを変更する
  6. ネットワーク設定を規定する




Linuxの場合、すべてが基本です。libguestfsにはOCamlで書かれた素晴らしいユーティリティがあります-virt -resize 、アイテム2から4は問題なく実行されます。



多くの理由により、「」「guestfish」にディスクサイズ変更を実装することはできません(mbrをguestfishにコピーすることはできません)。したがって、より機能的な手段を使用する必要があります。



$ guestfish <<EOF

allocate debian_guest_clone.img 10G

EOF

$ virt-resize --expand /dev/vda1 debian_guest.img debian_guest_clone.img









実際、仮想マシンイメージのクローン作成を実装するために知っておく必要があるのは、これだけです。



次の記事では、仮想マシンのリソースの制限について説明します。



All Articles