Using Overlay FS - h-sendai/RaspberryPi GitHub Wiki

Overlay File Systemの利用

複数のRaspberry Pi (RPi)をネットワークブートさせることを考える。 配布されているRaspberry Pi OSの設定ファイルを書き換えなければ ならないことがある。変更する設定ファイルには 各RPiで違う設定ファイルもあるが、共通する設定ファイルもある。 共通するものについてそれぞれで書き換えていては間違いが生じるし、 なにより面倒くさい。

サーバー、ネットワーク環境

  • サーバーはCentOS 8.2。
  • ネットワークは192.168.10.0/24を使用。
  • ネットワークブートするRPiは3台で、RPi 3 Model B (a0000000)、 RPi 3 Model B+ (b0000000)、RPi 4 Model B (c0000000)を使用。カッコ内は シリアルナンバー。
  • 使用ネットワークスイッチはCentreCOM 908TPL。

サーバー側ディレクトリ構成

配布ディスクrawイメージからファイルを取り出す

http://ftp.jaist.ac.jp/pub/raspberrypi/raspios_lite_armhf/images/raspios_lite_armhf-2020-05-28/2020-05-27-raspios-buster-lite-armhf.zip をダウンロードし、unzipして 2020-05-27-raspios-buster-lite-armhf.imgを取り出す。 kpartx -a 2020-05-27-raspios-buster-lite-armhf.imgすると /dev/mapper/loop0p1 (/boot)、/dev/mapper/loop0p2 (/)ができるので それぞれ適当な場所にマウントする。

# kpartx -a 2020-05-27-raspios-buster-lite-armhf.img
# mount -o ro /dev/mapper/loop0p1 /mnt1
# mount -o ro /dev/mapper/loop0p2 /mnt2

コピーするディレクトリを作りコピーする。コピーが終わったらumount、 kpartx -dする。

# mkdir raspberry-pi-os
# rsync -a /mnt2/ raspberry-pi-os/
# rsync -a /mnt1/ raspberry-pi-os/boot
# umount /mnt1
# umount /mnt2
# kpartx -d 2020-05-27-raspios-buster-lite-armhf.img

rsyncではなくcp -prでもよいかと思う。

方針

  • 各RPiごとにNFS Rootを用意する。
  • NFS RootにはRaspberry Pi OS全部を置くことにする。
  • Raspberry Pi OS全体をコピーし、これを一番下のlowerdirにする。
  • その上にlowerdirを作り、RPi共通設定はそこに置く。
  • 各RPi用mergedディレクトリを作りそれをNFS exportする。

overlay fsの構成

  • lowerdirはsite-common:raspberry-pi-osとし、各RPi共通なものは site-commonに書く(例: /etc/systemd/systemd-timesyncd.confのNTPサーバーの 指定。/etc/localtimeの向き先。場合によっては/etc/{passwd,group,shadow}。
  • upperには各RPiで変更するファイルを書く(例: /etc/hostname)

mountコマンド

ディレクトリ作成用シェルスクリプトを作った。githubリポジトリファイルの ほうにおいたので git clone https://github.com/h-sendai/RaspberryPi.git で取得できる。

実行すると シリアルナンバーごとのstart_x.elf、cmdline.txtなどがあるディレクトリ: a0000000、b0000000、c0000000 (各RPiはtftpでこのディレクトリからカーネル、cmdline.txtその他を取得する)、 およびNFS root用ディレクトリ nfsroot-a0000000、nfsroot-b0000000、nfsroot-c0000000 およびその他overlayfsに必要なworkdirなどがなければ作り、 a0000000, nfsroot-a0000000などにoverlayマウントされる。

a0000000/cmdline.txtをネットワークブート用に編集する。ほかも同様。 例: (長いので途中でおりかえしいるが実際には1行で書く)

console=tty1 console=serial0,115200 root=/dev/nfs nfsroot=192.168.10.201:/nfsroot-a0000000,vers=4.1,
proto=tcp rw ip=dhcp elevator=deadline rootwait rootfstype=nfs

nfsroot=192.168.10.201:/nfsroot-a0000000はNFSv4でマウントするときの書きかた。

site-commonに各RPiで共通に使うファイルを置くときにはumount.nfsrootでumount してから行う。

例:

site-common
`-- etc
    |-- fstab
    |-- group
    |-- localtime -> ../usr/share/zoneinfo/Asia/Tokyo
    |-- passwd
    |-- shadow
    `-- systemd
        `-- timesyncd.conf

再びmount.boot、mount.nfsrootを実行し、各マシンごとの設定を nfroot.a0000000/etc/hostnameなどに書く。

サーバー側/etc/exports

上記cmdline.txtのようにNFSv4でNFS mountする場合には/etc/exportsに下記のように それぞれでfsidを付ける必要がある。

/var/tftpboot/                 192.168.10.0/24(rw,no_root_squash,fsid=0)
/var/tftpboot/nfsroot-a0000000 192.168.10.0/24(rw,no_root_squash,fsid=1)
/var/tftpboot/nfsroot-b0000000 192.168.10.0/24(rw,no_root_squash,fsid=2)
/var/tftpboot/nfsroot-c0000000 192.168.10.0/24(rw,no_root_squash,fsid=3)

後半3行のfsid={1,2,3}がないとクライアントが

mount -t nfs -o vers=4.1 remote:/nfsroot-a0000000 /mnt1
mount -t nfs -o vers=4.1 remote:/nfsroot-b0000000 /mnt2

NFSすると mount ... /nfsroot-a0000000したときとmount ... /nfsroot-b0000000としたときと 同一のものがマウントされてしまう。journalctlで以下のログが残っている:

rpc.mountd[5821]: /var/tftpboot/nfsroot-a0000000 and /var/tftpboot/nfsroot-b0000000 have same filehandle for 192.168.10.0/24, using first