2019 年度 OSS リテラシ 3 : overlayfs の利用

はじめに

本作業を行う前に, (1) crontab でセンサーの計測コマンド (sensor.sh) が再起動時に自動実行されるようになっていることを確認, (2) ラズパイをセンサーとして各所に配置, しておくこと.

データがサーバに届いていることを確認した上で, ラズパイにリモートアクセスし, 以下の作業を行うとよい. なお, ラズパイの IP アドレスは DB の monitoring_hosts テーブルに保管されているのでそれを参照すること.

SD カードへの書き込みの抑制

センサーの本格稼働の前に SD カードへの書き込み抑制を行う.

これを行う理由は, ラズパイの SD カードは壊れやすいためである. 2016, 2017 年度の IoT 演習では, 10 秒おきにデータをファイル出力したところ, 稼働開始から数ヶ月で SD カードが壊れる事態が頻発した. また, ラズパイをセンサーとして運用していると電源ケーブルを抜き差しして ラズパイを再起動したくなることがあるが, SD カードの読み書き中に電源を切ると SD カードが壊れることがある.

SD カードへの書き込みを抑制するために overlayfs を用いる. overlayfs を用いることで, Readonly な下の層 (この場合は SD カード) と, Writable な上の層 (この場合はメモリー) を重ね合わせ 1 つのファイルシステムに見せることができる. データの書き出しは全てメモリ上に行われるので, 例え電源が抜き差ししても SD カードが壊れることはない.

実装の仕方は色々あるが, 今回は導入やメンテナンスが簡単な root-ro (Read-only Root-FS with overlayfs for Raspian) を用いる. 以下の作業は root-ro の README に基づいている.

swap 領域の無効化

まずは swap 領域を無効にする. swap はメモリ不足の時にディスクをメモリ代わりに使うものである. 今回はデータを全てメモリ上に置くので, swap を使う意味がない.

まずはメモリと swap の状態を確認する. swap が 100 MB あることがわかる.

# free
               total       used       free     shared    buffers     cached
  Mem:        947732     745712     202020      49428     167380     332228
  -/+ buffers/cache:     246104     701628
  Swap:       102396          0     102396

swap 領域の無効化を行う.

# dphys-swapfile swapoff

# dphys-swapfile uninstall

# update-rc.d dphys-swapfile disable

# systemctl disable dphys-swapfile

  dphys-swapfile.service is not a native service, redirecting to systemd-sysv-install.
  Executing: /lib/systemd/systemd-sysv-install disable dphys-swapfile

swap 領域が無効化されたことを確認する. 以下のように Swap の total が 0 になっていれば良い.

# free
                total        used        free      shared  buff/cache   available
  Mem:         949580      113572      499352       16012      336656      765948
  Swap:             0           0           0

root-ro の取得

root-ro は GitHub から入手する. それ以外は raspbian のパッケージを用いる (本演習では第 1 回目に, rsync, git, gawk, busybox, bindfs をインストール済み. もしインストールされていなければ apt-get コマンドを用いてこれらのパッケージをインストールすること).

$ sudo -s 

# cd 

# git clone https://github.com/josepsanzcamp/root-ro.git

root-ro の設定

GitHub から入手した root-ro のファイル群をシステム領域にコピーし, initramfs を作成し, 設定ファイル (/boot/config.txt) に修正を加える.

# rsync -va root-ro/etc/initramfs-tools/* /etc/initramfs-tools/

  sending incremental file list
  modules
  hooks/
  hooks/root-ro
  scripts/
  scripts/init-bottom/
  scripts/init-bottom/root-ro

  sent 10,494 bytes  received 93 bytes  21,174.00 bytes/sec
  total size is 10,130  speedup is 0.96

# mkinitramfs -o /boot/initrd.gz

# echo initramfs initrd.gz >> /boot/config.txt   (起動時に必要な設定をファイル末尾に書き込む)

再起動

# reboot

再起動後の確認

overlayfs が有効になっていることを確認するために, df コマンドを実行する. 以下のようにファイルシステムとして "overlay" が存在すれば良い.

$ df

  ファイルシス   1K-ブロック    使用  使用可 使用% マウント位置
  udev                464112       0  464112    0% /dev
  tmpfs                94960    2840   92120    3% /run
  /dev/mmcblk0p2    14777128 5057392 8949384   37% /mnt/root-ro
  tmpfs               474788   27520  447268    6% /mnt/root-rw
  tmpfs               474788       0  474788    0% /mnt/boot-rw
  /dev/mmcblk0p1       42708   33582    9126   79% /mnt/boot-ro
  /mnt/boot-ro         42708   33582    9126   79% /mnt/boot-ro2
  overlay             474788   27520  447268    6% /               <--ココ
  overlay             474788       0  474788    0% /boot           <--ココ
  tmpfs               474788       0  474788    0% /dev/shm
  tmpfs                 5120       4    5116    1% /run/lock
  tmpfs               474788       0  474788    0% /sys/fs/cgroup
  tmpfs                94956       0   94956    0% /run/user/109
  tmpfs                94956       0   94956    0% /run/user/1001

さらにホームディレクトリにファイルを作成し, 再びラズパイを再起動せよ.

$ touch test.txt

$ ls -l test.txt 

  -rw-r--r-- 1 hogehoge hogehoge 0 11月 20 17:23 test.txt

# reboot

再起動した直後, ホームディレクトリに test.txt が存在しないことを確認せよ. このように新たなデータは全てメモリ上に保管されるので, 再起動するとそれらのデータは全て失われる.

$ ls -l test.txt

  ls -l test.txt
  ls: 'test.txt' にアクセスできません: そのようなファイルやディレクトリはありません

参考 (1): SD カードを再び書き込み可能にする方法

SD カードに書き込みする場合には, ルートのファイルシステムを rw (read write) でマウントし直して, 設定ファイル (/boot/config.txt) を元に戻す. 但し, 絶対パスが /mnt/boot-ro/config.txt になることに注意せよ.

$ sudo mount -o remount,rw /mnt/boot-ro

$ sudo vi /mnt/boot-ro/config.txt

  末尾の命令を以下のようにコメントアウトする
  # initramfs initrd.gz 

$ sudo reboot

参考 (2): 再び overlayfs を有効にする.

再び SD カードに書き込みできない状態に戻すには, 設定ファイル (/boot/config.txt) の末尾の命令を有効にして再起動する.

$ sudo vi /boot/config.txt

  initramfs initrd.gz  (コメントアウトを外す)

$ sudo reboot