目的
手元のサーバに保存されている一部のデータを遠隔地にあるリモートサーバにバックアップしたい。しかしリモートサーバは信頼できるユーザだけがアクセスできるとは限らないため、データを暗号化して保存する必要がある。そのため、ZFSのスナップショットをOpenSSLで暗号化する。
やりかた
前提条件
- CentOS 7でZFS on Linux(0.7.3)を利用する
- ZFSのスナップショットを使いサービスを停止せずバックアップを転送する
- リモートサーバにはSSHで接続可能とする
- リモートサーバでZFSが利用できない可能性が高いとする
- 転送量を減らすため、pigzで並列して圧縮する
- データは送信前にOpenSSLで暗号化する
- バックアップはスナップショットイメージのまま保管したい
バックアップ
スナップショットを作成済みでリモートサーバにはSSHで公開鍵認証設定済みのとき、次のコマンドでスナップショットの差分を暗号化して転送する。
[スナップショット転送] → [gzip圧縮] → [OpenSSLで暗号化] → [SSHで送信] を一括で実施してる。
# /sbin/zfs send <pool@snapshot> | /bin/pigz -c | \
/bin/openssl enc -aes-256-cbc -e -pass file:/root/password.txt | \
/bin/ssh <user@remote.server> 'cat > /path/to/archive/<pool@snapshot>.zfsbkup'
圧縮についての検討
圧縮するのはファイルサイズの低減とバックアップ時間の短縮を目的としている。
2.5GBの色々なファイル(具体的な内容はメモに残っていなかった)でZFSのスナップショットを保存した場合は以下のようになった。
このテストでは2.5" USB2.0 HDD 3台でRAID-Zを構成しているためI/O速度は期待できない。また、CentOS 6、zfs-fuse 0.6.9、AMD FX-8300 Eight-Core Processorの環境となっている。
# df -h /zfs
Filesystem Size Used Avail Use% Mounted on
tank/pool1 457G 2.5G 454G 1% /zfs
# ls -RF | grep -v / | wc -l
385
# time zfs send tank/pool1@snapshot1 > /root/raw.bin
real 2m6.108s
user 0m0.000s
sys 0m0.002s
# time zfs send tank/pool1@snapshot1 | gzip -c > /root/comp.zip
real 1m33.384s
user 1m29.602s
sys 0m2.591s
# time zfs send tank/pool1@snapshot1 | bzip2 -c > /root/comp.bz2
real 7m18.095s
user 7m10.998s
sys 0m2.956s
# time zfs send tank/pool1@snapshot1 | xz -c > /root/comp.xz
real 12m27.685s
user 12m15.869s
sys 0m10.934s
無圧縮よりgzip圧縮した場合の方が若干高速になっている。
上記のものは全てシングルプロセスだが、マルチプロセス対応の場合はより高速化が期待できる。この実験環境では8並列の処理となっている。
# time zfs send tank/pool1@snapshot1 | pigz -c > /root/comp_p.zip
real 0m52.738s
user 1m54.288s
sys 0m2.740s
# time zfs send tank/pool1@snapshot1 | pbzip2 -c > /root/comp_p.bz2
real 1m25.417s
user 10m51.964s
sys 0m14.876s
# time zfs send tank/pool1@snapshot1 | pxz -c > /root/comp_p.xz
real 3m55.171s
user 17m37.772s
sys 0m6.262s
圧縮後のファイルサイズは以下のようになった。
# ll -h
合計 7.2G
-rw-r--r--. 1 root root 1.3G 2月 7 14:46 2014 comp.bz2
-rw-r--r--. 1 root root 1.1G 2月 7 14:59 2014 comp.xz
-rw-r--r--. 1 root root 1.3G 2月 7 15:40 2014 comp.zip
-rw-r--r--. 1 root root 1.3G 2月 7 15:05 2014 comp_p.bz2
-rw-r--r--. 1 root root 1.2G 2月 7 15:10 2014 comp_p.xz
-rw-r--r--. 1 root root 1.4G 2月 7 15:35 2014 comp_p.zip
-rw-r--r--. 1 root root 2.5G 2月 7 14:25 2014 raw.bin
この結果からpigzを使うことにした。xzの圧縮率が抜群だが、速度と見合わないと判断した。
OpenSSLでの暗号化を含めた場合の処理時間は以下のようになった。処理時間に対する暗号化の影響はほとんど見られない。
# time zfs send tank/pool1@snapshot1 | pigz -c | \
openssl enc -aes-256-cbc -e -k password > /root/pig_e.zip
real 0m54.551s
user 1m58.044s
sys 0m4.474s
検討その2
Xeon E5620 x2と高速ストレージの実環境下でテストした場合もpigzを利用した方が高速だった。
# zfs list -t snapshot
NAME USED AVAIL REFER MOUNTPOINT
tank/pool@full_201510242317 364K - 116G -
# time zfs send tank/pool@full_201510242317 | \
openssl enc -aes-256-cbc -e -k password > /nfs/full_201510242317.enc
real 61m24.104s
user 7m29.039s
sys 3m30.057s
# time zfs send tank/pool@full_201510242317 | pigz -c | \
openssl enc -aes-256-cbc -e -k password > /nfs/full_201510242317.zip.enc
real 52m42.727s
user 245m18.443s
sys 13m56.552s
# ll -h
合計 221G
-rw-r--r-- 1 nfsnobody nfsnobody 117G 10月 25 17:54 2015 full_201510242317.enc
-rw-r--r-- 1 nfsnobody nfsnobody 105G 10月 25 00:25 2015 full_201510242317.zip.enc
リストア
リストア時は何らかの方法で手元にファイルを持ってきている状態を想定している。
復元する場所はスナップショット取得時と同一のZFSプールである必要はない。
# /bin/openssl enc -aes-256-cbc -d -pass file:/root/password.txt -in /path/to/archive/<pool@snapshot>.zfsbkup | \
/bin/pigz -d | /sbin/zfs receive <pool/restore>