なにかの技術メモ置き場

なにかの技術メモ置き場

@インフラエンジニア

CentOS7のRaspberry PiをNFSブートする

f:id:none06:20210113230127j:plain

概要

CentOS7で構築済みのRaspberry PiNFSブートする。
OSがRaspbianの記事は散見されたが、CentOSは見つからなかったのでやってみた。

概要図

TBD

構成

ホスト名 IP 機種 OS 用途
rpi2bp 172.16.0.10 Raspberry Pi 2B+ CentOS 7.9.2009 -
file01 172.16.0.5 ReadyNAS Pro 2 RAIDiator 4.2.31 NFSサーバ
linux (任意) (任意) CentOS 8.3.2011 microSDHCカードをマウントするためのLinux物理マシン

※rpi2bpはストレージNW(172.16.1.0/24)用のIFを持っていないため、管理NW(172.16.0.0/24)用のIFを使用する。分けたほうが安全。いつか追加したい。

前提

手順

1 - NFSサーバの準備

NFSサーバにデータ移行先の領域を作成する。

file01:~# mkdir -p /nfs/rpi2bp/root
file01:~# ls -d /nfs/rpi2bp/root/
/nfs/rpi2bp/root/

2 - Raspberry Piの移行準備

Raspberry Piの移行元の領域を特定できる情報を確認しておく。具体例には、マウントポイント"/"にマウントされているパーティションのUUIDと、何番目のパーティションかを確認する。

[root@rpi2bp~]# cat /etc/fstab
#Generated by RootFS Build Factory
LABEL=1BBF2D52 /boot vfat noatime 0 0
#UUID=f28d9939-d00d-4e9e-aceb-1ac7b3e607ce swap swap noatime 0 0
UUID=8ceb6fa2-fa6e-4024-a5c6-71e3f063b21b / ext4 noatime 0 0
[root@rpi2bp~]# 
[root@rpi2bp~]# blkid 
/dev/mmcblk0p1: SEC_TYPE="msdos" LABEL="1BBF2D52" UUID="7E9B-D0E2" TYPE="vfat" 
/dev/mmcblk0p2: UUID="f28d9939-d00d-4e9e-aceb-1ac7b3e607ce" TYPE="swap" 
/dev/mmcblk0p3: UUID="8ceb6fa2-fa6e-4024-a5c6-71e3f063b21b" TYPE="ext4" 
/dev/mmcblk0: PTTYPE="dos" 

一応、"/"直下を目視しておく。移行前後の状態を比較するのが手堅いが、今回は割愛する。

[root@rpi2bp~]# ls -l /
(中略)
[root@rpi2bp~]# 

Raspberry Piをシャットダウンする。

[root@rpi2bp~]# systemctl poweroff 

3 - データ移行

Raspberry PiのmicroSDHCカードを取り外し、適当なLinuxの物理マシンにマウントする。そのへんに転がっていたmicroSDHCカード->USB Type-A変換アダプタを使用した。
NFSサーバに直接マウントできるならその方がスマート。その際、手順は柔軟に読み替えること。

[root@linux ~]# tail /var/log/messages
Jan 10 10:40:37 linux kernel: usbcore: registered new interface driver usb-storage
Jan 10 10:40:37 linux kernel: usbcore: registered new interface driver uas
Jan 10 10:40:38 linux kernel: scsi 4:0:0:0: Direct-Access     Generic- SD/MMC           1.00 PQ: 0 ANSI: 0 CCS
Jan 10 10:40:38 linux kernel: sd 4:0:0:0: Attached scsi generic sg4 type 0
Jan 10 10:40:39 linux kernel: sd 4:0:0:0: [sdc] 62333952 512-byte logical blocks: (31.9 GB/29.7 GiB) # microSDHCカードの容量で検討がつく
Jan 10 10:40:39 linux kernel: sd 4:0:0:0: [sdc] Write Protect is off
Jan 10 10:40:39 linux kernel: sd 4:0:0:0: [sdc] No Caching mode page found
Jan 10 10:40:39 linux kernel: sd 4:0:0:0: [sdc] Assuming drive cache: write through
Jan 10 10:40:39 linux kernel: sdc: sdc1 sdc2 sdc3
Jan 10 10:40:39 linux kernel: sd 4:0:0:0: [sdc] Attached SCSI removable disk
[root@linux ~]#

バイス名を確認する。

[root@linux ~]# fdisk -l
(中略)
ディスク /dev/sdc: 29.7 GiB, 31914983424 バイト, 62333952 セクタ
単位: セクタ (1 * 512 = 512 バイト)
セクタサイズ (論理 / 物理): 512 バイト / 512 バイト
I/O サイズ (最小 / 推奨): 512 バイト / 512 バイト
ディスクラベルのタイプ: dos
ディスク識別子: 0xc1356df5

デバイス   起動 開始位置 終了位置   セクタ サイズ Id タイプ
/dev/sdc1           2048   616447   614400   300M  c W95 FAT32 (LBA)
/dev/sdc2         616448  1665023  1048576   512M 82 Linux スワップ / Solaris
/dev/sdc3        1665024 62332927 60667904    29G 83 Linux
[root@linux ~]#

auto mountはされないらしい。LinuxサーバにUSBメモリを接続するのなんていつぶりだろう。

[root@linux ~]# df
ファイルシス            1K-ブロック       使用    使用可 使用% マウント位置
devtmpfs                   26658024          0  26658024    0% /dev
tmpfs                      26677076          0  26677076    0% /dev/shm
tmpfs                      26677076      25976  26651100    1% /run
tmpfs                      26677076          0  26677076    0% /sys/fs/cgroup
/dev/sda3                 138083456    2978132 135105324    3% /
/dev/sda1                   1038336     256112    782224   25% /boot
/dev/sdb                  524032000  139640064 384391936   27% /var/lib/libvirt/images
tmpfs                       5335412          0   5335412    0% /run/user/0
[root@linux ~]#

UUIDを元に該当のパーティションを特定する。

[root@linux ~]# blkid
/dev/sda1: UUID="152d7284-d558-4ae8-90f4-d5bc512df3ca" BLOCK_SIZE="512" TYPE="xfs" PARTUUID="823f64c0-01"
/dev/sda2: UUID="9bc5f618-dc5e-4737-bf1c-a4132416d5e8" TYPE="swap" PARTUUID="823f64c0-02"
/dev/sda3: UUID="bfc34690-3574-489b-a9c4-5eb365593778" BLOCK_SIZE="512" TYPE="xfs" PARTUUID="823f64c0-03"
/dev/sdb: UUID="0b516580-3c70-424e-932f-c4878aaee15a" BLOCK_SIZE="512" TYPE="xfs"
/dev/sdc1: SEC_TYPE="msdos" LABEL="1BBF2D52" UUID="7E9B-D0E2" BLOCK_SIZE="512" TYPE="vfat" PARTUUID="c1356df5-01"
/dev/sdc2: UUID="f28d9939-d00d-4e9e-aceb-1ac7b3e607ce" TYPE="swap" PARTUUID="c1356df5-02"
/dev/sdc3: UUID="8ceb6fa2-fa6e-4024-a5c6-71e3f063b21b" BLOCK_SIZE="4096" TYPE="ext4" PARTUUID="c1356df5-03"
[root@linux ~]#

該当のパーティションを任意のディレクトリにマウントする。ここでは/mediaとしている。

[root@linux ~]# mount /dev/sdc3 /media/
[root@linux ~]#
[root@linux ~]# df /media/
ファイルシス            1K-ブロック       使用    使用可 使用% マウント位置
/dev/sdc3                  29791292    7379480  21165432   26% /media
[root@linux ~]#

中身をぱっと見して、マウントしたパーティションが間違っていないことを目視しておく。

[root@linux ~]# ls -l /media/
(中略)
[root@linux ~]#

移行先のNFS領域を任意のディレクトリにマウントする。ここでは/mntとしている。

[root@linux ~]# mount file01:/nfs/rpi2bp/root /mnt/
[root@linux ~]#
[root@linux ~]# df /mnt
ファイルシス              1K-ブロック       使用    使用可 使用% マウント位置
file01:/nfs/rpi2bp/root  3876309120 3551585024 324724096   92% /mnt
[root@linux ~]#

マウントしたNFS領域が間違っていないことを確認する。空ディレクトリなのできっと大丈夫。

[root@linux ~]# ls -l /mnt/
合計 0
[root@linux ~]#

データをコピーする。

[root@linux ~]# cp -av /media/* /mnt/
'/media/4.1.11-v7+' -> '/mnt/4.1.11-v7+'
(中略)
'/media/var/www/html' -> '/mnt/var/www/html'
[root@linux ~]# 

# 7GBで6時間ほどかかった。どゆこと・・・

4 - fstabの変更

rootパーティションのエントリをコメントアウトする。

[root@linux ~]# vi /mnt/etc/fstab
(詳細は編集後のcat結果を参照)
[root@linux ~]# 
[root@linux ~]# cat /mnt/etc/fstab
#Generated by RootFS Build Factory
LABEL=1BBF2D52 /boot vfat noatime 0 0
#UUID=f28d9939-d00d-4e9e-aceb-1ac7b3e607ce swap swap noatime 0 0
#UUID=8ceb6fa2-fa6e-4024-a5c6-71e3f063b21b / ext4 noatime 0 0 # この行をコメントアウトした
[root@linux ~]#

5 - kernelのブートパラメータの変更

ここが核心。kernelのブートパラメータでrootパーティションを指定する箇所があるので、そこをNFSサーバに変更する。
該当ファイルが格納されている/bootパーティションがマウントされていないため、まずマウントする。マウント先は任意。

[root@linux ~]# mount /dev/sdc1 /media/boot/
[root@linux ~]#
[root@linux ~]# df /media/boot/
ファイルシス   1K-ブロック   使用 使用可 使用% マウント位置
/dev/sdc1           307016 109600 197416   36% /media/boot
[root@linux ~]#

設定ファイルをバックアップする。

[root@linux ~]# cp -p /media/boot/cmdline.txt{,_local}
[root@linux ~]#
[root@linux ~]# ls -l /media/boot/cmdline.txt*
-rwxr-xr-x 1 root root 120 12月  3  2015 /media/boot/cmdline.txt
-rwxr-xr-x 1 root root 120 12月  3  2015 /media/boot/cmdline.txt_local
[root@linux ~]#

編集する。

[root@linux ~]# cat /media/boot/cmdline.txt
dwc_otg.lpm_enable=0 console=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p3 rootfstype=ext4 elevator=deadline rootwait
[root@linux ~]#
[root@linux ~]# vi /media/boot/cmdline.txt
(詳細は編集後のcat結果を参照)
[root@linux ~]#
[root@linux ~]# cat /boot/cmdline.txt
dwc_otg.lpm_enable=0 console=ttyAMA0,115200 console=tty1 root=/dev/nfs nfsroot=172.16.0.5:/nfs/rpi2bp/root,tcp,vers=3 rw ip=172.16.0.10:::255.255.255.0::eth0:none elevator=deadline rootwait
[root@linux ~]#

参考サイトの内容から以下を変えている。環境の違いが理由。

  • console=tty1は残しておいた。モニタ直結して起動ログを見たかったため。
  • NFSバージョンを指定した。指定しなかったら起動に失敗したため。当環境のNFSサーバ(NAS)が古いのが原因だろう・・・
  • 固定IPにした。当環境のDHCPサーバは常時起動ではないため。

編集後の設定ファイルもバックアップしておく。理由は最後に説明する。

[root@linux ~]# cp -p /media/boot/cmdline.txt{,_nfs}
[root@linux ~]#
[root@linux ~]# ls -l /boot/cmdline.txt*
-rwxr-xr-x 1 root root 120 12月  4  2015 /boot/cmdline.txt
-rwxr-xr-x 1 root root 120 12月  4  2015 /boot/cmdline.txt_local
-rwxr-xr-x 1 root root 204  1月 11  2021 /boot/cmdline.txt_nfs
[root@linux ~]#

microSDHCカード、NFSサーバをアンマウントする。

[root@linux ~]# umount /media/boot
[root@linux ~]# umount /media
[root@linux ~]# umount /mnt
[root@linux ~]# df | grep -e "/media" -e "/mnt"
[root@linux ~]#

microSDHCカードを物理マシンから取り外す。ejectコマンドなんてまともに使った記憶がない・・・

[root@linux ~]# eject /dev/sdc
[root@linux ~]#
[root@linux ~]# fdisk -l /dev/sdc
fdisk: /dev/sdc を open できません: メディアが見つかりません
[root@linux ~]#
[root@linux ~]# blkid
/dev/sda1: UUID="152d7284-d558-4ae8-90f4-d5bc512df3ca" BLOCK_SIZE="512" TYPE="xfs" PARTUUID="823f64c0-01"
/dev/sda2: UUID="9bc5f618-dc5e-4737-bf1c-a4132416d5e8" TYPE="swap" PARTUUID="823f64c0-02"
/dev/sda3: UUID="bfc34690-3574-489b-a9c4-5eb365593778" BLOCK_SIZE="512" TYPE="xfs" PARTUUID="823f64c0-03"
/dev/sdb: UUID="0b516580-3c70-424e-932f-c4878aaee15a" BLOCK_SIZE="512" TYPE="xfs"
[root@linux ~]#
[root@linux ~]# tail /var/log/messages
(中略)
Jan 10 17:11:38 linux kernel: sdc: detected capacity change from 31914983424 to 0
[root@linux ~]#

6 - NFSブートの動作確認

microSDHCカードをRaspberry Piに戻し、電源を投入する。

(前略)
[    7.830480] smsc95xx 1-1.1:1.0 eth0: link up, 100Mbps, full-duplex, lpa 0xCDE1
[    7.873400] IP-Config: Complete:
[    7.879916]      device=eth0, hwaddr=b8:27:eb:c0:40:d2, ipaddr=172.16.0.10, mask=255.255.255.0, gw=172.16.0.254
[    7.896940]      host=172.16.0.10, domain=, nis-domain=(none)
[    7.906302]      bootserver=255.255.255.255, rootserver=172.16.0.5, rootpath=
[    7.964783] VFS: Mounted root (nfs filesystem) on device 0:19.
[    7.975329] devtmpfs: mounted
[    7.989648] Freeing unused kernel memory: 1024K
[    8.033763] Run /sbin/init as init process # この後にエラーが出なければたぶん大丈夫
[    8.581484] SELinux:  Disabled at runtime.
(後略)

無事OSが起動したらログインし、ルートパーティションのマウント元がNFSサーバであることを確認する。

[root@rpi2bp~]# df /
ファイルシス                 1K-ブロック       使用    使用可 使用% マウント位置
172.16.0.5:/nfs/rpi2bp/root  3876309064 3558929352 317379712   92% /
[root@rpi2bp~]#

比較用に、作業前の状態。

[root@rpi2bp~]# df /
ファイルシス   1K-ブロック    使用   使用可 使用% マウント位置
/dev/root         29791292 7378128 21166784   26% /
[root@rpi2bp~]#

おまけ

以降、ブート先の切り替えが一瞬でできる。これが大きなメリット。

[root@rpi2bp~]# ls -l /boot/cmdline.txt*
-rwxr-xr-x 1 root root 120 12月  4  2015 /boot/cmdline.txt
-rwxr-xr-x 1 root root 120 12月  4  2015 /boot/cmdline.txt_local # ローカルブート用
-rwxr-xr-x 1 root root 204  1月 11  2021 /boot/cmdline.txt_nfs # NFSブート用
[root@rpi2bp~]#

ローカル(microSDHCカード)ブートに切り替える。

[root@rpi2bp~]# cp -p /boot/cmdline.txt_local /boot/cmdline.txt
cp: `/boot/cmdline.txt' を上書きしますか? y
[root@rpi2bp~]#
[root@rpi2bp~]# systemctl reboot

NFSブートに切り替える。

[root@rpi2bp~]# cp -p /boot/cmdline.txt_nfs /boot/cmdline.txt
cp: `/boot/cmdline.txt' を上書きしますか? y
[root@rpi2bp~]#
[root@rpi2bp~]# systemctl reboot

参考1

cmdline.txtでNFSプロトコルのバージョンを指定しなかった場合の起動失敗ログ。

(前略)
[    6.874775] smsc95xx 1-1.1:1.0 eth0: link up, 100Mbps, full-duplex, lpa 0xCDE1
[    6.933338] IP-Config: Complete:
[    6.945020]      device=eth0, hwaddr=b8:27:eb:c0:40:d2, ipaddr=172.16.0.10, mask=255.255.255.0, gw=172.16.0.254
[    6.963939]      host=172.16.0.10, domain=, nis-domain=(none)
[    6.978492]      bootserver=255.255.255.255, rootserver=172.16.0.5, rootpath=
[    7.023662] VFS: Mounted root (nfs filesystem) on device 0:19.
[    7.039656] devtmpfs: mounted
[    7.059176] Freeing unused kernel memory: 1024K
[    7.103754] Run /sbin/init as init process
[   19.033459] nfs: server 172.16.0.5 not responding, still trying
[   19.033863] nfs: server 172.16.0.5 not responding, still trying
[   19.033879] nfs: server 172.16.0.5 not responding, still trying
[   20.153428] nfs: server 172.16.0.5 not responding, still trying
[   34.023903] random: crng init done
# ここで止まる(ハングしているわけではなさそう)

参考2

今回は、なるべく手間をかけたくなかったため、設定ファイルの編集程度で済む手法を選んだ。切り戻しも簡単だし。
一方、もう一歩踏み込んで、microSDHCカードにブート専用のイメージを書き込む手法もあった。こっちのほうが構成がわかりやすいし、iSCSIブートもできるらしい。ただ、OSは移行ではなく新規インストールになりそうなので、別件として試してみることにする。