ZFS (日本語) - ArchWiki

# ZFS (日本語)

関連記事

- ファイルシステム
- ZFS の実験
- ZFS に Arch Linux をインストール
- ZFS on FUSE

ZFS は (現在は Oracle によって吸収合併された) Sun Microsystems によって作成された先進的なファイルシステムで、2005年11月に OpenSolaris でリリースされました。ZFS には以下の機能があります: ストレージプール (統合ボリューム管理 -- zpool), Copy-on-write, スナップショット, データ整合性のチェックと自動修復 (スクラブ), RAID-Z, 最大16エクサバイトのファイルサイズ、最大256ゼタバイトのボリュームサイズ。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-git をインストールしてください。このパッケージは zfs-utils-git と spl-git を依存パッケージとしており、さらに spl-utils-git が依存パッケージとしてインストールされます。SPL (Solaris Porting Layer) は ZFS に対応するための Solaris API を実装する Linux カーネルモジュールです。

Note: zfs-git パッケージは AUR のオリジナルの zfs パッケージを置き換えます。ZFSonLinux.org は安定版リリースを出すのが遅いため、カーネル API の変更によって Arch の ZFSonLinux の安定版ビルドが破壊されます。ZFSonLinux の master ブランチへの変更はリグレッションテストがされているので安定していると考えられます。

安定版の ZFS ビルドを使いたいユーザーには、Arch User Repository か demz-repo-core リポジトリから zfs-lts がインストールできます。

Warning: ZFS と SPL カーネルモジュールは特定のバージョンのカーネルに固定されています。AUR や demz-repo-core リポジトリに新しいパッケージがアップロードされるまでは、カーネルのアップデートを適用してはいけません。

コマンドラインで `zpool status` を実行してインストールをテストしてください。"insmod" エラーが起こる場合は、`depmod -a` を実行してみてください。

### Archiso

ZFS の root ファイルシステムに Arch Linux をインストールする場合は、Arch User Repository か demz-repo-archiso リポジトリから zfs-git をインストールしてください。

詳しい情報は Installing Arch Linux on ZFS を参照。

### 自動ビルドスクリプト

依存関係が入れ子になっているため、上のビルド順序は重要です。以下のシェルスクリプトを使うことで、パッケージのダウンロードから全てのプロセスを自動化することができます。スクリプトを使うために必要なものは:

- sudo - 下のスクリプトを動作させるには `/usr/bin/clean-chroot-manager` を実行するための sudo の権限がユーザーに必要です。
- rsync - ビルドファイルを移動するのに必要。
- cower - AUR からソースを取得するのに必要。
- clean-chroot-manager - クリーンな 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"

## ZFS の実験

`~/zfs0.img` `~/zfs1.img` `~/zfs2.img` などのシンプルなファイルの仮想ブロックデバイス (ZFS では VDEV と呼称) を使って、データを消失する危険性なく、ZFS の実験を行いたいユーザーは Experimenting with ZFS の記事を見て下さい。RAIDZ アレイの作成や、意図的にデータを破損させてそれを復元したり、データセットのスナップショットなどの一般的な作業を取り扱っています。

## 設定

ZFS はその開発者から"ゼロアドミニストレーション"のファイルシステムであるとされています。そのため、ZFS の設定はとても簡単です。設定は主に2つのコマンドを使って行います: `zfs` と `zpool`。

Note: 下のセクションは root ファイルシステムを ZFS ボリュームにインストールしたい場合にのみ必要になります。データパーティションを ZFS で扱うユーザーは次のセクションを読む必要はありません。

### 自動起動

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 ファイルシステムを作成する前にドライブをパーティションする必要はありません、推奨もされていません。

Note: デバイスの一部または全部でソフトウェア RAID を使っている場合は、昔の RAID 設定情報を全て削除してください (Mdadm (日本語)#デバイスの準備)。
Warning: セクターサイズが 4KB の Advanced Format ディスクでは、パフォーマンスを最大限引き出すために ashift を 12 にすることが推奨されています。Advanced Format ディスクはレガシーなシステムとの互換性のために512バイトのセクターサイズをエミュレートするため、ZFS が使用する ashift の数字が望ましい数値にならないことがあります。プールを一度作成してしまった場合、ashift オプションを変更するにはプールを再作成するしかありません。また、ashift を 12 にすると利用できる容量が減少します。1.10 What’s going on with performance?, 1.15 How does ZFS on Linux handles Advanced Format disks?, ZFS and Advanced Format disks を見て下さい。

ドライブの一覧を確認できたら、次は zpool を追加するドライブの id を取得します。10デバイス以下の ZFS ストレージプールを作成する際はデバイス id を使うことを zfs on Linux の開発者は推奨しています。id を調べるには:

    $ ls -lah /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 プールがマウントされるか確認するためにマシンを再起動すると良いでしょう。データを移し替える前に全てのエラーに対処するのがベストです。

## チューニング

### 一般

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 はつまり、データの透過圧縮です。様々なオプションがあるので man ページを参照してください。最近名声が高いのは lz4 アルゴリズムで、素晴らしい圧縮パフォーマンスを実現します。zfs コマンドを使うことで lz4 (もしくは他のアルゴリズム) の圧縮を有効にできます:

    # 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

Note: これらのパラメータのチューニングは RDBMS などの特別なアプリケーションで相応しい類のものです。/home ディレクトリなどの一般目的のファイルシステムで上記チューニングを設定すると ZFS のパフォーマンスに害を与える可能性があります。

### /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/zroot/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-git パッケージにはスナップショットの管理の自動化を行うシェルスクリプトが入っています。スナップショットには日付とラベルで名前が付けられ (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-manager パッケージは 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

エラーは起こらないはずです。

## 参照

- ZFS に Arch Linux をインストール
- 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部からなるブログ記事を執筆しています。素晴らしい読み物です。

1. VDEVs
2. RAIDZ Levels
3. The ZFS Intent Log
4. The ARC
5. Import/export zpools
6. Scrub and Resilver
7. Zpool Properties
8. Zpool Best Practices
9. Copy on Write
10. Creating Filesystems
11. Compression and Deduplication
12. Snapshots and Clones
13. Send/receive Filesystems
14. ZVOLs
15. iSCSI, NFS, and Samba
16. Get/Set Properties
17. ZFS Best Practices

Category:

- File systems (日本語)