Chienomi

rsyncでなくsend/receiveを使うことでBtrfsに戻す

sync

  • TOP
  • Old Archives
  • rsyncでなくsend/receiveを使うことでBtrfsに戻す

概要

btrfsがrsyncで死んでしまうので、現在はLVM+XFSを使用しているが、いい加減容量は限界近いのでbtrfsに戻す。

rsyncで詰んでしまう以上、rsyncではなく、send/receiveを用いたものとする。 btrfs wikiによれば、rsyncを用いるよりも遥かに高速なのだという。

手順

まずはアンマウント

umount /MirrorSlave

そして、LVMをインアクティブに

vgchange -a n

btrfsを作る

mkfs.btrfs -L MirrorBtr /dev/mapper/btr*

/etc/fstabを編集する

UUID=0123456-7890-acbd-ef01-234567890ab /MirrorRoot           btrfs   noauto,noatime,autodefrag,compress-force=lzo,space_cache,subvol=mirror 0 0

初期化スクリプトを編集する

#!/bin/zsh

typeset -i index=1

for i in /dev/disk/by-id/{ata-foo,ata-bar,ata-baz,ata-quux}
do
#  print $i
  cryptsetup --hash=sha512 --cipher=twofish-xts-plain --offset=0 --key-file=/home/foo/key --key-size=512 open --type=plain "$i" "btrdm_$(printf "%02d" $index)" || exit 1
(( index++ ))
done

mount /MirrorRoot
    
#mount -U 7ebc7d8d-35c6-4d98-8457-3323c242e9fe -o noatime,autodefrag,compress-force=lzo,space_cache,subvol=mirror /MirrorRoot

#pvscan
#vgscan
#lvscan
#vgchange -a y MirrorVG
#lvchange -a y MirrorVG/MirrorLV
#mount -U "0d09b605-a52b-48f4-8ad5-ed26456ab6cd" /MirrorRoot

クライアント側スクリプト。

#!/usr/bin/zsh

notify-send "BtrSnapSync: Woke"

if ! btrfs subvolume snapshot -r /home/foo/share /home/foo/share/snapshots/snapshot-new 
then
  print "BtrSnapSync: **CRITICAL** Failed to create new snapshot"
  exit 2
fi

sync

notify-send "BtrSnapSync: Snapshot."

if [[ -e /home/foo/share/snapshots/snapshot-old ]]
then
  if btrfs send -v -p /home/foo/share/snapshots/snapshot-old /home/foo/share/snapshots/snapshot-new/  | ssh -v -i /root/.ssh/btrsnapsync daisy.local /usr/local/sbin/btrrecv.sh
  then
    notify-send "Send Snapshot."
    btrfs subvolume delete /home/foo/share/snapshots/snapshot-old
    mv /home/foo/share/snapshots/snapshot-new /home/foo/share/snapshots/snapshot-old
    notify-send "Deleted old Snapshot."
  else
    notify-send "Failed to send Snapshot"
    btrfs subvolume delete /home/foo/share/snapshots/snapshot-new
  fi
else
  if btrfs send -v /home/foo/share/snapshots/snapshot-new  | ssh -i /root/.ssh/btrsnapsync daisy.local /usr/local/sbin/btrrecv.sh
  then
    notify-send "Send Snapshot."
    mv /home/foo/share/snapshots/snapshot-new /home/foo/share/snapshots/snapshot-old
    notify-send "Deleted old Snapshot."
  else
    notify-send "Failed to send Snapshot"
    btrfs subvolume delete /home/foo/share/snapshots/snapshot-new
  fi
fi

サーバー側スクリプト

#!/bin/sh
btrfs receive /MirrorRoot && mv /MirrorRoot/snapshot-new /MirrorRooot/snapshot`date +%y%m%d%H%M`

rootのSSH鍵を生成(適宜)

mkdir .ssh
ssh-keygen -f .ssh/snapshot
chmod 700 .ssh
chmod 600 .ssh/*

鍵を転送(適宜)

scp .ssh/snapshot.pub server:.ssh/authorized_keys
ssh server
chmod 600 .ssh/authorized_keys

鍵をコマンドに結びつける

vim .ssh/authorized_keys

sshd_configでforced-commands-only

vim /etc/ssh/sshd_config

挙動

btrfsのsnapshotやsend/receiveについて知識がなかったため、挙動をひとつひとつ確認することにした。

まず、snapshotはディレクトリに見える。 そのディレクトリにはスナップショットの完全なファイルがあるように見える。常時アクセス可能な凍結された状態が存在するわけだ。

そして、スナップショットは元となるボリュームにネストされたサブボリュームになる。 つまり、/fooにマウントされているサブボリュームのスナップショットは、/foo/snapshot1のようになるというわけだ。この外、例えば/barには置けない。

この/foo/snapshot1はmvは可能だが、rmはできない。rmするのであれば、btrfs subvolume deleteでなければならない。

このスナップショットをsendする時、-pオプションがなければそのsnapshotを構成する全体を送信する。あれば、指定されたサブボリューム(マウントされたディレクトリを指定)との差分を送信する。

内容は標準出力に吐かれ、-fオプションで保存することもできるが、それはリダイレクトで保存しても良いようだ。

receiveについても、およそ似たような挙動である。 標準出力から読んで再編成するか、もしくは-fオプションでファイルから編成する。 これは、sharのようなものではなく、編成されるのはスナップショットである。 つまり、snapshot1というsnapshotをreceiveした場合、snapshot1というsnapshotが作られる。

mvで名前が変わった状態で、-pオプション付きで送りつけたsnapshotがどうなるのかは、まだ試していない。

snapshotにロールバックする場合は、マウントポイントの付け替えと、サブボリュームのデリートでよさそうだ。set-defaultが必要か?

多くのスナップショットを維持することでディスク容量やI/Oにどのように影響するのかはわからない。 英語文書を読めばよいのかもしれないが、なかなか大変そうなので、そこには当面手を付ける予定はない。

思わぬつまづき

rootユーザーでRSA鍵でsshログインできないという問題に遭遇した。 一般ユーザーならばできるし、またサーバー側がsshd -dで起動した場合は通る。 デバッグモードなら通るため、メッセージの確認もできない。 かなり困った。