Raspberry Pi を Read-Only Root-FS にする & メモリがいっぱいになったらどうなるのか
Raspberry Pi を Read-Only Root-FS にしておくと急にマシンがダウンした時でもファイルシステムが破損しにくくなります.
もちろん書き込み内容は永続化されなくなりますが (書き込み内容は tmpfs にストアされるので rebootで揮発する),得てして電プチなどの乱暴なオペレーションに晒されがちな Raspberry Pi にはそういった保護機構を入れておくと何かと良いことがあるかと思います.
というわけでコレを使います:
github.com
この repository にあるツールを利用することで,Raspberry Pi をお手軽に Read-Only Root-FS にすることが可能です.
内部的には OverlayFS を利用しており,Write アクセスについては tmpfs に対して操作し, Read アクセスについては SD カードの Read-Only な FS の内容と tmpfs の内容を重ね合わせることによって,所望の動作を実現しているようです.頭がよいですね.
実際のセットアップについては,repository の README.md に書いてある内容をそのまま実行すれば良いです (apt
で引っ張ってくる一部ツールに関する記述が欠落しているのでそれを追加で入れる必要あり: initramfs-tools
).
環境
# uname -a Linux 295057330043532 4.19.75-v7+ #1270 SMP Tue Sep 24 18:45:11 BST 2019 armv7l GNU/Linux # cat /etc/os-release PRETTY_NAME="Raspbian GNU/Linux 10 (buster)" NAME="Raspbian GNU/Linux" VERSION_ID="10" VERSION="10 (buster)" VERSION_CODENAME=buster ID=raspbian ID_LIKE=debian HOME_URL="http://www.raspbian.org/" SUPPORT_URL="http://www.raspbian.org/RaspbianForums" BUG_REPORT_URL="http://www.raspbian.org/RaspbianBugs"
Installation
基本的に README.md と同じですが,念の為メモ程度に残しておくこととする (オリジナルのドキュメントを参照することを強く勧めます):
sudo su apt update apt install -y git rsync gawk busybox bindfs initramfs-tools dphys-swapfile swapoff dphys-swapfile uninstall update-rc.d dphys-swapfile disable systemctl disable dphys-swapfile git clone https://github.com/josepsanzcamp/root-ro.git rsync -va root-ro/etc/initramfs-tools/* /etc/initramfs-tools/ mkinitramfs -o /boot/initrd.gz echo initramfs initrd.gz >> /boot/config.txt reboot
Swap が Disabled になっているかどうか見る
pi@raspberrypi:~ $ free total used free shared buff/cache available Mem: 443080 32452 199196 5904 211432 352712 Swap: 102396 0 102396 pi@raspberrypi:~ $ free total used free shared buff/cache available Mem: 443080 30756 351780 1504 60544 359840 Swap: 0 0 0
Disabled になってますね.
Read-Only になってるかどうかの確認
echo "howdy?" >> am_i_here sudo reboot # After a while... ls am_i_here # ^ Should be missing
Swap が disabled && Read-Only Root-FS 環境下でめちゃ write されたときの挙動
ちょっとどうなるか気になったので検証.
pi@raspberrypi:~ $ free total used free shared buff/cache available Mem: 443080 31296 383472 2240 28312 371056 Swap: 0 0 0
dd で書いてみる:
pi@raspberrypi:~ $ dd if=/dev/zero of=tmpfile bs=314572800 count=1 Killed pi@raspberrypi:~ $ echo $? 137
Out of memory っぽいエラーコード
1 MiB ずつファイルに書き込むスクリプトで検証:
#!/usr/bin/env perl use strict; use warnings; use utf8; open my $fh, '>>', './tmp' or die $!; for (my $i = 0; $i <= 400; $i++) { # puts 1 Mib each iteration print $fh 'x' x (1024 * 1024) or die "$i MiB: $!"; } __END__
$ perl check.pl 215 MiB: No space left on device at check.pl line 11. Warning: unable to close filehandle $fh properly: No space left on device at check.pl line 11.
Disk full と同じような挙動に見えますね.
free してみる:
$ free total used free shared buff/cache available Mem: 443080 31496 158672 223020 252912 148164 Swap: 0 0 0
shared
が増えて,free
及びavailable
が減少していますね.
もう一度スクリプトを実行してみる:
$ perl check.pl 0 MiB: No space left on device at check.pl line 11. Warning: unable to close filehandle $fh properly: No space left on device at check.pl line 11.
今度は書き込めずに Disk Full エラーが返却されていますね.
その一方で free
領域はある程度残っており,マシンがハングアップしてにっちもさっちもいかなくなる,という状況にはならないようです.こういった挙動はおそらく tmpfs 自体の挙動でしょう.
とはいえ swap を切っているので,実際にプロセスがメモリを食い切ると OOM Killer が走ったり,最悪マシンがハングしてしまうと思います.継続的なメモリ使用量の監視が必要かもしれません.そもそもファイルをもりもり書くタイプのワークロードには Read-Only な Root-FS は不向きな気がしました.
以上です.