2026年5月27日

2026年5月27日

btrfsスナップショットでファイルシステムをバックアップする方法(send/receiveで別ディスクへ)

btrfs では、サブボリュームの読み取り専用スナップショットを作り、btrfs send と btrfs receive で別のディスクやサーバーへ送ることで、変更分だけを効率よく転送するバックアップを組めます。スナップショットは同じファイルシステム上にあるので、それだけではバックアップになりません。この記事では、サブボリュームの確認から、初回の全体転送、2回目以降の差分転送、世代の削除、復元までの手順を、つまずきやすい点とあわせて説明します。

btrfs スナップショットの基本

btrfs はファイルシステム自体が copy-on-write(CoW)で動いており、スナップショットはデータを複製せずに「その時点のファイルの参照」を記録するだけです。そのため数十 GB のデータでも一瞬で作成でき、作成直後はほとんど容量を使いません。その後、元のファイルが書き換えられた分だけ容量を消費していきます。

押さえておきたい性質は次の3つです。

  • スナップショットの単位はサブボリューム:ディレクトリ単位ではなく、サブボリューム単位で取ります。対象のデータがサブボリュームになっていないと、思った範囲で取れません。
  • 入れ子のサブボリュームは含まれない:スナップショットを取ったサブボリュームの中に別のサブボリュームがあると、その中身は空のディレクトリとして扱われます。
  • 同じディスクの上にある:ディスク故障やファイルシステムの破損、誤ったフォーマットには無力です。外部へ送って初めてバックアップになります。

LVM のスナップショットと違って事前の領域確保が不要で、あふれて無効になることもありません。ただしファイルシステムの空き容量は消費するので、古い世代の削除は欠かせません。

手順1:サブボリュームの構成を確認する

まず、対象のディレクトリがどのサブボリュームにあるかを確認します。

sudo btrfs subvolume list /
findmnt -t btrfs
sudo btrfs filesystem usage /

Ubuntu や Fedora などのインストーラーは、@(ルート)や @home、root、home のような名前のサブボリュームを作り、subvol= オプションでマウントしていることが多いです。findmnt の出力で、どのサブボリュームがどこにマウントされているかが分かります。

WordPress のデータを置いている /var/www などがルートのサブボリュームに含まれている場合、ルート全体のスナップショットを取ることになり、ログやキャッシュも含まれて差分が大きくなります。データ用に専用のサブボリュームを作って分けておくと、バックアップの範囲を絞れます。既存のディレクトリをサブボリュームに移す作業はサービスの停止を伴うので、メンテナンス時間に、バックアップを取ってから行ってください。

手順2:読み取り専用スナップショットを作る

スナップショットを置くディレクトリを用意し、-r を付けて読み取り専用で作成します。btrfs send は読み取り専用スナップショットしか送れないため、-r は省けません。

sudo mkdir -p /srv/.snapshots
sudo btrfs subvolume snapshot -r /srv/www /srv/.snapshots/www-20261018-0300
sudo btrfs subvolume list -s /srv

スナップショットを置くディレクトリは、元のサブボリュームと同じ btrfs ファイルシステム上である必要があります。-s を付けた一覧でスナップショットだけを表示でき、作成されたことを確認できます。

手順3:データベースの整合性に注意する

btrfs のスナップショットはサブボリューム単位で瞬時に作られ、ファイルシステムとしては一貫した状態になります。ただし MySQL のように動作中のデータベースから見ると、電源断の直後と同じ「クラッシュ整合」の状態です。InnoDB はクラッシュリカバリで起動できることが多いものの、データベースはスナップショットとは別に mysqldump の --single-transaction などで論理バックアップを取っておくと安心です。

なお、データベースのファイルは CoW と相性が悪く、断片化で性能が落ちることがあります。データディレクトリに chattr +C で CoW を無効にする運用もありますが、新しく作るファイルにしか効かないこと、無効にしたファイルはチェックサムや圧縮の対象外になることを理解したうえで判断してください。

手順4:初回は全体を send/receive で送る

受け取り側も btrfs でフォーマットされている必要があります。外付けディスクや別サーバーに btrfs の領域を用意し、初回はスナップショット全体を送ります。

# 同じサーバーの別ディスクへ
sudo btrfs send /srv/.snapshots/www-20261018-0300 | sudo btrfs receive /mnt/backup/

# 別サーバーへ(受け取り側でも root 権限で btrfs receive を実行)
sudo btrfs send /srv/.snapshots/www-20261018-0300 \
  | ssh root@backup-host "btrfs receive /srv/backup/web01/"

受け取り側には同名の読み取り専用サブボリュームができます。SSH で root ログインを許可したくない場合は、受け取り専用のユーザーに sudo で btrfs receive だけを許可する、といった形で権限を絞ります。

手順5:2回目以降は差分だけを送る

2回目以降は、前回送ったスナップショットを親として -p で指定すると、その差分だけが送られます。

sudo btrfs subvolume snapshot -r /srv/www /srv/.snapshots/www-20261019-0300

sudo btrfs send -p /srv/.snapshots/www-20261018-0300 \
  /srv/.snapshots/www-20261019-0300 \
  | ssh root@backup-host "btrfs receive /srv/backup/web01/"

ここが最もつまずきやすいところです。差分転送には、親にしたスナップショットが送り側と受け取り側の両方に残っている必要があります。送り側で古いスナップショットを消しすぎると、次の差分の親がなくなり、全体を送り直すことになります。少なくとも「最後に送ったもの」は送り側に残す、というルールで世代を管理してください。

btrfs send -f ファイル名 でストリームをファイルに書き出し、btrfs ではないストレージに保存することもできます。ただし差分のストリームは親がないと戻せないため、どのファイルがどの親に依存しているかを管理する手間が増えます。

手順6:世代を整理して自動化する

古いスナップショットは btrfs subvolume delete で削除します。削除しても容量はすぐには戻らず、バックグラウンドで解放されます。

sudo btrfs subvolume delete /srv/.snapshots/www-20261011-0300

作成・送信・削除を自分のスクリプトで組むこともできますが、親の管理を間違えやすいため、既存のツールを使うのが現実的です。

  • btrbk:スナップショットの作成、send/receive による転送、送り側と受け取り側それぞれの保持世代の管理までを設定ファイルで行えるツールです。親の選択も自動で行います。
  • snapper:openSUSE などで使われる、スナップショットの定期作成と世代管理のツールです。主にローカルの巻き戻し用途で、外部への転送は別の仕組みと組み合わせます。

どちらもディストリビューションのパッケージで提供されていることが多いですが、設定の書式や既定値はバージョンによって違うため、導入するバージョンのドキュメントを確認してください(2026年10月現在)。

btrfs で qgroup(クォータ)を有効にしていると、スナップショットが多い環境で削除などの処理が重くなる場合があります。容量制限が不要なら、qgroup が有効かどうかを確認しておくとよいでしょう。

手順7:復元を試す

受け取り側のスナップショットは読み取り専用なので、ファイル単位で戻すならそこからコピーします。

sudo cp -a /srv/backup/web01/www-20261019-0300/wp-content/uploads/2026/10/ /tmp/restore-test/

サブボリュームごと戻す場合は、受け取り側から逆方向に send/receive で送り戻し、届いた読み取り専用スナップショットから書き込み可能なスナップショットを作って使います。

sudo btrfs subvolume snapshot /srv/restore/www-20261019-0300 /srv/www-restored

-r を付けずにスナップショットを作れば書き込み可能になります。元のサブボリュームと差し替えるときは、サービスを止めてから名前を入れ替え、マウント設定(/etc/fstab の subvol= など)も見直します。差し替えは取り返しがつきにくい作業なので、元のサブボリュームはすぐには消さず、動作を確認してから削除してください。

定期的に btrfs scrub start でチェックサムの検証を行うと、受け取り側のディスクでデータが壊れていないかも確認できます。

まとめ

  • btrfs のスナップショットはサブボリューム単位で瞬時に作れるが、同じディスク上にあるだけではバックアップにならない
  • btrfs send には -r の読み取り専用スナップショットが必要で、受け取り側も btrfs にする
  • 2回目以降は -p で親を指定して差分を送る。親は送り側と受け取り側の両方に残す
  • データベースはスナップショットとは別に論理バックアップも取っておく
  • 世代管理は btrbk などのツールに任せ、定期的に復元と scrub で中身を確認する

お気軽にご相談ください

お見積りへ お問い合わせへ
▲