Raspberry Pi OSのrootfs ROM 化 ― RAMディスク化しつつ、好きなパッケージを後から追加する方法


IoT においては、特に現場のデバイスの運用がこれから課題になります。
というのは、日常の運用で発生する程度の問題は、専門的な技能が無くとも自己解決ができる仕組みが必要です。
この 専門的な技能が無くとも自己解決ができる仕組み の一番確実なオペレーションは電源引っこ抜き、通称「電プチ」です。

Raspberry Pi (というか Raspberry Pi OS)で電プチできるようにしようというのが主旨です。Raspberry Pi OSに依存している仕組みでは無いので、例えば Debian 9やUbuntuでも同じようにできると思います。

検証環境

  • Raspberry Pi 3 model B+
  • Raspberry Pi OS (Lite; 32bit; 2020-12-02)

ちなみに Raspberry Pi OS なら raspi-config でも可能です

2019年時点で raspi-config からここで紹介している overlayfsを使ったRAMディスク化が簡単にできるようになっています。

RAMディスク有効化
$ sudo raspi-config nonint enable_overlayfs
$ sudo systemctl reboot
## これで次回起動は overlayfs を使った RAM ディスク起動となります
RAMディスク無効化
$ sudo raspi-config nonint disable_overlayfs
$ sudo systemctl reboot
## これで次回起動はmicroSDを使った起動となります
現状を知りたい場合
$ sudo raspi-config nonint get_overlay_now && echo "enabled" || echo "disabled"
## enabled / disabled が表示されます

処理内容は /usr/bin/raspi-config にスクリプトとして書かれています。

概要

[メモ] RaspberryPi: リードオンリーRoot-FS (overlayfs使用) を参考に、実際にやってみました。
加えて、自分用のパッケージや設定を行う方法について調査しています。

Raspberry Pi OS の rootfs ROM 化

[メモ] RaspberryPi: リードオンリーRoot-FS (overlayfs使用) の通りに行う事で達成できます。

上記は overlayfs を利用することで実現しています。

実行後の様子

 $ df -h  # 一部省略
 /dev/mmcblk0p2   30G  1.1G   28G   4% /mnt/root-ro
 tmpfs           464M  712K  463M   1% /mnt/root-rw
 overlay         464M  712K  463M   1% /

 $ mount  # 一部省略
 /dev/mmcblk0p2 on /mnt/root-ro type ext4 (ro)
 tmpfs on /mnt/root-rw type tmpfs (rw)
 overlay on / type overlay (rw)

自分好みのパッケージや設定を行う方法

さて本題です。
[メモ] RaspberryPi: リードオンリーRoot-FS (overlayfs使用) の手順通り行った後にパッケージやソフトウェアのインストールを行う方法ですが、二通りあります。

  • A: SD カードを RW として mount して起動する方法 (要するに通常の起動に戻してから作業をする)
  • B: SD カードを RW として remount してから chroot する方法

Aは通常起動に戻す時と、rootfs ROM化にする時と2回再起動が必要です。
Bは稼働中のRaspberry Piで作業可能ですが、rootfs ROM化にする時に1回再起動が必要となります。

A: SD カードを RW として mount して起動する方法

/boot/config.txt 内の initramfs initrd.gz と書かれている行をコメントアウトして再起動します。すると次回起動は overlayfs を使いません。
これは普通に SD カードで Raspbian が起動したという状態になるため、 apt を使ったり /etc を編集できます。

作業前に再起動は必須になります。また RO に戻す必要があります。
作業中はログなども書き込まれるため、クリーンアップが必要になる場合もあるので、クリーンアップをスクリプト化しておくことをお勧めします。

$ sudo mount -o remount,rw /mnt/boot-ro
$ sudo sed -i /mnt/boot-ro/config.txt -e 's/^initramfs .*/#&/g'
$ sudo systemctl reboot

## ここからは普通に立ち上がるので、設定を行う
## e.g.)
$ sudo timedatectl set-timezone Asia/Tokyo

## 最後の作業 (= SD カードの RO 化)
## 必要なら、ここでクリーンアップ
$ sudo sed -i /boot/config.txt -e 's/^#\(initramfs .*\)/\1/g'
$ sudo systemctl reboot

B: SD カードを RW として remount してから chroot する方法

/mnt/root-ro をRead/Writeでマウントしたうえで chroot の root としてから、作業を行います。
chroot 下での作業になるため、systemd の操作といった D-Bus などプロセス間通信が必要になる場合は失敗しますので注意が必要です。

例えば timedatectl set-timezone Asia/Tokyo など systemd と通信する必要のある作業は失敗します。
一方 apt install でもファイルを配置するだけのような単純な仕組みであれば可能です。
※ USB ドングルで SORACOM Air を使えるようにするスクリプト setup_air.sh も大丈夫でした

A のパターン同様、作業中はログなども書き込まれるため、クリーンアップが必要になる場合もあるので、クリーンアップをスクリプト化しておくことをお勧めします。

$ sudo -s
# mount -o remount,rw /mnt/root-ro
# chroot /mnt/root-ro
# mount -t proc proc /proc

## 設定を行う
## e.g.)
# curl https://soracom-files.s3.amazonaws.com/setup_air.sh
# bash setup_air.sh

## 最後の作業 (= SD カードの RO 化)
## 必要なら、ここでクリーンアップ
# systemctl reboot

永続化が必要なデータの保存場所

例えばログです。

  • ローカル永続化ストレージの利用
  • ネットワークを前提としたクラウド側での管理
    • ネットワーク不通時の対処を検討する必要があります → fluentd 等の利用など

あとがき

やっぱり2日くらい集中してやれると、それなりに作業できますね。
本記事は65%のカツオのたたきで出来ています。

以上