initramfs: 仕組みとツール
(initramfs-tools, dracut, etc.)
        for TokyoDebian勉強会, 2011/4/16




                    @tyamadajp
initramfsとは?
・Linuxが実システム起動前に
 稼動させるpreboot環境

・起動に必要(例:/のデバイス
 認識)なドライバロード等をする

・とはいえ、普通のLinux環境なので
 様々な事に活用可能(されている)
initramfsとは?(具体的に)
・単にLinux環境をcpioで固めて、
 gzip等で圧縮したもの

・この内容がramfs上に展開され、
 中の/initが起動時に呼ばれる

・initの中身は色々
 → Debianではシェル(busybox)
   スクリプト → 拡張が簡単!
        ※nashとかいう酷い物体を使う可哀想な
         環境も世にはありました・・・
典型的な/initの流れ
1./proc/cmdlineから引数を読む
2.LAN/disk等のデバイスを有効化
3.MD/LVM/cryptfsなどの論理構成を
  さらに積み上げる
4.root=...で指定のデバイスを
  マウント
5.そこが/になるようmount+chroot
6.最後にinit=...での指定を起動
initramfsの中身
・普通のLinux環境を、「cpio -o -H
 newc」で固めるだけ(圧縮は任意

・が、普通に作ると巨大に・・・
 →レスキュー系では40MB gzipとか

・メモリ消費は一時の話だからOK。
 でも、起動が遅くなるのはマズー

→結局、busyboxやスクリプトで
 コンパクトにまとめる努力が必要
initramfs-tools and dracut
・カスタマイズ等、「まっとうな」
 initramfsを構築するツール
・イメージの生成処理と起動時の
 フック呼び出しを整理している
 →これがないと、手製initramfsに
  なって管理が面倒
 →生成時に独自ツールを含めたり、
  特殊なブート処理をさせられる

  ※最後はcpioするだけなので、initrd builderは
   他にも世にたくさんありますが、この2つはお勧め
initramfs-tools
・Debianでの定番
=特徴=
・機能分解/拡張ポイントが豊富で
 柔軟に高機能なinitramfsを生成
・多様なブート環境を作れる。また、
 update-initramfsと組み合わせて
 ほぼシステムを自動管理

例:カーネルを更新した→自動でu-i
例:mdadm/lvm/cryptsetup等を入れた
  →自動的にinitrdに組み込まれる
活用1:レスキュー能力強化
・kernel break=<stage> で各起動
 段階のpreboot環境のshに抜ける
  ・<stage>=top/modules/premount/mount/
       mountroot/bottom/init/...
  ・自由定義可能なので、探すならmaybe_breakでgrep
・この時、復旧用コマンドがあると
 便利。netboot環境とセットが○

=方法=
入れたいコマンドをコピーする
スクリプトをフックフォルダに入れる
活用1:/etc/initramfs-tools/hook/
 $ cat cttyhack
①#!/bin/sh

 case "$1" in
 prereqs) echo ""; exit 0;;           ②
 esac

 . /usr/share/initramfs-tools/hook-functions
 copy_exec /usr/local/bin/cttyhack /usr/bin
 copy_exec /usr/bin/setsid         /usr/bin

 exit 0
 ③                     ④
 →initramfs環境でjob control有効化
活用2:起動処理の拡張
・スクリプトを登録すると、主要な
 起動ポイントで呼び出してくれる
 ・init-top→init-premount→(local|nfs)-top
   →(local|nfs)-premount→(local|nfs)-bottom
    →init-bottom
  ・完全把握したい時は grep -r run_script


=方法=
/etc/initramfs-tools/scripts/*/に
スクリプトを置くだけ
活用2:起動処理の拡張(具体例)
例:scripts/init-bottom/rootaufs

・root deviceにtmpfsを重ねて
 rootfsをすり替える
・システムは同じように上がるが
 書き込みは全部tmpfsに行く
・悪い予感がするアップグレードに
・ファイル一切無変更でDVD/USBに
 コピるだけで稼動
        ※見てないけどたぶんDebianLiveと同じ
rootaufs(1)
#!/bin/sh
case "$1" in
prereqs) exit 0;;
esac
. /scripts/functions

for p in    `cat /proc/cmdline`; do
     case   "$p" in
     *=*)   eval $p;;
     *)     eval $p=1;;
     esac   2> /dev/null
done
test -n "$aufs" || exit 0
maybe_break aufs
rootaufs(2)
modprobe -q aufs || panic "[AUFS] Failed to..."
mkdir -p /ro /rw /aufs

rw_type=$(IFS=:; set -- $aufs;          echo "$1")
rw_opts=$(IFS=:; set -- $aufs;          echo "$2")
rw_path=$(IFS=:; set -- $aufs; shift 2; echo "$*")

case "$rw_type" in
nfs)
   nfsmount          -o   ${rw_opts:=rw} 
   ${rw_path:=none} /rw   || panic "[AUFS] Failed..."
   ;;
*)
   mount -t $rw_type -o   ${rw_opts:=rw} 
   ${rw_path:=none} /rw   || panic "[AUFS] Failed ..."
   ;;
esac
rootaufs(3)
## allocate space for xino
mkdir -p /rw/.aufs
mount -t tmpfs xino /rw/.aufs
## unionize /aufs = /ro + /rw
mount --move $rootmnt /ro
mount -t aufs -o dirs=/rw:/ro=ro,
xino=/rw/.aufs/.xino none /aufs || panic "..."
## switch to root-as-aufs
mkdir -p /aufs/ro /aufs/rw
mount --move /ro /aufs/ro
mount --move /rw /aufs/rw
mount --move /aufs $rootmnt
...
イメージ作成時の処理内容/mkinitramfs
1.miniroot用の空フォルダを作る

2.$base/hooks/* を呼ぶ(中でコピーしたりする)
 ※$base={/usr/share,/etc} 以下同様

3.$base/{init,scripts,conf.d} をコピー

4.$base/modules の指定モジュールをコピー

5.必須コマンドや基本モジュールセットをコピー

6.最後に cpio + ${COMPRESS:=gzip} で生成

他にもupdate-grub連携など生cpio+gzipにはない
細かい処理
dracut - RedHatによるパク^H^H回答
・RedHat系は従来イマイチだったが、
 これで自分的には名誉挽回
・ファイル名以外はi-tとほぼ同様

  動作設定:/etc/dracut.conf
イメージ生成:
 /usr/share/dracut/modules.d/*/
 {check,install,installkernel}
起動時フック:
 上のinstall*の中でスクリプト等を
 inst_*シェル関数で登録する
dracut構成(続)
・/init
 →/usr/share/dracut/modules.d/99base/initに

・起動時ブレークポイント(rdbreak=*)
 →cmdline/pre-udev/pre-trigger/initqueue/
  pre-mount/mount/pre-pivot

・起動時フック
 →emergency/cmdline/pre-udev/pre-trigger/
  pre-mount/pre-pivot
initramfs-tools vs dracut(1)
・同じ。でも初期状態が(Debian|Redhat)的

=比較(初期状態で)=
使い勝手:i-t > dracut
・i-tはシステム側と管理者側のファイルを
 自動集約するので分けて保持しやすい
・dracutは一箇所しか見ず、dracut.confでは
 指定するだけなので勝手が落ちる
・i-tは起動時フックしたければ、スクリプト
 書いてhooks/に置くだけ
・dracutはモジュールを登録して、その
 モジュールにスクリプトをコピーさせる
initramfs-tools vs dracut(2)
=比較=
モジュール度の高さ:dracut > i-t
・i-tはhooks/*とscripts/<stage>/*と分散し
 セットで管理しにくい
・dracutはmodules.d/<mod>/*に集中配置で、
 関係ファイルの把握が楽

処理の読みやすさ:dracut>i-t
・i-tはupdate-grub連携などDebian的機能も
 埋め込まれてるので、見通しが落ちる
・i-tの方が便利だが、単独の独自initramfs
 開発ツールとしてはdracut?
おまけ:initramfs TIPS
・initramfsはカーネルにも埋め込めるので、
 initrd=非対応でも使える
 →埋込はarch依存のもある(ようだ)が、
  see CONFIG_INITRAMFS_SOURCE
 →埋込initramfsにinitrd=がマージされる

・initramfsは複数ロードできる、上書き用
 initramfsを0+の後に連結でOK
 →ローダによるがinitrd=foo,bar,bazなど

・これ絡みのLinuxの互換性維持の努力に涙
 →initrd=<non-initramfs-image>の扱い
 →rootwait=やrootdelay=の扱い方とか

Introduction to Initramfs - Initramfs-tools and Dracut