Proxmox VEの仮想マシンイメージのクラウドバックアップをRcloneを使って実現する方法

Proxmox VEの仮想マシンイメージのクラウドバックアップをRcloneを使って実現する方法
Page content

バックアップを手堅く

1年ほど前、仮想化プラットフォーム (仮想化基盤) Proxmox VE (以下「PVE」) の環境構築について書きました。

このPVEの上で稼働している仮想マシンのイメージを、クラウドへバックアップしたくなったと想定します。PVEには様々な形式に対応したストレージ連携機能が標準で備わっていますが、たとえばGoogle Cloud Storageはその対応外です。

そこで、Rcloneというツールを使ってPVEサーバにGoogle Cloud Storageをマウントした上で、PVE上のVMイメージをクラウドバックアップする仕組みを実現してみました。PVEのVMイメージを遠隔地バックアップする一つの方法としてご紹介です。今回のPVEの環境は次の通り。

項目内容備考
PVE OSDebian GNU/Linux 11 (bullseye)
PVE サーバ名proxmoxve
PVE ユーザIDroot一般ユーザ権限を常用している場合は下記手順のコマンドに適宜sudoを加えてください

設定手順

Step-1. PVEサーバからGoogle Cloud StorageへアクセスできるようにRcloneを設定する

  1. 手元のPCにてターミナル画面を開いて、53682/tcpのローカルポート転送を効かせた ssh -L 53682:localhost:53682 root@proxmoxve でPVEサーバに接続する (そのまま維持する)
  2. PVEにrcloneをシェルでインストールする
# sudo -v ; curl https://rclone.org/install.sh | sudo bash
(snip)
rclone v1.62.2 has successfully installed.
Now run "rclone config" for setup. Check https://rclone.org/docs/ for more details.
  1. rclone config を実行してGoogle Cloud Storageと接続する (基本的にはdefault値を採用して進める)
    • VMイメージバックアップ専用のプロジェクトを事前にGoogle Cloudに作成しておくほうがわかりやすいし安全かもしれない
    • 詳細: Rclone > Google Cloud Storage https://rclone.org/googlecloudstorage/
      • 途中、「Project number」としてはProject IDを入力する (数字とは限らない)
      • 途中、認証のために手元のPCで開くURLはこのようになる: http://127.0.0.1:53682/auth?state=... (ポート転送しているのでターミナル画面に表示されるURLをそのまま使用できる)
No remotes found, make a new one?
n) New remote
s) Set configuration password
q) Quit config
n/s/q> n

Enter name for new remote.
name> google-cloud-storage
〜〜〜〜〜〜〜〜〜〜
Option object_acl.
Access Control List for new objects.
Choose a number from below, or type in your own value.
Press Enter to leave empty.
   / Object owner gets OWNER access.
 1 | All Authenticated Users get READER access.
   \ (authenticatedRead)
   / Object owner gets OWNER access.
 2 | Project team owners get OWNER access.
   \ (bucketOwnerFullControl)
   / Object owner gets OWNER access.
 3 | Project team owners get READER access.
   \ (bucketOwnerRead)
   / Object owner gets OWNER access.
 4 | Default if left blank.
   \ (private)
   / Object owner gets OWNER access.
 5 | Project team members get access according to their roles.
   \ (projectPrivate)
   / Object owner gets OWNER access.
 6 | All Users get READER access.
   \ (publicRead)
object_acl> 4 # rclone default
〜〜〜〜〜〜〜〜〜〜
Option bucket_acl.
Access Control List for new buckets.
Choose a number from below, or type in your own value.
Press Enter to leave empty.
   / Project team owners get OWNER access.
 1 | All Authenticated Users get READER access.
   \ (authenticatedRead)
   / Project team owners get OWNER access.
 2 | Default if left blank.
   \ (private)
 3 / Project team members get access according to their roles.
   \ (projectPrivate)
   / Project team owners get OWNER access.
 4 | All Users get READER access.
   \ (publicRead)
   / Project team owners get OWNER access.
 5 | All Users get WRITER access.
   \ (publicReadWrite)
bucket_acl> 2 # rclone default
〜〜〜〜〜〜〜〜〜〜
Option location.
Location for the newly created buckets.
Choose a number from below, or type in your own value.
Press Enter to leave empty.
 1 / Empty for default location (US)
   \ ()
 2 / Multi-regional location for Asia
   \ (asia)
 3 / Multi-regional location for Europe
   \ (eu)
 4 / Multi-regional location for United States
   \ (us)
(snip)
location> ?? # https://cloud.google.com/storage/pricing での安いロケーションから例えばus-west1を選択
〜〜〜〜〜〜〜〜〜〜
Option storage_class.
The storage class to use when storing objects in Google Cloud Storage.
Choose a number from below, or type in your own string value.
Press Enter for the default (REGIONAL).
 1 / Default
   \ ()
 2 / Multi-regional storage class
   \ (MULTI_REGIONAL)
 3 / Regional storage class
   \ (REGIONAL)
 4 / Nearline storage class
   \ (NEARLINE)
 5 / Coldline storage class
   \ (COLDLINE)
 6 / Archive storage class
   \ (ARCHIVE)
 7 / Durable reduced availability storage class
   \ (DURABLE_REDUCED_AVAILABILITY)
storage_class> 4
  1. rclone mkdir google-cloud-storage:/example を実行し、バケットexampleを作成する
  2. Google Cloud Storageの管理画面にて、安全のため、作成したバケットexampleの「アクセス権の編集」を実行して「公開アクセス: 非公開」とする
    • 具体的には、「公開アクセスの防止」をクリックして「このバケットへの公開アクセスを禁止しますか?」にて [確認] (Yes) をクリックする
  3. rclone lsd google-cloud-storage:/ を実行して、バケットexampleが表示されることを確認する

Step-2. PVEサーバにrcloneコマンドでGoogle Cloud Storageをマウントする

  1. PVEサーバにて mkdir /mnt/example でマウントポイントを作成する
  2. rclone mount -v google-cloud-storage:/example /mnt/example してエラーが発生しないことを確認する (実行後数秒してエラーが発生しないならば正常とみなし、Ctrl+Cで終了する)
    • Fatal error: failed to mount FUSE fs: fusermount: exec: "fusermount3": executable file not found in $PATH というエラーが出た場合は、apt install fuse3 してから再度実行する
  3. daemonモードに切り替えて rclone mount --daemon google-cloud-storage:/example /mnt/example した後、マウント状態を df -h /mnt/example で確認する
# df -h /mnt/example
Filesystem                    Size  Used Avail Use% Mounted on
google-cloud-storage:example  1.0P     0  1.0P   0% /mnt/example
  1. echo HELLO > /mnt/example/hello.txt した後、ls -al /mnt/example/hello.txt でファイルが一覧表示されることを確認する
  2. cat /mnt/example/hello.txt でファイル内容が表示されることを確認する
# cat /mnt/example/hello.txt 
HELLO
  1. rm /mnt/example/hello.txt でファイルが削除されることを確認する
  2. umount /mnt/example でマウントを解除する

Step-3. PVEサーバのmountコマンドからrcloneを呼び出す設定をする

  1. which rclone mount.fuse で2つのプログラムのpathを確認する
# which rclone mount.fuse
/usr/bin/rclone
/usr/sbin/mount.fuse
  1. rcloneを、mount.fuseと同じpathにあるmount.rcloneとして呼び出すことができるように、ln -s /usr/bin/rclone /usr/sbin/mount.rclone する
  2. which mount.rclone でmount.rcloneのpathを確認する
# which mount.rclone
/usr/sbin/mount.rclone
  1. mount -t rclone google-cloud-storage:/example /mnt/example -o config=/root/.config/rclone/rclone.conf した後、マウント状態を df -h /mnt/example で確認する
  2. umount /mnt/example && rm -r /mnt/example でマウントの解除とマウントポイントの削除を実行する

Step-4. PVEサーバにGoogle Cloud Storageのフェイルセーフなautomountを設定する

PVEサーバが仮想マシンのイメージをバックアップする際に、インターネット経由で利用するクラウドストレージ (Google Cloud Storage) のマウントが外れている・途中で外れる事態を想定しておく必要があるのでは……と考えた。

何らかの事故でマウントが外れた状態だと、特になんの対策もしていない場合、数十GB規模のバックアップがマウントポイントを作成しているローカルストレージに直接保存されていき、当該領域を食いつぶす可能性があり、PVEインストール時のデフォルトでは /mnt/ (ルートパーティション) に属しているので、最悪の事態としてはバックアップ動作がProxmox VE自体の動作に影響するかもしれない。

このような事態を発生させないためには、マウントポイントを作成する領域をPVEから隔離すれば良いはず。この方針に基づき、今回はあらかじめ、クラウドストレージ用のマウントポイントを数十MBといった容量小さめのtmpfs (オンメモリ) の中に作成しておき、クラウドストレージのマウントが意図通り行えていない場合にはVMイメージのバックアップをわざと早々に失敗させる、フェイルセーフ機構を仕込むことにした。

  1. tmpfsを使うためのマウントポイントを mkdir /mnt/tmpfs で作成する
  2. /etc/fstab に次の内容を追記する
# CUSTOM
tmpfs /mnt/tmpfs tmpfs defaults,size=64m 0 0
  1. mount /mnt/tmpfs を実行した後、マウント状態を df -h /mnt/tmpfs で確認する (/mnt/tmpfsはtmpfs (オンメモリ) に存在する最大容量64MBの領域だと分かる)
# df -h /mnt/tmpfs
Filesystem      Size  Used Avail Use% Mounted on
tmpfs            64M     0   64M   0% /mnt/tmpfs
  1. 「/mnt/tmpfsがオンメモリ領域ならばそこにマウントポイントを作成してGoogle Cloud Storageをマウントする」という意図である df -t tmpfs /mnt/tmpfs >/dev/null && mkdir /mnt/tmpfs/Google-Cloud-Storage && mount -t rclone google-cloud-storage:/example /mnt/tmpfs/Google-Cloud-Storage -o allow_other,vfs_cache_mode=writes,vfs_cache_mode=writes,config=/root/.config/rclone/rclone.conf をワンライナーとして実行した後、2箇所のマウント状態を df -h /mnt/tmpfs /mnt/tmpfs/Google-Cloud-Storage で確認する
# df -h /mnt/tmpfs /mnt/tmpfs/Google-Cloud-Storage
Filesystem                    Size  Used Avail Use% Mounted on
tmpfs                          64M     0   64M   0% /mnt/tmpfs
google-cloud-storage:example  1.0P     0  1.0P   0% /mnt/tmpfs/Google-Cloud-Storage
  1. ユーザrootのcrontabで次の内容が実行されるようにする (4のワンライナーをreboot時に実行する内容である)
# crontab -l
@reboot df -t tmpfs /mnt/tmpfs >/dev/null && mkdir /mnt/tmpfs/Google-Cloud-Storage && mount -t rclone google-cloud-storage:/example /mnt/tmpfs/Google-Cloud-Storage -o allow_other,vfs_cache_mode=writes,vfs_cache_mode=writes,config=/root/.config/rclone/rclone.conf
  1. 可能であれば、PVEサーバを再起動して /mnt/tmpfs/Google-Cloud-Storage がautomountされることを確認する

初めに述べた、クラウドストレージのマウントが意図通り行えていない場合のフェイルセーフ機構としては、次の点を考慮している。

  • Linux起動時には /etc/fstab が解釈された後にcronの「@reboot」が実行されるので、今回のautomountは意図通りの順で実行されるはず
  • もし仮に、「mkdir /mnt/tmpfs/Google-Cloud-Storage」が失敗したらこのディレクトリは存在しないままであるため、本ディレクトリへのPVEによるバックアップ実行は自動的に失敗するはず
  • もし仮に、tmpfs領域での「mkdir /mnt/tmpfs/Google-Cloud-Storage」は成功し、次の「mount -t rclone google-cloud-storage:/example /mnt/tmpfs/Google-Cloud-Storage ...」によるクラウド領域のマウントは失敗している場合、/mnt/tmpfs/Google-Cloud-Storage はクラウド領域ではなくtmpfs領域 (最大容量64MB) のままということになる。この場合、PVEによるバックアップ実行は容量不足を招いて自動的に失敗するはず

Step-5. PVEにGoogle Cloud Storageを使用するバックアップ設定を追加する

  1. PVEの管理画面にログインし、Datacenter > Storage > Add > Directory を選択し、次のような設定でストレージ領域として /mnt/tmpfs/Googlg-Cloud-Storage/ を追加する
  2. Datacenter > Backup > Add を選択し、次のような設定で任意の仮想マシンのバックアップジョブを追加する
  3. 追加したバックアップジョブをまずは [Run now] で実行し、画面下部のTasksの当該行をダブルクリックして、バックアップが正常に完了したことを確認する
  4. PVEサーバの /mnt/tmpfs/Google-Cloud-Storage/dump/ (マウントしているGoogle Cloud Storage領域) にバックアップファイルが作成されていることを確認する
# ls -alh /mnt/tmpfs/Google-Cloud-Storage/dump/
total 2.8G
drwxr-xr-x 1 root root    0 May  7 23:34 .
drwxr-xr-x 1 root root    0 May  7 23:25 ..
-rw-r--r-- 1 root root 2.5K May  7 23:43 vzdump-qemu-107-2023_05_07-23_42_32.log
-rw-r--r-- 1 root root 2.8G May  7 23:43 vzdump-qemu-107-2023_05_07-23_42_32.vma.zst
-rw-r--r-- 1 root root   11 May  7 23:43 vzdump-qemu-107-2023_05_07-23_42_32.vma.zst.notes
  1. バックアップのテストは成功したとして、バックアップ本番時の領域使用量に関係する設定、具体的にはBackupのジョブごとのScheduleやRetention (バックアップの保持期間) や、Storageごとの設定にあるBackup Retentionを適切に設定する

感想

以上、オープンソースソフトウェアでかつ使い勝手の良い仮想化プラットフォーム「Proxmox VE」を活用していくための一つの情報です。ところどころ端折っているので、技術記事としては整っていない内容かもしれないと思う一方、私自身の勉強としては、Google Cloud Storage自体を今回の件で初めて使用し、フェイルセーフ機構を実現するためのtmpfsを使ったマウントポイントの工夫 (ベストかどうかは不明) を考えるのにもそれなりに頭をひねったので、このまま少しでも誰かの役に立てばいいや……という勢いで書きました。