Intel 8 Series/C220 Series Chipset (具体的にはC226)の Onboard RAID (RAID5)上で LUKS の暗号化を入れて,その上で btrfs を置いて NFS でファイルサーバにしているのだが,そのパフォーマンスについて.
ちなみに CPU は4コア4スレッド(stable 運用で,kernel は backports の linux-image-4.6.0-0.bpo.1-amd64 4.6.4-1~bpo8+1).暗号化しているのは廃棄の手間を考えて,btrfs は snapshot による daily backup のため.RAID5 が Onboard (ソフトウェア RAID)なのは予算の都合上.
だいたい2年半ぐらい運用していて,それなりにファイル数も増えて,snapshot数も増えた状態で,頻繁にiowaitで固まるようになった.
以下チューニングのポイント.
-
brtfs は default で relatime で mount される.つまりファイル読み出しを行えばファイルの atime (アクセス時刻)が更新されるが,更新タイミングは多くとも1日1回 (古いatimeが現在より1日前までの時刻であれば更新されない,はず).とはいえsnapshotをとっている環境では,ファイル自体に変更がなければ容量が増えないのであるが,atime が更新されるタイミング(つまり読み込んだだけ)で COW (copy-on-write)が発生する.daily snapshot をとっている環境ではこれは辛い.ということで noatime option で mount するようにする (書き込みが減って,容量増加が抑えられる).
-
snapshot をとっている環境では各 snapshot がどの程度の容量になっているのかを調べるため quota を enable する設定もあるが,これをするとパフォーマンスが落ちる(詳しくは見ていないが COW発生とともに何がしかのコンシステンシをとるための transaction が大量に発生するとか?).
-
https://btrfs.wiki.kernel.org/index.php/Quota_support#Known_issues
Combining quota with (too many) snapshots of subvolumes can cause performance problems, for example when deleting snapshots.
-
https://btrfs.wiki.kernel.org/index.php/Manpage/btrfs-quota#PERFORMANCE_IMPLICATIONS
When the quotas are turned on, they affect all extent processing, taking a performance hit. It is not recommended to turn on qgroups unless the user intends to actually use them.
-
-
この transaction (process 名は btrfs-transaction もしくは btrfs-transacti) は default では 30秒間隔で実行される (default の option が commit=30 になっている).なにかを書き込んだ際に iowait で応答がなくなるわけではなくて,周期的に iowait で固まるので,原因を追うのに困難した.
-
transaction の量が多いと disk-io がしばらく埋まる.早めに吐き出そうと commit=3 等にしても,そもそも transaction の量が多いのが問題であまり解決にはならなかった.ちなみに commit=0 の設定をすると強制的に default の commit=30 になる.transaction の量が何で決まるのかは正確には追えていない (たぶん quota enable だと増える).
-
あまり効果がないかもしれないが noflushoncommit option を付ける (default は flushoncommit).
-
RAID5側のチューニングも考える.たとえば以下
# echo 32768 > /sys/block/md126/md/stripe_cache_size
-
負荷状態をモニタするには dstat が便利(以下 btrfs-transaction の iowait で詰まっている様子.この状態で nfs のアクセスがある一定量あれば iowait が 100% になってしばし固まる).
% sudo dstat --top-bio -d -n -c ----most-expensive---- -dsk/total- -net/total- ----total-cpu-usage---- block i/o process | read writ| recv send|usr sys idl wai hiq siq btrfs-trans 412k 109M| 41M 29M| 317k 16k| 0 7 71 22 0 0 btrfs-trans 0 17M| 31M 59M| 338B 3124B| 0 11 49 40 0 0 kworker/u8: 0 64k| 32M 0 |2474B 6486B| 0 1 50 49 0 0 nfsd 0 108k| 31M 0 |4826B 5704B| 0 0 50 49 0 0 | 32M 0 |2884B 3606B| 0 1 50 49 0 0 nfsd 0 72k| 28M 0 | 38k 144k| 0 1 50 49 0 0 nfsd 0 56k| 30M 0 | 70k 209k| 0 1 50 49 0 0 | 31M 0 | 442B 2208B| 0 0 51 49 0 0 | 30M 0 | 816B 1648B| 0 0 51 49 0 0 | 11M 19M| 510B 2048B| 1 2 50 48 0 0 | 0 25M| 170k 3166B| 0 0 51 49 0 0 | 0 29M|6894B 1600B| 0 0 50 49 0 0 kworker/u8: 0 64k| 0 29M|2448B 2766B| 0 0 50 49 0 0 | 0 27M| 396B 2138B| 0 0 51 49 0 0 | 0 25M| 984B 1456B| 0 1 50 49 0 0 | 0 29M| 396B 1548B| 0 0 50 49 0 0 | 0 28M|1618B 2026B| 0 0 50 49 0 0 kworker/u8: 0 16k| 0 28M|1386B 1362B| 0 1 50 49 0 0 |5552k 21M|1102B 2380B| 0 3 49 48 0 0 smbd 0 84k| 27M 16k|3792B 3042B| 0 0 50 49 0 0 | 31M 0 |1220B 1460B| 0 0 50 49 0 0 | 32M 0 | 670B 2376B| 0 1 50 49 0 0 | 32M 0 |1478B 2656B| 0 0 50 50 0 0 smbd 0 16k| 35M 0 | 938B 1950B| 0 1 50 49 0 0 | 13M 20M|1422B 2592B| 0 1 50 48 0 0 | 0 26M|1218B 2264B| 0 0 52 48 0 0 | 0 30M|5520B 2968B| 1 0 49 50 0 0 | 0 31M| 482B 2480B| 0 1 50 49 0 0 | 0 32M| 752B 1968B| 0 1 50 49 0 0 | 0 39M|1450B 2090B| 0 1 50 49 0 0 nfsd 0 1212k|2216k 11M|1290k 7204k| 0 5 69 25 0 0 nfsd 0 596k| 72k 72k| 315k 11M| 0 1 98 0 0 1 nfsd 0 1312k| 516k 584k|1305k 4603k| 0 1 96 3 0 0 nfsd 0 10M| 0 0 | 11M 77k| 0 1 99 0 0 0 nfsd 0 44k| 0 0 | 48k 43k| 0 0 100 0 0 0 nfsd 0 4096B| 0 0 |6972B 6322B| 0 0 99 0 0 0 nfsd 0 76k| 0 0 | 56k 87k| 0 0 100 0 0 0 nfsd 0 132k| 72k 72k| 112k 233k| 0 0 99 0 0 0 | 0 0 |3262B 4372B| 1 0 100 0 0 0 nfsd 0 4096B| 0 0 |2556B 3012B| 0 0 100 0 0 0 nfsd 0 280k| 88k 52k| 229k 19k| 0 1 99 0 0 0
追記(2016/12/7)
ionice や renice で nfsd や btrfs-transacti の優先度を下げて(I/O については ionice -c 3 で idle class にして,プロセス優先度も nice -n 19 するとか)負荷が上がった時でも譲り合ってもらえるような設定を試してみたが,やはりうまく行かない.
結局 btrfs-transacti が間欠的に書き込みを行うのが問題らしい.通常は数十MBなのだが,たまに数百Mbyte級の read/write が発生する (なにに由来してサイズが変動するのか未調査).ちょっと微妙だが btrfs-transacti の kernel thread を起こすタイミングを手動で調整することにする.というか,mount -o remount すると btrfs-transacti が起きるので,あとはずっと sleep してもらうようにする.具体的には以下.
- /etc/fstab で btrfs の mount option を commit=172800 とする.172800 は2日の commit interval だが,適当に充分大きくしておく.
- cron で1日に1回(たとえば深夜に) remount を行う.remount 時に commit option を付けないと default の commit=30 になってしまうようなので,commit interval を remount の度にきっちり設定ことが必要.
mount -o remount,commit=172800 /mount_opint
とか. - 深夜は commit interval を default の 30 にして運用するとかのバリエーションも考えられる.
commit interval が長いと不具合発生時に未 commit のものが残ることになる(ように思われる)ので,その点要注意.手動で再起動する前にも一旦 remount したほうが良いのかもしれない.
ちなみに数時間分の commit すべきなにかを溜め込んだだろう状態で remount して一気に commit してみたが,それほど disk access は無かった.適切に merge されたりするのかもしれない.あと,メモリ使用量(もしくは disk 上のバッファ?)とかも気になるところ (際限なく溜め込めるわけでもないような気がする).