Raspberry Piはリソースも小さく、CPUもそれほど高速ではないために運用中にハングアップしてしまうことがあります。多くのIoTデバイスは遠隔地にあり、エンジニアが常にいるとは限りません。そんな時、現場の人たちにできることと言えば電源を抜いて差し込み直すと言った作業です。エンジニアであれば分かることですが、それで解決できる問題は多くありません。むしろファイルが壊れてしまって問題が複雑化する可能性すらあります。

そこで使えるのがrootfsのROM(Read Only Memory)化です。ストレージを読み込み専用にしてしまうことで、電源を抜いたら元に戻る仕組みが作れます。この仕組みを用意しておけば、何かあったら電源を抜いて元に戻すというフローが実現できます(ストレージが壊れてしまった場合は再起動が困難ですが、今回はハードウェア障害は想定しません)。しかし、このフローの問題はライブラリのアップデートなどストレージを更新したい作業ができないことです。正しく言えば更新はできるのですが、再起動すると更新前に戻ってしまいます。

今回はこの二つの問題を解決する方法を紹介します。rootfsの状態を遠隔地からコントロールすることで、普段は読み込み専用として運用し、必要なタイミングで書き込みできるようにします。

rootfsのROM化について

まずROM化するための設定を行います。これは下記の記事が詳しいです。

具体的な内容はjosepsanzcamp/root-ro: Read-only Root-FS with overlayfs for Raspianに書かれている内容を実行します。

cd /home/pi
sudo bash

echo Installing all dependencies
apt-get install git rsync gawk busybox bindfs -y

echo Disabling swap
dphys-swapfile swapoff
dphys-swapfile uninstall
update-rc.d dphys-swapfile disable
systemctl disable dphys-swapfile

echo Cloning repository
git clone https://github.com/josepsanzcamp/root-ro.git

echo Doing the setup
rsync -va root-ro/etc/initramfs-tools/* /etc/initramfs-tools/
mkinitramfs -o /boot/initrd.gz
echo initramfs initrd.gz >> /boot/config.txt

echo Restarting RPI
reboot

ROM化されているかどうかを判定する

ROMになっている場合 /mnt/root-ro がマウントされています。これは以下のように判定できます(Node.js を使った場合)。

const {promisify} = require('util');
const fs = require('fs');
(async () => {
  try {
    let stats = await promisify(fs.access)('/mnt/root-ro', fs.constants.R_OK);
    console.log('ROM mode');
  } catch (e) {
    console.log('Normal mode');
  }
})();

これで書き込める状態にした場合の処理、逆に読み込みのみの状態の処理分けが可能になります。

読み書きの設定を行う

ROM化したRaspberry Piを読み書きできる状態にするには以下のように /boot/config.txt を書き換えます。再起動が必要なので注意してください。

const exec = require('await-exec')

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

これで再起動後、書き込みが行える状態になり、通常のコマンドが実行できます。書き込みできるかという判定はROM判定と同じく、 /mnt/root-ro の存在によって判定できます。そして更新処理がすべて終わったら、起動時に読み込むファイルを initrd.gz にします。こちらもまた、再起動が必須です。

await exec('sudo mkinitramfs -o /boot/initrd.gz')
await exec('sudo sed -i /boot/config.txt -e \'s/^#\(initramfs .*\)/\1/g\'')
await exec('sudo systemctl reboot')

rootfsをROM化することで、普段の運用時はSDカードへの書き込みが発生しなくなります。その結果、SDカードの寿命も延びるはずです。また、電源の抜き差しで元の状態に戻るので、緊急時対応に向いているでしょう。

開発時やメンテナンス時には通常のファイルシステム、運用時にはROM化するのがお勧めです。それらの遠隔地操作もisaaxを使うことで容易に実現できます。

おわりに

センサーからアイディアを得たり、今自分の困っていることを解決してみるでも良いでしょう。さぁ手を動かしてみましょう。やり方がわからない方はぜひIoTエンジニア養成キットで学習してください。

その際にはぜひ、IoTプロジェクトの開発が容易になるisaaxと組み合わせてみてください。


0 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *