本業に忙殺され長らく(2年ほど)本ブログの更新をサボってしいました。
その間にも彼此、コメントでの質問がたまっていましたので、少しずつ回答記事を作成していこうかと思っています。かなり急いでコメントされた方もいるみたいですが、誠に恐縮ですが今更の回答になってしまうことをお許しください。
さて、lvm関連での質問で、OSを再起動するたびにデバイスマップ名がコロコロ変更されてしまう件に関して回答いたします。実際に口頭でやり取りしたわけではないので、あくまでも憶測になりますが、テキスト文章から察するに回答としては、「initramfs」ファイルの再作成が必要となります。詳しくは後述します。恐らく、ディスクの容量が足りずに後から外部ストレージ側のLUNを追加されていませんでしょうか?
再起動後にデバイスマップが変わる原因
Linux OSで外部ストレージからLUN(Logical Unit Number)を追加し、再起動後にデバイスマップが変わる原因は、主に以下の要因によるものです。
デバイスマップが変わる原因
過去の経験から、再起動時にデバイス名が入れ替わる代表的な(ケース)原因をいくつか挙げてみます。(どれも実際に筆者が過去にぶち当たった障害です。)
恐らく下記ケースの中にある「ストレージ構成の変更」が原因と思われます。
ケースの具体例
- カーネル関連の変更
・新しいカーネルをインストールした場合
カーネルをアップデートすると、対応する新しいinitramfsが必要です。
・カーネルモジュールの変更
カーネルモジュール(例: ファイルシステムなど)を追加・削除・更新した。 - ストレージ構成の変更
・ディスクやパーティションの追加・変更
ブートプロセスに影響するディスク、パーティションを変更した。
・マルチパス(multipath)の設定変更
SAN(ストレージエリアネットワーク)環境でmultipath.confを編集した。 - ブート構成の変更
・「/etc/fstab」の変更
UUIDやLABELを利用してファイルシステムを指定し直した。
・LVM(論理ボリューム管理)の変更
ルートファイルシステムがLVM上にあるLVMの構成を変更した。
・ファイルシステムの変更
新しいファイルシステム(例: XFS, ZFSなど)をルートパーティションに使用した。 - 特殊なケース
・カーネルパラメータの変更
ブートローダー(GRUBなど)でカーネルパラメータを変更した。
・システムの復旧作業
initramfsが破損している場合や、システムが正常に起動しない。
通常外部ディスクのLUN領域は、余裕を見てサイズを切り出し、未使用領域は後の拡張分として切り出しておくのが一般的です。ただし、昨今は予算の関係から必要と思われるサイズギリギリでLUNを切り出し、不足分はその都度追加する切り張りプロジェクトが増えている気がします。
上記の理由などからOS起動段階で読み込まれるイメージファイル内のデバイス構成情報と起動後にMODPROBEによって認識されるデバイス構成情報に差が発生しているのではないかと思われます。
LinuxOSがデバイスを認識するプロセス
特に上記の「1. カーネル関連の変更」「カーネルモジュールの変更」にフォーカスします。これは主に外部ディスクの容量が足りずに後から外部ストレージ側のLUN(スライス)を追加した場合によく起こる障害です。(実際これ系の質問が一番届いていました。)
OSが外部デバイスを認識する順序は下記のとおりです。
外部デバイス認識順序の「ブートローダが「カーネル」イメージをロード」の時、内部ではカーネルがイメージファイルを読み込み、小さなLINUXを展開します。(「initramfs」とは、この時カーネルから読み込まれるイメージファイルの正体です。)
展開された小さなLINUXが起動してカーネルが起動した後、「systemd(旧/sbin/init)」が実行され、正式なLINUXシステムが起動します。狭義の"Linux"とは、このカーネル部分のみを指しています。一連の処理を終えて、いよいよLinuxが立ち上がります。
なぜこのような煩わしい仕組みが採用されているかは、昨今のOSシステムの肥大化に伴い、システム起動までに必要な時間が長くなる傾向にあります。そこで予め小さなLINUXを内部で立ち上げ、システム起動までの時間を短く見せかける必要があるためです。
正式なLINUXが起動後、「MODPROBE」モジュールが実行され始めて最新のデバイス情報が認識されます。「initramfs:イメージファイル」の中身は、初期構築時に作成され自動で更新することはありません。その後、新たなデバイスの追加が発生した場合は「initramfs」を最新の情報を反映させるため再作成する必要があるのです。
Linuxのブートストラップで読み込まれるイメージ
initramfsは、Linuxシステムが起動する際に非常に重要な役割を果たし、カーネルがハードウェアを認識し、必要なドライバやツールを提供するために使用されます。ブートプロセスの初期段階でシステムが正しく動作するために欠かせない部分です。
- カーネル起動
Linuxカーネルがシステムのブートプロセスを開始します。
- initramfs実行
小さなLinux環境がカーネルによって立ち上がります。この環境は、構築時の必要なドライバやツール情報を含んでおり、各種デバイスとの接続を行います。
- ドライバ提供
initramfsは、ハードウェアデバイスを操作するためのドライバを提供します。これにより、システムは周辺機器と通信できるようになります。
- ファイルシステムの準備
必要なファイルシステムがマウントされ、システムが正常に動作するための準備が整います。
- システム初期化
システムの初期化が行われ、必要なサービスやプロセスが起動されます。
- ルートファイルシステム切り替え(正規Linux)
最後に、initramfsから正規のLinuxルートファイルシステムに切り替えられ、完全なLinux環境が立ち上がります。
initramfsとは
initramfsはLinuxシステムの起動において不可欠な役割を果たしており、ハードウェアとの接続やファイルシステムの準備を行うことで、スムーズなブートプロセスを実現しています。
1. initramfsとは何か?
- 初期RAMファイルシステム(initramfs)は、Linuxカーネルが起動する際に、システムが必要とする初期的なドライバやツールを含む、一時的なファイルシステムです。通常、initramfsは圧縮されたアーカイブ形式(例:initramfs.img)として提供され、システムメモリ(RAM)に展開されます。
2. 役割と目的
- カーネルのサポート: initramfsは、カーネルがディスクを正しく認識するために必要なドライバを提供します。これにより、カーネルがブート時にハードウェアやファイルシステムにアクセスできるようになります。
- ファイルシステムの準備:
ルートファイルシステム(通常はHDDやSSDにある)をマウントするための準備をします。これが完了すると、initramfsは通常のファイルシステムに切り替わります。 - システムの初期化:
initramfsは、カーネルが起動する前に必要なツール(たとえば、ディスクのマウント、LVMやRAIDの設定など)を実行します。
3. initramfsが使用される場面
- 新しいハードウェアのサポート:
特定のハードウェアを認識するためのドライバを提供する。 - 暗号化されたディスク:
例えば、LUKS(Linux Unified Key Setup)で暗号化されたディスクを復号化する際に使用されます。 - 特殊なストレージ構成:
RAIDやLVM、ネットワークブートなど、複雑なストレージ設定を行う際にも使用されます。
4. 起動プロセスとの関係
- カーネル起動:
カーネルがロードされ、initramfsがメモリに展開されます。 - 2.initramfsの実行:
必要なドライバや設定を実行し、最終的にルートファイルシステムをマウントします。 - 3.ルートファイルシステムへの切り替え:
initramfsが終了し、実際のルートファイルシステムが使用されるようになります。
5. initramfsとinitrdの違い
- initramfsとinitrd(Initial RAM Disk)は似たような役割を持ちますが、initramfsはより新しい技術で、initrdよりも柔軟で効率的に動作します。
initramfsの再作成手順
initramfsの再作成は、ストレージデバイス関連の初期化プロセスに関わる重要な変更を適用するために必要な場合があります。設定後に予期しない動作を防ぐため、変更内容を正確に理解し、適切に再作成するようにしてください。
step
1現在のinitramfsの確認
現在の「initramfs」を確認します。「initramfs」は「/boot/」は以下に作成されています。
ls -l /boot/initramfs-$(uname -r).img
cp -ip initramfs-$(uname -r).img initramfs-$(uname -r).img_$(date +%Y%m%d)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
[root@job01 boot]# cd /boot [root@job01 boot]# ls -l /boot/initramfs-$(uname -r).img -rw------- 1 root root 18365340 Jul 14 2022 initramfs-3.10.0-1160.71.1.el7.x86_64.img [root@job01 boot]# cp -ip initramfs-$(uname -r).img initramfs-$(uname -r).img_$(date +%Y%m%d) [root@job01 boot]# ------------------------------------------------- [root@job01 boot]# ls -l drwxr-xr-x. 3 root root 4096 Nov 25 2020 efi drwxr-xr-x. 2 root root 4096 Nov 25 2020 grub drwx------. 5 root root 4096 Jul 14 2022 grub2 -rw------- 1 root root 18365340 Jul 14 2022 initramfs-3.10.0-1160.71.1.el7.x86_64.img -rw------- 1 root root 18365340 Jul 14 2022 initramfs-3.10.0-1160.71.1.el7.x86_64.img_20241130 👈 バックアップファイル [root@job01 boot]# ------------------------------------------------- [root@job01 boot]# rm initramfs-3.10.0-1160.71.1.el7.x86_64.img rm: remove regular file ‘initramfs-3.10.0-1160.71.1.el7.x86_64.img’? y [root@job01 boot]# ------------------------------------------------- [root@job01 boot]# ls -l drwxr-xr-x. 3 root root 4096 Nov 25 2020 efi drwxr-xr-x. 2 root root 4096 Nov 25 2020 grub drwx------. 5 root root 4096 Jul 14 2022 grub2 -rw------- 1 root root 18365340 Jul 14 2022 initramfs-3.10.0-1160.71.1.el7.x86_64.img_20241130 |
※ 思わぬ事故を防ぐために必要に応じてバックアップを取得してから実行してください。
「initramfs」の上書き再作成は怒られてしまうため、一旦現在の「initramfs」ファイルを削除してから再作成コマンドを実行します。
step
2再作成コマンドの実行
Linuxでは、各カーネルバージョンに対応したinitramfsイメージが/bootディレクトリに保存されています。
末尾に$(uname -r)が付いている理由は、現在使用しているカーネルバージョンを動的に取得し、適切なバージョンに対応するinitramfsを再作成するためです。
- RHEL/CentOS系
dracut -f /boot/initramfs-$(uname -r).img $(uname -r)
1 2 |
[root@job01 boot]# dracut "initramfs-$(uname -r).img" $(uname -r) [root@job01 boot]# |
特に問題がなければ、イメージファイルの作成ご、プロンプトが帰ってきます。
すでに同じカーネルバージョンが存在する状態でオーバーライド(上書き)しようとすると怒られます。
1 2 3 4 5 6 7 |
[root@job01 boot]# dracut "initramfs-$(uname -r).img" $(uname -r) Will not override existing initramfs (/boot/initramfs-3.10.0-1160.71.1.el7.x86_64.img) without --force Broadcast message from systemd-journald@job01 (Fri 2024-12-06 13:12:24 JST): dracut[27105]: Will not override existing initramfs (/boot/initramfs-3.10.0-1160.71.1.el7.x86_64.img) without --force Message from syslogd@job01 at Dec 6 13:12:24 ... dracut:Will not override existing initramfs (/boot/initramfs-3.10.0-1160.71.1.el7.x86_64.img) without --force [root@job01 boot]# ls -l |
- Debian/Ubuntu系
update-initramfs -u -k $(uname -r)
step
3変更を確認
コマンド実行後、作成された「initramfs」のカーネルがマシンのカーネルと一致していることを確認します。
ls -l /boot/initramfs-$(uname -r).img
1 2 3 |
[root@job01 boot]# ls -l /boot/initramfs-$(uname -r).img -rw------- 1 root root 18364187 Dec 6 13:14 /boot/initramfs-3.10.0-1160.71.1.el7.x86_64.img [root@job01 boot]# |
step
4再起動
カーネルの更新が必要なため、必ずOSの再起動を行なう必要があります。
reboot
※実行する場合は、必ずバックアップファイルを作成してからコマンドを実行してください。
ココに注意
- dracutやupdate-initramfsでエラーが発生した場合、設定ファイル(例:/etc/fstab, multipath.conf, udevルール)を再確認してください。
- /etc/fstabに誤った設定がある場合、ブートプロセスが停止する可能性があるため、特に注意が必要です。
initramfsの中身について
lsinitrdコマンドを実行すると、kernelディレクトリ内のファイル一覧が表示されます。Dracutツールを使って作成されたinitrd(またはinitramfs)の場合、次にモジュールが表示され、その後でinitrdに含まれているファイルがリストされます。もしモジュールの後に表示されるファイル名が不要な場合、「-m」(または--mod)オプションを指定することで、それを省略できます。
initramfsに組み込まれたモジュール一覧を表示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
[root@job01 boot]# lsinitrd -m Image: /boot/initramfs-3.10.0-1160.71.1.el7.x86_64.img: 18M ======================================================================== Early CPIO image ======================================================================== drwxr-xr-x 3 root root 0 Dec 6 13:14 . -rw-r--r-- 1 root root 2 Dec 6 13:14 early_cpio drwxr-xr-x 3 root root 0 Dec 6 13:14 kernel drwxr-xr-x 3 root root 0 Dec 6 13:14 kernel/x86 drwxr-xr-x 2 root root 0 Dec 6 13:14 kernel/x86/microcode -rw-r--r-- 1 root root 36864 Dec 6 13:14 kernel/x86/microcode/GenuineIntel.bin ======================================================================== Version: dracut-033-572.el7 dracut modules: bash nss-softokn i18n network ifcfg drm plymouth kernel-modules qemu rootfs-block terminfo udev-rules biosdevname systemd usrmount base fs-lib microcode_ctl-fw_dir_override shutdown ======================================================================== [root@job01 boot]# |
例えば外部ストレージからLUNを「Multipath」モジュールを使ってOSへ接続している場合、上記の「dracut modules:」一覧配下に「Multipath」が出力表示されます。
initramfsにあるファイルの内容を表示
1 2 3 4 |
[root@job01 boot]# lsinitrd -f /etc/conf.d/systemd.conf systemdutildir="/usr/lib/systemd" systemdsystemunitdir="/usr/lib/systemd/system" systemdsystemconfdir="/etc/systemd/system" |
上記はイメージファイル中の「/etc/conf.d/systemd.conf」を覗いています。
念押しでもう一度伝えます。
LinuxOSを起動する際に外部デバイス認識順序の「ブートローダが「カーネル」イメージをロード」をロードします。内部ではカーネルがイメージファイルを読み込み、小さなLINUXを展開します。(「initramfs」とは、この時カーネルから読み込まれるイメージファイルの正体です。)展開された小さなLINUXが起動してカーネルが起動した後、「systemd(旧/sbin/init)」が実行され、正式なLINUXシステムが起動します。
上記の例は、最初に展開される小さなLinuxの中身です。ここで言う小さなLinuxと、この後、起動される正式なLINUXシステムのデバイス情報間の誤差が原因でデバイス名が変わってしまうのです。