きっかけ
プログラムを並列処理するための並列クラスタが作れたら面白そうだなとふと思った。
作る際に、各クラスタをネットワークブートにすると以下の利点がありそうなので、ラズパイで試しに作ってみることにしてみた。
・同一のOSイメージ/rootファイルから起動すれば全てのクラスタが同じ環境になる
・クラスタ用のOSイメージやrootファイルの一元管理がしやすそう
手順
クライアント(クラスタ)側
-
通常の起動方法と同様にOSが書き込まれたmicroSDを挿して起動する
-
ネットワークブートの設定を有効にする
- 下記コマンドで設定を開く
$ sudo raspi-config
- 以下
raspi-config
内での設定する-
6 Advanced Options Configure advanced settings
を選択 -
A4 Boot Order Choose SD, network, USB or NVMe device boot priority
を選択 -
B3 Network Boot Boot from Network unless override by SD Card
を選択 - 設定を保存して終了
-
- 再起動後、以下コマンドを入力して
BOOT_ORDER=0xf21
が出力されることを確認する
pi@raspberrypi:~ $ vcgencmd bootloader_config [all] BOOT_UART=0 WAKE_ON_GPIO=1 POWER_OFF_ON_HALT=0 [all] BOOT_ORDER=0xf21
- microSDカードを抜く
サーバー(ネットワークブート用のデータ格納)側
-
ブートディレクトリとルートディレクトリの作成と設定
- 起動するカーネルイメージをダウンロードする
$ wget https://downloads.raspberrypi.org/raspios_lite_armhf/images/raspios_lite_armhf-2024-11-19/2024-11-19-raspios-bookworm-armhf-lite.img.xz $ xz -dv 2024-11-19-raspios-bookworm-armhf-lite.img.xz #解凍する
- 起動させるカーネルイメージに含まれるパーティションをデバイスファイルにマップし、マウントする。各パーティションの中身を別のディレクトリにコピーする
$ sudo apt install kpartx $ sudo kpartx -av 2024-11-19-raspios-bookworm-armhf-lite.img add map loop0p1 (253:0): 0 524288 linear 7:4 8192 ←マップされたブートパーティション add map loop0p2 (253:1): 0 3096576 linear 7:4 532480 ←マップされたルートディレクトリのパーティション $ sudo mkdir /mnt/boot #仮マウントするディレクトリを作成 $ sudo mkdit /mnt/rootfs #仮マウントするディレクトリを作成 $ sudo mount /dev/mapper/loop0p1 /mnt/boot #ブートパーティションをマウント $ sudo mount /dev/mapper/loop0p2 /mnt/rootfs #ルートディレクトリをマウント $ sudo mkdir -p /nfs/client1 #ルートディレクトリ格納場所の作成 $ sudo mkdir /tftpboot #ブートパーティションをの内容格納場所の作成 $ sudo chmod 777 /tftpboot #アクセス権限を変更する $ sudo rsync -av /mnt/boot/ /tftboot #ブートパーティションの内容をコピーする $ sudo rsync -av /mnt/rootfs/ /nfs/client1 #ルートディレクトリの内容をコピーする $ sudo umount /mnt/boot #アンマウントする $ sudo umount /mnt/rootfs #アンマウントする $ sudo kpartx -d 2024-11-19-raspios-bookworm-armhf-lite.img #マッピングを解除する
- ブートディレクトリのcmdline.txtを編集する
$ sudo mv /tftpboot/cmdline.txt /tftpboot/cmdline.txt.old #一応バックアップとる $ echo "console=serial0,115200 console=tty1 root=/dev/nfs nfsroot=192.168.0.12:/nfs/client1,vers=3, rw ip=dhcp rootwait elevator=deadline" | sudo tee /tftpboot/cmdline.txt #ネットワークブート時のNFSでのルートディレクトリの場所や設定を記述(IPアドレスはサーバーのアドレス)
- ルートディレクトリ上のfstabの設定(マウント先)を変更する
※fstabには元から記述されているprocとechoで追加するブートディレクトリのみにする
元々ある/
やboot/firmware
等の他のマウント設定が記述されていると起動しない
$ echo "192.168.0.xx:/tftpboot /boot/firmware/ nfs defaults,vers=3 0 0" | sudo tee -a /nfs/client1/etc/fstab #IPアドレスはサーバーのアドレスを入力する
-
ネットワークブートサーバーのの設定
-
10-eth0.netdev
に以下内容を追加する
sudo vi /etc/systemd/network/10-eth0.netdev[Match] Name=eth0 [Network] DHCP=no
-
11-eth0.netdev
に以下内容を追加する
sudo vi /etc/systemd/network/11-eth0.netdev[Match] Name=eth0 [Network] Address=192.168.0.xx/24 サーバー側のアドレス DNS=192.168.0.1 #Gate way(ルーター)のアドレス [Route] Gateway=192.168.0.1 #Gate way(ルーター)のアドレス
-
resolved.conf
に以下内容を追加する
sudo vi /etc/systemd/resolved.conf[Resolve] DNS=192.168.0.1 #Gate way(ルーター)のアドレス #FallbackDNS=
-
systemd-networkd
を有効にする
sudo systemctl enable systemd-networkd sudo reboot
-
dnsmasq
をインストールし、有効にする
sudo apt install tcpdump dnsmasq sudo systemctl enable dnsmasq
-
dnsmasq.conf
を新規作成し、設定を追加する
echo | sudo tee /etc/dnsmasq.conf
sudo vi /etc/dnsmasq.conf# Note: comment out port if you want DNS services for systems on the network. port=0 dhcp-range=192.168.0.255,proxy log-dhcp enable-tftp tftp-root=/tftpboot pxe-service=0,"Raspberry Pi Boot"
-
dnsmasq.service
を再起動する
sudo systemctl restart dnsmasq.service
-
-
NFSサーバーの設定
-
nfs-kernel-server
をインストールする
sudo apt install nfs-kernel-server
-
/etc/exports
にNFSの設定を書き込む
echo "/nfs/client1 *(rw,sync,no_subtree_check,no_root_squash)" | sudo tee -a /etc/exports
- 関連するサービスを有効にする
sudo systemctl enable rpcbind sudo systemctl restart rpcbind sudo systemctl enable nfs-kernel-server sudo systemctl restart nfs-kernel-server
-
参考にしたサイト