我が家の物理サーバーを VMware ESXi 4.0 化するまで CentOS 上で稼働していた VMware Server 1.0 では、仮想マシン (以下 VM) 操作コマンド vmware-cmd をシェルスクリプトに組み込んで活用していたが、VMware ESXi 4.0 ではこれに相当するコマンドが vim-cmd (VMware Server 2.0 では vmware-vim-cmd) となり、オプションや使い方が大幅に変わった。また通常のコマンドのオプションやシェル環境も CentOS と異なるため、VMware Server 1.0 時代のバックアップ・スクリプトをそのまま流用することはできない。

しかし比較的急務と言える ESXi 用 VM バックアップ・スクリプトの作成は、忙しかったこともあって、ずっと後回しになっていた。こう言う空隙を突いて発生しがちなトラブルに備えて、とりあえず VM のバックアップは手動で行っていたが、いい加減面倒になって来たので、そろそろ自動化することにした。

動作中の VM の仮想ディスク・ファイルは ESXi によってロックされていて、直接コピーできない。仮想ディスク・ファイルをコピーするには ESXi のロックを解除する必要があり、VM を停止させるか、ESXi でスナップショットを作成することで、ロックを解除できる (スナップショット・ファイルが新たにロックされる) 。スナップショットを利用すれば VM の無停止バックアップも可能なので、VM を止めたくない場合には便利だ。

ただいくら可能とは言え、動いている真っ最中の VM を丸ごとバックアップするのは気持ちが悪いし、VM が DRBD + Heartbeat による HA クラスタリングの片割れだった場合、恐らくリストア時に面倒なことになるはず (未検証)。無用のトラブルを避けるため、VM のバックアップは以下の方針で行うことにした。

  1. ESXi マシンが搭載する 4台の HDD (=CentOS 時代の名残) のうち、1台をバックアップ・データ保管用 Datastore とする。(容量に余裕があれば、NFS サーバー上の VM もここにバックアップ)
  2. VM の仮想ディスクは VMFS を使用し、vmx ファイルと同じディレクトリに配置する (RDM 非対応)。
  3. 動作中の VM は、シャットダウン後にスナップショットを作成してすかさず起動させ、ダウンタイムを最小にする。
  4. ロックされていない VM 構成ファイル群をコピー。ただし、我が家ではスナップショットの影響を受けない独立モード (Independent) の仮想ディスクにはバックアップ不要のデータしか保存しないようにしているため、独立モードの仮想ディスク・ファイルはコピーから除外する (バックアップ不要の仮想ディスクを他と区別するために、独立モードを使うようにした)。
  5. バックアップの取得は全自動で定期的に実施。

実際の処理の大まかな流れは、以下の通り。

  1. VM 名から Datastore 中の vmx ファイル (と格納ディレクトリ) を特定。
  2. VM の vmid を特定。
  3. VM が使う仮想ディスク (独立モード以外) の合計サイズと、バックアップ先 Datastore の空き容量を確認。空き容量が VM のサイズより少ない場合は、十分な空き容量が確保できるまで現在の VM の過去のバックアップ・データを古い順に削除する。古いバックアップ・データを一定数削除しても十分な空き容量が確保できない場合は、バックアップを中止。
  4. VM が動作中の場合はシャットダウン (「動作中だった」 フラグ ON)。
  5. バックアップ先ディレクトリを作成。
  6. 設定ファイル (*.vmx*, *.vmsd, *.nvram 等) をコピー。
  7. 「動作中だった」 フラグが ON の場合は、バックアップ用スナップショットを作成 (「スナップショット作成」 フラグ ON)。
  8. 「動作中だった」 フラグが ON の場合は、VM を起動。OFF の場合はそのまま放置。
  9. vmx ファイル中で定義されている仮想ディスク・ファイル (*.vmdk) をコピー。
  10. 「スナップショット作成」 フラグが ON の場合は、バックアップ用スナップショットを削除。スナップショットは運用上の理由で既に複数世代存在している場合があるので、削除するのは、直近のバックアップ用スナップショットのみとする。

"7." でバックアップ用スナップショットを作成する前の段階で設定ファイルをコピーするのは、リストア時の手間を省くため。スナップショットを作成すると、vmx ファイル中の vmdk ファイル名が新たにロックされてコピーできないスナップショット・ファイルに書き換えられるので、スナップショットを作成する前にコピーしておかないと、リストア時に vmdk ファイルの指定を元のファイル名に修正する手間が発生してしまう。

コピーから除外する独立モードの仮想ディスクは、vmx ファイルから使用中の vmdk ファイル名を grep する際に "scsi:0:0" 等のデバイス名を確認しておき、このデバイスの ".mode" を見れば特定できる (vim-cmd vmsvc/ のサブコマンドで把握できても良さそうなものだが・・・)。ただしこの vmdk ファイルは仮想ディスクの実体ではないので、このファイル自体は「独立モードになっててコピーしなかった仮想ディスクがあるよ」 と言うアピールのためにコピーし、除外するのは "-flat" が付いた実体の vmdk ファイルのみとした。

一点残念だったのが、バックアップ・データのチェックサムが作成できなかったこと。通常の Linux では何気なく利用している md5sum や sha1sum 等のコマンドが、ESXi には見当たらない。バックアップ対象となる vmdk ファイルのサイズは GB クラスなので、本来ならバックアップ完了時やリストア時に何かしらのチェックサムを利用してバックアップ・データが正常か否かを確認したいところだが、致し方ない。

※ 2010-10-31 追記 ---
VMware ESXi 4.1 では、md5sum も sha1sum も普通に使える。du もそうだが、4.1 か、4.0 のどれかの Update か、どこかのタイミングで追加されたのだろうか。ただ、思いの外チェックサムの計算コストが高かった (=CPU 使用率が跳ね上がる) ため、結局バックアップ時に *sum は使っていない。
---

バックアップ・スクリプトが完成したら、バックアップ・データから正常にリストアできることを確認する。バックアップとリストアは常にセットで考え、リストア方法や、そもそもそのバックアップ・データから間違いなくリストアできるのかどうか等、事が起こる前に確認しておいた方がいい。

今回の方法だと、Datastore の HDD が壊れていない状態のリストアは

  1. リストア対象の VM をインベントリから削除。
  2. Datastore 上のオリジナルの VM ディレクトリを適当な名前にリネーム。
  3. バックアップ・データを元の Datastore に VM ディレクトリごとコピー。
  4. コピーしたバックアップ・データのディレクトリ名をオリジナルに戻す。
  5. 改めて VM をインベントリに登録。

と言う手順になる。HDD が壊れた場合は、"3." のコピー先を適当な場所に変えるだけだ。

通常の Linux とは異なる制約が多い ESXi のシェル環境では、スクリプト中で普段慣れ親しんだ書式が使えなかったり、慣れないうちは両手を縛って泳がされるような不自由さを感じた。今回書いたスクリプトもあまり美しくない部分があるが、要件は全て満たしているので、まァよしとしよう。

尚、ESXi はユーザーが作成したファイルを起動時に捨てる悪い癖があるので、ゴリゴリと書いた自作スクリプトは ESXi にやられないよう、/vmfs/volumes 以下の任意の Datastore 中に保存しておくのが無難だ。僕は ESXi の vi が使いにくいため、ESXi 用スクリプトは CentOS の NFS 共有ディレクトリに置いて、CentOS 上で編集するようにしている。

あとはこのスクリプトを cron に登録して自動実行できれば完成だが、長くなったので別エントリーで。

Comments are closed.