Category Archives: zfs

zfs snapshotの差分send/recvについて

Pocket

 

zfs snapshotの差分send/recvについて

zfsのバックアップは、snapshotを撮っておいて、自ホストの別zpool、あるいは他ホストの別zpoolに移すことで行われる。
バックアップは定期的に行われるものであるが、ではそのsnapshotを移す際、毎回毎回まるまる送っていたんでは帯域も時間もディスク寿命も無駄である。
zfsはそこも考慮していて、差分だけを送ればいいようにincrementalオプションがきちんと用意されている。

書式は以下の通りsendに-iオプションを与えるだけ。
(recv側にはsnapshotAがすでに転送済みの前提)

zfs send -i <snapshotA> <snapshotB> | zfs recv <target pool>

 

よろしい。では次回からは…?

ふむ。
では二回目以降はどうするのだろう?
上記の書式例でsnapshotCが出来たらどうするのだろう?
まさかsnapshotA, B, Cを全部並べるのか?と思ったけどそれは間違いで、snapshotB, Cだけでよい。

recv側にはsnapshotAがすでにあるとき。
zfs send -i snapshotA snapshotBでAとBの差分のみが送られる。
つぎにzfs send -i snapshotB snapshotCでBとCの差分のみが送られる、というわけ。

では早速試してみる。が。

「転送先が更新されているため差分を転送できません」

こんなエラーがでる。

cannot receive incremental stream: destination warehouse/dir has been modified
since most recent snapshot

まあ文字通りなんですが。
バックアップ用の転送先が更新されるのはなぜか分からないが(atimeだろうか?)。

こういう場合には、recv側で-Fオプションを与えればよい。
-Fオプションによりrecv側は最新snapshotに強制rollbackして、それからsnapshotを受け取る。

下記の例だと、recv側は@20131226にいったんrollbackしてから受け取る。

$ sudo sh -c "zfs send -i vault/chamber@20131226 vault/chamber@2014010
2 | zfs recv -F warehouse/chamber"

 

atimeのoff

recv側がなぜ更新されてるのか、atimeが怪しいのでoffにしておく。
recv側のzpoolに対してzfs set atime=offするだけ。
(zpoolから切り出されたzfsすべてに適用される)

$ zfs get atime warehouse
NAME       PROPERTY  VALUE  SOURCE
warehouse  atime     on     default
$ sudo zfs set atime=off warehouse
$ zfs get atime warehouse
NAME       PROPERTY  VALUE  SOURCE
warehouse  atime     off    local
$ zfs get atime warehouse/chamber
NAME               PROPERTY  VALUE  SOURCE
warehouse/chamber  atime     off    inherited from warehouse

 

[メモ]zpoolのVersionについて(Versionナンバはもう使われない)

Pocket

 

過日、zpool v28のアップグレードをして、いくつかのfeature flagsを有効にした。
したのだが、よく分からないことがいくつかあった。

すなわち、最新のはずのv28なのにアップグレードを促されたこと、アップグレードしたら zpool get allの結果からバージョンが消えてしまったこと、である。

WikipediaのZFSやOpenZFSを眺めてみて分かったのは、zpool((Open)ZFS)はv28以降、バージョンナンバの使用を止めてしまったせいとの由。
http://en.wikipedia.org/wiki/OpenZFS
http://en.wikipedia.org/wiki/ZFS#RELEASEHISTORY

以下に調べた結果を示す。
なお、ご覧の通り情報の出所はwikipediaである。
問題ないとは思うが、各位においてはご留意されたい。

ZFSの歴史

もともと、zpoolやZFS filesytemに機能が追加されるたび、バージョンナンバがインクリメントされてきた。
しかし2010年、OpenSoralisの開発が停止され、ZFSはオープンソースではなくなった。
本家(Oracle)のZFSはプロプライエタリとなって、2013/12/24現在、ZFS filesystemはv6, ZFS Poolはv34まで進んでいる。

それはそれとして、illumos(OpenSolaris後継)やBSD/Linux/OSX関連の方々は、オープンであったzfs v5, zpool v28をベースに本家とは別の開発が進める。
これが2013年にOpenZFSとなる。

バージョンナンバとフィーチャーフラグ

OpenZFSはいろんな所でいろんな人々が開発を続けている。
こういった状態で、単一のバージョンナンバを付与することは不可能である。
そこでフィーチャーフラグ(feature flags)という考え方を導入する。
機能ごとに個別の名前を与える、というもの。

個別の名前は、feature@<org-name>:<feature-name>という書式で表される。
org-nameは当該機能を開発した組織名。一意の名前。もちろん、勝手につけることは許されない。
org-nameが明らかな場合には、feature@<feature-name>と短縮してもよい。
feature@async_destroyというように。

フィーチャーの状態

フィーチャーの状態には三つある。
disabled, enabled, activeである。

  • disabled: 無効。機能を使えない状態。
  • enabled: 機能を使える状態。有効にはなっていない。
  • active: 機能が有効。旧バージョンとの互換性がなくなっている。

フィーチャーの種類

  • features for write : 書き込みには必須の機能。読み込みのみであれば不要。
  • features for read : 読み込み、あるいはpoolを開くために必須の機能。

たとえばasync_destroyはデータ書き込みの時だけ必要な機能なのでfeatures for write。

バージョンについて

一つでもフィーチャーを有効にするとpoolのバージョンは1000になる。
1000とはめちゃくちゃな数に見えるかもしれないが、本家のバージョンと被らないようにするため。

おわりに

ここで改めてzpoolの出力を見てみると、poolのバージョンがハイフンになっていることや、フィーチャーの記載など、なるほどと理解できることがありますな。

$ zpool get all|grep vault
vault size 2.27T -
vault capacity 64% -
vault health ONLINE -
vault version - default
(略)
vault feature@async_destroy enabled local
vault feature@empty_bpobj enabled local
vault feature@lz4_compress enabled local

 

[メモ]zpoolのupgrade

Pocket

 

zpoolのupgradeをしたのでメモ。
結論としては、zpoolのupgradeとは、単にversionを上げるだけ以外にもあるようだ。

legacy on-disk formatでformat??

気がつくと、zpool statusで文句を言われていた。

$ zpool status
  pool: vault
 state: ONLINE
status: The pool is formatted using a legacy on-disk format.  The pool can
        still be used, but some features are unavailable.
action: Upgrade the pool using 'zpool upgrade'.  Once this is done, the
        pool will no longer be accessible on software that does not support feature
        flags.
(略)

曰く、「このpoolはlegacy on-disk formatでフォーマットされている。
もちろんpoolは引き続き使えるけれども、いくかの機能が使えない。」とのこと。

zpoolを調べてみたが、最新のv28である。

$ zpool get all|grep vault
vault      size                   2.27T                  -
vault      capacity               64%                    -
vault      health                 ONLINE                 -
vault      version                28                     local
(略)

 

zpool upgradeで調べて分かってきた。
zpoolバージョンではなくfeature flagsのことを言っているわけだ。

$ zpool upgrade
This system supports ZFS pool feature flags.

The following pools are formatted with legacy version numbers and can
be upgraded to use feature flags.  After being upgraded, these pools
will no longer be accessible by software that does not support feature
flags.

VER  POOL
---  ------------
28   vault

Use 'zpool upgrade -v' for a list of available legacy versions.
Every feature flags pool has all supported features enabled.

 

で、もういちど調べてみると。

$ zpool get all|grep vault
vault      size                   2.27T                  -
vault      capacity               64%                    -
vault      health                 ONLINE                 -
vault      version                28                     local
(略)
vault      feature@async_destroy  disabled               local
vault      feature@empty_bpobj    disabled               local
vault      feature@lz4_compress   disabled               local

featureがいくつかdiabledになっている。
そうと分かれば素直にupgradeである。

zpoolのupgrade

zpool upgradeとするだけ。
ただ、バージョンが変わらないとはいえ、ファイルシステムの基盤をアップグレードするわけだからバックアップは取っといた。

$ sudo zpool upgrade vault
This system supports ZFS pool feature flags.

Successfully upgraded 'vault' from version 28 to feature flags.
Enabled the following features on 'vault':
  async_destroy
  empty_bpobj
  lz4_compress

あっけなく終了。

調べてみるとversionが消えて(なぜ….でもpropertiesがdefaultだからよしとしよう)、その代りfeatureはすべてenabledに変化したことが分かる。
なお、enabledは「その機能が使えますよ」という表示。
実際に有効にするとenabledはactiveに変化する。

$ zpool get all|grep vault
vault      size                   2.27T                  -
vault      capacity               64%                    -
vault      health                 ONLINE                 -
vault      version                -                      default
(略)
vault      feature@async_destroy  enabled                local
vault      feature@empty_bpobj    enabled                local
vault      feature@lz4_compress   enabled                local

 

zpool upgrade、zpool statusの表示いずれも問題なし。

$ zpool upgrade
This system supports ZFS pool feature flags.

All pools are formatted using feature flags.

Every feature flags pool has all supported features enabled.

$ zpool status
  pool: vault
 state: ONLINE
  scan: scrub repaired 0 in 4h53m with 0 errors on Sat Jul 27 14:35:23 2013
config:

        NAME        STATE     READ WRITE CKSUM
        vault       ONLINE       0     0     0
          ada1      ONLINE       0     0     0

errors: No known data errors

 

No tags for this post.

[メモ] ディスクを追加してZFSを作り、他zpoolのsnapshotを送り込む

Pocket

 

HDDを増設してZFSを作ったのでメモ。
一本のHDDにpool、zfsを作成し、圧縮、重複排除機能の有効化まで。
環境は(残念ながら10.0-Rではなく)FreeBSD 9.2-RELEASE-p1。

lz4でzfsの圧縮機能を気軽に試せるように

ファイルシステムで圧縮機能を有効にすると、読み書きのいずれにもCPUパワーが必要で、要するに遅くなる。
非力なCPUを使っているとなかなか使いにくい機能なのだが、圧縮方法にlz4が選べるようになってハードルは下がったように思う。
lz4はここでも触れたが、めっぽう速い圧縮アルゴリズムである。
これはぜひとも使ってみなければ。

 

 

ディスクの確認とzfs機能の確認

物理ディスクを追加し、ブートしたらdmesgを確認する。

$ uname -r
9.2-RELEASE
$ dmesg|grep ada
ada2 at ahcich2 bus 0 scbus2 target 0 lun 0
ada2: <WDC WD30EZRX-00D8PB0 80.00A80> ATA-9 SATA 3.x device
ada2: 300.000MB/s transfers (SATA 2.x, UDMA6, PIO 8192bytes)
ada2: Command Queueing enabled
ada2: 2861588MB (5860533168 512 byte sectors: 16H 63S/T 16383C)
ada2: quirks=0x1<4K>
ada2: Previously was known as ad8

ada2とのこと。

作業前にzfs, zpoolのバージョンを確認しておいてもいいかも。
zfs, zpoolそれぞれにupgradeオプションを与えればよい。
upgradeという名前の通り、upgradeのためのコマンドだが、バージョン確認にも使える。

$ zfs upgrade
This system is currently running ZFS filesystem version 5.

All filesystems are formatted with the current version.
$
$ zpool upgrade
This system supports ZFS pool feature flags.

The following pools are formatted with legacy version numbers and can
be upgraded to use feature flags.  After being upgraded, these pools
will no longer be accessible by software that does not support feature
flags.

VER  POOL
---  ------------
28   vault

Use 'zpool upgrade -v' for a list of available legacy versions.
Every feature flags pool has all supported features enabled.

zfsはバージョン5、zpoolはバージョン28。
このバージョンであれば、lz4による圧縮機能(LZ4 Compression algorithm support)と、重複排除機能(Deduplication)を使える。

pool、zfsの作成

warehouseというzpoolを作り、そこからbackupというボリュームを切り出す。

まずzpoolを作る。
ほんと簡単で速くて助かる。

$ sudo zpool create backup /dev/ada2
$

で確認。

$ mount
/dev/ada0p2 on / (ufs, local, journaled soft-updates)
devfs on /dev (devfs, local, multilabel)
vault/itunes on /itunes (zfs, local, noatime, nfsv4acls)
vault/chamber on /chamber (zfs, local, noatime, nfsv4acls)
backup on /backup (zfs, local, nfsv4acls)

$ zpool status
pool: backup
state: ONLINE
scan: none requested
config:

NAME        STATE     READ WRITE CKSUM
backup      ONLINE       0     0     0
ada2      ONLINE       0     0     0

errors: No known data errors

pool: vault
state: ONLINE
(略)

$ df
 Filesystem     1K-blocks      Used      Avail Capacity  Mounted on
 /dev/ada0p2    239436440  20822200  199459328     9%    /
 devfs                  1         1          0   100%    /dev
 vault/itunes  1436646199 598670122  837976077    42%    /itunes
 vault/chamber 1796007595 958031518  837976077    53%    /chamber
 warehouse     2873622450        31 2873622419     0%    /warehouse

ではzpoolからzfsの切り出し。
先ほど作成したwarehouseからbackupという名前で。

$ sudo zfs create warehouse/backup
$
$ mount
/dev/ada0p2 on / (ufs, local, journaled soft-updates)
devfs on /dev (devfs, local, multilabel)
vault/itunes on /itunes (zfs, local, noatime, nfsv4acls)
vault/chamber on /chamber (zfs, local, noatime, nfsv4acls)
warehouse on /warehouse (zfs, local, nfsv4acls)
warehouse/backup on /warehouse/backup (zfs, local, nfsv4acls)
$ df
Filesystem        1K-blocks      Used      Avail Capacity  Mounted on
/dev/ada0p2       239436440  20823572  199457956     9%    /
devfs                     1         1          0   100%    /dev
vault/itunes     1436646199 598670122  837976077    42%    /itunes
vault/chamber    1796007595 958031518  837976077    53%    /chamber
warehouse        2873622404        32 2873622372     0%    /warehouse
warehouse/backup 2873622403        31 2873622372     0%    /warehouse/backup

あとは/etc/fstabに書くだけ。
warehouse/backupを/backupにマウントするとして以下のように書いておき。

warehouse/backup        /backup zfs     rw      0       0

/warehouse/backupをいったんunmountしてそれからmount。

$ sudo umount /warehouse/backup
$
$ mount
/dev/ada0p2 on / (ufs, local, journaled soft-updates)
devfs on /dev (devfs, local, multilabel)
vault/itunes on /itunes (zfs, local, noatime, nfsv4acls)
vault/chamber on /chamber (zfs, local, noatime, nfsv4acls)
warehouse on /warehouse (zfs, local, nfsv4acls)
$
$ sudo mount /backup
$
$ mount
/dev/ada0p2 on / (ufs, local, journaled soft-updates)
devfs on /dev (devfs, local, multilabel)
vault/itunes on /itunes (zfs, local, noatime, nfsv4acls)
vault/chamber on /chamber (zfs, local, noatime, nfsv4acls)
warehouse on /warehouse (zfs, local, nfsv4acls)
warehouse/backup on /backup (zfs, local, nfsv4acls)

 

圧縮機能と重複排除機能を有効に

ではさっそく圧縮機能と重複排除機能を有効にする。
といっても、すっごく簡単なんだけどね。

$ sudo zfs set dedup=on warehouse/backup
$
$ sudo zfs set compression=lz4 warehouse/backup
$

確認。
zfs getで対象zfsの属性を確認できる。

$ zfs get dedup warehouse/backup
NAME              PROPERTY  VALUE          SOURCE
warehouse/backup  dedup     on             local
$
$ zfs get compression warehouse/backup
NAME              PROPERTY     VALUE     SOURCE
warehouse/backup  compression  lz4       local
$

タイプが面倒ならzfs get allですべての属性を表示させ、grepすればよい。

$ zfs get all warehouse/backup|egrep "compre|ded"
warehouse/backup  compressratio         1.00x                    -
warehouse/backup  compression           lz4                      local
warehouse/backup  dedup                 on                       local
warehouse/backup  refcompressratio      1.00x                    -

 

書き込んでみる

今回追加したHDDはもともとバックアップ用途のつもり。
ここにスナップショットを流しこんでみる。

以下のようにしてスナップショットを作成する。

$ sudo zfs snapshot vault/itunes@`date +%Y%m%d`
$
$ sudo zfs snapshot vault/chamber@`date +%Y%m%d`

スナップショットのサイズは以下のとおりである。

$ zfs list -t snapshot
NAME                     USED  AVAIL  REFER  MOUNTPOINT
vault/chamber@20131121      0      -   914G  -
vault/itunes@20131121       0      -   571G  -

これらスナップショットをバックアップのHDDに流し込む。
zfs sendとzfs recvをパイプで繋ぐ必要がある。
sudoを使う場合にはsh -cで。

$ sudo sh -c "zfs send vault/chamber@20131121 | zfs recv warehouse/backup/chamber"

注意点がある。
以上のようにsnapshotを送ると、受け側では:
①warehouse/backup/chamber ができ、さらに;
②warehouse/backup/chamber@20131121 つまり;
実ディレクトリで言えばwarehouse/backup/chamber/.zfs/snapshot/20131121ができる。

漠然とvault/chamber@20131121の内容がwarehouse/backup/chamberに書き込まれる思っていたので驚いた。

 

また、ロードアベレージを監視するような仕組みは特に入れていなかったので、topの出力を見たところ5を超えてた。ちょっと怖い。

last pid: 10483;  load averages:  5.37,  2.84,  1.36           up 2+23:24:54  22:01:40
45 processes:  3 running, 42 sleeping
CPU:  0.0% user,  0.0% nice, 56.8% system,  0.3% interrupt, 42.9% idle
Mem: 20M Active, 96M Inact, 1592M Wired, 11M Cache, 200M Buf, 120M Free
ARC: 1039M Total, 58M MFU, 826M MRU, 103M Anon, 11M Header, 40M Other
Swap: 907M Total, 10M Used, 897M Free, 1% Inuse

そしてたかだか913GBのsnapshotの転送にかかった時間であるが。

real    3756m59.109s
user    0m0.048s
sys     192m3.897s

まる二日半て…。
これは圧縮か重複排除か、どちらか止めた方がいいかもわからんね。

差分snapshotの転送

オリジナルディスクで複数回snapshotを作成した場合、バックアップディスクにはその差分を送ることができる。
zfs sendに-iを与え、二つのsnapshotを指定すればよいだけ。

$ sudo sh -c "zfs send -i vault/chamber@20131121 vault/chamber@20131125 | zfs recv warehouse/backup/chamber"

以上

FreeBSD 10インストーラからのzfs on rootを試してみたよー

Pocket

 

FreeBSD 10.0-RELEASEから、インストールの際にファイルシステムとしてZFSが選べるようになる。
システムの置かれるファイルシステムをZFSにする、ということは、今までも出来ないことはなかったけど、そりゃもう面倒な手順を経る必要があった。
それがインストールの時の選択ひとつで出来るようになったというのは、けっこうすごいこと。

また、システムをZFSに置けると、まずパーティションの切り方に悩まなくて済む。
あとで/varが足らないとか/usr/localがとかそういったことが無くなる。

そのうえで、システムまるごとzfsのアドバンテージを満喫できる。
まるまるスナップショット取れたりするからね。

ただ、2012/10/10現在、いまだテスト中のところであり、10.0-BETA1あたりに入るかも、という状態。(2013/10/15追記; 10.0-BETA1に入ってました)
そんな状態で試してみた顛末を記す。

なお一次情報は以下の通り。

 

インストーラでのzfs on rootを試す

前提:FreeBSD 10.0-ALPHA5, zfsbootonly.2013-10-09.isoをvirtualboxで試しています。
注意: 先述の通りテストの真っ最中なので、下記の内容が変わる可能性は十分にあります。

Allan Jude氏のページからインストーラをダウンロードする。
通常通り起動し、10.0になっても相変わらず愛想のかけらもないメニューを選択して進むと、以下の通りフォーマットのところでZFSが選べる。

 

menu001

ZFSを選ぶとこのように。

menu002

使うディスクを選び、進む。

menu003

あとは通常通り。

 

unameはこの通り。

FreeBSD yaryka 10.0-ALPHA5 FreeBSD 10.0-ALPHA5 #0 r256092: Sun Oct  6 22:30:23 UTC 2013     root@snap.freebsd.org:/usr/obj/usr/src/sys/GENERIC  amd64

 

カーネルモジュールがこのように組み込まれている。

$ kldstat
Id Refs Address            Size     Name
 1   10 0xffffffff80200000 17fbc88  kernel
 2    1 0xffffffff819fc000 2b66d0   zfs.ko
 3    2 0xffffffff81cb3000 8098     opensolaris.ko

 

 

ディスクの内容はこのように。

$ df -h
Filesystem                   Size    Used   Avail Capacity  Mounted on
zroot/bootenv/default         61G    856M     60G     1%    /
devfs                        1.0k    1.0k      0B   100%    /dev
zroot/tmp                     60G    176k     60G     0%    /tmp
zroot/usr/home                60G    184k     60G     0%    /usr/home
zroot/usr/local               60G    144k     60G     0%    /usr/local
zroot/usr/obj                 60G    144k     60G     0%    /usr/obj
zroot/usr/ports               60G    160k     60G     0%    /usr/ports
zroot/usr/ports/distfiles     60G    144k     60G     0%    /usr/ports/distfiles
zroot/usr/ports/packages      60G    144k     60G     0%    /usr/ports/packages
zroot/usr/src                 60G    144k     60G     0%    /usr/src
zroot/var                     60G    452k     60G     0%    /var
zroot/var/crash               60G    148k     60G     0%    /var/crash
zroot/var/db                  60G    240k     60G     0%    /var/db
zroot/var/db/pkg              60G    144k     60G     0%    /var/db/pkg
zroot/var/empty               60G    144k     60G     0%    /var/empty
zroot/var/log                 60G    196k     60G     0%    /var/log
zroot/var/mail                60G    144k     60G     0%    /var/mail
zroot/var/run                 60G    228k     60G     0%    /var/run
zroot/var/tmp                 60G    152k     60G     0%    /var/tmp

 

No tags for this post.

ZFS scrubを過信してはいけません。

Pocket

ZFS運用を始めてはや数か月。なんの問題もなく使っておりますが、

 「scrubって定期的にやるといいらしいよ」

 「なんかね、fsckみたいなこと、やってくれるらしいよ」

などという話を聞いた。

全くそんなことやってないので、慌てて調べてみた。

結論として、やっといた方がいいけど、なんか「fsckみたいな」と表現するのはおかしいよな、との理解に至った次第。

ZFSのおさらい

ZFSのキモのひとつは、セルフヒーリングにある。

格納されているデータに対して、強力なチェックサムを持っていて、不整合があっても勝手に修復する。

勝手に、というのはどういうことかというと、不整合を見つけ「次第」、つまりアクセスしたファイルに不整合があったらその場で修復してしまう、というところ。

だから、http://docs.oracle.com/cd/E19253-01/819-6260/gbbxi/index.html のとおり

データの不一致が ZFS 構成内のディスク上で発生するとすれば、それはハードウェア障害が発生した場合か、ZFS ソフトウェアにバグが存在する場合だけ

なので、ZFSソフトウェアバグはさておき、論理的なデータ不一致の発生リスクについてはとくに手だて不要というわけだ。

ハードウェア障害ならもうそこは物理的なディスクの冗長でなんとかせい、ということになる。

言い換えると、ZFS上のファイルにアクセスできない場合には、もうこれは尋常ではない障害が起こっているということであり、あなたはヘビーな状況下にいるということである。(その場合はこちら。)

http://docs.oracle.com/cd/E19253-01/819-6260/gbctt/index.html

じゃあscrubってなによ

そういった仕組みを踏まえてscrubというツール。

これは、上述の「不整合があったら修復する」というのを全データに対して行うだけ。

…ということは。

scrubをすれば全データのチェックはする。するけれども、そもそもscrubしてようがしてまいが、そんなことはお構いなしに、個々のファイルにアクセスしたらそのときに不整合チェックはされる。

カブってるじゃないか。

むしろscrub頻繁にやったらディスクに無用な負荷かけないか?

となるとscrubのメリットは何か。

http://docs.oracle.com/cd/E19253-01/819-6260/gbbyd/index.html

ZFS では、すべての不一致を定期的にチェックする機構が用意されています。この 機能は「スクラブ」と呼ばれ、メモリーやほかのシステム内で、ハードウェアまたはソフトウェア障害が発生する前にエラーを検出および回避する手段として一 般的に使用されます。

定期的にスクラブを実行すると、システム上のすべてのディスクへの継続的な入出力が保証されます。

スクラブを行なっているときまたは必要なファイルにアクセスしているときにエラーが発生した場合には、そのエラーが内部でログに記録されるので、そのプールで認識されているすべてのエラーの概要をすぐに確認できます。

とのこと。

「scrubすれば不整合があっても修復される」というのは、まあ間違ってはいないけど、むしろscrubの主目的はそこよりも、障害の予兆をつかむことにあると理解している。

たとえば。

scrubの定期的な実行をしないとする。

するとデータ不整合チェックは、個々のファイルアクセス契機で行われる。

不整合があればその都度、解消されるだろうし、解消されない場合には、ヘビーな状況だとして障害復旧を行うだろう。

しかし、滅多にアクセスしないファイルで致命的な、おそらく物理的な障害が発生し、影響が徐々に広がっていくような場合、このスタイルでは検知が遅れる可能性がある。

それを防ぐには、定期的にscrubで全ファイルをチェックし、「そのプールで認識されているすべてのエラーの概要」も定期的にチェックすればよい。

結果、「ハードウェアまたはソフトウェア障害が発生する前にエラーを検出および回避」できる可能性が高くなる、と。

scrubの使い方

というわけで使ってみた。まあコマンド例はいくらでもあるから淡々と。

$ zpool list
NAME    SIZE  ALLOC   FREE    CAP  DEDUP  HEALTH  ALTROOT
vault  2.27T  1.30T   990G    57%  1.00x  ONLINE  -

このpoolに対して実行。

$ sudo zpool scrub vault
$  

(すぐプロンプトが返ってくる)

$ sudo zpool status -v
pool: vault
state: ONLINE
scan: scrub in progress since Tue Dec 18 22:53:46 2012
154M scanned out of 1.30T at 5.70M/s, 66h19m to go
0 repaired, 0.01% done
config:
NAME        STATE     READ WRITE CKSUM
vault       ONLINE       0     0     0
ada1      ONLINE       0     0     0
errors: No known data errors

えっ66時間かかるの?

(いまだに冗長化してないのが恥ずかしい。今回scrub調べてほんとに危ないのでディスク買わねばと思った)

$ sudo zpool status -v
パスワード:
pool: vault
state: ONLINE
scan: scrub in progress since Tue Dec 18 22:53:46 2012
239G scanned out of 1.30T at 81.4M/s, 3h48m to go
0 repaired, 17.95% done
config:
NAME        STATE     READ WRITE CKSUM
vault       ONLINE       0     0     0
ada1      ONLINE       0     0     0
errors: No known data errors

OKOK。

なお、エラーが発生すれば、このstatusのほかに、syslogに表示されるし、たとえばFreeBSDならroot宛のメールにZFS poolsの状態も記載される。こんな感じに;

Checking status of zfs pools:

all pools are healthy

vaultに対するログにもきっちりと(こういうとこZFSって素敵だ)

$ sudo zpool history vault
History for 'vault':
2012-03-05.22:41:40 zpool create vault ada1
2012-03-05.22:54:14 zfs create vault/chamber
2012-03-05.22:56:44 zfs set mountpoint=/chamber vault/chamber
2012-03-18.00:37:52 zfs create vault/test
2012-03-18.00:43:27 zfs set dedup=on vault/test
2012-03-18.00:46:48 zfs destroy vault/test
2012-12-18.22:53:55 zpool scrub vault

なお、scrubの停止は-sコマンドで。

No tags for this post.

ZFSの重複ファイル節約機能dedupがすげえ(ただしメモリ大尽に限る)

Pocket

最初にお断りするが、十分なメモリ、あるいはSSDをお持ちでない方は帰っていただいて結構です。

 

Dedupとは

ZFSにはdedupという機能がある。

その機能を有効にすると、例えばここに1GBのファイルが一つあるとして、それをコピーしても、場所が同じpool内である限り、1GBのディスクしか消費しない。

 

何それただのハードリンクと思うのは早い。

 

仮に同一のファイルA, Bがあるとする。いずれも1GB。

ハードリンクすればディスク消費量は1GBだ。

さてここで、ファイルBの一部、1bitだけを変えたいとする。

もはやハードリンクはできず、別個のファイルとして扱うことになる。

したがってディスク消費は2GB。

 

ではdedupだとどうなるか。

1bit違う1GBのファイル二つがあっても、なんと1GBと128KBだけしかディスクを消費しないという驚きの仕組み。

 

どういうことかというと、dedupはファイルが同じかどうかをブロックごとに判断するということ。

先の例でいえば、異なる1bitを含むブロック分だけを追加で確保し、それ以外はファイルAと同じものを使う。

なお、ZFSでブロックサイズは512B~128KB。

つまり大目に見積もっても1GBと128KBだけの消費でよいわけ。

 

種明かし:テーブルと大量のメモリ

なぜそんなことができるのか。

ZFSはプール上にあるデータのすべてのブロックのハッシュをメモリ上に持っている。

あるファイルをディスクに書き込む前に、ファイルをブロックに分解しハッシュテーブルと照合、書き込み要否を判断するという仕組み。

 

問題はメモリ上に置くテーブルのサイズだ。

dedupを有効に使うには、テーブルを置けるほど十分なメモリが必要になる。

しかし、のちほど見積もりをするが、数TBのディスクを考えるとメモリで賄うのは少々厳しい。

当然、メモリをこればっかりに使うわけにもいかないのだし。

もちろん、テーブルをハードディスクに置くことはできるが、ファイルを書き込むたびにディスク上のハッシュテーブルを参照することになる。

つまりすっごく遅くなる。

よろしい。ならばSSDだ。

とはいえ、Dedupの目的がディスクの容量節約ならば、安いHDDケチってメモリ、SSD無理して買うのも本末転倒という話になってくる。

月並みだけど、よく考えた方がいいよね。

 

Dedupの見積もり。

では仮に2TBのデータが詰まったZFSでDedupしたら、どれくらいのメモリが必要か。

ハッシュテーブルは1ブロックにつき320Bytes。

zfsのブロックサイズは512Bから128KBで可変。

ざっくり64KBとみなす。

では計算。

 

2TB=1024 * 1024 * 1024 * 2 = 2147,483,648KB。

2TB/64KB=33,554,432 blocks

2TBは33,554,432 blocks。

1blockあたり320Bytesなので、かければテーブルに必要なサイズが出る。

 

33,554,432 blocks * 320 Bytes = 10,737,418,240 = 10GBytes

 

はい解散。

と言いたくなるレベルですな。

念のため記載するが、上記は2TBのデータを使っているときのdedupテーブルの試算。

2TBのプールに100bytes程度のファイル一つ置いただけなら、ハッシュテーブルは320Bytes程度。

 

Dedupの活きる道

そもそも2TB全部にDedupするのが間違いであった。

Dedupを活かしたいなら、扱うファイルで決めるのも手。

ざっくり言えばオフィスドキュメント、仮想マシンイメージなど、重複が見込まれるファイルを多く保管するディレクトリに対してのみDedupするとよいでしょう。

一方で動画などはあまり有効ではないでしょう。

なお、プールでDedupするとどれくらい得か、というのは調べることができる。

zdbにプール名を与えてやればいい。

一番下に重複具合が表示される。以下の例では1.06。あまり意味はないってことですな。

ちなみに、あるプールに同一のファイルを3つだけ置くとここが3.00になる。

$ sudo zdb -S vault
パスワード:
Simulated DDT histogram:
bucket              allocated                       referenced
______   ______________________________   ______________________________
refcnt   blocks   LSIZE   PSIZE   DSIZE   blocks   LSIZE   PSIZE   DSIZE
------   ------   -----   -----   -----   ------   -----   -----   -----
1    8.22M   1.02T   1.02T   1.02T    8.22M   1.02T   1.02T   1.02T
2     406K   50.6G   50.6G   50.6G     815K    102G    102G    102G
4      185   17.1M   17.1M   17.1M      835   73.6M   73.6M   73.6M
8      146   14.2M   14.2M   14.2M    1.75K    182M    182M    182M
16       17   8.50K   8.50K   8.50K      407    204K    204K    204K
32      150   16.7M   16.7M   16.7M    5.43K    600M    600M    600M
64        9    132K    132K    132K      820   9.49M   9.49M   9.49M
128        6      3K      3K      3K    1.02K    521K    521K    521K
256        3    129K    129K    129K      884   40.5M   40.5M   40.5M
64K        1    128K    128K    128K    73.4K   9.18G   9.18G   9.18G
Total    8.62M   1.07T   1.07T   1.07T    9.10M   1.13T   1.13T   1.13T
dedup = 1.06, compress = 1.00, copies = 1.00, dedup * compress / copies = 1.0

DedupのONのしかた

まあzfs set dedup=ONとかすればいいんだけど、現状使う予定もないので詳しく調べてない。

No tags for this post.

ZFS優しすぎ涙がでた。

Pocket

前口上

試しにZFSを使ってみて(VMware Playerで気軽に試せるようになったとは、なんと便利な世の中か)本当に驚いた。

ディスク繋いでzpoolコマンド一発ですぐ使える。パーティションに頭を悩ませる必要もない。RAIDだって楽勝。ディレクトリごとに圧縮することもできるし、気が変わったら、いつでも止めることもできる。スナップショットも早い。

実は、何年か前にZFSについて調べたときはまだまだバギーな印象だったのと、ZFSを使えるようなパワフルマシンがなく保留にしてたんだけど、すごく損した気分。

いままで幾たび、fdiskやnewfs失敗してひどい目にあったことか。電子の海に消えたデータを思う。

 

そしてRAID。ソフトRAIDで言えばlvmも有名だが、俺にはもうコマンドが複雑すぎて覚えられない(lv…が論理ボリュームを、pv…が物理ボリュームを扱うんだって?)。

これはすごく危険。

だってソフトRAID含め、こういったディスクを扱うコマンドを使うのは、初期設定と、問題の発生したとき。

俺みたいなオッチョコチョイが、問題が発生して焦っているときに、コマンドが複雑だと二次災害を引き起こすんだって。

…正直に言うと実際に引き起こした。

 

ZFSならとにかくzpool、zfsさえ覚えておけばいいのだ。

 

ZFS

宅鯖ではZFSを使いたいからFreeBSDを選んだ。

そして、いろいろwebを渉猟するにi386でZFSは辛そうなのでamd64とし、下記の通りzpoolのバージョンもどーんと上がっているので, 9.0-RELEASEを入れた。メジャーバージョンの最初はちょっと不安ではあるけれど。

ZFSのバージョン

8.2+ – zpool v15

9.0+ – zpool v28

あとは、特に難しいこともなく、2.5Tのディスク1本買ってきて、つないで、領域作って、こんな感じ。

作業ログは後述。

$ sudo zpool status
パスワード:
pool: vault
state: ONLINE
scan: none requested
config:
NAME        STATE     READ WRITE CKSUM
vault       ONLINE       0     0     0
ada1      ONLINE       0     0     0
errors: No known data errors
$ zpool list
NAME    SIZE  ALLOC   FREE    CAP  DEDUP  HEALTH  ALTROOT
vault  2.27T  1007G  1.28T    43%  1.00x  ONLINE  -

 

ディスク1本なので、RAIDも組まず、圧縮もせず(データがjpg写真とか自炊本、自炊DVD、CDとか圧縮の効かないものばかりだから)。

あんなに煽っておいてアレだが、だってまだディスク高いし・・。

 

チューニング

ただまあ、ここを見てチューニングだけはしておいた。

http://wiki.freebsd.org/ZFSTuningGuide

 

/boot/loader.confにおけるチューニング

vfs.zfs.prefetch_disable="1"
vfs.zfs.txg.timeout="5"

1行目

ZFSのprefetchを無効にすると全体的にスピードが向上する。

ただし読み書きが頻繁に発生する状態だとシステムが遅くなる傾向あり。

なお、4GB以上のメモリが実装されているとデフォルトで0になるとのこと。

2行目

txgが何の意味か分からないけど(task queue?)、こうしておくとスループットが上がる上に、システムが極端に遅くなる問題が改善される。

(In my case 50-100% CPU is used by ZFS with *no* disk activity during the pauses then a burst of rapid disk activity and then another pause. なんて言ってる)

なお、これはZFS v28からはデフォルト。

 

/etc/sysctl.confにおける設定

kern.maxvnodes=250000
vfs.zfs.write_limit_override=131072

1行目でvnodes数の上限をデフォルトの約200000(a little over 200,000)から増やす。

2行目でTXG write limitの値を減らす。デフォルト値は知らん。

4GBメモリなら256MB、と書いてあるので、2GBを積んでる俺は128MBにした。

なお、ZFS v28より前ではvfs.zfs.txg.write_limit_overrideとのこと。

そのほかの設定:periodic script

/etc/periodic/daily/404.status-zfsにスクリプトがある。

有効にすると、毎日zpoolの状態をしらべて、daily output, security outputでメールしてくれる。

そうそう、root宛のメールは転送設定しておくと便利。

$ sudo /etc/periodic/daily/404.status-zfs
Checking status of zfs pools:
all pools are healthy

 

/etc/periodic.confに以下を追記しておけばOK

daily_status_zfs_enable="YES"

 

以下は作業ログ

作業ログ

ディスクをつないで起動、dmesgで確認

$ dmesg|grep ada
ada0 at ahcich0 bus 0 scbus0 target 0 lun 0
ada0: <VB0250EAVER HPG7> ATA-8 SATA 2.x device
ada0: 300.000MB/s transfers (SATA 2.x, UDMA5, PIO 8192bytes)
ada0: Command Queueing enabled
ada0: 238475MB (488397168 512 byte sectors: 16H 63S/T 16383C)
ada0: Previously was known as ad4
ada1 at ahcich1 bus 0 scbus1 target 0 lun 0
ada1: <WDC WD25EZRX-00MMMB0 80.00A80> ATA-8 SATA 3.x device
ada1: 300.000MB/s transfers (SATA 2.x, UDMA6, PIO 8192bytes)
ada1: Command Queueing enabled
ada1: 2384658MB (4883781168 512 byte sectors: 16H 63S/T 16383C)
ada1: Previously was known as ad6

ada1が新しく繋いだディスク。

ここにZFS用のpoolを作成する。

$ sudo zpool create vault ada1
Password:
$ mount
/dev/ada0p2 on / (ufs, local, journaled soft-updates)
devfs on /dev (devfs, local, multilabel)
vault on /vault (zfs, local, nfsv4acls)
$ df -h
Filesystem     Size    Used   Avail Capacity  Mounted on
/dev/ada0p2    228G     15G    194G     7%    /
devfs          1.0k    1.0k      0B   100%    /dev
vault          2.2T     31k    2.2T     0%    /vault

 

無事完成。

なんと勝手にマウントまでしてくれる。これですぐ使える。

2.5Tなのに数秒程度で完了。

ビクビクしながらfdiskしたりnewfsしたりする必要がない。電卓も要らない(そういう時代もあったのです)。

衝撃的です。

コマンドが簡単なうえに、早いというのは、重ねて言うけど障害復旧に極めて有利な点。

大きなディスクをnewfsするときの、遅々として進まないカウンタを見てジリジリしたことのある人なら共感してくれるはず。

 

なお、この状態では/etc/fstabに何も書き込まれていないので、再起動すればマウントは外れる。

 

ではこのpoolからディレクトリを切り出す。

itunes用と、通常の共有ディレクトリ用の二つを作る。

 

$ sudo zfs create vault/itunes
$ sudo zfs create vault/chamber
$ mount
/dev/ada0p2 on / (ufs, local, journaled soft-updates)
devfs on /dev (devfs, local, multilabel)
vault on /vault (zfs, local, nfsv4acls)
vault/itunes on /vault/itunes (zfs, local, nfsv4acls)
vault/chamber on /vault/chamber (zfs, local, nfsv4acls)
$ df -h
Filesystem      Size    Used   Avail Capacity  Mounted on
/dev/ada0p2     228G     15G    194G     7%    /
devfs           1.0k    1.0k      0B   100%    /dev
vault           2.2T     32k    2.2T     0%    /vault
vault/itunes    2.2T     31k    2.2T     0%    /vault/itunes
vault/chamber    2.2T     31k    2.2T     0%    /vault/chamber

 

これらを/export配下に移動させる。

これが既存の考えにはない動作。頭の中でファイルシステムに対する考え方がグニョっとなるのを俺は感じたよ。

 

$ sudo zfs set mountpoint=/export/itunes vault/itunes
$ sudo zfs set mountpoint=/export/chamber vault/chamber
$ mount
/dev/ada0p2 on / (ufs, local, journaled soft-updates)
devfs on /dev (devfs, local, multilabel)
vault on /vault (zfs, local, nfsv4acls)
vault/itunes on /export/itunes (zfs, local, nfsv4acls)
vault/chamber on /export/chamber (zfs, local, nfsv4acls)

そしたら/etc/fstabに書き込んでおしまい。

昔はデバイス名を書き込んでいた場所にZFSのディスクプールを書くわけですな。

vault/itunes    /export/itunes         zfs     rw      0       0
vault/chamber   /export/chamber                zfs     rw      0       0

afpでファイルをコピーしているのだが、あまり負荷はかかっていない模様。

ZFSはリソース食いと聞いてたのでコワゴワコピーしたんだけど、まあ100Mbpsのネットワーク越しですしな。

last pid:  1773;  load averages:  0.11,  0.21,  0.17    up 0+00:45:03  23:54:03
42 processes:  1 running, 41 sleeping
CPU:  0.2% user,  0.0% nice, 15.0% system,  0.4% interrupt, 84.4% idle
Mem: 46M Active, 189M Inact, 1426M Wired, 64M Cache, 200M Buf, 119M Free
Swap: 907M Total, 556K Used, 906M Free
PID USERNAME     THR PRI NICE   SIZE    RES STATE   C   TIME   WCPU COMMAND
1697 root           1  31    0 55860K  4288K select  1   3:55 16.36% afpd

そのほか

重大な作業をするときは必ず-nオプションを付けること。

ドライランと呼ばれるもので、実際の作業はせずに結果をシミュレートできる。

 

ストレージプールを作業するときには明示的にexportすること。

exportすれば、未書き込みのデータがすべて処理され、システムから削除される。

そこで引数なしでimportを実行すると、import可能な、言い換えるとexport済みのプールが表示される。

No tags for this post.