ZFS
ZFS は (現在は Oracle によって吸収合併された) Sun Microsystems によって作成された先進的なファイルシステムで、2005年11月に OpenSolaris でリリースされました。ZFS には以下の機能があります: ストレージプール (統合ボリューム管理 -- zpool), Copy-on-write, スナップショット, データ整合性のチェックと自動修復 (スクラブ), RAID-Z, 最大16エクサバイトのファイルサイズ、最大256ゼタバイトのボリュームサイズ。ファイルシステム (データセット) やファイルの数は無制限です [1]。ZFS は Common Development and Distribution License (CDDL) でライセンスされています。
"The last word in filesystems" では ZFS は安定していて高速、セキュアで、そして将来性を考えた設計をしていると述べられています。ライセンスが CDDL で、GPL と互換がないため、ZFS は Linux カーネルと一緒に配布することができません。しかしながら、サードパーティによってネイティブの Linux カーネルモジュールを開発・配布することは可能です。それが zfsonlinux.org (ZOL) になります。
ZOL はローレンス・リバモア国立研究所による後押しを受けているプロジェクトで、その大規模なストレージ要件とスーパーコンピュータに合うようなネイティブの Linux カーネルモジュールを開発することを目標としています。
目次
インストール
Arch User Repository か demz-repo-core リポジトリから zfs-gitAUR をインストールしてください。このパッケージは zfs-utils-gitAUR と spl-gitAUR を依存パッケージとしており、さらに spl-utils-gitAUR が依存パッケージとしてインストールされます。SPL (Solaris Porting Layer) は ZFS に対応するための Solaris API を実装する Linux カーネルモジュールです。
安定版の ZFS ビルドを使いたいユーザーには、Arch User Repository か demz-repo-core リポジトリから zfs-ltsAUR がインストールできます。
コマンドラインで zpool status
を実行してインストールをテストしてください。"insmod" エラーが起こる場合は、depmod -a
を実行してみてください。
Archiso
ZFS の root ファイルシステムに Arch Linux をインストールする場合は、Arch User Repository か demz-repo-archiso リポジトリから zfs-gitAUR をインストールしてください。
詳しい情報は ZFS に Arch Linux をインストールを参照。
自動ビルドスクリプト
依存関係が入れ子になっているため、上のビルド順序は重要です。以下のシェルスクリプトを使うことで、パッケージのダウンロードから全てのプロセスを自動化することができます。スクリプトを使うために必要なものは:
- sudo - 下のスクリプトを動作させるには
/usr/bin/clean-chroot-manager
を実行するための sudo の権限がユーザーに必要です。 - rsync - ビルドファイルを移動するのに必要。
- cowerAUR - AUR からソースを取得するのに必要。
- clean-chroot-managerAUR - クリーンな chroot でビルドしてローカルリポジトリにパッケージを追加するのに必要。
以下のようにローカルリポジトリを /etc/pacman.conf
に追加してください:
$ tail /etc/pacman.conf
[chroot_local] SigLevel = Optional TrustAll Server = file:///path/to/localrepo/defined/below
~/bin/build_zfs
#!/bin/bash # # ZFS Builder by graysky # # define the temp space for building here WORK='/scratch' # create this dir and chown it to your user # this is the local repo which will store your zfs packages REPO='/var/repo' # Add the following entry to /etc/pacman.conf for the local repo #[chroot_local] #SigLevel = Optional TrustAll #Server = file:///path/to/localrepo/defined/above for i in rsync cower clean-chroot-manager; do command -v $i >/dev/null 2>&1 || { echo "I require $i but it's not installed. Aborting." >&2 exit 1; } done [[ -f ~/.config/clean-chroot-manager.conf ]] && . ~/.config/clean-chroot-manager.conf || exit 1 [[ ! -d "$REPO" ]] && echo "Make the dir for your local repo and chown it: $REPO" && exit 1 [[ ! -d "$WORK" ]] && echo "Make a work directory: $WORK" && exit 1 cd "$WORK" for i in spl-utils-git spl-git zfs-utils-git zfs-git; do [[ -d $i ]] && rm -rf $i cower -d $i done for i in spl-utils-git spl-git zfs-utils-git zfs-git; do cd "$WORK/$i" sudo ccm s done rsync -auvxP "$CHROOTPATH/root/repo/" "$REPO"
DKMS
DKMS (Dynamic Kernel Module Support) を利用することでカーネルのアップグレードがあったときに自動的に ZFS モジュールを再ビルドすることができます。
Mkinitcpio の wiki エントリを読んで、初期 RAM ディスク環境に関することを理解してから、Mkinitcpio#HOOKS に書かれているように dkms フックを追加します。
zfs-dkmsAUR や zfs-dkms-gitAUR をインストールして、パッケージから表示されるインストール後の手順に従ってください。
ZFS の実験
~/zfs0.img
~/zfs1.img
~/zfs2.img
などのシンプルなファイルの仮想ブロックデバイス (ZFS では VDEV と呼称) を使って、データを消失する危険性なく、ZFS の実験を行いたいユーザーは ZFS の実験の記事を見て下さい。RAIDZ アレイの作成や、意図的にデータを破損させてそれを復元したり、データセットのスナップショットなどの一般的な作業を取り扱っています。
設定
ZFS はその開発者から"ゼロアドミニストレーション"のファイルシステムであるとされています。そのため、ZFS の設定はとても簡単です。設定は主に2つのコマンドを使って行います: zfs
と zpool
。
自動起動
ZFS を"ゼロアドミニストレーション"の名に負うように使うには、zfs デーモンを起動時にロードする必要があります。このため /etc/fstab
で zpool をマウントする必要はありません。zfs デーモンが自動的に zfs プールをインポートしてマウントを行います。デーモンは /etc/zfs/zpool.cache
ファイルを読み込んで zfs プールをマウントします。
zfs デーモンによって自動でマウントしたいプール毎に次を実行:
# zpool set cachefile=/etc/zfs/zpool.cache <pool>
Systemd
ブート時に自動的に起動するようにサービスを有効化:
# systemctl enable zfs.target
デーモンを手動で起動するには:
# systemctl start zfs.target
ストレージプールの作成
利用できるドライブの一覧を見るには # parted --list
を使います。zfs ファイルシステムを作成する前にドライブをパーティションする必要はありません、推奨もされていません。
ドライブの一覧を確認できたら、次は zpool を追加するドライブの id を取得します。10デバイス以下の ZFS ストレージプールを作成する際はデバイス id を使うことを zfs on Linux の開発者は推奨しています。id を調べるには:
# ls -lh /dev/disk/by-id/
id は以下のように表示されます:
lrwxrwxrwx 1 root root 9 Aug 12 16:26 ata-ST3000DM001-9YN166_S1F0JKRR -> ../../sdc lrwxrwxrwx 1 root root 9 Aug 12 16:26 ata-ST3000DM001-9YN166_S1F0JTM1 -> ../../sde lrwxrwxrwx 1 root root 9 Aug 12 16:26 ata-ST3000DM001-9YN166_S1F0KBP8 -> ../../sdd lrwxrwxrwx 1 root root 9 Aug 12 16:26 ata-ST3000DM001-9YN166_S1F0KDGY -> ../../sdb
そして、いよいよ ZFS プールを作成します:
# zpool create -f -m <mount> <pool> raidz <ids>
- create: プールを作成するサブコマンド。
- -f: 強制的にプールを作成する。"EFI label error" を無視します。#Does not contain an EFI label を見て下さい。
- -m: プールのマウントポイント。指定されない場合、プールは
/<pool>
にマウントされます。
- pool: プールの名前。
- raidz: デバイスのプールから作成される仮想デバイスのタイプ。Raidz は raid5 の特殊な実装です。raiz に関する詳細は Jeff Bonwick's Blog -- RAID-Z を見て下さい。
- ids: プールに含まれるドライブまたはパーティションの名前。
/dev/disk/by-id
で取得。
完全なコマンドは以下のようになります:
# zpool create -f -m /mnt/data bigdata raidz ata-ST3000DM001-9YN166_S1F0KDGY ata-ST3000DM001-9YN166_S1F0JKRR ata-ST3000DM001-9YN166_S1F0KBP8 ata-ST3000DM001-9YN166_S1F0JTM1
Advanced format ディスク
セクターサイズが512バイトではなく4096バイトの Advanced Format ディスクを使用する場合、レガシーなシステムとの後方互換性のため ZFS のセクターサイズ自動検出アルゴリズムが512バイトと検出して、パフォーマンスが落ちてしまうことがあります。正しいセクターサイズが使われるように、ashift=12
オプションを使用して下さい (ZFS on Linux FAQ を参照)。この場合の完全なコマンドは以下の通りになります:
# zpool create -f -o ashift=12 -m /mnt/data bigdata raidz ata-ST3000DM001-9YN166_S1F0KDGY ata-ST3000DM001-9YN166_S1F0JKRR ata-ST3000DM001-9YN166_S1F0KBP8 ata-ST3000DM001-9YN166_S1F0JTM1
プールの作成の確認
コマンドが成功しても、何も出力はされません。$ mount
コマンドを使うことでプールがマウントされているかどうか表示できます。# zpool status
を使えばプールが作成されたか表示されます。
# zpool status
pool: bigdata state: ONLINE scan: none requested config: NAME STATE READ WRITE CKSUM bigdata ONLINE 0 0 0 -0 ONLINE 0 0 0 ata-ST3000DM001-9YN166_S1F0KDGY-part1 ONLINE 0 0 0 ata-ST3000DM001-9YN166_S1F0JKRR-part1 ONLINE 0 0 0 ata-ST3000DM001-9YN166_S1F0KBP8-part1 ONLINE 0 0 0 ata-ST3000DM001-9YN166_S1F0JTM1-part1 ONLINE 0 0 0 errors: No known data errors
この段階で、起動時に ZFS プールがマウントされるか確認するためにマシンを再起動すると良いでしょう。データを移し替える前に全てのエラーに対処するのがベストです。
GRUB 互換のプールを作成する
デフォルトでは、zpool はプールの全ての機能を有効にします。/boot
を ZFS 上に配置して GRUB を使用する場合、GRUB によってサポートされている読み取り専用、あるいは読み取り専用ではない機能だけを有効にしてください (バージョン 2.02.beta2 現在 lz4_compress
)。そうしないと GRUB がプールを読み込むことができなくなります。
# zpool create -d \ -o feature@async_destroy=enabled \ -o feature@empty_bpobj=enabled \ -o feature@lz4_compress=enabled \ -o feature@spacemap_histogram=enabled \ -o feature@enabled_txg=enabled \ <pool_name> <vdevs>
チューニング
一般
zfs ファイルシステムでは多数のパラメータを使うことができます。パラメータの完全なリストは zfs get all <pool>
で見ることが可能です。調整するパラメータとしては atime と compression が一般的です。
atime はデフォルトで有効にされていますが、ほとんどのユーザーにとっては zpool に余分な書き込みになります。zfs コマンドを使うことで atime を無効にできます:
# zfs set atime=off <pool>
atime を完全にオフにする代わりとして、relatime を使うこともできます。ext4/xfs のデフォルトの atime の処理と同じで、変更日時が更新されたとき、または24時間で一度もアクセス日時が更新されなかった場合にのみ、ファイルのアクセス日時が更新されます。atime=off と atime=on の折衷案になります。このプロパティは atime が on になっているときだけ適用されます:
# zfs set relatime=on <pool>
compression はつまり、データの透過圧縮です。ZFS は様々なアルゴリズムに対応しており、現在は lz4 はデフォルトです。あまり書き込みを行わないようなデータなら gzip を有効にすることで高い圧縮率を実現できます。詳しくは man ページを読んでください。zfs コマンドを使って圧縮を有効にするには:
# zfs set compression=lz4 <pool>
また、zfs コマンドを使うことで zfs の他のオプションを表示できます:
# sudo zfs get all <pool>
データベース
ZFS は他のファイルシステムとは異なり、(一般的にはブロックサイズと呼ばれる) レコードサイズを変えることができます。デフォルトでは、ZFS のレコードサイズは 128KiB で、書き込むファイルのサイズにあわせて 512B から 128KiB までのサイズのブロックを動的に割り当てます。数バイトの書き込みの時でも新規に 128KiB のブロックを割り当てなくてはならないという代償を払って、断片化やファイルアクセスが補助されます。
ほとんどの RDBMS はデフォルトで 8KiB サイズのブロックで動作します。MySQL/MariaDB, PostgreSQL, Oracle のブロックサイズは調整することできますが、デフォルトのブロックサイズは3つとも 8KiB を使っています。パフォーマンスの影響を考え、また、(バックアップ用の) スナップショットの差異を最小限にするために、以下のようなコマンドを使って ZFS をデータベースに適応するよう設定するのが望ましいでしょう:
# zfs set recordsize=8K <pool>/postgres
これらの RDBMS にはそれぞれ独自のキャッシュアルゴリズムが実装されており、大抵は ZFS の ARC と同じようなメカニズムです。メモリの節約の観点から、ZFS によるデータベースのファイルデータのキャッシュを無効にして、キャッシュについてはデータベースに任せるのが良いでしょう:
# zfs set primarycache=metadata <pool>/postgres
プールにログデバイスが設定されていない場合、ZFS はインテントログ (ZIL) のためにプールのデータディスク上に領域を取っておきます。ZFS はクラッシュからのリカバリの際にこのスペースを使いますが、データベースは大抵トランザクションがコミットされるたびにデータファイルをファイルシステムに同期させます。この結果 ZFS が二回データをデータディスクに引き渡すことになるので、パフォーマンスにかなり影響が出てしまう可能性があります。ZFS が ZIL を使わないように設定することができ、この場合は、データがファイルシステムに渡されるのは一度だけになります。データベース以外のファイルシステムや、ログデバイスが設定されているプールでこの設定を行うと、逆にパフォーマンスが下がってしまうことになるので、注意してください:
# zfs set logbias=throughput <pool>/postgres
ファイルシステムの作成時に以上の設定を行うこともできます、例えば:
# zfs create -o recordsize=8K \ -o primarycache=metadata \ -o mountpoint=/var/lib/postgres \ -o logbias=throughput \ <pool>/postgres
/tmp
ZFS を使って /tmp
ディレクトリを保存したい場合、ファイルシステムの同期を無効にすることで /tmp
への書き込みを行うアプリケーションのパフォーマンスを向上させることがあります。これによって ZFS はアプリケーションの同期リクエスト (例: fsync
や O_SYNC
) を無視して、すぐに戻るようになります。アプリケーションサイドのデータの一貫性を保つのが難しくなる一方 (データベースで同期を無効化してはいけません)、/tmp
のファイルはあまり重要でないことが多いため、影響は限られます。ZFS 自体の整合性には影響を与えないので注意してください。アプリケーションがディスク上にあると期待しているデータが実際に書きだされなくてクラッシュが起こる可能性があるくらいです。
# zfs set sync=disabled <pool>/tmp
さらに、セキュリティ上の理由で、/tmp
ファイルシステムの setuid と devices を無効化すると良いでしょう。特権昇格攻撃やデバイスノードの使用をふせぐことができます:
# zfs set setuid=off <pool>/tmp # zfs set devices=off <pool>/tmp
上記の全てをまとめると create コマンドは以下のようになります:
# zfs create -o setuid=off -o devices=off -o sync=disabled -o mountpoint=/tmp <pool>/tmp
また、ZFS に /tmp
を配置するときは、systemd の tmpfs による自動的な /tmp
をマスク (無効化) する必要があるので注意してください。そうしないと ZFS が起動時やインポート時にデータセットをマウントできなくなってしまいます:
# systemctl mask tmp.mount
zvol
zvol は RDBMS と同じようにブロックサイズ関連の問題を被りますが、zvol のデフォルトの recordsize は始めから 8KiB になっているので大丈夫です。可能であれば、zvol に含まれているパーティションは recordsize にあわせて (fdisk と gdisk の最新版ではデフォルトで 1MiB セグメントに合わせます)、ファイルシステムのブロックサイズも同じサイズに合わせるのがベストです。それ以外にも、必要に応じて recordsize を zvol 内のデータに適合させることもできます (ほとんどのファイルシステムでは 8KiB で十分ですが、4KiB のブロックを使用した方が良いときもあります)。
RAIDZ と Advanced Format 物理ディスク
zvol の各ブロックにはそれぞれパリティディスクが存在しており、もし、論理ブロックサイズが 4096B, 8192B などの物理メディアを使用していて、パリティを物理ブロック全体に保存する必要がある場合、zvol に必要な容量が劇的に増えてしまう可能性があります。zvol の論理容量の2倍位上の物理ストレージ容量が必要になります。recordsize を 16k や 32k に設定することでこの必要容量をかなり減らすことができるかもしれません。
詳しくは ZFS on Linux issue #1807 を参照。
使用方法
zpool の下に手動でディレクトリを作成するのに対して、任意で zpool の下にデータセットを作成することができます。データセットはスナップショットに加えて制御のレベルを増加させます (クォータなど)。データセットの作成とマウントをするときは、同じ名前のディレクトリが zpool に存在してはいけません。データセットを作成するには、次を使用:
# zfs create <nameofzpool>/<nameofdataset>
データセットには ZFS の特定属性を適用させることができます。例えば、データセット内の特定のディレクトリにクォータ制限をかけることが可能です:
# zfs set quota=20G <nameofzpool>/<nameofdataset>/<directory>
ZFS で利用できるコマンドを全て表示するには、次のコマンドを使用:
$ man zfs
または:
$ man zpool
スクラブ
少なくとも週に一度は ZFS プールをスクラブするべきです。プールをスクラブするには:
# zpool scrub <pool>
週一で自動的にスクラブするようにするには、root の crontab に次の行を設定してください:
# crontab -e
... 30 19 * * 5 zpool scrub <pool> ...
<pool>
は ZFS プールの名前に置き換えて下さい。
zfs プールの状態を確認
読み書きエラーなどの情報を含む、ZFS プールの統計が書かれた表を表示するには、次を使用:
# zpool status -v
ストレージプールを破壊
ZFS ではマウントされているストレージプールを破壊して、ZFS デバイスに関する全てのメタデータを簡単に削除することができます。次のコマンドはプールに含まれているデータを全て破壊します:
# zpool destroy <pool>
状態を確認すると:
# zpool status
no pools available
プールの名前を確認するには、#zfs プールの状態を確認 を見て下さい。
ストレージプールをエクスポート
ストレージプールを他のシステムで使用するときは、まずエクスポートする必要があります。また、archiso からプールをインポートしたときも、archiso での hostid と起動環境での hostid が異なるのでプールをエクスポートしなくてはなりません。zpool コマンドはエクスポートされていないストレージプールのインポートを拒否します。-f
引数を使って強制的にインポートすることもできますが、良い手段とは言えません。
エクスポートされていないストレージプールをインポートするとストレージプールが他のシステムによって使用されているというエラーが発生します。このエラーは起動時に発生することがあり、busybox コンソールでシステムが突然停止して、archiso による応急処置が必要になります。プールをエクスポートするか、またはカーネルのブートパラメータに zfs_force=1
を追加してください (こちらの方法はあまり芳しくありません)。#起動時に zfs プールがマウントされない: "pool may be in use from other system" を参照。
プールをエクスポートするには:
# zpool export bigdata
Zpool の名前を変更
既に作成済みの zpool の名前の変更は2ステップで行います:
# zpool export oldname # zpool import oldname newname
別のマウントポイントを設定
指定の zpool のマウントポイントは一つのコマンドで随意に移動することができます:
# zfs set mountpoint=/foo/bar poolname
スワップボリューム
ZFS ではスワップファイルを使うことはできませんが、ユーザーは ZFS ボリューム (ZVOL) をスワップとして利用することができます。ZVOL のブロックサイズをシステムページサイズと一致するように設定するのが重要です。システムページサイズは getconf PAGESIZE
コマンドで取得することができます (x86_64 でのデフォルトは 4KiB)。また、メモリが少ないシチュエーションでシステムを上手く動作させ続けるには zvol データのキャッシュを行わないほうが良いでしょう。
8GiB の zfs ボリュームを作成:
# zfs create -V 8G -b $(getconf PAGESIZE) \ -o primarycache=metadata \ -o com.sun:auto-snapshot=false <pool>/swap
スワップパーティションとして設定:
# mkswap -f /dev/zvol/<pool>/swap # swapon /dev/zvol/<pool>/swap
この設定を永続化させるには、/etc/fstab
を編集します。ZVOL は discard をサポートしており、ZFS のブロックアロケータの役に立ったり、スワップが満杯になったときに他のデータセットにおける断片化を減らすことができます。
/etc/fstab
に次の行を追加:
/dev/zvol/<pool>/swap none swap discard 0 0
ハイバネートフックはファイルシステムよりも前にロードされる必要があり、ZVOL をスワップとして使うとハイバネート機能が使えなくなることを覚えておいて下さい。ハイバネートが必要な場合は、スワップ用のパーティションを取っておいて下さい。
マシンを再起動する前に ZFS ファイルシステムを全てアンマウントしてください。マウントされていると ZFS プールはインポートできません:
# zfs umount -a
自動スナップショット
Linux の ZFS 自動スナップショットサービス
AUR の zfs-auto-snapshot-gitAUR パッケージにはスナップショットの管理の自動化を行うシェルスクリプトが入っています。スナップショットには日付とラベルで名前が付けられ (1時間毎、1日毎など)、全ての ZFS のデータセットを素早く簡単にスナップショットできます。15分毎・1時間毎・1日毎・1週間毎・1ヶ月毎にスナップショットを作成する cron タスクもインストールされます。任意で --keep パラメータを調整することでスナップショットを保存する期間を設定できます (1ヶ月毎のスクリプトはデフォルトで1年間までデータを保存します)。
データセットがスナップショットされないようにするには、データセットに com.sun:auto-snapshot=false
を設定してください。同じように、ラベルで細かい設定をすることができます。例えば、1ヶ月毎のスナップショットを作成しないようにするには com.sun:auto-snapshot:monthly=false
を設定します。
ZFS スナップショットマネージャ
AUR の zfs-snap-managerAUR パッケージは ZFS データセットのスナップショットを毎日作成して "Grandfather-father-son" 方式で削除していく python サービスを提供します。7日毎、5週間毎、3ヶ月毎、2年間毎などのスナップショットを保持するよう設定できます。
このパッケージは ZFS が動作している他のマシンへのレプリケーションもサポートしており zfs send
と zfs receive
を使います。同期先のマシンでもこのパッケージを使用している場合、複製したスナップショットを長期間にわたって保持するように設定することが可能です。これによって、同期元のマシンには毎日のスナップショットだけを少しだけローカルに保存して、リモートのストレージサーバーに大量のスナップショットを保存するという構成ができます。
トラブルシューティング
ZPool の作成が失敗する
以下のエラーが発生した場合:
# the kernel failed to rescan the partition table: 16 # cannot label 'sdc': try using parted(8) and then provide a specific slice: -1
ZFS がプールの作成が1秒未満で終わることを要求しているのが原因の一つです。通常状態では問題ありませんが、1秒以上かかってしまう状況というのはたくさんあります。もう一度作成を試行する前に、それぞれのドライブをクリアにする必要があります。
# parted /dev/sda rm 1 # parted /dev/sda rm 1 # dd if=/dev/zero of=/dev/sdb bs=512 count=1 # zpool labelclear /dev/sda
力づくで何度も作成してみることもでき、運が良ければ ZPool の作成が1秒未満で終わるでしょう。作成のスローダウンが一度発生すると、ドライブのバースト読み書きが遅くなることがあります。ZPool の作成と並行して読み込むことで、バースト速度を向上させることが可能です。
# dd if=/dev/sda of=/dev/null
複数のディスクで行うには、上記のコマンドをそれぞれのディスクでファイルに保存して次を実行:
# cat $FILE | parallel
そして同時に ZPool の作成を実行します。
ZFS の使用 RAM が多すぎる
デフォルトでは、ZFS はホストのシステムメモリの3分の2まで使用してファイル操作をキャッシュします (ARC)。ZFS はエンタープライズクラスのストレージシステム用に設計されたことを思い出して下さい。ARC サイズを調整するには、以下をカーネルパラメータのリストに追加します:
zfs.zfs_arc_max=536870912 # (for 512MB)
他の設定オプションや、より詳しい説明は gentoo-wiki:zfs#arc を見て下さい。
Does not contain an EFI label
zfs ファイルシステムを作成しようとするときに以下のエラーが発生することがあります:
/dev/disk/by-id/<id> does not contain an EFI label but it may contain partition
このエラーを打破するには zfs の create コマンドで -f
を使って下さい。
No hostid found
起動時に initscript の出力が表示される前に以下のエラーが発生する場合:
ZFS: No hostid found on kernel command line or /etc/hostid.
この警告は ZFS モジュールが spl hosted にアクセスできないのが原因です。この問題には2つの解決方法があります。一つはブートローダーのカーネルパラメータに spl hostid を記述することです。例えば、spl.spl_hostid=0x00bab10c
を追加します。
もう一つの解決方法は /etc/hostid
に hostid があることを確認して、initramfs イメージを再生成することです。それによって hostid 情報が initramfs イメージにコピーされます。
# mkinitcpio -p linux
起動時に zfs プールがマウントされない: "pool may be in use from other system"
プールがエクスポートされていない
zpool がインポートできないために新しいインストール環境が起動しない場合、インストール環境に chroot して zpool を正しくエクスポートしてください。#archzfs による chroot の応急処置 を参照。
chroot 環境に入ったら、ZFS モジュールをロードして強制的に zpool をインポートします:
# zpool import -a -f
そしてプールをエクスポートします:
# zpool export <pool>
利用可能なプールを確認するには、次を使用:
# zpool status
ZFS は hostid を使って zpool が作成されたシステムを追跡するのでプールをエクスポートする必要があります。hostid はネットワークの設定時に生成されます。archiso でのインストール中、ネットワーク設定が違うせいで新しい環境に含まれている hostid と異なる hostid が生成されることがあります。zfs ファイルシステムをエクスポートしたら新しい環境でインポートしなおしてください。それで hostid はリセットされます。参照: Re: Howto zpool import/export automatically? - msg#00227。
起動する度に ZFS が "pool may be in use" と表示する場合は、上記のようにプールを適切にエクスポートして、通常通りに ramdisk を再生成してください:
# mkinitcpio -p linux
hostid が間違っている
プールが正しくエクスポートされていることを確認してください。zpool をエクスポートすると所有者を示す hostid がクリアされます。そのため最初の起動時に zpool を正しくマウントする必要があります。マウントされなかった場合、他の問題が起こります。
hostid が正しく設定されておらず zfs が混同されているために zfs プールがマウントできないときは、もう一度再起動してください。手動で zfs に適切な数字を指定します。hostid は再起動しても変わらないため zpool は適切にマウントされます。
zfs_force を使って起動して hostid をメモします。例:
% hostid 0a0af0f8
この数字を spl.spl_hostid=0a0af0f8
のようにしてカーネルパラメータに追加してください。もう一つの解決方法は hostid を initram イメージの中に書き出すことです。この方法についてはインストールガイドの説明を見て下さい。
カーネルパラメータに zfs_force=1
を追加することでチェックを常に無視することができます。ただし恒久的に使用するのは推奨されません。
デバイスのセクタアライメントが異なっている
ドライブが故障したときは、できるだけはやく同じドライブでドライブを交換してください。
# zpool replace bigdata ata-ST3000DM001-9YN166_S1F0KDGY ata-ST3000DM001-1CH166_W1F478BD -f
ただし、この場合、以下のエラーが発生します:
cannot replace ata-ST3000DM001-9YN166_S1F0KDGY with ata-ST3000DM001-1CH166_W1F478BD: devices have different sector alignment
ZFS は ashift オプションを使って物理ブロックサイズを調整しています。故障したディスクを置き換えるとき、ZFS は ashift=12
を使用しますが、故障したディスクの ashift が異なっている (例えば ashift=9
) 場合、結果としてこのエラーが起こってしまいます。
ブロックサイズが 4KB の Advanced Format ディスクの場合、一番良いパフォーマンスを出すため ashift は 12 が推奨されます。1.10 What’s going on with performance? や ZFS and Advanced Format disks を見て下さい。
zpool の ashift を確認するには zdb を使います: zdb | grep ashift
。
-o
引数を使って交換用ドライブの ashift を設定してください:
# zpool replace bigdata ata-ST3000DM001-9YN166_S1F0KDGY ata-ST3000DM001-1CH166_W1F478BD -o ashift=9 -f
zpool status で確認を行なって下さい:
# zpool status -v
pool: bigdata state: DEGRADED status: One or more devices is currently being resilvered. The pool will continue to function, possibly in a degraded state. action: Wait for the resilver to complete. scan: resilver in progress since Mon Jun 16 11:16:28 2014 10.3G scanned out of 5.90T at 81.7M/s, 20h59m to go 2.57G resilvered, 0.17% done config: NAME STATE READ WRITE CKSUM bigdata DEGRADED 0 0 0 raidz1-0 DEGRADED 0 0 0 replacing-0 OFFLINE 0 0 0 ata-ST3000DM001-9YN166_S1F0KDGY OFFLINE 0 0 0 ata-ST3000DM001-1CH166_W1F478BD ONLINE 0 0 0 (resilvering) ata-ST3000DM001-9YN166_S1F0JKRR ONLINE 0 0 0 ata-ST3000DM001-9YN166_S1F0KBP8 ONLINE 0 0 0 ata-ST3000DM001-9YN166_S1F0JTM1 ONLINE 0 0 0 errors: No known data errors
Tips and tricks
archzfs パッケージを archiso に埋め込む
必要なソフトウェアが含まれるインストールメディアを作成するのは良い考えです。ただし、最新の archiso インストールメディアを CD や USB キーに書き込む必要があります。
既存の環境から、archiso に zfs
を埋め込むには、archiso
パッケージをダウンロード:
# pacman -S archiso
プロセスを開始:
# cp -r /usr/share/archiso/configs/releng /root/media
packages.x86_64
ファイルを編集して以下の行を追加:
spl-utils-git spl-git zfs-utils-git zfs-git
pacman.conf
ファイルを編集して以下の行を追加 (TODO, correctly embed keys in the installation media?):
[demz-repo-archiso] SigLevel = Never Server = http://demizerone.com/$repo/$arch
必要であれば他のパッケージも packages.both
, packages.i686
, packages.x86_64
に追加してイメージを作成します。
# ./build.sh -v
イメージは /root/media/out
ディレクトリにできます。
プロセスの詳細は このガイド や Archiso の記事で読めます。
UEFI 環境にインストールする場合は、Unified Extensible Firmware Interface#ISO から UEFI ブータブル USB を作成する を見て UEFI に対応するインストールメディアを作成してください。
ZFS on linux で暗号化
ZFS on linux は直接暗号化をサポートしていませんが、zpool を dm-crypt ブロックデバイスの中に作成することができます。zpool は平文の抽象レイヤー上に作成されるので、重複排除や圧縮、データの堅牢性といった ZFS の利点を全て活かしながらデータを暗号化することが可能です。
dm-crypt (LUKS) は /dev/mapper
にデバイスを作成し、デバイスの名前は固定されます。そのため、zpool create
コマンドを変更してその名前を使う必要があります。/dev/mapper
ブロックデバイスを作成してそこから zpool をインポートするようにシステムを設定することが狙いです。zpool は複数のデバイスに作成することができるので (raid, mirroring, striping, ...)、全てのデバイスを暗号化するのが重要です。そうしないと保護が部分的に欠ける恐れがあります。
例えば、以下を使うことでプレーンな dm-crypt (LUKS は使わない) で暗号化された zpool を作成することができます:
# cryptsetup --hash=sha512 --cipher=twofish-xts-plain64 --offset=0 --key-file=/dev/sdZ --key-size=512 open --type=plain /dev/sdX enc # zpool create zroot /dev/mapper/enc
root ファイルシステムのプールの場合、mkinicpio.conf
の HOOKS 行でパスワードを入力するためのキーボードを有効にしたり、デバイスを作成、プールをロードします。以下のようになります:
HOOKS="... keyboard encrypt zfs ..."
/dev/mapper/enc
の名前は固定されているためインポートエラーは発生しません。
暗号化された zpool の作成は問題なく動作します。ただし、ディレクトリの暗号化が必要な場合、例えばユーザーのホームを保護したいとき、ZFS は機能をいくつか失います。
ZFS は平文の抽象レイヤーではなく暗号化されたデータを回覧するので、圧縮や重複排除は動作しません。暗号化されているデータは高エントロピーであり圧縮がうまく効かないのと、入力と出力が異なって重複排除ができなくなってしまうからです。不必要なオーバーヘッドを減らすために、暗号化ディレクトリにサブファイルシステムを作成して、その上で eCryptfs を使うことができます。
例えばホームを暗号化するには: (暗号化とログインの2つのパスワードは同じである必要があります)
# zfs create -o compression=off \ -o dedup=off \ -o mountpoint=/home/<username> \ <zpool>/<username> # useradd -m <username> # passwd <username> # ecryptfs-migrate-home -u <username> <log in user and complete the procedure with ecryptfs-unwrap-passphrase>
archzfs による chroot の応急処置
以下はメンテナンスのために archiso を使って ZFS ファイルシステムに入る方法です。
最新の archiso を起動してネットワークを立ち上げる:
# wifi-menu # ip link set eth0 up
ネットワーク接続をテスト:
# ping google.com
pacman パッケージデータベースを同期:
# pacman -Syy
(任意) テキストエディタのインストール:
# pacman -S vim
archzfs の archiso リポジトリを pacman.conf
に追加:
/etc/pacman.conf
[demz-repo-archiso] Server = http://demizerone.com/$repo/$arch
pacman パッケージデータベースを同期:
# pacman -Syy
archzfs のメンテナの PGP 鍵をローカルの (インストーライメージの) 信頼リストに追加:
# pacman-key --lsign-key 0EE7A126
ZFS パッケージグループをインストール:
# pacman -S archzfs-git
ZFS カーネルモジュールをロード:
# modprobe zfs
プールをインポート:
# zpool import -a -R /mnt
(存在する場合) ブートパーティションをマウント:
# mount /dev/sda2 /mnt/boot # mount /dev/sda1 /mnt/boot/efi
ZFS ファイルシステムに chroot:
# arch-chroot /mnt /bin/bash
カーネルのバージョンを確認:
# pacman -Qi linux # uname -r
uname は archiso のカーネルバージョンを表示します。バージョンが異なる場合、chroot 環境の適切なカーネルバージョンで depmod を (chroot の中で) 実行してください:
# depmod -a 3.6.9-1-ARCH (version gathered from pacman -Qi linux)
これで chroot 環境にインストールされているカーネルバージョンに合ったカーネルモジュールがロードされます。
ramdisk の再生成:
# mkinitcpio -p linux
エラーは起こらないはずです。
バインドマウント
以下では /mnt/zfspool
から /srv/nfs4/music
へのバインドマウントを作成します。バインドマウントを作成する前に zfs プールの準備ができていることを確認してください。
fstab
systemd-fstab-generator を使って systemd が fstab を mount ユニットファイルにどうやって変換するのかは systemd.mount を見てください。
/etc/fstab
/mnt/zfspool /srv/nfs4/music none bind,defaults,nofail,x-systemd.requires=zfs-mount.service 0 0
systemd マウントユニット
zfs プールの準備をする前に fstab が読み込まれるため、fstab を使って zfs 上のディレクトリを他のディレクトリにバインドマウントできない場合、systemd の mount ユニットを使うことでバインドマウントすることが可能です。マウントユニットの名前は "Where" の後ろに記述するディレクトリと一致している必要があります。スラッシュはマイナスに置き換えてください。詳しくは [[2]] や [[3]] を参照。
srv-nfs4-music.mount
[Mount] What=/mnt/zfspool Where=/srv/nfs4/music Type=none Options=bind [Unit] DefaultDependencies=no Conflicts=umount.target Before=local-fs.target umount.target After=zfs-mount.service Requires=zfs-mount.service ConditionPathIsDirectory=/mnt/zfspool [Install] WantedBy=local-fs.target
参照
- ZFS on Linux
- ZFS on Linux FAQ
- FreeBSD Handbook -- The Z File System
- Oracle Solaris ZFS Administration Guide
- Solaris Internals -- ZFS Troubleshooting Guide
- Pingdom details how it backs up 5TB of MySQL data every day with ZFS
- Aaron Toponce は ZFS に関する17部からなるブログ記事を執筆しています。素晴らしい読み物です。
- VDEVs
- RAIDZ Levels
- The ZFS Intent Log
- The ARC
- Import/export zpools
- Scrub and Resilver
- Zpool Properties
- Zpool Best Practices
- Copy on Write
- Creating Filesystems
- Compression and Deduplication
- Snapshots and Clones
- Send/receive Filesystems
- ZVOLs
- iSCSI, NFS, and Samba
- Get/Set Properties
- ZFS Best Practices