LoginSignup
5
5

More than 3 years have passed since last update.

vSphere Hypervisor (ESXi)でカジュアルにホットバックアップするスクリプト

Last updated at Posted at 2019-08-12

2020/02/12追記

復元するときにシンプルで、仕組みをわかっている方が安全だろうと自作してみましたが、結局こちらに落ち着きました。
https://github.com/lamw/ghettoVCB

似たような処理を行っており、使い勝手や安定性も遥かに上です。

ESXiのバックアップに苦労した過去

久々にESXiを触りました。名前がvSphere Hypervisorになっていたとは。

以前バージョン5のときに社内でサーバーを運用するのに使っていましたが、バックアップの運用に苦労しました。

色々探してもちょうどいいソリューションがなく、諦めてバックアップにはActonis製のソフトウェアを使っていました。
当時はもうちょっと安かったですが、それでもいい値段しました。
https://www.acronis.com/ja-jp/business/backup/virtual-machine/

でもこれが、まあ安定して動いてくれない。動かしてた環境がしょぼかったのもあると思いますが。

この前、VirtualBoxをハイパーバイザーとして使う際のバックアップスクリプトを作ったので、そのvSphere版を作ってみました。

VirtualBoxのVMをライブ/オンライン/無停止バックアップするスクリプト
https://qiita.com/miyanaga/items/39c19f1aa1171b2b402e

個人用なので作りが甘く、もっとよいやり方があると思いますが、プライベートな仮想環境のバックアップに参考ください。

やってること

各VMについて、.vmxファイル、.vmdkファイル、.logファイルをバックアップします。
バックアップの直前にスナップショットを作成し、バックアップ後にそのスナップショットを削除します。

起動中のVMは、ブロックデバイスのイメージファイルがロックされるのでコピーできません。仮にコピーできても整合性が保たれないので危険です。

そこでスナップショットをとると、イメージファイルが一度凍結され、差分が別のファイルに書き込まれます。その差分ファイルのみロックされるので、ファイルコピーで安全にイメージファイルをバックアップできます。

最初はVMのディレクトリにある全ファイルをコピーしていたのですが、メタデータとの不整合のためかVMを起動できませんでした。それで上記の拡張子のみコピーしています。

有償版のvSphereではライブマイグレーションができたと記憶していますが、それに比べると貧弱です。
スナップショットの作成と削除で謎の標準エラーが出ます。
スナップショットのIDはインクリメントされるのでどんどん増えていきます(特に不都合はないですが)。

まあ個人用なのでよしとします。

使い方

vSphere Hypervisor上で実行します。
backup=""を実際のバックアップ先に変更してください。
各VMには便宜的にでも一つ以上のスナップショットを作っておくと、高速な差分バックアップが実現します。

#!/bin/sh

# vsphare Hypervisor(6.7で動作確認)のホットバックアップスクリプト

# TODO
# * スナップショットの作成と削除で'Create Snapshot:: not found'という標準エラー
# * スペースを含むVMへの対応
# * 名称が重複するVMへの対処
# * バックアップ先の同期削除(rsync的な動作)

# datastoreが存在するvolumesパスとバックアップ先
volumes="/vmfs/volumes"
backup="/backup"

completed=""

# VMをリストアップ
vms=$(vim-cmd vmsvc/getallvms | tail -n +2)

# スナップショットを作成する関数
# 引数は整数によるVMのID、戻り値はスナップショットID(失敗した場合は""か0)
create_snapshot() {
  vmid="$1"

  # 日付付きスナップショットラベル
  ts=$(date '+%Y-%m-%d %H:%M:%S')
  label="backup $ts"

  # スナップショットを作成
  $(vim-cmd vmsvc/snapshot.create "$vmid" "$label" 2>/dev/null)

  # スナップショットIDはインクリメントされるので数値として最も大きなIDを取得
  # 正常に取得できない場合は初期値0のまま
  snapshotid=$(vim-cmd vmsvc/snapshot.get $vmid | grep 'Snapshot Id' | awk 'BEGIN{ id=0 } { if ($4>id) id=$4 } END{ print id }')

  echo $snapshotid
}

# スナップショットを削除する関数
# 引数は整数によるVMのIDとスナップショットID
remove_snapshot() {
  vmid="$1"
  snapshotid="$2"

  # スナップショットを削除
  $(vim-cmd vmsvc/snapshot.remove "$vmid" "$snapshotid" 2>/dev/null)
}

# VMレコードを解析する正規表現
re_vm_record='^([0-9]+) +([^ ]+) +\[([^\]+)\]\s+([^ ]+).+'

# リストアップしたVMを1件ずつ処理
IFS=$'\n'
for record in $vms; do
  # レコードを解析して整数のID、データストア、.vmxファイルパス、vmパスを取得
  vmid=$(echo "$record" | sed -r "s!$re_vm_record!\1!")
  datastore=$(echo "$record" | sed -r "s!$re_vm_record!\3!")
  vmx=$(echo "$record" | sed -r "s!$re_vm_record!\4!")
  vm=$(dirname "$vmx")

  # 意図しないレコードフォーマットなどで.vmxファイルパスを取得できなかった場合は次のVMへ
  if [ "$vmx" = "" ]; then
    echo "Could not parse vmx in '$record'"
    continue
  fi

  # .vmxファイルのフルパス
  path="$volumes/$datastore/$vmx"
  file=$(basename "$path")
  dir=$(dirname "$path")

  # .vmxファイルがもし存在しない場合は次のVMへ
  if [ ! -f "$path" ]; then
    echo "'$path' does not exists"
    continue
  fi

  # バックアップ先ディレクトリ
  dest="$backup/$vm"
  mkdir -p "$dest"

  # 一旦、現時点のvmxをコピーしておく
  cp -au "$path" "$dest/$file.tmp"

  # バックアップ用のスナップショット
  snapshot=$(create_snapshot "$vmid")

  # スナップショットIDが""または0の場合は作成に失敗したため次のVMへ
  if [ "$snapshot" = "" -o "$snapshot" = "0" ]; then
    echo "Failed to create snapshot of '$vmx'"
    continue
  fi

  # .vmemと.vmsnはスナップショットごとに追加されるので蓄積しないように削除
  # rm -f "$dest/"*.vmem "$dest/"*.vmsn
  # cp -au "$dir/"* "$dest"

  # vmdkファイルのコピーだけでも復元する
  cp -au "$dir/"*.vmdk "$dir/"*.log "$dest"

  # 一時ファイルからスナップショット作成まえの.vmxファイルを復元
  mv -f "$dest/$file.tmp" "$dest/$file"

  # バックアップ用のスナップショットを削除
  $(remove_snapshot "$vmid" "$snapshot")

  # 完了したVMを記録
  completed="$completed $vm"
done

echo "Backup complated:$completed"
5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5