LeavaTailの日記

LeavaTailの日記

システムソフトウェアエンジニアを目指す技術者の備忘録

Raspberry Pi 4 で OverlayFS を併用した Read-Only な rootfs を構築する

背景

組込み機器では、セキュリティやストレージデバイスの摩耗を抑えるなどといった観点からルートファイルシステムを読み取り専用にすることがある。 Raspberry Pi OS では、raspi-configoverlayroot によってルートファイルシステムを読み取り専用に変更することができる。

overlayroot では、既存のルートファイルシステムに OverlayFS を導入しやすくするのツールの一つである。 このパッケージによって読み取り専用となったルートファイルシステムに対して、tmpfsのような一時ファイルシステムを上位のレイヤに追加することで、達成することができる。

overlayrootでの複数レイヤによる書き込みと読み込みの分離

Linux では、読み取り専用ファイルシステムがいくつかサポートしている。 こういったファイルシステムは、読み取り専用に設計されているため、圧縮や重複除去といった機能がサポートされている。 Android では、SquashFS(Android 9 以前)、EROFS をシステムパーティションとして利用している。

本稿では、Raspberry Pi 4 のルートファイルシステムを読み取り専用に変更し、そのうえで SquashFS や EROFS として作成することを目指す。

実行環境

Raspberry Pi 4 は microSDカード経由でRaspberry Pi OSを起動させる。

計測環境の概要

ここで使用するRaspberry Pi 4のスペックについて、必要な情報だけ抜粋したものを下記に示す。

項目 Raspberry Pi 4
CPU Cortex-A72 (ARM v8) 1.5GHz
メモリ 4GB LPDDR4-3200
OS Raspberry Pi OS (Mar 15th 2024)
Linux kernel 6.6.261
micro SD card KTHN-MW016G

ファイルシステムを Read-Only化する

  1. raspi-config から Non-Interactiveモードで OverlayFS による Read-Only な rootfs を有効化する。(必要であれば追加パッケージのインストールされる)

     pi@raspberrypi:~$ sudo raspi-config nonint enable_overlayfs
    
  2. システムを再起動する

     pi@raspberrypi:~$ sudo systemctl reboot
    
  3. 再起動後にシステムのマウント状況を確認する

     pi@raspberrypi:~$ mount | grep -E 'mmc|root-ro|root-rw'
     /dev/mmcblk0p2 on /media/root-ro type ext4 (ro,relatime)
     tmpfs-root on /media/root-rw type tmpfs (rw,relatime)
     overlayroot on / type overlay (rw,relatime,lowerdir=/media/root-ro,upperdir=/media/root-rw/overlay,workdir=/media/root-rw/overlay-workdir/_,uuid=on)
     /dev/mmcblk0p1 on /boot/firmware type vfat (rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=ascii,shortname=mixed,errors=remount-ro)        
    

読み取り専用ファイルシステムを使用する

ルートファイルシステムSquashFSに変更する

SquashFS は 読み取り専用の圧縮ファイルシステムとなっており、ファイルやディレクトリ、それらメタデータを圧縮することができる。(gzip/xz/lzo/zstdなどがサポートされている)

SquashFSファイルシステムを作成するためには、mksquashfs プログラムを使用する必要がある。 mksquashfs では、圧縮アルゴリズムの選択や作成されるファイルシステムのメタ情報を調整することができる。

ここでは、デフォルトのパラメータ(gzipによる圧縮)でSquashFSファイルシステムを作成する。

  1. Raspberry Pi OS の SDメモリカードのイメージをバックアップする

     $ sudo dd if=/dev/sdd1 of=bootfs.img
     $ sudo dd if=/dev/sdd2 of=rootfs.img
    
  2. SquashFSファイルシステムを作成する

     $ sudo mksquashfs /mnt/ rootfs_gzip.sfs
    
  3. 作成したSquashFSファイルシステムSDメモリカードに書き込む

     $ sudo dd if=rootfs_gzip.sfs of=/dev/sdd2
    

また、overlayrootのインストールによって、カーネルコマンドラインにも変更が加わっている。
SquashFSでマウントするように次のような修正をする。

// 1:
--- cmdline.txt.orig    2024-05-05 17:51:26.000000000 +0900
+++ cmdline.txt 2024-05-05 17:51:50.000000000 +0900
@@ -1 +1 @@
-overlayroot=tmpfs console=serial0,115200 console=tty1 root=PARTUUID=9e2953b9-02 rootfstype=ext4 fsck.repair=yes rootwait quiet splash plymouth.ignore-serial-consoles cfg80211.ieee80211_regdom=JP
+overlayroot=tmpfs console=serial0,115200 console=tty1 root=PARTUUID=9e2953b9-02 rootfstype=squashfs fsck.repair=yes rootwait quiet splash plymouth.ignore-serial-consoles cfg80211.ieee80211_regdom=JP

このSDメモリカードRaspberry Pi 4 を起動させたとき、SquashFSでマウントされていることが確認できる。

pi@raspberrypi:~$ mount | grep 'mmcblk0p2'
/dev/mmcblk0p2 on /media/root-ro type squashfs (ro,relatime,errors=continue)

ルートファイルシステムをEROFSに変更する

EROFS も 読み取り専用の(圧縮)ファイルシステムとなっており、ファイルやディレクトリ、それらメタデータを圧縮することができる。(lz4/lzmaなどがサポートされている)

SquashFSファイルシステムを作成するためには、mkfs.erofs プログラムを使用する必要がある。 mkfs.erofs では、圧縮アルゴリズムの選択や作成されるファイルシステムのメタ情報を調整することができる。

ここでは、デフォルトのパラメータ(非圧縮)でSquashFSファイルシステムを作成する。

  1. EROFSファイルシステムを作成する

     $ sudo mkfs.erofs rootfs.erofs /mnt
    
  2. 作成したEROFSファイルシステムSDメモリカードに書き込む

     $ sudo dd if=rootfs.erofs of=/dev/sdd2
    

また、EROFSでマウントするようにカーネルコマンドラインを次のような修正をする。

// 1:
--- cmdline.txt.orig    2024-05-05 17:51:26.000000000 +0900
+++ cmdline.txt 2024-05-05 17:51:50.000000000 +0900
@@ -1 +1 @@
-overlayroot=tmpfs console=serial0,115200 console=tty1 root=PARTUUID=9e2953b9-02 rootfstype=ext4 fsck.repair=yes rootwait quiet splash plymouth.ignore-serial-consoles cfg80211.ieee80211_regdom=JP
+overlayroot=tmpfs console=serial0,115200 console=tty1 root=PARTUUID=9e2953b9-02 rootfstype=erofs fsck.repair=yes rootwait quiet splash plymouth.ignore-serial-consoles cfg80211.ieee80211_regdom=JP

このSDメモリカードRaspberry Pi 4 を起動させたとき、SquashFSでマウントされていることが確認できる。

pi@raspberrypi:~$ mount | grep mmcblk0p2
/dev/mmcblk0p2 on /media/root-ro type erofs (ro,relatime,user_xattr,acl,cache_strategy=readaround)

測定

起動時間と圧縮率の二つの観点でそれぞれの起動方法を評価していく。 起動時間は systemd-analyzeから kernel と userpaceの合計時間(s)、圧縮率はデフォルトのイメージサイズ (4580120.72 KB) との割合から計測した。

S No. 項目 mkfsのオプション 起動時間(s) 圧縮率
1 ext4 (R/W) - 16.553 -
2 ext4 (R/O) - 15.988 -
3 SquashFS (uncompressed) -noD -noI -noX -noF 18.789 -
4 SquashFS (gzip) none 19.000 38.45%
5 SquashFS (LZ4HC) -comp lz4 -Xhc 16.751 44.18%
6 SquashFS (xz) -comp xz 28.728 32.74%
7 SquashFS (lzo) -comp lzo 17.563 41.63%
8 SquashFS (zstd) -comp zstd 16.891 36.11%
9 EROFS (uncompressed) none 15.842 -
10 EROFS (LZ4HC) -zlz4hc,12 15.842 54.70%
11 EROFS (lzma) -zlzma 22.001 32.75%
12 EROFS (big pcluster) -zlz4hc -C65536 15.779 48.81%
13 EROFS (multiple) --well-compressed=docs/compress-hints.example -zlz4hc,12 17.419 45.01%
14 EROFS (well-compressed) -C1048576 -Eztailpacking -Eall-fragments -Ededupe -zlz4hc,12 18.820 43.39%

x軸を起動時間として、y軸を圧縮率としたときに次のようなグラフが得られた。

Raspberry Pi 4の起動時間とrootfsのイメージ圧縮率

このグラフでは、プロットが左にあればあるほど起動時間が短く、下にあればあるほどrootfsのイメージサイズが小さいことを表している。

変更履歴

  • 2024/05/12: 記事公開

参考文献


  1. 2024年4月17日現在の Raspberry Pi OS のカーネルでは、SquashFS や EROFS がビルドインされていないため、カーネルは手元でビルドしたものに更新している。