2020年 07月 26日
BtrFS の甘い罠、SUSE Linux (openSUSE Leap15/SLE15)アップデート前の空き容量の確認と確保
どんなショボいシステムでも、安易に変更は加えない方がいいわけです。openSUSE Leap 15.1 のシステムを# zypper dupしたところ、見事に罠にハマりました。BtrFS の罠です。スナップショットを取っているので、空き容量がなかったんです。空き容量がないところでパッケージのアップデートなんかすると、openSUSE Leap 15x はルートパーティションが Copy On Write の BtrFS ですからファイルは上書きではなく、差分をドンドンと CoW してしまう。遂にディスクの空きを使い果たして、中途半端な zypper dup の結果、「システムが立ち上がらない」という最悪の結果に陥りました。BtrFS のスナップショットの残骸ってロック掛かっていて、レスキューディスクで起動しても消せないのですね。という事で、BtrFS のファイルシステムに変更を加える場合は「空き容量を確認して空きを確保してから行え」という「鉄の法則」を学びました。
How much free space do I have? or My filesystem is full, and I've put almost nothing into it!
1 Linuxファイルシステムの概要
これらのドキュメントによるとopensuse151:~ # btrfs fi showLabel: none uuid: 8466aee4-2738-4b0a-924a-79edad4b4676Total devices 1 FS bytes used 8.13GiBdevid 1 size 14.00GiB used 10.57GiB path /dev/vda2opensuse151:~ #"ファイルシステムの合計サイズとその使用量を表示します。最後の行のこれら2つの値が一致する場合、ファイルシステム上の領域はすべて割り当て済みです。"上のケースでは14Gbのデバイスサイズのうち、 10.57Gb 使用中です。
opensuse151:~ # btrfs fi df /Data, single: total=8.01GiB, used=7.50GiBSystem, DUP: total=32.00MiB, used=16.00KiBMetadata, DUP: total=1.25GiB, used=641.95MiBGlobalReserve, single: total=30.22MiB, used=0.00Bopensuse151:~ #
"ファイルシステムの割り当て済みの領域(total)および使用済みの領域の値を表示します。メタデータのtotalおよびusedの値がほぼ等しい場合、メタデータ用の領域はすべて割り当て済みです。”
メタデータ 1.25 Gb 中、641Mb 使用中です。opensuse151:~ # btrfs fi usage /Overall:Device size: 14.00GiBDevice allocated: 10.57GiBDevice unallocated: 3.43GiBDevice missing: 0.00BUsed: 8.76GiBFree (estimated): 3.93GiB (min: 2.22GiB)Data ratio: 1.00Metadata ratio: 2.00Global reserve: 30.22MiB (used: 0.00B)Data,single: Size:8.01GiB, Used:7.50GiB/dev/vda2 8.01GiBMetadata,DUP: Size:1.25GiB, Used:641.95MiB/dev/vda2 2.50GiBSystem,DUP: Size:32.00MiB, Used:16.00KiB/dev/vda2 64.00MiBUnallocated:/dev/vda2 3.43GiBopensuse151:~ #”前の2つのコマンドを組み合わせたのと同様のデータを表示します”
つまり btrfs fi usage <mount_point> が一番使われやすいコマンドだという事です。
duコマンドは当てになりません。ncdu でルートからスキャンしたらこれ。このシステムは物理的に25Gbしかない仮想VMです。
スナップショットサイズが「150Gb 使用中」と、あり得ない数字を示しています。
こちらの文書の中に
How much free space do I have? or My filesystem is full, and I've put almost nothing into it!
"So, in general, it is impossible to give an accurate estimate of the amount of free space on any btrfs filesystem. Yes, this sucks. If you have a really good idea for how to make it simple for users to understand how much space they've got left, please do let us know, but also please be aware that the finest minds in btrfs development have been thinking about this problem for at least a couple of years, and we haven't found a simple solution yet."
"したがって、一般に、btrfsファイルシステムの空き容量を正確に見積もることは不可能です。はい、これは最悪です。ユーザーがどれだけのスペースを残したかを簡単に理解できるようにする方法について本当に良いアイデアがある場合は、私たちに知らせてください。また、btrfs開発の最高の心がこの問題について考えていることに注意してください。少なくとも数年間は、簡単な解決策はまだ見つかりませんでした。"
例えば、openSUSE Leap 15.x では / (ルート)の BtrFS パーティションは、最低でも 15Gb のサイズ以上確保しておかないと、インストールの際、警告が出ます。実際のインストールで使用されるディスク容量は openSUSE Leap 15.2/SLE15 で 7.5 Gb 程度です。SLE12 では6Gb 程度でした。空き容量の把握は難しいので、長期運用でバージョンアップに伴い必要とされる空き容量は、将来に渡って不明です。将来バージョンアップしたり、パッチを頻繁に充てるクリティカルなシステムなら 25Gb ~ 30Gb 程度のルートパーティションサイズが欲しいところです。「ディスク容量を食う」点は、誰も指摘していませんが BtrFS の隠されたデメリットです。もし、コンパクトで JeOS な仮想サーバーを作りたいのであれば ext3、4 などの古来のファイルシステムを検討すれば 10Gb 程度でも使えるわけです。
デフォルトではシステムは毎週 scrub によるメタデータの修復、デフラグ、破損ファイルの修復を実行します。scrub はファイルシステムの破損などがないかメタデータをチェックし、自動修復する機能です。sysconfig に設定されます。BtrFS の信頼性を確保するための重要な機能です。
手動で scrub するには# brtfs scrub start <mount point>を実行し、 btrfs scrub status -d -R <mount point> で結果を確認できます。
スナップショットの作成と削除は自動化されています。こちらの文書によると SUSE Linux(SLE15) においては
7.1.3.4 スナップショットのアーカイブの制御
"デフォルトでは、最大10個の重要なインストールスナップショットと管理スナップショット、および最大10個の標準のインストールスナップショットと管理スナップショットが保持されます。これらのスナップショットがルートファイルシステムのサイズの50%超を占有する場合、追加のスナップショットは削除されます。最低でも、4つの重要なスナップショットと2つの標準スナップショットは常に保持されます。"
とあり、この定義は snapper -c MySnapConfig create-config <partition> によって作成された /etc/snapper/configs/ にされた MySnapConfig ファイルによって定義されます。
7.4.1 既存の設定の管理
7.6.2 タイムラインスナップショットのクリーンアップ
それぞれ、スナップショットの作成と削除はタイムラインによって snapper -c MySnapConfig ファイルに作成されます。
opensuse151:/etc/snapper/configs # cat mysnapconfig | grep TIMELINETIMELINE_CREATE="yes"TIMELINE_CLEANUP="yes"TIMELINE_MIN_AGE="1800"TIMELINE_LIMIT_HOURLY="10"TIMELINE_LIMIT_DAILY="10"TIMELINE_LIMIT_WEEKLY="0"TIMELINE_LIMIT_MONTHLY="10"TIMELINE_LIMIT_YEARLY="10"opensuse151:/etc/snapper/configs #
通常運用では問題にならないので、デフォルトの scrub のタイミングも、スナップショットを有効化した場合の、スナップショットのメンテナンス間隔は、そのままで構わないでしょう。
手動でのスナップショットの状態、最新のスナップショットの状態確認は YaST2 Snapper で確認し、内容のチェックとロールバック、削除などの操作を行います。
4.1.1 スナップショットとディスク容量
”ヒント: 容量を空ける/ディスクの使用率スナップショットを含むBtrfsパーティションの容量を空けるには、ファイルではなく、不要なスナップショットを削除する必要があります。古いスナップショットは、最近のスナップショットよりも多くの領域を使用します。”
とある様に、アップデートに必要な空き領域を確保するには、古いスナップショット、意図的に取得した古いスナップショットを削除して、空き領域を確保し、 btrfs fi usage <Partition> か btrfs fi df <Partition> コマンドで空き容量を確認し、その後、明示的にアップデートからのスナップショットロールバック、復元ポイントを作ってから、アップデートを実施すべきでしょう。
忘れてはならないのは、zypper up や zypper patch など、あるいはメジャーアップデートする時、同じファイルであっても物理的なファイルそのものが上書きされずに、古いファイルはスナップショットに「移動」し、空き領域に新しいファイルが作られることです。