Ubuntu 19.10ではデスクトップのインストール時にファイルシステムとしてZFSを選択できる機能が実験的に 導入されました。そこで今回はそのZFSを実際に使ってみましょう。
なぜZFSをデスクトップに?
Ubuntu Weekly Topicsの2019年8月9日号 でも紹介しているように、Ubuntu 19.10からインストール時に「デスクトップ」のルートファイルシステムとして、ZFS on Linux のZFSを選択できるようになりました[1] 。これはあくまで実験的な 機能であり、ZFS特有の機能がすぐに活用できる状態になるわけでもありませんし、環境や使い方によっては不安定になる可能性もあります。将来の可能性に向けたお試し機能であることを十分に理解しておいてください。
ZFSそのものはUbuntu 15.10の頃から利用可能でした。その後、19.10に向けて次の対応が行われます。
GRUBからZFSなルートファイルシステムを簡単に選択できるようにする[2]
LinuxカーネルのパッケージにZFSのカーネルモジュールを同梱する[3]
インストーラー(Ubiquity)でZFSなルートファイルシステムを作成できるようにする
これらの対応により、デスクトップ環境において「インストール直後のルートファイルシステム」としてZFSを指定できるようになったのです。
UbuntuとZFSの関係やライセンスに関する話は、現在発売中の『Software Design 2019年12月号 』に掲載されている「Ubuntu Monthly Report」の『【 115】Ubuntu 19.10とZFS』にて、あわしろいくや氏がいろいろと言及していますので、そちらを参照してください。
ZFSは非常にメモリを使うファイルシステムです。ZFS on LinuxのFAQにも「Hardware Requirements 」として、「 ECCの利用を強く推奨」「 最良のパフォーマンスを得るためには8GB以上のメモリを。2GB以下でもきちんと動きはするが、重複削除(dedup)機能を使うより多くのメモリが必要になる」とあります。
最近ではPC用途でも8GB以上のメモリは一般的になったものの、ECC付きとなるとまだワークステーションやサーバークラスのマシンになってしまいます。ましてや、ZFSの強みはファイルシステムとしてRAIDやスクラビングによる故障検知、そして障害発生時のホットスワップなど、「 複数のストレージデバイス」が前提になっている機能が大半です。
よってデスクトップやノートPCで「ZFS」と言われても、一般的なユーザー[4] には機能の使い道がなく、オーバーキル気味な印象を受けます。とは言えスナップショット・リストアや暗号化など個人でも使いやすい機能もたくさん存在するため、今後Ubuntuとしてどういうユースケースを提案していくのか楽しみです[5] 。
[4] この記事では1台のクライアントマシンに1台(HDD or SSD or eMMC)ないし2台(HDD and SSD and eMMC)な内蔵ストレージデバイスを繋いでいるユーザーを「一般的なユーザー」と定義しています。それ以外の人はアブノーマルです。
とにもかくにも食わず嫌いは良くありません。今回は実際にZFSを使っていろいろ試してみることにします。あらかじめ仮想マシンか何かに、Ubuntu 19.10をZFSでインストールしておいてください[6] 。
[6] 本記事では4GBのメモリと20GBのQCOW2ディスクで作成したKVMによる仮想マシンインスタンス上にインストールして動作確認しました。もちろんVirtualBoxなどでも問題なく使えるはずです。
図1 インストーラーで「実験的機能」を選択する勇気
インストール直後の状態確認
まずはインストール直後の状態を確認してみましょう。最初にパーティションレイアウトを見てみます。
$ sudo parted /dev/vda unit MiB print
モデル: Virtio Block Device (virtblk)
ディスク /dev/vda: 20480MiB
セクタサイズ (論理/物理): 512B/512B
パーティションテーブル: gpt
ディスクフラグ:
番号 開始 終了 サイズ ファイルシステム 名前 フラグ
1 1.00MiB 513MiB 512MiB fat32 EFI System Partition boot, esp
2 513MiB 563MiB 50.0MiB ext4
3 563MiB 1486MiB 923MiB linux-swap(v1)
4 1486MiB 3534MiB 2048MiB zfs
5 3534MiB 20480MiB 16946MiB zfs
最初のパーティションはEFI System Partition(ESP)です。今回はUEFIファームウェアを利用したため、EFI OSローダー(GRUBやセキュアブート用のshimなど)を保存するためのESPが作られています。ESPはFAT12/16/32のいずれかである必要があるため、ZFSで作ることはできません。
第2パーティションはGRUBの設定ファイルやモジュール類をインストールする領域です。GRUB自体は「insmod zfs
」を実行して初めてZFSの内容を確認できます。つまりGRUBがカーネルやinitramfsをZFSからロードするためには、GRUBのモジュール類はGRUBが標準でサポートしているファイルシステムに置かれている必要があるのです。このための領域をext4として作成しています。
ただしこれはESPと分離する意味があまりないため、Ubuntu 20.04 LTSからはESPに統合されます。結果としてBIOSモードでも(UEFIが動かない環境でも) 、ESP相当のGRUBモジュールがインストールされるパーティションが作られます。
第3パーティションは見てのとおりスワップパーティションです。Ubuntuは17.04からスワップパーティションを作らずに、ファイルシステム上のスワップファイルを利用することになりました。ZFSはスワップファイルを使えないため、明示的にスワップパーティションを作っています。ちなみにZFS上にスワップ用のボリュームを作ることも可能です[7] 。この部分は将来的に変わるかもしれません。
第4パーティションと第5パーティションがZFS用のパーティションです。前者が起動カーネルなどを保存する「/boot」用、後者がそれ以外のデータを保存するルートファイルシステム用に用意されています。
ちなみにリリースノートで指摘されていたインストーラーがストレージをフォーマットする際にZFSがなくext4だけ表示される問題 は、パーティションフォーマットの確認ダイアログで、第3パーティション以降が表示されないことを意味しています。
図2 vda上にZFSを作ったのにESPとext4しか表示されない
ZFSパーティションのレイアウトを計算するのは、このパーティション確認ダイアログが表示されるタイミングよりも後ろだったのです。つまり第1と第2しか表示されないので、「 ZFSを選択したのにext4を作ろうとしている」と勘違いするような表記になっていました。これがリリースノートで「動作としては正しいのですが、利用者に混乱を引き起こす表示」と記載された理由となります。
Ubuntu 20.04 LTSのインストーラーでは、ダイアログが表示されるタイミングでZFSのパーティション情報も表示するように修正されています。
次に「/etc/fstab
」がどうなっているか確認してみましょう。
$ cat /etc/fstab
# /etc/fstab: static file system information.
#
# Use 'blkid' to print the universally unique identifier for a
# device; this may be used with UUID= as a more robust way to name devices
# that works even if disks are added and removed. See fstab(5).
#
# <file system> <mount point> <type> <options> <dump> <pass>
# /boot/efi was on /dev/vda1 during installation
UUID=8977-6786 /boot/efi vfat umask=0077 0 1
UUID=0a9b50b8-7a66-4ae1-8a7d-35796345aca0 /boot/grub ext4 errors=remount-ro 0 1
UUID=892fa4dc-22ef-49fa-9340-2676ce19cbd7 none swap discard 0 0
あれ、ルートファイルシステムのエントリーが存在しませんね。実はZFSにはそのファイルシステム情報の中に「マウントポイント」を記録するフィールドが存在します。
ストレージプールのレイアウト
それでは今度は実際にZFSの情報を表示してみましょう。最初にZFSには「ストレージプール」と「データセット」というふたつの概念が存在します。
ストレージプールはいわゆるボリューム管理のような機能です。複数のストレージデバイス・パーティションをまとめて、ひとつのボリュームのように扱います。Ubuntu 19.10のインストーラーでは単一のパーティションから単一のプールを作成していますが、複数のストレージデバイスをひとつのプールとしてストライピングやミラーリングしたり、RAIDのように信頼性・可用性を向上させることも可能になっています。また、ZFSとしてのログデバイスやキャッシュを別のより少量・高速なデバイスに指定するなど、かなり柔軟な構成が可能です。
ストレージプールの操作はzpoolコマンドで行います。
$ zpool list
NAME SIZE ALLOC FREE CKPOINT EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
bpool 1.88G 159M 1.72G - - - 8% 1.00x ONLINE -
rpool 16.5G 3.98G 12.5G - - 5% 24% 1.00x ONLINE -
先ほども説明したように、Ubuntuではふたつのストレージプールを用意しています。詳細はzpool status
コマンドで確認できます。
$ zpool status
pool: bpool
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.
scan: none requested
config:
NAME STATE READ WRITE CKSUM
bpool ONLINE 0 0 0
vda4 ONLINE 0 0 0
errors: No known data errors
pool: rpool
state: ONLINE
scan: none requested
config:
NAME STATE READ WRITE CKSUM
rpool ONLINE 0 0 0
vda5 ONLINE 0 0 0
errors: No known data errors
『Software Design 2019年12月号 』でも詳しく説明しているように、bpoolは少し特殊です。bpool(/boot)はカーネルやinitramfsが保存される領域なので、GRUBから見えなくてはなりません。しかしながらGRUBのZFSモジュールは、ZFSのすべての機能を実装しているとは限りません。
そこでbpoolについてはより保守的な使い方であることを明示するために、featureフラグをすべて落としてバージョン名を明記しているのです。これが上記で言うところの「a legacy on-disk format」です。「 zpool get all
」コマンドでversionプロパティを見ても、bpoolだけバージョンが設定されていることがわかります。
$ zpool get all | grep version
bpool version 28 local
rpool version - default
よってbpoolについては、アップグレードは実行しないでください。スナップショットやバックアップといった基本的な機能は使えるので、そのままでも実用上問題はないはずです。
ちなみにUbuntu 20.04 LTSでは、必要なfeatureフラグがセットされたbpoolが作られます。つまりUbuntu 20.04 LTSのインストーラーを用いてインストールした環境だと、上記の警告はでなくなるはずです。
データセットのレイアウト
ストレージプールは論理ボリュームのようなものです。ここから実際に読み書きできる領域として切り出したものが「データセット」です。データセットには「ファイルシステム」「 ボリューム」「 スナップショット」「 ブックマーク」の4種類が存在します。
ファイルシステムはその名の通りファイルシステムです。実際にファイルシステムのどこかにマウントされ、読み書きる状態になります。もっとも基本的な種類です。ZFSではストレージプールをブロックデバイスとして切り出せます。これが「ボリューム」です。たとえばKVMなどの仮想マシン用のストレージデバイスを作りたい際に利用します。
ファイルシステムやボリュームは、ある時点の状態を「スナップショット」として保存し、必要に応じてリストアできます。それに対して「ブックマーク」は「ある時点」のみを記録するラベルのような仕組みです。差分バックアップを生成する際に有用になります。
Ubuntuインストール直後に使われているデータセットはファイルシステムだけです。データセットのリストはzfs list
コマンドで確認できます。
$ zfs list
NAME USED AVAIL REFER MOUNTPOINT
bpool 159M 1.59G 176K /boot
bpool/BOOT 158M 1.59G 176K none
bpool/BOOT/ubuntu_08z65m 158M 1.59G 158M /boot
rpool 3.98G 12.0G 96K /
rpool/ROOT 3.98G 12.0G 96K none
rpool/ROOT/ubuntu_08z65m 3.98G 12.0G 3.49G /
rpool/ROOT/ubuntu_08z65m/srv 96K 12.0G 96K /srv
rpool/ROOT/ubuntu_08z65m/usr 200K 12.0G 96K /usr
rpool/ROOT/ubuntu_08z65m/usr/local 104K 12.0G 104K /usr/local
rpool/ROOT/ubuntu_08z65m/var 495M 12.0G 96K /var
rpool/ROOT/ubuntu_08z65m/var/games 96K 12.0G 96K /var/games
rpool/ROOT/ubuntu_08z65m/var/lib 492M 12.0G 379M /var/lib
rpool/ROOT/ubuntu_08z65m/var/lib/AccountServices 96K 12.0G 96K /var/lib/AccountServices
rpool/ROOT/ubuntu_08z65m/var/lib/NetworkManager 128K 12.0G 128K /var/lib/NetworkManager
rpool/ROOT/ubuntu_08z65m/var/lib/apt 77.5M 12.0G 77.5M /var/lib/apt
rpool/ROOT/ubuntu_08z65m/var/lib/dpkg 35.6M 12.0G 35.6M /var/lib/dpkg
rpool/ROOT/ubuntu_08z65m/var/log 1.96M 12.0G 1.96M /var/log
rpool/ROOT/ubuntu_08z65m/var/mail 96K 12.0G 96K /var/mail
rpool/ROOT/ubuntu_08z65m/var/snap 112K 12.0G 112K /var/snap
rpool/ROOT/ubuntu_08z65m/var/spool 112K 12.0G 112K /var/spool
rpool/ROOT/ubuntu_08z65m/var/www 96K 12.0G 96K /var/www
rpool/USERDATA 3.44M 12.0G 96K /
rpool/USERDATA/root_e8xd45 112K 12.0G 112K /root
rpool/USERDATA/shibata_e8xd45 3.24M 12.0G 3.24M /home/shibata
多いですね。Ubuntuでは大雑把な重要度と用途に合わせてデータセットを分けているようです。データセットの名前は「ストレージプール/名前」で指定されます。名前の「ubuntu_
」「 root_
」「 shibata_
」の後ろの英数字はインストール時に自動生成したランダムな6文字となります。
注目すべきは「MOUNTPOINT」です。これはデータセットのmountpointプロパティの値であり、ZFSをマウントしたときに自動的にマウントポイントとして利用されるパスになります。
つまりZFSは/etc/fstab
にルートファイルシステムを明示的に書かなくても、ZFS配下のデータセットが適切な場所にマウントされるというわけです。
ちなみにGRUBは、カーネルについてはbpool以下のデータセットのパスを、ルートファイルシステムについてはrpoolも含めたパスを指定します。
$ cat /proc/cmdline
BOOT_IMAGE=/BOOT/ubuntu_08z65m@/vmlinuz-5.3.0-23-generic root=ZFS=rpool/ROOT/ubuntu_08z65m ro quiet splash vt.handoff=1
上記の「root=
」がルートファイルシステムの指定です。
GRUBのデータセットの指定方法は、update-grub
実行時にzfsコマンドを駆使して行います。詳細は「/etc/grub.d/10_linux_zfs
」のスクリプトを確認してください。
スナップショットとロールバック
ZFSの便利な機能のひとつが「スナップショット」と「ロールバック」です。openSUSEのBtrfs/Snapper/YaSTを組み合わせた「何かあったらロールバックする」仕組みが羨ましくて、枕を涙で濡らした夜もあるでしょう。ZFSとコマンドを駆使すれば、Ubuntuでもこの仕組みを実現できる可能性がないとは言い切れない状態にはなんとか持っていけます[8] 。
たとえばUbuntuのインストール直後はアップグレードが必要なパッケージがたくさん溜まっていますよね。アップグレード前にスナップショットを取って、アップグレードした上で、ロールバックしてみましょう。
$ apt list --upgradable
(中略)
uno-libs3/eoan-updates 6.3.3-0ubuntu0.19.10.1 amd64 [6.3.2-0ubuntu2 からアップグレード可]
ure/eoan-updates 6.3.3-0ubuntu0.19.10.1 amd64 [6.3.2-0ubuntu2 からアップグレード可]
whoopsie/eoan-updates,eoan-security 0.2.66ubuntu0.3 amd64 [0.2.66 からアップグレード可]
zfs-zed/eoan-updates 0.8.1-1ubuntu14.1 amd64 [0.8.1-1ubuntu14 からアップグレード可]
スナップショットは「zfs snapshot データセット名@スナップショット名
」です。今回は日時を付けてみます。
$ sudo zfs snapshot -r rpool@`date +%Y%m%d%H%M%S`
上記のように「-r
」オプションを付けることで、下位のデータセットも再帰的にたどってスナップショットを取ってくれます。今回はrpool以下すべてのスナップショットを取っていますが、本来はもう少し制限すべきです。たとえばopenSUSEは/var/logや/var/runなどはスナップショットの除外対象にしています 。
作成されたスナップショットはzfs list
コマンドに「-t snapshot
」オプションを付けることで確認できます。
$ zfs list -t snapshot
NAME USED AVAIL REFER MOUNTPOINT
rpool@20191130232337 0B - 96K -
rpool/ROOT@20191130232337 0B - 96K -
rpool/ROOT/ubuntu_08z65m@20191130232337 0B - 3.49G -
rpool/ROOT/ubuntu_08z65m/srv@20191130232337 0B - 96K -
rpool/ROOT/ubuntu_08z65m/usr@20191130232337 0B - 96K -
rpool/ROOT/ubuntu_08z65m/usr/local@20191130232337 0B - 104K -
rpool/ROOT/ubuntu_08z65m/var@20191130232337 0B - 96K -
rpool/ROOT/ubuntu_08z65m/var/games@20191130232337 0B - 96K -
rpool/ROOT/ubuntu_08z65m/var/lib@20191130232337 0B - 379M -
rpool/ROOT/ubuntu_08z65m/var/lib/AccountServices@20191130232337 0B - 96K -
rpool/ROOT/ubuntu_08z65m/var/lib/NetworkManager@20191130232337 0B - 136K -
rpool/ROOT/ubuntu_08z65m/var/lib/apt@20191130232337 0B - 77.5M -
rpool/ROOT/ubuntu_08z65m/var/lib/dpkg@20191130232337 0B - 35.6M -
rpool/ROOT/ubuntu_08z65m/var/log@20191130232337 692K - 2.07M -
rpool/ROOT/ubuntu_08z65m/var/mail@20191130232337 0B - 96K -
rpool/ROOT/ubuntu_08z65m/var/snap@20191130232337 0B - 112K -
rpool/ROOT/ubuntu_08z65m/var/spool@20191130232337 0B - 112K -
rpool/ROOT/ubuntu_08z65m/var/www@20191130232337 0B - 96K -
rpool/USERDATA@20191130232337 0B - 96K -
rpool/USERDATA/root_e8xd45@20191130232337 0B - 112K -
rpool/USERDATA/shibata_e8xd45@20191130232337 0B - 3.50M -
USEDがほぼ0Bになっていますね。ZFSはデータセット単位のCopy-on-Writeに対応しているので[9] 、スナップショットを作成したタイミングではストレージを消費しません。
アップグレード前のスナップショットを取得したので、次はアップグレードしてみましょう。
$ sudo apt full-upgrade -y
$ apt list --upgradable
一覧表示... 完了
無事にアップグレードが完了しましたね。この状態でスナップショットを表示してみましょう。
$ zfs list -t snapshot
NAME USED AVAIL REFER MOUNTPOINT
rpool@20191130232337 0B - 96K -
rpool/ROOT@20191130232337 0B - 96K -
rpool/ROOT/ubuntu_08z65m@20191130232337 753M - 3.49G -
rpool/ROOT/ubuntu_08z65m/srv@20191130232337 0B - 96K -
rpool/ROOT/ubuntu_08z65m/usr@20191130232337 0B - 96K -
rpool/ROOT/ubuntu_08z65m/usr/local@20191130232337 56K - 104K -
rpool/ROOT/ubuntu_08z65m/var@20191130232337 0B - 96K -
rpool/ROOT/ubuntu_08z65m/var/games@20191130232337 0B - 96K -
rpool/ROOT/ubuntu_08z65m/var/lib@20191130232337 21.2M - 379M -
rpool/ROOT/ubuntu_08z65m/var/lib/AccountServices@20191130232337 0B - 96K -
rpool/ROOT/ubuntu_08z65m/var/lib/NetworkManager@20191130232337 100K - 136K -
rpool/ROOT/ubuntu_08z65m/var/lib/apt@20191130232337 516K - 77.5M -
rpool/ROOT/ubuntu_08z65m/var/lib/dpkg@20191130232337 8.36M - 35.6M -
rpool/ROOT/ubuntu_08z65m/var/log@20191130232337 1.01M - 2.07M -
rpool/ROOT/ubuntu_08z65m/var/mail@20191130232337 0B - 96K -
rpool/ROOT/ubuntu_08z65m/var/snap@20191130232337 72K - 112K -
rpool/ROOT/ubuntu_08z65m/var/spool@20191130232337 64K - 112K -
rpool/ROOT/ubuntu_08z65m/var/www@20191130232337 0B - 96K -
rpool/USERDATA@20191130232337 0B - 96K -
rpool/USERDATA/root_e8xd45@20191130232337 0B - 112K -
rpool/USERDATA/shibata_e8xd45@20191130232337 988K - 3.50M -
主にルートディレクトリのデータセット(rpool/ROOT/ubuntu_08z65m)を中心にUSEDがぐっと増えました。
スナップショット同士、もしくはファイルシステムとスナップショット間で差分を確認することも可能です。
$ sudo zfs diff rpool/ROOT/ubuntu_08z65m@20191130232337 rpool/ROOT/ubuntu_08z65m
M /etc
M /etc/apparmor.d
M /etc/apport
M /etc/bash_completion.d
M /etc/cron.daily
M /etc/default
M /tmp
M /var/cache/apt
M /var/cache/apt/archives/partial
M /etc/firefox
(後略)
今回は多くのパッケージがアップグレードされてしまったため、差分がかなり多くなっていますが、日常のアップグレード程度なら比較しやすいでしょう。
次にアップグレード前、つまりスナップショット取った環境にロールバックします。注意すべき点として、現在のZFSには再帰的にロールバックする仕組みが存在しません 。よってスクリプトで存在するスナップショットをすべてロールバックすることにします。
$ for i in `zfs list -t snapshot | grep 20191130232337 | awk '{print $1}'`; do
sudo zfs rollback -r -R -f $i;
done
zfs rollback
に付加しているオプションはそれぞれ次のような意味になります。
「-r
」 :指定したスナップショットより新しいスナップショットとブックマークを削除する
「-R
」 :指定したスナップショットより新しいスナップショットとブックマークとそれらのクローンを削除する
「-f
」 :クローンされたデータセットがマウントされていたら、削除する前にアンマウントする
zfs rollback
は「最も新しいスナップショット」以外にロールバックしようとするとエラーになります。それを無視して強制的にロールバックするのが「-r
」オプションです。当然、ロールバック先より新しいスナップショットは意味をなさなくなるので、破棄されます。
zfs clone
コマンドを使うと、任意のデータセットを別名でクローンできます。クローンしたデータセットはクローン元と親子関係が発生するため、ロールバックによってクローン元が破棄されると困ります。クローンも一緒に削除してしまうのが「-R
」オプションです。
ロールバックが成功したら、スナップショットの様子を見ていましょう。
$ zfs list -t snapshot
NAME USED AVAIL REFER MOUNTPOINT
rpool@20191130232337 0B - 96K -
rpool/ROOT@20191130232337 0B - 96K -
rpool/ROOT/ubuntu_08z65m@20191130232337 8K - 3.49G -
rpool/ROOT/ubuntu_08z65m/srv@20191130232337 0B - 96K -
rpool/ROOT/ubuntu_08z65m/usr@20191130232337 0B - 96K -
rpool/ROOT/ubuntu_08z65m/usr/local@20191130232337 0B - 104K -
rpool/ROOT/ubuntu_08z65m/var@20191130232337 0B - 96K -
rpool/ROOT/ubuntu_08z65m/var/games@20191130232337 0B - 96K -
rpool/ROOT/ubuntu_08z65m/var/lib@20191130232337 8K - 379M -
rpool/ROOT/ubuntu_08z65m/var/lib/AccountServices@20191130232337 0B - 96K -
rpool/ROOT/ubuntu_08z65m/var/lib/NetworkManager@20191130232337 8K - 136K -
rpool/ROOT/ubuntu_08z65m/var/lib/apt@20191130232337 0B - 77.5M -
rpool/ROOT/ubuntu_08z65m/var/lib/dpkg@20191130232337 8K - 35.6M -
rpool/ROOT/ubuntu_08z65m/var/log@20191130232337 80K - 2.07M -
rpool/ROOT/ubuntu_08z65m/var/mail@20191130232337 0B - 96K -
rpool/ROOT/ubuntu_08z65m/var/snap@20191130232337 0B - 112K -
rpool/ROOT/ubuntu_08z65m/var/spool@20191130232337 0B - 112K -
rpool/ROOT/ubuntu_08z65m/var/www@20191130232337 0B - 96K -
rpool/USERDATA@20191130232337 0B - 96K -
rpool/USERDATA/root_e8xd45@20191130232337 0B - 112K -
rpool/USERDATA/shibata_e8xd45@20191130232337 8K - 3.50M -
USEDがスナップショット前と同じくらいに減っている、つまり現在の状態とスナップショットの状態にほぼ差がなくなっていることがわかります。
さらにapt list
コマンドを実行すると、「 アップグレード前」に戻っていることがわかるはずです。
$ apt list --upgradable
(中略)
uno-libs3/eoan-updates 6.3.3-0ubuntu0.19.10.1 amd64 [6.3.2-0ubuntu2 からアップグレード可]
ure/eoan-updates 6.3.3-0ubuntu0.19.10.1 amd64 [6.3.2-0ubuntu2 からアップグレード可]
whoopsie/eoan-updates,eoan-security 0.2.66ubuntu0.3 amd64 [0.2.66 からアップグレード可]
zfs-zed/eoan-updates 0.8.1-1ubuntu14.1 amd64 [0.8.1-1ubuntu14 からアップグレード可]
今回はシステム全体をロールバックしましたが、前述したように本来はデータセットごとにスナップショットを取るか、ロールバックするかを判断すべきです。
zsnapdパッケージとして提供されている「zfs-snap-manager 」などのように、自動的にスナップショットを作成するソフトウェアも存在します。スナップショット・ロールバックを本格的に使う際は、これらの自動化ツールを活用すると良いでしょう。
バックアップとリストア
一般ユーザーにおけるZFSのもうひとつの利点が、バックアップとリストアが簡単なことです。まずはzfs send
コマンドでホームディレクトリのデータセットのバックアップを取ってみましょう。なお、zfs send
の対象はスナップショットかマウントされていないデータセットとなりますので、とりあえず現在のスナップショットを作成してからバックアップします。
$ echo "backuped data" > ~/backup.dat
$ zfs snapshot rpool/USERDATA/shibata_e8xd45@backup1
$ sudo zfs send rpool/USERDATA/shibata_e8xd45@backup1 > /var/tmp/home_backup.bin
$ ls -lh /var/tmp/home_backup.bin
-rw-rw-r-- 1 shibata shibata 13M 12月 1 23:21 /var/tmp/home_backup.bin
zfs send
はバイナリストリームを出力しますので、任意のファイルにリダイレクトできます。たとえばパイプを使って「| gzip -c > backup.gz
」のように圧縮することも可能です。
バックアップデータができたので、今度はそれをzfs recv
コマンドでリストアしましょう。今回は単純に「別の名前」でリストアします。
$ sudo zfs recv rpool/USERDATA/shibata_backup1 < /var/tmp/home_backup.bin
$ zfs list rpool/USERDATA/shibata_backup1
NAME USED AVAIL REFER MOUNTPOINT
rpool/USERDATA/shibata_backup1 3.59M 11.1G 3.52M /shibata_backup1
$ cat /shibata_backup1/backup.dat
backuped data
$ sudo zfs destroy -r rpool/USERDATA/shibata_backup1
リストアしたデータセットは自動的にセットされたマウントポイントにマウントされます。ここから先は個々のバックアップポリシーに依存しますが、たとえば今回の場合だと単にファイルのコピーで完了ですね。リストアしたデータセットはzfs destroy
で削除できます。ただし、今回の例だとデータセットの中にスナップショットも含まれるので、「 -r
」オプションも付けておかないと削除できません。
zfs recv
は標準入力からバイナリストリームを受け取ってそれをリストアしています[10] 。つまりパイプを駆使すれば、バックアップとリストアをひとつのコマンド列で実行できるということです。
[10] zfs recv
はzfs receive
のエイリアスとなっています。ただしsendと文字数が同じほうが打ちやすいですし、そもそも「recei ve」だったか「recie ve」だったか思い出すのに時間がかかる人にもrecvを使うことをおすすめします。
よくあるのは、別のZFSが使われているマシンにSSH越しにリストアする例です。
$ sudo zfs send rpool/USERDATA/shibata_e8xd45@backup1 | \
ssh foo.local sudo zfs recv rpool/USERDATA/shibata_backup
自動化するならスナップショット・リストアする際のオプションをある程度決めないと失敗するかもしれません。詳細はzfsのmanページ を参照してください。
たとえばあらかじめ次のようなコマンドで、ホームディレクトリのクォータを設定しておけば、リモートマシン側であふれることも防げるでしょう。
$ sudo zfs set quota=20G prpool/USERDATA/shibata_e8xd45
前項でも取り上げたzsnapdパッケージとして提供されている「zfs-snap-manager 」には定期的なバックアップとレプリケーション機能も備わっているようです。
ZFSのメモリの使用量
ZFSを使う上で気になるのがメモリの使用量です。ZFSはprocfsやsysfs経由で数多くの情報を提供し、設定をカスタマイズ可能です。ただあまりに多すぎて把握するのが大変でもあります。
そこでざっくりと情報を把握するのに便利なのがarc_summary
コマンドです。早速使ってみましょう。zfsutils-linuxパッケージに含まれているので、Ubuntuなら最初からインストールされているはずです。
$ arc_summary -g
ARC: 922.5 MiB (46.9 %) MFU: 415.3 MiB MRU: 453.8 MiB META: 133.6 MiB (1.4 GiB) DNODE 20.0 MiB (147.5 MiB)
+----------------------------------------------------------+
|FFFFFFFFFFFFRRRRRRRRRRRRRO |
+----------------------------------------------------------+
ARC(Adaptive Replacement Cache)はメモリ上に配置しているZFS用のディスクキャッシュです。つまりZFSのキャッシュだけで1GiB程度使っているということです。
ARCの最大サイズは環境にも依存しますが、たとえばarc_maxはメモリの半分 が初期値のようです。他にも高速なストレージデバイス上にキャッシュを構築するL2ARCもありますが、これはさらにメモリを使用するとのこと。Ubuntuでは、初期状態では設定されていません。
$ arc_summary | grep L2ARC
L2ARC not detected, skipping section
なんらかの理由でARCの最大サイズを変更したい場合は、次のようにモジュールパラメーターをセットした上で、initramfsを再構築し、システムを再起動してください。
$ echo 'options zfs zfs_arc_max=1073741824' | sudo tee /etc/modprobe.d/zfs.conf
$ sudo update-initramfs -u -k all
この方法は他のモジュールパラメーターにも有効です。