春雨日記 about me tags

kexecを用いてブートストラップをしつつRAIDアレイ上からLinuxを動作させるメモ

はじめに

現在、市販の中華NUCを用いて新サーバを製作中なのですが、今使っているProLiantのようなリモート管理機能を持たない一般PCにて、外部からOSを自由に入れ替える方法を模索した結果kexec1に辿り着きました。

kexecはLinuxカーネルの機能で、Linuxカーネル上から別のLinuxカーネルを起動できる機能です。 Dockerやsystemd-nspawnといったコンテナとは全く異なり、再起動したかのような動作を経て新しいカーネルが起動します。

話は変わりますが、RAIDアレイ上のOSを起動する際、(GPTでは)冗長化されていないもしくはRAID1の起動ディスクからブートローダを実行し、RAIDに対応しているLinuxカーネルを読みだした上で起動するという流れが行われると思います。

ここで、このブートストラップ的な場面でkexecを使い、非冗長なSDカード上に踏み台のArch Linuxを設置した上でRAIDアレイ上のOSを起動する事にしました。

というのも、(うまくいけば)近々サーバ製作記を書くと思うのですが、無理やり拡張した都合上利用可能なストレージが

  • 「起動できない」SATA
  • USBの何か
  • 内臓SDカードスロット

に限られてしまっており、割り切って考えてOKだったためです。(本当は良くない)

まあ、この記事を残しておけばいつでも復旧できるはずですし、イメージでバックアップを取れば十分でしょう…

手順

大まかに

  1. 起動ディスクにArchをインストール
  2. RAIDアレイを用意
  3. 本命のOSインストール
  4. kexecで起動

です。 今更Archのインストールなど説明する必要もないので2まで飛ばします。

ちなみに、今回はRAID1を使います。

RAIDアレイを用意

1
2
3
4
5
6
7
mdadm --zero-superblock /dev/sda
mdadm --zero-superblock /dev/sdb
mdadm --create --verbose --level=1 --metadata=1.2 --raid-devices=2 /dev/md0 /dev/sda /dev/sdb
mdadm --detail --scan >> /etc/mdadm.conf
mkfs.ext4 /dev/md0
mount /dev/md0 /var/disk
genfstab -U / > /etc/fstab

本命のOSインストール

debootstrapとかpacstrapとかで自由にインストールします。

systemd-nspawnと異なりAlpine Linuxなどの非systemd環境もインストール可能です。

1
2
3
4
pacstrap -K /var/disk base base-devel linux-lts linux-lts-headers linux-firmware mdadm nano sudo openssh
genfstab -U /var/disk > /var/disk/etc/fstab
arch-chroot /var/disk
mdadm --detail --scan >> /etc/mdadm.conf

ブートローダのインストールは不要です。 vmlinuzとinitramfsが/bootにあるようにします。

ただし、initramfs上のhookは忘れずに有効化します。 (/etc/mkinitcpio.conf内のHOOKSmdadm_udevを追加2

(実験)kexecで起動

踏み台OSにて

1
2
3
pacman -S kexec-tools
kexec -l /var/disk/boot/vmlinuz-linux-lts --initrd=/var/disk/boot/initramfs-linux-lts.img --command-line=root=/dev/md0 md=1,/dev/sda,dev/sdb rw rootwait nomodeset
systemctl kexec

私の環境特有なのかわかりませんが、kexecで起動するとHDMI1しか映像出力されずハマりました。

元々nomodesetでないと映像が出ないような不安定さがある環境なので何が悪いのか微妙な所です。。。

自動起動

  • /etc/systemd/system/boot-main.service

    [Unit]
    Description=kexec boot
    RefuseManualStart=no
    RefuseManualStop=yes
    
    [Service]
    Type=oneshot
    ExecStart=/usr/local/bin/boot-main.sh
    [Unit]
    Description=delayed kexec boot
    
    [Timer]
    OnBootSec=5min
    
    [Install]
    WantedBy=timers.target
    
  • /etc/systemd/system/boot-main.timer

    [Unit]
    Description=delayed kexec boot
    
    [Timer]
    OnBootSec=5min
    
    [Install]
    WantedBy=timers.target
    
  • /usr/local/bin/boot-main.sh

    1
    2
    3
    
    #!/bin/bash
    kexec -l /var/disk/boot/vmlinuz-linux-lts --initrd=/var/disk/boot/initramfs-linux-lts.img --command-line=root=/dev/md0 md=1,/dev/sda,dev/sdb rw rootwait nomodeset
    systemctl kexec
    

のようにファイルを作り

1
systemctl enable boot-main.timer

で有効化します。 この例だと5分後に自動で起動します。

おわりに

kexecを用いる事でRAIDからの起動を可能にしつつ、遠隔でのレスキュー環境を整える事ができました。

自宅サーバ勢でPCサーバな方如何でしょうか(笑)