ミルク色の記録

やったこと、やってみたこと

RaspbianのOSイメージのパーティションを分割した

動機

公式で配布されているRaspbian OSイメージはbootとrootfsのパーティションのみで構成されていて、 Raspberry PIに入れて起動するとrootfsが自動でSDカード全体まで拡張される。

そのまま常時稼働で運用していると、OSのログやtmpやswapの利用でSDカードへの書き込みがチクチク行われて、 NANDフラッシュの書き込み上限を迎えてある日ディスクが壊れることになる。

NANDフラッシュはSLC、MLCTLCで書き込み上限が異なるので、なるべく上限の多いタイプを選ぶべきだけど、 それでも上限があることには変わりないし、工業用のSLCのSDカードとか結構高価。

なのでなるべくディスクへの書き込みは最小限にしたい。

また、電源ぶち切りとか停電とか考えると、そもそもrootfsはReadOnlyにしたい。

ただし、ReadOnlyにすると設定ファイルの書き換えみたいな最低限の書き込みや変更ができなくなってしまうので、 書き込みができる領域が別にほしいということになる。

というわけで、公式のRaspbian OSイメージをカスタマイズして、bootとrootfsの他にもう一つパーティションを追加する手順をまとめた。

作業環境とRaspbian OSイメージのバージョン

作業環境は今回もLinux PC。

Raspbianのイメージは(もう新しいの出てるけど)2018-11-13-raspbian-stretch-lite.imgを利用した。

カスタマイズ手順

作業は次のように行った。

カスタマイズ用のOSイメージを作ってパーティションの状況確認

まずカスタマイズ用に公式イメージのコピーを作成した。

$ cp 2018-11-13-raspbian-stretch-lite.img 2018-11-13-raspbian-stretch-lite-custom.img

次にfdiskで現在のイメージのパーティション状況を確認した。

$ fdisk -l 2018-11-13-raspbian-stretch-lite-custom.img
Disk 2018-11-13-raspbian-stretch-lite-custom.img: 1.8 GiB, 1866465280 bytes, 3645440 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x7ee80803

デバイス                                     起動 Start 最後から セクタ  Size Id タイプ
2018-11-13-raspbian-stretch-lite-custom.img1       8192    98045   89854 43.9M  c W95 FAT32 (LBA)
2018-11-13-raspbian-stretch-lite-custom.img2      98304  3645439 3547136  1.7G 83 Linux

バイス2018-11-13-raspbian-stretch-lite-custom.img1がbootパーティションで、 2018-11-13-raspbian-stretch-lite-custom.img2がrootfsパーティションに当たる。

OSイメージのファイルサイズを増やす

パーティションを追加できるようにするために、まずtruncateを使ってOSイメージのファイルサイズを増やす。

$ truncate -s 4GiB 2018-11-13-raspbian-stretch-lite-custom.img

とりあえず4GBまで増やした。

改めてfdiskでイメージの状況を確認する。

$ fdisk -l 2018-11-13-raspbian-stretch-lite-custom.img
Disk 2018-11-13-raspbian-stretch-lite-custom.img: 4 GiB, 4294967296 bytes, 8388608 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x7ee80803

デバイス                                     起動 Start 最後から セクタ  Size Id タイプ
2018-11-13-raspbian-stretch-lite-custom.img1       8192    98045   89854 43.9M  c W95 FAT32 (LBA)
2018-11-13-raspbian-stretch-lite-custom.img2      98304  3645439 3547136  1.7G 83 Linux

イメージのサイズが1.8GBから4GBまで増えたことが確認できる。

rootfsのパーティションサイズを変更

次にrootfsのパーティションサイズを拡張する。

fdiskの対話モードでカスタムイメージを開いて、dコマンドで一度rootfsのパーティションを削除し、nコマンドで改めて作りなおす。 この時新たに作るパーティションのFirst sectorはもともとの値(今回であれば98304)を指定する。 Last sectorは今回はrootfsを3GB固定にするので+3Gを指定した。

$ fdisk 2018-11-13-raspbian-stretch-lite-custom.img

Welcome to fdisk (util-linux 2.27.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.


コマンド (m でヘルプ): d
パーティション番号 (1,2, default 2): 2

Partition 2 has been deleted.

コマンド (m でヘルプ): n
Partition type
   p   primary (1 primary, 0 extended, 3 free)
   e   extended (container for logical partitions)
Select (default p): p
パーティション番号 (2-4, default 2): 2
First sector (2048-8388607, default 2048): 98304
Last sector, +sectors or +size{K,M,G,T,P} (98304-8388607, default 8388607): +3G

Created a new partition 2 of type 'Linux' and of size 3 GiB.

作りなおしたrootfsパーティションをpコマンドで確認すると次のようになる。

コマンド (m でヘルプ): p
Disk 2018-11-13-raspbian-stretch-lite-custom.img: 4 GiB, 4294967296 bytes, 8388608 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x7ee80803

デバイス                                     起動 Start 最後から セクタ  Size Id タイプ
2018-11-13-raspbian-stretch-lite-custom.img1       8192    98045   89854 43.9M  c W95 FAT32 (LBA)
2018-11-13-raspbian-stretch-lite-custom.img2      98304  6389759 6291456    3G 83 Linux

書き込み用領域のパーティションを追加

次に書き込み領域にする予定のパーティションをnコマンドで追加する。 First sectorは2018-11-13-raspbian-stretch-lite-custom.img2の最後のセクタ + 1の値(今回であれば6389760)とし、 Last sectorは指定せずにイメージファイルのサイズいっぱいまでを使う。

コマンド (m でヘルプ): n
Partition type
   p   primary (2 primary, 0 extended, 2 free)
   e   extended (container for logical partitions)
Select (default p): p
パーティション番号 (3,4, default 3): 3
First sector (2048-8388607, default 2048): 6389760
Last sector, +sectors or +size{K,M,G,T,P} (6389760-8388607, default 8388607):

Created a new partition 3 of type 'Linux' and of size 976 MiB.

追加したパーティションをpコマンドで確認する。

コマンド (m でヘルプ): p
Disk 2018-11-13-raspbian-stretch-lite-custom.img: 4 GiB, 4294967296 bytes, 8388608 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x7ee80803

デバイス                                     起動   Start 最後から セクタ  Size Id タイプ
2018-11-13-raspbian-stretch-lite-custom.img1         8192    98045   89854 43.9M  c W95 FAT32 (LBA)
2018-11-13-raspbian-stretch-lite-custom.img2        98304  6389759 6291456    3G 83 Linux
2018-11-13-raspbian-stretch-lite-custom.img3      6389760  8388607 1998848  976M 83 Linux

wコマンドでパーティションの変更を反映してfdiskの対話モードを抜ける。

コマンド (m でヘルプ): w
The partition table has been altered.
Syncing disks.

書き込み用領域のフォーマットとラベル付け

追加したパーティションはまだフォーマットしていないので、フォーマットするためにイメージをLinux PCでマウントできるようにする。 これにはkpartxを利用してイメージファイル内のパーティションをデバイスマッピングする。

$ sudo kpartx -av 2018-11-13-raspbian-stretch-lite-custom.img
add map loop0p1 (253:0): 0 89854 linear 7:0 8192
add map loop0p2 (253:1): 0 6291456 linear 7:0 98304
add map loop0p3 (253:2): 0 1998848 linear 7:0 6389760

パーティション/dev/mapper下にマッピングされる。

$ ls /dev/mapper
control  loop0p1  loop0p2  loop0p3

/dev/mapper/loop0p1がboot、/dev/mapper/loop0p2がrootfs、/dev/mapper/loop0p3が今回追加したパーティションに当たる。

/dev/mapper/loop0p3EXT4でフォーマットする。

$ sudo mkfs -t ext4 /dev/mapper/loop0p3
mke2fs 1.42.13 (17-May-2015)
Discarding device blocks: done
Creating filesystem with 249856 4k blocks and 62464 inodes
Filesystem UUID: 828efd40-40d9-42f9-85f7-5d39b1154840
Superblock backups stored on blocks:
        32768, 98304, 163840, 229376

Allocating group tables: done
Writing inode tables: done
Creating journal (4096 blocks): done
Writing superblocks and filesystem accounting information: done

わかりやすいようにパーティションにラベルをつける。

$ sudo e2label /dev/mapper/loop0p3 extrafs

ラベルがついたか確認。

$ sudo e2label /dev/mapper/loop0p3
extrafs

rootfsの自動リサイズを無効化・書き込み用領域のマウントを設定

bootとrootfsのファイルに手を加えるために、それぞれのマウントポイントを作成する。

$ mkdir boot
$ mkdir rootfs

bootをマウントする。

$ sudo mount /dev/mapper/loop0p1 boot

rootfsをマウントする。

$ sudo mount /dev/mapper/loop0p2 rootfs

boot/cmdline.txtを編集し、末尾のinit=/usr/lib/raspi-config/init_resize.shを削除して、初回起動時のrootfsの自動拡張を無効にする。

$ sudo vi boot/cmdline.txt`

編集後のboot/cmdline.txt`は次のようになる。

dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=PARTUUID=7ee80803-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait quiet

rootfs/etc/fstabを編集し、extrafsパーティションが起動時にマウントされるように設定する。 末尾に/dev/mmcblk0p3 /extra ext4 defaults,noatime 0 1を追加する。

$ sudo vi rootfs/etc/fstab

編集後のrootfs/etc/fstabは次のようになる。

proc            /proc           proc    defaults          0       0
PARTUUID=7ee80803-01  /boot           vfat    defaults          0       2
PARTUUID=7ee80803-02  /               ext4    defaults,noatime  0       1
/dev/mmcblk0p3  /extra      ext4    defaults,noatime  0       1

他のパーティションがPARTUUID指定なのでちょっと歪だけどとりあえずこれで行く。

rootfs内にextrafs用のマウントポイントを追加しておく。

$ sudo mkdir rootfs/extra

bootとrootfsをアンマウントする。

$ sudo umount boot
$ sudo umount rootfs

バイスマッピングを解除する。

$ sudo kpartx -d 2018-11-13-raspbian-stretch-lite-custom.img

カスタムイメージの動作確認

出来上がったカスタムイメージをSDカードに書き込む。

$ sudo dd if=2018-11-13-raspbian-stretch-lite-custom.img of=/dev/mmcblk0 bs=1M
4096+0 レコード入力
4096+0 レコード出力
4294967296 bytes (4.3 GB, 4.0 GiB) copied, 776.849 s, 5.5 MB/s

書き込み完了したSDカードをRaspberry PIに入れて起動する。

起動したRaspbianにログインし、fdiskでパーティションの状況を確認する。

$ sudo fdisk -l /dev/mmcblk0
Disk /dev/mmcblk0: 7.4 GiB, 7969177600 bytes, 15564800 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x7ee80803

Device         Boot   Start     End Sectors  Size Id Type
/dev/mmcblk0p1         8192   98045   89854 43.9M  c W95 FAT32 (LBA)
/dev/mmcblk0p2        98304 6389759 6291456    3G 83 Linux
/dev/mmcblk0p3      6389760 8388607 1998848  976M 83 Linux

mountの状況を確認する。

$ mount
/dev/mmcblk0p2 on / type ext4 (rw,noatime,data=ordered)
devtmpfs on /dev type devtmpfs (rw,relatime,size=217616k,nr_inodes=54404,mode=755)
sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,relatime)
proc on /proc type proc (rw,relatime)
tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev)
devpts on /dev/pts type devpts (rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000)
tmpfs on /run type tmpfs (rw,nosuid,nodev,mode=755)
tmpfs on /run/lock type tmpfs (rw,nosuid,nodev,noexec,relatime,size=5120k)
tmpfs on /sys/fs/cgroup type tmpfs (ro,nosuid,nodev,noexec,mode=755)
cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,release_agent=/lib/systemd/systemd-cgroups-agent,name=systemd)
cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,devices)
cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpu,cpuacct)
cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,blkio)
cgroup on /sys/fs/cgroup/net_cls type cgroup (rw,nosuid,nodev,noexec,relatime,net_cls)
cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,freezer)
sunrpc on /run/rpc_pipefs type rpc_pipefs (rw,relatime)
debugfs on /sys/kernel/debug type debugfs (rw,relatime)
systemd-1 on /proc/sys/fs/binfmt_misc type autofs (rw,relatime,fd=35,pgrp=1,timeout=0,minproto=5,maxproto=5,direct)
mqueue on /dev/mqueue type mqueue (rw,relatime)
configfs on /sys/kernel/config type configfs (rw,relatime)
/dev/mmcblk0p1 on /boot type vfat (rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=ascii,shortname=mixed,errors=remount-ro)
/dev/mmcblk0p3 on /extra type ext4 (rw,noatime,data=ordered)
tmpfs on /run/user/1000 type tmpfs (rw,nosuid,nodev,relatime,size=44384k,mode=700,uid=1000,gid=1000)

/dev/mmcblk0p3 on /extra type ext4 (rw,noatime,data=ordered)となっていれば/extraに追加したパーティションがマウントされていることが確認できる。

まとめ

とりあえず分割までできた。

この作業をいちいち手でやるのが面倒になったので、作成用スクリプト作った。

github.com

$ sudo ./create-extra-partition <path to>/YYYY-MM-DD-raspbian-stretch-lite.img

みたいな感じで作成できる。