GeekFactory

int128.hatenablog.com

ext4 on GPT on Linux RAID1 on SATA, booting by extlinux に関するメモ

以下の構成でLinuxを構築したときのメモです。

  • Linux Software RAID1を採用する。
  • ディスク全体でRAIDボリュームを構成する。
  • パーティションテーブルはGPTを採用する。
  • 以下のパーティションは固定的に確保する。
    • /boot
    • /
    • /var
    • swap
  • 必要に応じてLVMで拡張する。
  • ブートローダはextlinuxを採用する。
  • (今回は)sdbのみ構築して、後からsdaを追加する。

ディスク全体をRAID1ボリュームとして扱い、Linuxのシステム部分を通常のパーティションに配置することでシンプルな構成になります。データは必要に応じてLVMを使えばいいと思います。

RAIDパーティションの構成

Gentoo LiveCDから起動します。

まず、RAIDボリュームを作成します。RAIDメタデータがディスクの末尾に配置されるよう、メタデータバージョンは1.0とします。

mdadm --create --level=1 --raid-devices=2 --metadata=1.0 /dev/md0 missing /dev/sdb
ls -l /dev/md0

アライメントに注意しながらパーティションを構成します。AFTディスクの場合はセクタ境界が8の倍数になるようにします。また、RAID1の場合はセクタ境界がRAIDチャンクサイズに合うようにします。チャンクサイズ64kB、セクタサイズ512byteの場合は128の倍数にすればいいはず*1

parted /dev/md0
mklabel gpt
mkpart(略)

/dev/md0 の中にパーティションテーブルを作ると、Linuxからは /dev/md0p1, /dev/md0p2,... のように見えます。これらは、カーネルが/dev/md0の中にあるパーティションテーブルを認識した契機で、devtmpfsまたはudevによって動的に作成されます。

brw-rw---- 1 root disk   9, 0  1月 23  2012 /dev/md0
brw-rw---- 1 root disk 259, 0  1月 23  2012 /dev/md0p1
brw-rw---- 1 root disk 259, 1  1月 23  2012 /dev/md0p2
brw-rw---- 1 root disk 259, 2  1月 22 23:43 /dev/md0p3

パーティションができたら通常通りGentooをインストールします。これ以降はchrootしている前提です。

カーネルの作成

以下のカーネルオプションを有効にしておくと、initramfsで /dev/md0p1 などが自動的に構成されるようになります。このオプションが無効の場合は自分で mknod する必要があります。

Device Drivers  --->
Generic Driver Options  --->
[*] Maintain a devtmpfs filesystem to mount at /dev
[*]   Automount devtmpfs at /dev, after the kernel mounted the rootfs

この他に GPT, RAID, Device Mapper サポートを有効にしておきます。

ブートローダの構成

ブートローダをインストールします。

emerge syslinux
extlinux --install /boot/syslinux/
dd bs=440 conv=notrunc count=1 if=/usr/share/syslinux/gptmbr.bin of=/dev/sdb
vim /boot/syslinux/extlinux.conf

extlinuxをインストールしたパーティションには legacy_boot 属性を付与します。partedの場合は toggle コマンドを使います。

extlinuxを設定します。

UI vesamenu.c32
DEFAULT gentoo
PROMPT 1
TIMEOUT 100

LABEL gentoo
        MENU LABEL Gentoo Linux
        LINUX ../vmlinuz
        APPEND root=/dev/md0p3
        INITRD ../initramfs/raid.gz

initramfs を生成します。以下のinitスクリプトを作成します。

#!/bin/sh
PATH=/sbin:/bin
show_message() {
        echo -e "\x1b[1;32m *\x1b[0m" "$@"
}
fallback_when_failed() {
        if ! "$@"; then
                show_message "Fallback to shell (cause: $@)"
                exec sh
        fi
}
skip_when_testmode() {
        [ "$$" -eq 1 ] && "$@" || echo "$@"
}

skip_when_testmode mount -t proc none /proc
skip_when_testmode mount -t sysfs none /sys
skip_when_testmode mount -t devtmpfs none /dev
skip_when_testmode mount -t tmpfs none /etc

show_message "Looking for RAID devices"
mdadm -E -s | tee /etc/mdadm.conf
for d in `grep -o '/dev/md/[0-9]*' < /etc/mdadm.conf`; do
        show_message "Activating... $d"
        skip_when_testmode mdadm --assemble "$d"
done

# scan again, workaround for detection of md partitions
mdadm -E -s

ROOT="`sed -ne 's,.*root=\([^ ]*\).*,\1,p' < /proc/cmdline`"
show_message "Mounting root filesystem... $ROOT"
skip_when_testmode fallback_when_failed test -b "$ROOT"
skip_when_testmode fallback_when_failed mount -o ro "$ROOT" /point

show_message "Switching to root filesystem"
skip_when_testmode umount /sys /proc /dev /etc
skip_when_testmode exec switch_root /point /sbin/init

show_message "Fallback to shell (switch_root failed)"
skip_when_testmode fallback_when_failed false

スクリプトの途中で mdadm -E -s を再実行していますが、これがないと /dev/md0 の中にあるパーティションテーブルを認識してくれませんでした。不思議です。

initramfsの生成には geninitramfs を使いました。

emerge busybox cpio

mkdir /boot/initramfs
cd /boot/initramfs
wget http://coderepos.org/share/export/39103/platform/linux/initramfs-util/geninitramfs

# busyboxとmdadmをインストールする
mkdir /boot/initramfs/content
cd /boot/initramfs/content
tar xf /usr/share/busybox/busybox-links.tar
rm linuxrc
mkdir lib64
ln -s lib64 lib
cp -a /sbin/mdadm sbin/

# 依存関係を解決する
../geninitramfs -r
chmod +x lib/*

# initスクリプトを作成する
vim init

# イメージを生成する
../geninitramfs ../raid.gz

これで完成です。リブートしてみます。initramfsのinitスクリプトが失敗する場合はシェルにフォールバックされるので、根気よく原因を探しましょう。

LVMの構成

まず、LVMパーティションを作成します。GPTの場合はタイプを lvm (8e00) にします。物理ボリュームを作成するときに、アライメントがRAIDチャンクサイズに合うようにします。

pvcreate --dataalignment 64k /dev/md0p5

参考

大変参考になりました。

*1:自信ないのでツッコミ歓迎です。