ESXiでもクローンをしたかった。

vCenterとかないと使えない機能だけど、複数の環境を作りたいときはやっぱりクローンはほしい。


といっても、普通にデータストアにディレクトリ作って、vmdkとvmxをコピペすればいいんだけども、
この場合、vmdkの名称が変更できないのがイケてなかったので、却下。
vmdkの複製はESXiでも出来るので、そこから無理やり設定ファイルを反映させて、インベントリに追加します。


でも、ESXiにsshで入ってコンソール操作しないとだめだし、
複製した仮想ディスクとvmxファイルはインベントリに追加しないと仮想マシンとして動かせないし、
追加後のネットワーク設定はコンソール上で設定しないとだめ、などなど制約はあるけれど。
(上2つに関しては、PerlSDK使えば出来そうだけど、調べるのがめんどうでやっていない)


(12/06/14:追記)
複製スクリプトの自動化度がレベルアップしました。


ベースとなる仮想マシンを作る。

  • CentOS 6.2
  • NICは1枚、eth0で固定とする。
  • ディスクも1個。
  • IPは静的で割り当て、MACとIP以外は一緒
(設定例) /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE="eth0"
HWADDR="00:0C:29:4E:A2:65"
NM_CONTROLLED="yes"
ONBOOT="yes"
IPADDR="192.168.11.130"
NETMASK="255.255.255.0"
GATEWAY="192.168.11.1"
BOOTPROTO="static"

あとはミドルウェア入れるなり、VMWareTools入れるなりします。


あと、複製後のネットワーク設定をちょっとラクにするツールを置いておきます。
複製前に入れておくと、複製後にこいつを1回叩けば複製で問題があったネットワーク周りの設定が完了するのでラクです。
使い方は後で説明します。

ethxto0.sh
#!/bin/bash

if [ $# -ne 2 ]; then
	echo "usage: $0 ethX IPADDR"
	exit 0
fi

ETH=$1
IP=$2

# ethXのMACアドレスを取得
MAC_ADDRESS=`ifconfig -a | grep $ETH | awk '{print $5}'`

# 取得できないなら、多分必要ない
if ["$MAC_ADDRESS" == "" ]; then
	echo "必要ありません";
	exit 0
fi

# NICのなにか
NET_RULES=/etc/udev/rules.d/70-persistent-net.rules

# NICのなにかをバックアップ & 古いものを削除扱いにする(再起動で反映)
BAK_SUFFIX=`date +%Y%m%d-%H%m%S`.bak
mv $NET_RULES $NET_RULES.$BAK_SUFFIX

# ifcfg-eth0の編集...といっても、めんどっちいので、sed置換. MAC_ADDRESSとIPADDRを置き換える
echo "updating ifcfg-eth0 ..."
IFCFG_ETH0=/etc/sysconfig/network-scripts/ifcfg-eth0
mv $IFCFG_ETH0 $IFCFG_ETH0.$BAK_SUFFIX
sed "s/HWADDR=\"[0-9A-Fa-f:]*\"/HWADDR=\"$MAC_ADDRESS\"/" $IFCFG_ETH0.$BAK_SUFFIX |
sed "s/IPADDR=\"\\([0-9]\\{1,3\\}\\.\\)\\{3\\}[0-9]\\{1,3\\}\"/IPADDR=\"$IP\"/" > $IFCFG_ETH0

# IF再起動
echo "done."
reboot


用が済んだらシャットダウンしておきます。

vmdk複製ツールを書く

やるべきことはこのあたりです

  • vmdkの複製(XXX-flat.vmdkのことではない)
  • vmxの複製していい感じに修正
  • VM起動
  • 起動時のメッセージに応答

vmdk自体にOSとかの情報が入っていて、vmxにCPUとかメモリとかのハードウェアの情報とか、vmdkの位置情報とかいろいろ入ってます。
vmdkはcpするよりも、vmkfstoolsを使ったほうが早くておいしいです。
vmxは単純に複製元のVM名を複製後のVM名へ置き換えます(普通に仮想マシンを作れば問題ないはず)
起動とかのvSphereでやるような操作はだいたいvim-cmdを使うと出来ます。


あと、vmxの修正はVM名について置き換えているだけなので、uuidなどの置き換えは行われていません。
そのためか、初回起動時に「仮想マシンの質問」と評して確認メッセージが出てくるので、
これはコピーしたものです、と答える必要があります。


このへんを全部やる複製スクリプトを書きました。

vmdkclone.sh
#!/bin/sh

if [ $# -lt 3 -o $# -gt 4 ]; then
        echo "usage $0 BASE_VOLUME BASE_VM_HOSTNAME [STORE_VOLUME] VM_HOSTNAME"
        exit 0
fi

OPTION="-d thin"

BASE_VOLUME=$1
BASE_VM_HOSTNAME=$2
STORE_VOLUME=$3
VM_HOSTNAME=$4

if [ "$VM_HOSTNAME" == "" ] ; then
        VM_HOSTNAME="$STORE_VOLUME"
        STORE_VOLUME="$BASE_VOLUME"
fi

BASE_DIR="`dirname $BASE_VOLUME`/`basename $BASE_VOLUME`/$BASE_VM_HOSTNAME"
BASE_VMDK="$BASE_DIR/$BASE_VM_HOSTNAME.vmdk"

STORE_DIR="`dirname $STORE_VOLUME`/`basename $STORE_VOLUME`/$VM_HOSTNAME"
STORE_VMDK="$STORE_DIR/$VM_HOSTNAME.vmdk"

if [ -e $STORE_DIR ]; then
        echo "error: exists directory: $STORE_DIR";
        exit 1;
fi

mkdir $STORE_DIR

echo "cloning $STORE_VMDK ..."
vmkfstools -i "$BASE_VMDK" $OPTION "$STORE_VMDK"
echo "copy setting files"
cp "$BASE_DIR/$BASE_VM_HOSTNAME.vmx" "$STORE_DIR/$VM_HOSTNAME.vmx"
sed -i "s/$BASE_VM_HOSTNAME/$VM_HOSTNAME/g" "$STORE_DIR/$VM_HOSTNAME.vmx"

echo "register vm..."
vim-cmd "solo/registervm" "$STORE_DIR/$VM_HOSTNAME.vmx"


VMID=`vim-cmd vmsvc/getallvms | grep "\[$(basename $STORE_VOLUME)\] $VM_HOSTNAME" | awk '{print $1}'`


vim-cmd "vmsvc/power.on" $VMID &

echo "waiting VM startup ..."
sleep 5;

RETRY=5
MSGID=

echo "getting Virtual machine message"

while [ $RETRY -ne 0 ]; do
        sleep 3;
        MSGID=`vim-cmd vmsvc/message $VMID | grep "^Virtual machine message" | awk '{print $4}' | cut -d : -f 1`
        if [ "$MSGID" != "" ]; then
                break
        fi
        RETRY=`expr $RETRY - 1`
done

if [ $RETRY -eq 0 ]; then
        echo "could not get message. VMID=$VMID"
        exit 0
fi

echo "vim-cmd vmsvc/message $VMID $MSGID 2"
vim-cmd vmsvc/message $VMID "$MSGID" 2

echo "done."


使い方はこんな感じです。

# TemplateVMと同じデータストアへ、CloneVM1を複製する
/usr/local/bin/vmdkclone.sh /vmfs/volumes/datastore_small1 TemplateVM CloneVM1
# TemplateVMを別データストアのCloneVM2へ複製する
/usr/local/bin/vmdkclone.sh /vmfs/volumes/datastore_small1 TemplateVM /vmfs/volumes/datastore_big1 CloneVM2

空白が入っていたりしても、ダブルクォートで囲めば多分大丈夫。
これで、vmdkの複製からインベントリの追加、起動までやってくれます。
(2013/01/14 同名のゲストOS名を指定すると起動されなかったりするのを修正。)

ネットワーク設定

MACアドレスが変わってしまうので、複製元のときにあったNICがなくなった状態になります。
ネットワーク設定も古いままなので、新しいものに変える必要があります。


変更箇所は以下の2箇所です。

  • /etc/sysconfig/network-scripts/ifcfg-eth0
  • /etc/udev/rules.d/70-persistent-net.rules

ifcfg-eth0は、ネットワークの設定情報が入ってます(IPとかSUBNETMASKとか)
70-persistent-net.rulesは接続されているNICとその識別名の情報を記録してます。
新しいNICが追加されると、eth1...というように登録されます。


ここで複製前に入れたツールを使います。
NICが1枚であれば、古いeth0と、複製で作られたeth1があるので、eth1をeth0に置き換えます。

# eth1の情報をeth0に置き換え、IPADDRに192.168.11.131を設定する
./ethxto0.sh eth1 192.168.11.131

reboot後、疎通がとれたら完了です。
クローンの挙動とかなり近い感じになってると思います(OSの設定とかやってくれないけど。)

おしまい

VMWare Server(評価版)を使ったら負けかなと思ってる。


ESXiも試用版みたいなもんだけど、ESXiサーバがコンパクトだし(2GBメモリでも運用できる)、vShpereによるコンソール機能とかある程度そろってるので。
でもvCenterのクローン操作はこんな面倒なことをしなくても、GUIでポチポチやれば出来ちゃうので正直言えば使いたいry