FreeBSD ZFS の基本

(2015.11 新規作成.)

PC-BSD をうまく動かせなかったのと, FreeNAS が中で何をしているかよく分からなかったので, 改めて FreeBSD でZFSを試す。

FreeBSD 10.2-RELEASE

ZFS

ZFS は多くの優れた特徴を持つファイルシステム。ただし、CPU, メモリの要求レベルが高い。

ZFS は, ZFS Storage Pool (zpool) と ZFS File System (zfs) の2階層で管理される。

1. zpool が物理ディスクドライブをまとめる。zpool のレベルで, ソフトウェアRAID機能を持つ。

  • mirror = RAID1相当。
  • raidz RAID-Z = RAID5改良. N本 (N ≧ 3) のデヴァイスに対して, (N - 1) 本分の容量。1台までの故障に耐える。
  • raidz2 RAID-Z2 = RAID6改良。N本 (N ≧ 4) のデヴァイスに対して, (N - 2) 本分の容量。2台までの故障に耐える。
  • raidz3 RAID-Z3 = トリプルパリティ

ハードウェアRAIDと組み合わせる場合は, 構成をよく考える必要がある。

2. ファイルシステム (zfs) は, ストレージプール (zpool) から切り出す。しかし, zpool と zfs は繋がっていて, ファイルシステム作成時に容量を指定する必要がない。

特に指定しないと、複数のファイルシステムで zpool がシェアされる。zpool にディスクを追加すると、ファイルシステム容量の上限が増える.

情報源

UNIXサーバ SPARC Enterprise 技術情報 Technical Park : 富士通
ここにある「ZFSを使ってみよう(基本編)」が、概要を知るのにいい。

使うコマンドは zpoolzfs. それぞれサブコマンドがたくさんある。マニュアルは man 8 zpool, man 8 zfs.

ただ, man page は, 単にテキストがずらずら書いてあるだけで、サブコマンドが多い ZFS では読みにくい。

バージョン

FreeBSD のZFSのコードは, OpenZFS を利用している。

illumos, FreeBSD, ZFS on Linux, OpenZFS on OS X で共有されているようだ。

zpool version 28. Oracle Solaris のzpool バージョン29 以降とは互換性がない; ZFS Pool Versions - Managing ZFS File Systems in Oracle® Solaris 11.3

zpool の作成

今, HDD が2台, da0da1 が接続されている。da1 は空ドライブ。

# gpart show da0
=>      34  41942973  da0  GPT  (20G)
        34         6       - free -  (3.0K)
        40      1024    1  freebsd-boot  (512K)
      1064       984       - free -  (492K)
      2048   4194304    2  freebsd-swap  (2.0G)
   4196352  37744640    3  freebsd-zfs  (18G)
  41940992      2015       - free -  (1.0M)

[2021.5] FreeBSD 13: UEFI 環境では, freebsd-boot の前に efi パーティション (260Mバイト) がある。

da1 の下準備

(2015.11.22) このステップは不要。da1 全体を zpool にできる。また, パーティションを切らずに zpool に加えるほうが, 推奨されているようだ。

da1 のフォーマット.

# gpart create -s GPT da1
da1 created

全部を freebsd-zfs にする。

# gpart add -t freebsd-zfs da1
da1p1 added

確認。

# gpart show da1
=>      34  20971453  da1  GPT  (10G)
        34  20971453    1  freebsd-zfs  (10G)

zpoolを作る

物理的なディスクドライブは zpool にまとめる。zpool のレベルで, striping や mirroring などをおこなう。

今回は、ディスクドライブの故障をテストしたいので、別の zpool で作ってみる。

まずは現在の状態を確認.

# zpool list -v
NAME         SIZE  ALLOC   FREE  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
zroot       17.9G  4.99G  12.9G         -    11%    27%  1.00x  ONLINE  -
  da0p3     17.9G  4.99G  12.9G         -    11%    27%

RAID0 (冗長性なし, striping) で作る。まず -n オプションで dry run (実際には実行しない);

# zpool create -n datatank /dev/da1p1
would create 'datatank' with the following layout:

        datatank
          da1p1

実際に作る.

# zpool create datatank /dev/da1p1

できたかな?

% zpool list -v
NAME         SIZE  ALLOC   FREE  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
datatank    9.94G   219K  9.94G         -     0%     0%  1.00x  ONLINE  -
  da1p1     9.94G   219K  9.94G         -     0%     0%
zroot       17.9G  5.03G  12.8G         -    12%    28%  1.00x  ONLINE  -
  da0p3     17.9G  5.03G  12.8G         -    12%    28%

zpool を作ると, 勝手に mount されてしまう。... 'datatank' という名前は zpool であると同時にファイルシステムでもある。/etc/fstabファイルは参照されない。

この挙動は非常に紛らわしい。zfsコマンドで 自動 mount を止める。

# df datatank
Filesystem 1K-blocks Used    Avail Capacity  Mounted on
datatank    10094380   19 10094361     0%    /datatank
# zfs set mountpoint=none datatank
# zfs list
NAME                 USED  AVAIL  REFER  MOUNTPOINT
datatank            74.5K  9.63G    19K  none
zroot               4.99G  12.3G    96K  /zroot
zroot/ROOT          4.32G  12.3G    96K  none
zroot/ROOT/default  4.32G  12.3G  4.32G  /
zroot/tmp           39.0M  12.3G  39.0M  /tmp
zroot/usr            629M  12.3G    96K  /usr
zroot/usr/home      4.60M  12.3G  4.60M  /usr/home
zroot/usr/ports      624M  12.3G   624M  /usr/ports
zroot/usr/src         96K  12.3G    96K  /usr/src
zroot/var           9.44M  12.3G    96K  /var
zroot/var/audit       96K  12.3G    96K  /var/audit
zroot/var/crash       96K  12.3G    96K  /var/crash
zroot/var/log        256K  12.3G   256K  /var/log
zroot/var/mail       128K  12.3G   128K  /var/mail
zroot/var/tmp       8.79M  12.3G  8.79M  /var/tmp

Avail. がファイルシステム間で共有されていることに注目。

状態表示

# zpool status datatank
  pool: datatank
 state: ONLINE
  scan: none requested
config:

        NAME        STATE     READ WRITE CKSUM
        datatank    ONLINE       0     0     0
          da1p1     ONLINE       0     0     0

errors: No known data errors

ZFSデータセット

ZFS では「データセット(dataset)」という用語を使う。データセットは次の3つのいずれか;

ファイルシステム
ヴォリューム ... ブロックデバイス
スナップショット

コマンドによって, これらを相互に区別せず扱える場合もあるし、そうでない場合もある。

ZFSファイルシステムを作る

必ず2レベル以上にして, zpool と区別しやすいようにする。

ファイルシステムの作成はzfs create コマンド. mountpoint を指定しよう.

# zfs create -o mountpoint=/usr/home/share datatank/share

自動マウントされる;

# df | grep datatank
datatank/share      10094504      19 10094485     0%    /usr/home/share

マウントポイントを変更するには, zfs set mountpoint=. 次の例は, datatank/home ZFSファイルシステムを /mnt/home にマウントする。

# zfs set mountpoint=/mnt/home datatank/home

プロパティ

それぞれのZFSファイルシステムは「プロパティ」を持つ。マウントポイントもプロパティの一つ。プロパティはZFS名で見た親から継承される。

プロパティは zfs get コマンドで表示できる。ZFS名を指定しないとリスト表示される。SOURCE 欄で, そのプロパティがどこから継承されたか表示される。

# zfs get mountpoint
NAME                PROPERTY    VALUE            SOURCE
datatank            mountpoint  none             local
datatank/share      mountpoint  /usr/home/share  local
zroot               mountpoint  none             local
zroot/ROOT          mountpoint  none             local
zroot/ROOT/default  mountpoint  /                local
zroot/tmp           mountpoint  /tmp             local
zroot/usr           mountpoint  /usr             local
zroot/usr/home      mountpoint  /usr/home        inherited from zroot/usr
zroot/usr/ports     mountpoint  /usr/ports       inherited from zroot/usr
zroot/usr/src       mountpoint  /usr/src         inherited from zroot/usr
zroot/var           mountpoint  /var             local
zroot/var/audit     mountpoint  /var/audit       inherited from zroot/var
zroot/var/crash     mountpoint  /var/crash       inherited from zroot/var
zroot/var/log       mountpoint  /var/log         inherited from zroot/var
zroot/var/mail      mountpoint  /var/mail        inherited from zroot/var
zroot/var/tmp       mountpoint  /var/tmp         inherited from zroot/var

割当上限 (quota), 割当予約 (reservation) プロパティは継承されない。いずれも, 子孫を含んだ大きさを指定するため。

ファイルサーバ用途では, atime は無効化したほうがいいらしい;

# zfs get atime
NAME                PROPERTY  VALUE  SOURCE
datatank            atime     on     default
datatank/share      atime     on     default
datatank/share@s2   atime     -      -
zroot               atime     off    local
zroot/ROOT          atime     off    inherited from zroot
zroot/ROOT/default  atime     off    inherited from zroot
zroot/tmp           atime     off    inherited from zroot
zroot/usr           atime     off    inherited from zroot
zroot/usr/home      atime     off    inherited from zroot
zroot/usr/ports     atime     off    inherited from zroot
zroot/usr/src       atime     off    inherited from zroot
zroot/var           atime     off    inherited from zroot
zroot/var/audit     atime     off    inherited from zroot
zroot/var/crash     atime     off    inherited from zroot
zroot/var/log       atime     off    inherited from zroot
zroot/var/mail      atime     on     local
zroot/var/tmp       atime     off    inherited from zroot

デフォルトでは on になるようなので、off にする。

# zfs set atime=off datatank

確認

# zfs get atime datatank datatank/share
NAME            PROPERTY  VALUE  SOURCE
datatank        atime     off    local
datatank/share  atime     off    inherited from datatank

Mirroring - RAID1相当

シングル構成の状態に1台ドライヴを追加して、ミラーリングする。

何もデータがないのを確認してから、パーティションを切る。

# gpart show da1
gpart: No such geom: da1.

# gpart create -s gpt da1
da1 created

# gpart add -t freebsd-zfs -l hdd-2-1 da1
da1p1 added

確認。一つだけ。

# gpart show da1
=>      40  41942960  da1  GPT  (20G)
        40  41942960    1  freebsd-zfs  (20G)

既存の zpool にこのデヴァイスを追加する。まず、状況確認。

# zpool status zroot
  pool: zroot
 state: ONLINE
config:

        NAME        STATE     READ WRITE CKSUM
        zroot       ONLINE       0     0     0
          da0p4     ONLINE       0     0     0

errors: No known data errors

zpool コマンドがややこしい。新しい zpool を作るには zpool create コマンド。既存の zpool にデヴァイスのペアを追加して、zpool を拡張するときは zpool add コマンド。

新しいデヴァイスを追加して, 既存のデヴァイスとペアにするのは zpool attach コマンド。既存のデヴァイスはミラー化されていなくても、されていても構わない。後者の場合は 3方向ミラーになる。

ミラーリングしたい既存のデヴァイスと新しいデヴァイスを指定する。自動的にresilver される。銀色になるという意味ではなく、利用可能になる、という意味のようだ。

# zpool attach zroot da0p4 gpt/hdd-2-1

# zpool status zroot
  pool: zroot
 state: ONLINE
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 Wed Aug  4 16:05:07 2021
        9.49G scanned at 120M/s, 1.88G issued at 23.8M/s, 9.49G total
        1.90G resilvered, 19.84% done, 00:05:27 to go
config:

        NAME             STATE     READ WRITE CKSUM
        zroot            ONLINE       0     0     0
          mirror-0       ONLINE       0     0     0
            da0p4        ONLINE       0     0     0
            gpt/hdd-2-1  ONLINE       0     0     0  (resilvering)

errors: No known data errors