仮想マシン(KVM)のバックアップスクリプト

現在稼働しているサーバー

  • WEBサーバー(このサイト)
  • ゲームサーバー(insurgency: sandstorm)
  • Zabbixサーバー(監視サーバー)
  • AlmaLinux 9 Test Server
  • AlmaLinux 10 Test Server

これらはすべて仮想化して運用している。
仮想化している理由は管理が楽そうだから。
実際テストサーバーに関していえば、
壊しても他に影響がないので気にすることなくスクリプトを試したりできる。

そして、Linuxのバックアップの仕方がいまいち掴めないのも一つの理由としてある。
仮想環境ならイメージファイルをコピーしておけば、
とりあえずリストアできるのでかなりお手軽。
なのだが、一度仮想サーバーを停止してからじゃないとファイルの整合性が取れなくなるため、
リストアに失敗してしまう。

その点、Proxmoxとかを使えば簡単にできそうではあるが、
今のところ仮想化基盤はAlmaLinuxを使っているため、ちょっと面倒。
恐らくできると思われるが、やり方が複数あってこれが正解というのが無いため、
検証しなくてはならず大変。

とはいえ、毎回手動でバックアップするのも面倒なので、
今回重い腰を上げてスクリプト化することにした。

まずは、一番簡単で確実な仮想サーバーをすべて停止して、
イメージファイルを全てコピーするバージョン。
今回は、シェルスクリプトの勉強が目的でもないので、
ChatGPTにほぼコードを作ってもらった。

まぁ一番最初は手動でやっていた作業をスクリプトで書いて、
それをベースに発展形をChatGPTに書いてもらい、
それの検証をして、こういうことは可能か?みたいにChatGPTに伝えて修正・・・
ってことを繰り返した感じ。

あんまりChatGPTに任せすぎると、だんだん複雑なスクリプトになってきたりして、
検証でうまく動かない時に、
何が悪いか分からなくなるので注意しながら。(自分のキャパを超える)

とりあえず、完成系がこちら

#!/bin/bash

BACKUP_DIR="/backup/libvirt"

mkdir -p "$BACKUP_DIR/images" "$BACKUP_DIR/qemu"

# **最初に稼働していたゲストのリストを保存**
running_vms=$(virsh list --name)

# **すべてのVMを通常シャットダウン**
if [ -n "$running_vms" ]; then
    for vm in $running_vms; do
        virsh shutdown "$vm"
    done

    # **シャットダウンを最大30秒待機**
    SECONDS_LEFT=30
    while [ -n "$(virsh list --name)" ] && [ $SECONDS_LEFT -gt 0 ]; do
        printf "\rWaiting: %2d seconds remaining..." "$SECONDS_LEFT"
        sleep 1
        ((SECONDS_LEFT--))
    done

    # **まだ動いているVMを強制停止**
    remaining_vms=$(virsh list --name)
    if [ -n "$remaining_vms" ]; then
        for vm in $remaining_vms; do
            virsh destroy "$vm"
        done
    fi
fi

# **すべてのVMの設定ファイルをコピー**
for vm in $(virsh list --all --name); do
    virsh dumpxml "$vm" > "$BACKUP_DIR/qemu/$vm.xml"
done

# **ディスクイメージをバックアップ**
rsync -ah --progress /var/lib/libvirt/images/ "$BACKUP_DIR/images/"

# **最初に稼働していたゲストを再起動**
if [ -n "$running_vms" ]; then
    for vm in $running_vms; do
        virsh start "$vm"
    done
fi

echo "✅  Backup complete. Running VMs have been restarted."

やっていることは現在稼働中の仮想マシンを記憶して、
全てを停止させる。
きちんと停止したかをチェックして、
30秒たっても停止してなかったら強制終了させる。
次に仮想マシンの設定を全て(稼働していないものも含む)
バックアップフォルダにxmlファイルで作成して、
イメージファイルをフォルダごとコピー。

この時、通常のコピーコマンドを使わず、
rsyncコマンドを使ったのはコピーの状態を表示させるため。
rsyncコマンドはLinuxのバックアップで定番の様だけど、
いまいち使い方が分からない。
今回はChatGPTさんがコピー中の状態を表示させるのに適していると教えてくれた。
まぁ、いまだにrsyncコマンドの実態はよくわかっていない。

最後に一番初めに記憶していた、
スクリプトを実行する前に起動していた仮想マシンを、
起動させて終了するというとても簡単なスクリプト。

難点はゲームサーバーの容量が250GBほどあり、
コピーに10分ほどかかる為、
全仮想サーバーのダウンタイムが最低でも10分以上かかってしまう。

そこで一台ずつ停止させて、
個別にバックアップするやり方をスクリプトで作ろうとしたが、
どうしても上手くいかず、今回は諦めた。

次にオンラインバックアップのスクリプトを作ろうとしてみたが、
これもうまくいかず。
スナップショットを使ったやり方がおすすめらしいが、
いまいち理解できず。
スナップショットを使わないやり方だと、
どうしても稼働中の仮想マシンのイメージファイルのロック状態を解除できずうまくいかず。

もちろん単純なコピーコマンドでコピーは可能だが、
その場合ファイルの整合性が取れなくなり、
リストアできない可能性がありこれはダメ。

ここで言う整合性が取れないとは、
ファイルのコピー中にすでにコピー済みの元ファイルのエリアに何か書き込みがあると、
コピーしたファイルと元ファイルが完全に同じものにならなくなるということ。

まぁ色々試したけど、今回の目的はバックアップを確実に取ることなので、
オンラインバックアップは諦めることにした。

危うく、スクリプトで何とかできないかと熱中して、
手段が目的になるところだった。
一応今回のスクリプトもGitHubにアップしておいた。
意外と単純なスクリプトの方が需要があるようなので。

GitHub - smileygames/kvm_backup: VM環境のオフラインバックアップスクリプト

VM環境のオフラインバックアップスクリプト. Contribute to smileygames/kvm_backup development by creating an account on GitHub.

今回は完全に自分の環境用のスクリプトなので、環境次第ではうまく動かない可能性があります。
もし使うなら、あくまで参考用にお使いください。
上手く動かなかった場合はご自身で修正するなりしてみてね~。

そのうち、オンラインバックアップ用のスクリプトを作りたい気もするが、
もういっそProxmoxに移行した方が速いような気がしないでもない。

ただし、移行が面倒そうなんだよなぁ。
まずは勉強用に触ってみないとだしなぁ。
下手に移行するより、
新規に仮想マシンを作って設定だけ移行した方が確実で早いのかもしれん。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です