Category Archives: zfs

[zfs] zfsnap2を使った日々のzfs snapshot

Pocket

zfsnap2(面倒くさいので以降zfsnap)のおかげで気軽にzfs snapshotできるようになった。
あとはこれをcronに仕込んで日々、snapshotを取得、削除するだけである。

zfsnapをpkg、あるいはportsからインストールすると、cron用のシェルスクリプトも付いてくる。
これを加工してperiodic用のディレクトリに放り込めば、あとは全部、zfsnapがやってくれる。

基本はここを見ながら。
https://github.com/zfsnap/zfsnap/wiki/zfSnap-periodic.conf

なお、本稿で扱う周期、契機は日週月次に限る。

全体の流れ

  1. スナップショットの方針を決める
  2. cron用シェルスクリプトを日・週・月ごとのperiodicディレクトリにコピーし、ファイル名を変更する
  3. スクリプトの内容を修正する
  4. /etc/periodic.confにバックアップ方針に沿った設定を書き加える

では早速。

スナップショット方針を決める

ここでは簡単に、あるzpool丸ごとに対して;

  • 毎日のスナップショットは1週間と1日、保存する
  • 毎週のスナップショットは1か月と1日、保存する
  • 毎月のスナップショットは1年と1週間、保存する

とする

[補足]periodicから実行されるときのsnapname

zfsnap付属のスクリプトを使うと、snapnameの頭にdaily, weekly, monthlyと付く。
もちろん変更可能だが、本稿ではそのまま使う。

zfsnapのcron用スクリプトはどこにある

cron用スクリプトは、zfsnapインストール時にshareにコピーされる。
例えば以下のようにして探す

$ pkg list|grep zfsnap
/usr/local/etc/bash_completion.d/zfsnap.sh
/usr/local/man/man8/zfsnap.8.gz
/usr/local/sbin/zfsnap
/usr/local/share/doc/zfsnap/AUTHORS
/usr/local/share/doc/zfsnap/NEWS
/usr/local/share/doc/zfsnap/PORTABILITY
/usr/local/share/doc/zfsnap/README.md
/usr/local/share/examples/zfsnap/completion/zfsnap-completion.bash
/usr/local/share/examples/zfsnap/completion/zfsnap-completion.tcsh
/usr/local/share/examples/zfsnap/completion/zfsnap-completion.zsh
/usr/local/share/examples/zfsnap/periodic/xPERIODICx_zfsnap.sh
/usr/local/share/examples/zfsnap/periodic/xPERIODICx_zfsnap_delete.sh
/usr/local/share/licenses/zfsnap2-2.0.0.b3/BSD3CLAUSE
/usr/local/share/licenses/zfsnap2-2.0.0.b3/LICENSE
/usr/local/share/licenses/zfsnap2-2.0.0.b3/catalog.mk
/usr/local/share/zfsnap/commands/destroy.sh
/usr/local/share/zfsnap/commands/recurseback.sh
/usr/local/share/zfsnap/commands/snapshot.sh
/usr/local/share/zfsnap/core.sh
/usr/local/share/zsh/site-functions/_zfsnap

上記のうち以下が狙いのスクリプトである。
スナップショット取得用、削除用の2種類。
/usr/local/share/examples/zfsnap/periodic/xPERIODICx_zfsnap.sh
/usr/local/share/examples/zfsnap/periodic/xPERIODICx_zfsnap_delete.sh

スクリプトのコピーとファイル名の変更

さてこれを、日・週・月のperiodicディレクトリにコピーし設定していくが、まずは日次で試す。
日ごとのperiodicディレクトリは/usr/local/etc/periodic/dailyである。
ここにコピーし、ファイル名を変える。
ファイル名のxPERIODICxを、日次・週次・月次、どの周期用かに合わせて変える。
具体的にはそれぞれdaily, weekly, monthlyに。
以下の例では日次のスクリプトなので、dailyに変えている。
prefixの番号は好きなようにしたまえ。


$ cd /usr/local/etc/periodic/daily
$ sudo cp /usr/local/share/examples/zfsnap/periodic/* .
$ sudo mv ./xPERIODICx_zfsnap.sh ./500.daily_zfsnap.sh
$ sudo mv ./xPERIODICx_zfsnap_delete.sh  ./500.daily_zfsnap_delete.sh
$ ls
411.pkg-backup                  500.daily_zfsnap_delete.sh      998.ntpdate
490.status-pkg-changes          500.daily_zfsnap.sh             smart

スクリプトの修正

スクリプト(取得用)の内容は以下の通りである。
変える場所はxPERIODICxとxPREFIXxである。
xPERIODICxは周期に合わせて、xPREFIXxはzfsnapのお置いてあるパス、つまり/usr/local/sbin/zfsnapに。


#!/bin/sh

# This file is licensed under the BSD-3-Clause license.
# See the AUTHORS and LICENSE files for more information.

# If there is a global system configuration file, suck it in.
if [ -r /etc/defaults/periodic.conf ]; then
    . /etc/defaults/periodic.conf
    source_periodic_confs
fi

# xPERIODICx_zfsnap_enable          - Enable xPERIODICx snapshots (values: YES | NO)
# xPERIODICx_zfsnap_flags           - `zfsnap snapshot` flags
# xPERIODICx_zfsnap_fs              - Space-separated ZFS filesystems to create non-recursive snapshots
# xPERIODICx_zfsnap_recursive_fs    - Space-separated ZFS filesystems to create recursive snapshots
# xPERIODICx_zfsnap_ttl             - Explicit TTL value
# xPERIODICx_zfsnap_verbose         - Verbose output (values: YES | NO)
# xPERIODICx_zfsnap_enable_prefix   - Create snapshots with prefix (values: YES | NO) (Default = YES)
# xPERIODICx_zfsnap_prefix          - set prefix for snapshots (Default = xPERIODICx)

case "${xPERIODICx_zfsnap_enable-"NO"}" in
    [Yy][Ee][Ss])
        OPTIONS="$xPERIODICx_zfsnap_flags"

        case "${xPERIODICx_zfsnap_verbose-"NO"}" in
            [Yy][Ee][Ss]) OPTIONS="$OPTIONS -v" ;;
        esac

        case "${xPERIODICx_zfsnap_enable_prefix-"YES"}" in
            [Yy][Ee][Ss]) OPTIONS="$OPTIONS -p ${xPERIODICx_zfsnap_prefix:-"xPERIODICx-"}" ;;
        esac

        case 'xPERIODICx' in
            'hourly')
                default_ttl='3d'
                ;;
            'daily'|'reboot')
                default_ttl='1w'
                ;;
            'weekly')
                default_ttl='1m'
                ;;
            'monthly')
                default_ttl='6m'
                ;;
            *)
                printf '%s\n' "ERR: Unexpected error" >&2
                exit 1
                ;;
        esac

        xPREFIXx/zfsnap snapshot $OPTIONS -a ${xPERIODICx_zfsnap_ttl:-"$default_ttl"} $xPERIODICx_zfsnap_fs -r $xPERIODICx_zfsnap_recursive_fs
        exit $?
        ;;

    *)
        exit 0
        ;;
esac

# vim: set ts=4 sw=4:

vimなら:%s/xPERIODICx/daily/g などとコマンド叩いて一括置換する。
以下が修正後。


#!/bin/sh

# This file is licensed under the BSD-3-Clause license.
# See the AUTHORS and LICENSE files for more information.

# If there is a global system configuration file, suck it in.
if [ -r /etc/defaults/periodic.conf ]; then
    . /etc/defaults/periodic.conf
    source_periodic_confs
fi

# daily_zfsnap_enable          - Enable daily snapshots (values: YES | NO)
# daily_zfsnap_flags           - `zfsnap snapshot` flags
# daily_zfsnap_fs              - Space-separated ZFS filesystems to create non-recursive snapshots
# daily_zfsnap_recursive_fs    - Space-separated ZFS filesystems to create recursive snapshots
# daily_zfsnap_ttl             - Explicit TTL value
# daily_zfsnap_verbose         - Verbose output (values: YES | NO)
# daily_zfsnap_enable_prefix   - Create snapshots with prefix (values: YES | NO) (Default = YES)
# daily_zfsnap_prefix          - set prefix for snapshots (Default = daily)

case "${daily_zfsnap_enable-"NO"}" in
    [Yy][Ee][Ss])
        OPTIONS="$daily_zfsnap_flags"

        case "${daily_zfsnap_verbose-"NO"}" in
            [Yy][Ee][Ss]) OPTIONS="$OPTIONS -v" ;;
        esac

        case "${daily_zfsnap_enable_prefix-"YES"}" in
            [Yy][Ee][Ss]) OPTIONS="$OPTIONS -p ${daily_zfsnap_prefix:-"daily-"}" ;;
        esac

        case 'daily' in
            'hourly')
                default_ttl='3d'
                ;;
            'daily'|'reboot')
                default_ttl='1w'
                ;;
            'weekly')
                default_ttl='1m'
                ;;
            'monthly')
                default_ttl='6m'
                ;;
            *)
                printf '%s\n' "ERR: Unexpected error" >&2
                exit 1
                ;;
        esac

        /usr/local/sbin/zfsnap snapshot $OPTIONS -a ${daily_zfsnap_ttl:-"$default_ttl"} $daily_zfsnap_fs
 -r $daily_zfsnap_recursive_fs
        exit $?
        ;;

    *)
        exit 0
        ;;
esac

# vim: set ts=4 sw=4:

削除用も同じようにしたら、periodic.confに指示を書き入れる。

/etc/periodic.confにおけるzfsnap設定の書式

/etc/periodic.confは無ければ作る。

zfsnapのperiodic向け書式は以下の通り。
https://github.com/zfsnap/zfsnap/wiki/zfSnap-periodic.conf

以下、日次のものとして記す。
週、月次の場合はdailyをそれぞれweekly, monthlyに変えればよい。

snapshot取得の有効化

daily_zfsnap_enable
YES/NOで指定

共通オプション(generic option)

daily_zfsnap_flags
例えばscrub, resilver中は避け、日付シリアルの秒を切り捨て、というような設定をここで行う。。
-v, -dを指定しないこと。
初めて作るときにはテスト実行オプションを付けて試験する。

zfs, zpoolの指定

daily_zfsnap_fs
daily_zfsnap_recursive_fs
recursiveとなっているのは、当然ながら子孫も含めて再帰的に取得される
複数あるなら、スペースを空けて列挙

冗長アウトプット指定

daily_zfsnap_verbose
YES/NOで指定

保存期間指定

daily_zfsnap_ttl
指定がなければ日次は1週間、週次は1か月、月次は6か月になる。

スナップショット削除有効化

daily_zfsnap_delete_enable
YES/NOで指定

periodic.conf例

ということで、periodic.confに追加したのは以下の通り。


# zfsnap_daily
daily_zfsnap_enable="YES"
daily_zfsnap_recursive_fs="vault"
daily_zfsnap_verbose="YES"
daily_zfsnap_delete_enable="YES"
daily_zfsnap_flags="-n -s -S -z"
daily_zfsnap_ttl="1w1d"

試験

zfsnap_flagsに-nを付けた状態で試験。


$ sudo /usr/local/etc/periodic/daily/500.daily_zfsnap.sh
/sbin/zfs snapshot  vault/chamber@daily-2018-12-03_02.14.00--1w1d
/sbin/zfs snapshot  vault/itunes@daily-2018-12-03_02.14.00--1w1d

大丈夫そうなので-nを外す。

最終的なperiodic.confの結果

週次、月次で同じようにperiodic用のスクリプトを作成する。


$ pwd
/usr/local/etc/periodic
$ find ./ -name '*zfsnap*'
./weekly/999.weekly_zfsnap.sh
./weekly/999.weekly_zfsnap_delete.sh
./daily/500.daily_zfsnap.sh
./daily/500.daily_zfsnap_delete.sh
./monthly/910.monthly_zfsnap.sh
./monthly/910.monthly_zfsnap_delete.sh

最終的なperiodic.confの結果は以下の通り。


# zfsnap_weekly
weekly_zfsnap_enable="YES"
weekly_zfsnap_recursive_fs="vault"
weekly_zfsnap_verbose="YES"
weekly_zfsnap_delete_enable="YES"
weekly_zfsnap_flags="-s -S -z"
weekly_zfsnap_ttl="1m1d"
# zfsnap_daily
daily_zfsnap_enable="YES"
daily_zfsnap_recursive_fs="vault"
daily_zfsnap_verbose="YES"
daily_zfsnap_delete_enable="YES"
daily_zfsnap_flags="-s -S -z"
daily_zfsnap_ttl="1w1d"
# zfsnap_monthly
monthly_zfsnap_enable="YES"
monthly_zfsnap_recursive_fs="vault"
monthly_zfsnap_verbose="YES"
monthly_zfsnap_delete_enable="YES"
monthly_zfsnap_flags="-s -S -z"
monthly_zfsnap_ttl="1y1d"

翌日以降、root宛には以下のようなメールが届くので、結果はここで確認する。

/sbin/zfs snapshot -r vault@daily-2018-12-02_04.47.0<wbr />0--1w1d ... DONE

[zfs][zpool] らくらくスナップショットzfsnap2

Pocket

zfsは本当に本当に便利で助かるのだが、それでも面倒なことはある。
私にとって面倒なのは、スナップショット作成とスナップショットの差分転送である。

スナップショットの簡素化について。
スナップショットを作成する際には、ファイルシステムやボリュームに続けてスナップショットの名前、スナップネームを指定する必要がある。
スナップネームはスナップショットを特定するために必要なものなので文句を言う筋合いはないのだが、いちいち名前を付けるのが面倒なんである。日付でもなんでも自動的に付けてほしい。

なんとか改善したくていろいろ調べてみた。

スナップショット取得補助ツール

スナップショット関連ではzfstools, zfsnap2, zapの三つを調べた。
結論から言うと、zfsnap2を選択した。

zfstools

https://github.com/bdrewery/zfstools
https://www.freshports.org/sysutils/zfstools/
よさそうだけどruby依存なのでその一点で対象外に。
このツールのためだけにrubyを入れますか、という話で。
なるべく依存の少ないツールがよい。

zap

https://www.freshports.org/sysutils/zap
https://github.com/Jehops/zap
よさそうだけど、zfsに独自のプロパティ(zap:)を設定する必要があるっぽい。
独自プロパティの設定が、zfsとして許容されている作法であっても、対象のファイルシステムに何らかの手を加えるのは躊躇する

zfsnap2

https://www.freshports.org/sysutils/zfsnap2
https://github.com/zfsnap/zfsnap
単純なシェルスクリプト。
よさそう。

zfsnap2 お手軽snapshot

まず、zfsnap2は、取得すると日付シリアルをsnapnameに付けてくれる。
例えば。

 
vault/chamber@2018-11-11_09.48.00--1y
 

ご覧の通り2018/11/11 09:48:00と日付をsnapnameに付ける
なお、末尾に1yと書いてあるがこれは1年という意味である。
これは何かというと(次項につづく)

zfsnap2 snapshot削除の仕組みとTTL

snapshotは取得するだけでなく、消す方の面倒を見ることも重要。
zfsnap2は、取得したタイムスタンプとTTL(Time To Live)をsnapnameに含めておくのがアイデア(他みも同じようなツールあるかもしれないけど)。
先ほどの例でいえば、末尾の1yがそれ。1yだから1 year、1年ですな。

vault/chamber@2018-11-11_09.48.00--1y

上記の通り、取得日付、保存期間をsnapname自体に持たせるので、ツール側では状態を記憶しておく必要がない。
削除を指示されたら、zfsnap2はその都度、snapnameだけを見て判断・処理をするということ。
何より人間もsnapnameから保存期限を判断できる。これはよい。

とりあえず使う

管理者権限でzfsnap snapshotに続けてzfs/zpoolを指定するだけ。
日付も付けてくれる。

# zfsnap snapshot zroot/var/tmp
$ zfs list -t snapshot|grep 'zroot/var/tmp'
zroot/var/tmp@20181120                   56K      -    88K  -
zroot/var/tmp@2018-12-01_22.19.13--1m      0      -    88K  -

zfsnap書式概要

詳細はman等するとして、概要を示す。
書式は以下の通り。

zfsnap コマンド <共通オプション> <個別オプション> zpool/zfs

zfsnapのコマンド

コマンドにはsnapshot, destroy, recursebackの三つがある。
それらに続けてzpool, zfsを指定する。こちらの指定は複数でもよい。
共通オプション(generic option)は、その名の通り、共通的なオプション。
個別オプションはzpool, zfsごとのオプションである。

コマンドのsnapshot, destroyは当然ながらそれぞれsnapshot作成、削除。
recursebackは、zfs rollbackの拡張で、rollbackの際、指定のdataset配下すべてをrollbackするもの。
本稿では扱わない。

共通オプション(generic option)

主なものだけ示す

-s  : resilver中は作業しない
-S : scrub中は作業しない
-z : 日付シリアルの秒切り捨て(18:06:15を18:06:00にする)
-n : dry run。テスト実行。ファイルシステムに変更を加えない。
-v : 冗長output

-s, -Sは常時付けておいたほうがいいかな。

個別オプション

個別オプションなので、これに続けて指定されたzpool/zfsにのみ効果がある。
主なものだけ示す

-a : TTL。指定がなければ1m = 1か月
-r : 再帰オプション。再帰的にsnapshotを取得
-R : 非再帰オプション。再帰的なsnapshotを取得「しない」

TTLオプション

以下のうち、必要なものだけをズラズラ書けばよい

y : 年(365日)
m : 月(30日)
w : 週(7日)
d : 日
h : 時
M : 分
s : 秒

1週間と1日なら-a 1w1d。
2か月なら-a 2m。

実行例

以上を踏まえて;
resilver, scrub中は実行せず、日付シリアルの秒切り捨て、冗長アウトプットでsnapshotをテスト実行。
対象zfsその1はzroot/usrで、再帰的に取得し、TTLは1週間と1日。その2はzroot/ROOTで、再帰的に取得「せず」、TTLは1分。
という実行例。

# zfsnap snapshot -sSvzn -a1w1d -r zroot/usr -R -a1M zroot/ROOT
/sbin/zfs snapshot -r zroot/usr@2018-12-01_22.33.00--1w1d
/sbin/zfs snapshot  zroot/ROOT@2018-12-01_22.33.00--1M

よさそうなのでテスト実行オプションを省いて本番実行すると;

# zfsnap snapshot -sSvz -a1w1d -r zroot/usr -R -a1M zroot/ROOT
/sbin/zfs snapshot -r zroot/usr@2018-12-01_22.34.00--1w1d ... DONE
/sbin/zfs snapshot  zroot/ROOT@2018-12-01_22.34.00--1M ... DONE

zfs listで結果を確認。zroot/usrにのみ配下にもスナップショットが出来ている。

$ zfs list -t snapshot | grep '2018-12-01'
zroot/ROOT@2018-12-01_22.34.00--1M             0      -    88K  -
zroot/usr@2018-12-01_22.34.00--1w1d            0      -    88K  -
zroot/usr/home@2018-12-01_22.34.00--1w1d       0      -  5.97M  -
zroot/usr/ports@2018-12-01_22.34.00--1w1d      0      -    88K  -
zroot/usr/src@2018-12-01_22.34.00--1w1d        0      -    88K  -

では削除のほうも。
zroot/ROOT、zroot/usr配下のTTL切れsnapshotを削除
ただしzroot/ROOTは非再帰的、zroot/usrは再帰的に。
テスト実行。

# zfsnap destroy -sSvn -R zroot/ROOT -r zroot/usr
/sbin/zfs destroy zroot/ROOT@2018-12-01_22.34.00--1M

期限切れはzroot/ROOT@2018-12-01_22.34.00–1Mのみ。
じゃ、それで本番実行

# zfsnap destroy -sSv -R zroot/ROOT -r zroot/usr
/sbin/zfs destroy zroot/ROOT@2018-12-01_22.34.00--1M ... DONE

以上。

[ZFS][zpool]zpoolのHDDをスタンバイモードにして消費電力を減らそう

Pocket

我が家のNASサーバーはFreeBSDの入ったHP microserverである。
HP microserverにはHDDを4つ入れることができる。
たいへん便利なのだが、HDDが4つとも24時間動きっぱなしというのは精神衛生上、よろしくない。

実は、HDD4つのうちメインで使っているのはOSの入っているものと、Samba共有しているものの2つだけで、残りの2つはバックアップ用である。
少なくとも、残りの2本はバックアップを取得するときだけ動いてくれればよいので、それ以外の間は、HDD内円盤の回転を止めておきたい(スピンダウン)。

しかしSamba共有しているもの、バックアップ用のHDD(要するにOSの入っているHDD)以外はすべてzfsのzpoolを構成しているものである。
気軽にスピンダウンしてしまってよいものだろうか。

というのが調査を始めたきっかけである。

ああ、それと、頻繁に止めたり動かしたりすることがHDDに悪い、というのは重々承知の上。

結論(camcontrol standbyしろ)

結論から言うと、camcontrolでディスクを止めろ。
ディスク停止には、”standby”で。”idle”はやめておけ。

ATAデバイスのモード

ATAデバイスには4つのPower Modeがあり、条件によりそれぞれを行き来する。

  1. Active
  2. Idle
  3. Standby
  4. Sleep

Activeモードは、通常のデータのやり取りができる状態のこと。
それ以外は、Idle > Standby > Sleep の順に消費電力が下がり、反応速度も遅くなる。
詳細は以下書類(PDF注意)の4.18.3 Power modesを参照されたし。
http://www.t13.org/Documents/UploadedDocuments/docs2007/e07163r2-Comments_on_ATA8-ACS_revision_4a.pdf

これを踏まえて、任意のタイミング、あるいは、一定時間アクセスがないタイミングでIdle/Standby/Sleepに遷移させられれば目的が達成できる。
FreeBSDにおいて、Power modeの遷移にはcamcontrolコマンドを使う。
しかしその前に、zfs/zpoolで使えるPower Modeを調べねばならない。

zfsにはStandby

FreeBSD Forumにあるcamcontrol standby weirdnessというスレッドを見ると、以下のような記述がある。要するにStandbyを使えと。Idleだとzfsは当該ディスクをlost/defect/detachedと判断し、zpoolはdegradedになるか、unavailableになるという。

First of all: ZFS is fine with disks that go into STANDBY (accessing a zpool with disks in STANDBY will wake them up and ZFS will wait for it). ZFS cannot handle disks that are in IDLE mode (it considers the disks lost/defect/detached and the zpool will go degraded or even unavailable).

https://forums.freebsd.org/threads/camcontrol-standby-weirdness.59296/#post-340121

自分で試す気にはならないので、そのまま受け取る。

camcontrolによるstabdby操作

再びFreeBSD Forum。[AHCI] Spinning down ada(4) disksというスレッドの以下のポストを参照
https://forums.freebsd.org/threads/ahci-spinning-down-ada-4-disks.8841/page-2#post-98640

camcontrol standby adaXとすればよい。
またcamcontrol standby adaX -T sssとすれば、ただちにstandbyモードに移行し、その後もsss秒、アクセスがなければstandbyモードに移行することができる。
以下なら/dev/ada3をすぐにstandbyモードに移行させるとともに、20分の間アクセスがなければやはりstandbyモードに遷移するようタイマー設定している。今すぐはstandbyモードにしなくてもいいけど、タイマーだけ設定したい、という方法はないみたいだ。

# camcontrol standby ada3 -T 12000

しかし上記のコマンドを実行したとしても、応答はない。なしのつぶてである。
standbyモードに移ったのか。かくなる上はHDDの回転数はいかほどか、耳を澄ますほかはない。
そんなご無体な、とgoogle先生に訴えたところ、FreeNASのフォーラムに以下のポストを発見。

Spinning Down your Drives and Checking Power States. (New Script)

上記にあるスクリプトを使えば、power modeを知ることができる。
本記事の末尾に転載しておく。
get_drive_status.shとして保存しておいた。
実行してみると;

$ sudo drivestatus.sh
ada0:  FF
ada0: Running
ada1:  FF
ada1: Running
ada2:  FF
ada2: Running
ada3:  FF
ada3: Running

camcontrolでstandbyにしておいて再実行。

$ sudo drivestatus.sh
ada0:  FF
ada0: Running
ada1:  00
ada1: Standby
ada2:  00
ada2: Standby
ada3:  00
ada3: Standby

/dev/ada0はOSのあるHDDだからActiveですな。

運用方法(なにかが変)

よしこれで解決。
と思ったのだが、タイマー満了してもpower modeがstandbyに移らないのである。
その割に、そのディスクのディレクトリにアクセスすると、ファイル一覧の表示に待たされたりするのである。

先に引用した彼も同じことに悩んでいる。

But, then, when the disk is idle for > 1800sec (monitor with “zpool iostat 60”), it will not spin down. Huh?

https://forums.freebsd.org/threads/camcontrol-standby-weirdness.59296/#post-339820

この彼は、zpool iostat でディスクへの読み書きをモニターできるので、何分かアクセスがなければidleモードに移すスクリプトを書いた、と言っている。
常駐スクリプトを運用するのが面倒なので、cronジョブでstandbyさせるようにした。

結果

ワットチェッカーなんてものは持っていないので、単純に温度で確認した。
以下がそのグラフ。
ある日を境に、(OSのある/dev/ada0を除いて)温度が劇的に下がっていて、現時点ではまあ満足。

power mode確認スクリプト

#!/bin/bash
#
# Created by: Motorahead
# Date: 02/19/2016
# Checks For Running Status of Connected ADA Devices

# Look for Connected Devices
DEVICELIST=($( camcontrol devlist | grep -o 'ada[0-9]' ))

# Checks Drive Status, but only outputs relative field $10
STATUS(){
camcontrol cmd ${LIST} -a "E5 00 00 00 00 00 00 00 00 00 00 00" -r - | awk '{print $10}'
}

# Loop through each device found in ${DEVICELIST}
for LIST in ${DEVICELIST[@]}; do
        echo -n "${LIST}:  "
        STATUS
# If the Output is 00, then the drive is in Standby. If it's FF, then it's active.
        if [[ "$(STATUS)" == "FF" ]]; then
                echo "${LIST}: Running"
        elif [[ "$(STATUS)" -eq "00" ]]; then
                echo "${LIST}: Standby"
        else
                echo "${LIST} is in a unrecognized state."
    fi
done

[zfs][zpool] zfsの別ディスクへの移行

Pocket

zpoolを容量の多い別HDDに移したのでメモ。
一度、同じようなことはやっているが、時間も経っているので。
最初に書いておくが移行元でまずscrubしておくこと。

流れとしては以下の通り。

  1. 移行元HDD
    1. scrubしておく
    2. snapshot
  2. 移行先HDD
    1. GPTでzfsのパーティションを作成
    2. zpool作成
  3. zfs send, recvで丸々コピー

以下、実作業に触れる前に補足。

方針についての補足

なぜmirrorにしないのか

上記の方法のほかには、追加のディスクをmirrorとしてzpoolに追加し、resilveringが終わったら旧ディスクを外してexpandという手がある。
が、その手は採らない。
実は、zpool statusをする都度、以下のメッセージが表示されていた。
旧ディスクは512Bセクタになっていると文句を言っているのである。
ディスクを交換するか、新Poolに移せ、と。

  pool: vault
 state: ONLINE
status: One or more devices are configured to use a non-native block size.
        Expect reduced performance.
action: Replace affected devices with devices that support the
        configured block size, or migrate data to a properly configured
        pool.
  scan: scrub repaired 0 in 8h3m with 0 errors on Sun Nov  4 04:16:39 2018
config:

        NAME        STATE     READ WRITE CKSUM
        vault       ONLINE       0     0     0
          ada1      ONLINE       0     0     0  block size: 512B configured, 4096B native

 

512Bセクタのpoolにmirrorを追加したら、やっぱり512Bになるんではと心配になったので、mirrorではなく新規ディスクの新規Poolに移す。

なぜディスクをまるっと使わずgptでパーティションを切るのか

zpoolは、わざわざgptパーティションにしなくても、ディスクをまるっと使ってzpoolに指定できる。
できるのだが、/dev/ada2なんて名前よりも、gptラベルでpoolを作成したいのである。
これの有利な点は、例えば当該ディスクの物理的な位置で名前を付けることができる点である。
具体的には、slot_1とか名前を付けておくと、ディスク交換の時に楽。
幸いにもFreeBSDにおいては、gptパーティションを切ってもディスクをそのまま使っても、いずれもパフォーマンスに違いはない。
それならgptにしましょう。

https://www.freebsd.org/doc/handbook/zfs-zpool.html
There is no performance penalty on FreeBSD when using a partition rather than a whole disk.
(2018/11/09)

ではさっそく作業を。

実作業(移行元ディスクの準備)

scrubをしておく。

zpool scrub で。
かなり時間がかかるので覚悟しておくように。
なおscrubは最低3か月に一回が推奨
https://www.freebsd.org/doc/handbook/zfs-term.html#zfs-term-scrub
recommended at least once every three months

作業直前にsnapshot。

pool内に複数のディレクトリがある場合、最上階層でsnapshot -r(recursive)すればよい。
たとえばvaultというpoolにchamber, itunesがある場合に;

vault
vault/chamber
vault/chamber@20170503
vault/itunes
vault/itunes@20170503

※zfs list -t allの出力を一部削除したもの

zfs snapshot vault@20181109とすれば;

vault
vault@20181109
vault/chamber
vault/chamber@20180503
vault/chamber@20181109
vault/itunes
vault/itunes@20180503
vault/itunes@20181109

※zfs list -t allの出力を一部削除したもの

となる。いちいち各ディレクトリ配下でコマンドを叩かなくてよい。

 

移行先作業

GPTパーティションの作成

以下のようなディスク

ada3 at ahcich3 bus 0 scbus3 target 0 lun 0
ada3: ACS-3 ATA SATA 3.x device
ada3: Serial Number WD-WCC7K3PU64NE
ada3: 300.000MB/s transfers (SATA 2.x, UDMA6, PIO 8192bytes)
ada3: Command Queueing enabled
ada3: 3815447MB (7814037168 512 byte sectors)

GPTスキームをcreateし、全領域をfreebsd-zfsに割り当てる。
このとき、-lオプションでラベルを付ける。
同じくgpart showに-lオプションを付ければ名前を確認できる。

# gpart create -s GPT ada3
ada3 created
# gpart add -l slot_4 -t freebsd-zfs /dev/ada3
ada3p1 added
$ gpart show ada3
          40  7814037088  ada3  GPT  (3.6T)
          40  7814037088     1  freebsd-zfs  (3.6T)

$ gpart show -l /dev/ada3
          40  7814037088  ada3  GPT  (3.6T)
          40  7814037088     1  slot_4  (3.6T)

zpoolの作成

/dev/ada3ではなくGPTラベルで指定する。
GPTラベルで指定するときは、gpt/<GPTラベル>というように指定する。

# zpool create warehouse gpt/slot_4
# zpool status warehouse
  pool: warehouse
 state: ONLINE
  scan: none requested
config:
        NAME               STATE     READ WRITE CKSUM
        warehouse          ONLINE       0     0     0
          gpt/slot_4  ONLINE       0     0     0

プロパティの変更

zfsを作成する前に。
圧縮モードをlz4にする。lz4はCPU負荷の割には非常に効率が良いので積極的に有効にしたい。
また、atime(アクセスタイムの記録)もoffに。これがonだと差分snapshotが失敗するから、というのが一つと、これをoffにするとパフォーマンスが上がる(can result in significant performance gains)から。
zfs get <プロパティ名> で現在の値を取得。
zfs set <プロパティ名>=<値> で値のセット。
圧縮モードのプロパティ名はcompression、atimeはatime。

$ zfs get compression warehouse
NAME       PROPERTY     VALUE     SOURCE
warehouse  compression  off       default
$ zfs get atime warehouse
NAME       PROPERTY   VALUE     SOURCE
warehouse  atime      on        default

# zfs set compression=lz4 warehouse
# zfs set atime=off warehouse
$ zfs get compression warehouse
NAME       PROPERTY     VALUE     SOURCE
warehouse  compression  lz4       local
$ zfs get atime warehouse
NAME       PROPERTY   VALUE     SOURCE
warehouse  atime      off       local

ディレクトリの用意とsend/recv

# zfs create warehouse/itunes
# zfs create warehouse/chamber

このとき、勝手にマウントされないようにすべきだった。-uを付ければよかったかな。
いずれにせよzfs set mountpointで後から変えられる。

sendに-Rを付けると、子孫やスナップショットもまとめてsendされる。

# zfs send -R vault/chamber@20181109 | zfs receive warehouse/chamber
# zfs send -R vault/itunes@20181109 | zfs receive warehouse/itunes

かかった時間、容量は以下の通り。うーむ。ちょっとかかったかな。

 991GiB 3:09:00 [89.5MiB/s]
1.10TiB 3:58:24 [80.3MiB/s] 

このとき適当にhtopを叩いた結果。CPU負荷はそんなんでもないので、ボトルネックは別のところにあるように思われる。

  1  [|||||||||||||||||||||                47.6%]   Tasks: 43, 0 thr; 2 running
  2  [|||||||||||||||||                    37.7%]   Load average: 0.91 1.77 1.86 
  Mem[||||||||||||||||||||||||||||||||642M/1.84G]   Uptime: 12:03:30
  Swp[|||||||||                        176M/907M]

なおCPUはAMDのTurionである。

compression=lz4の結果は.
プロパティused(HDD上の容量)とlogicalused(圧縮前容量)で調べられる。

warehouse  used                  2.00T                    -
warehouse  logicalused           2.02T                    -

本来なら2.02Tのところ、2.00Tで済んでる。

これで引っ越し完了。

以上

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

 

[メモ] ディスクを追加して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

 

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コマンドで。