【Linux】大容量デバイスにOSをインストールしたら起動できなかった件

こんにちは、キクです。

先日、物理ホストの流用をしてUbuntuをインストールした際に、OSが起動してこない事象に遭遇しました。

本記事では、OSが起動できなかった原因の調査や解消対応の中で学んだことを整理していこうと思います。

それでは、よろしくお願いします。

構成とエラー内容

本記事に直接的に関与した要素の構成としては以下の通りです。

今回の構成(抜粋)

OS:Ubuntu24.04

ストレージ:RAID10(約2.7TB×4本)

Ubuntuインストールの「Storage configration」は以下の状態でした。

FILE SYSTEM SUMMARY
 Mount Point :/
 SIZE:5.456TB
 TYPE:new ext4
 DEVICE TYPE:new partition of local disk

AVAILABLE DEVICES
 No available devices

USED DEVICE
 DEVICE:ローカルディスク(乱数)
 └ partition1 new, BIOS grub spacer
   SIZE:1.000M
 └ partition2 new, to be formatted as ext4, mounted at / 
   SIZE:5.456T

順調にインストールは完了し、いざ起動してみようとすると以下のエラーと共に起動失敗

error: attempt to read or write outside of disk `hd0`.
Entering resque mode…
grub rescue>

試したこと

1. レスキューモードでの復旧対応(失敗)

grub rescueにて以下のような復旧対応を試みましたが、結果としては失敗に終わりました。

grub rescue> ls
(hd0) (hd0,gpt2)  (hd0,gpt1)
grub rescue> ls (hd0)/
error: unknown filesystem.
grub rescue> ls (hd0,gpt2)/
./ ../ lost+found/ bin lib lib64 sbin bin.usr-is-merged/ boot/ cdrom/ dev/ etc/ [
home/ lib.usr-is-merged/ media/ mnt/ opt/ proc/ root/ run/ sbin.usr-is-merged/
snap/ srv/ sys/ tmp/ usr/ var/ swap.img
grub rescue> ls (hd0,gpt1)/
error: unknown filesystem.
grub rescue> set prefix=(hd0,gpt2)/boot/grub
grub rescue> set root=(hd0,gpt2)
grub rescue> insmod nomal
error: attempt to read or write outside of disk `hd0`.
grub rescue> normal
Unkown command `normal`.

元々のエラーに戻ってきてしまい解決できませんでした。

2. RAID設定時に小さな論理ドライブを作成してシステム用として割り当てる(成功)

どうしたものかと思い調べていると、以下のような情報を発見しました。

Ubuntuをインストールするときに4TBあるすべての領域を1つのパーティションにしたら grub rescue が出てきて Ubuntu が起動しなくなりました。

結論から言うとBIOSが古すぎて /boot を大きな領域に置くことができない不具合が原因でした。

対策としては Ubuntu をインストールするときに HDD の最初に 100 GB のパーティションを作り、そこに / (ルートディレクトリ)を置き、残りを別のパーティションにすることが必要でした。 私は、残りの大きな領域に /home をマウントするように設定して Ubuntu のインストールを行いました。

参考:Mathtodon(五味斎)

今回は5TBのローカルディスク(RAID)を使っているので「まさにこれでは!?」と感じました。

これを踏まえて、以下のようなストレージ構成に組み替えることで対応することにしました。

[変更前]
RIAD10
└ 論理ドライブ:5.456TB

[変更後]
RAID10
└ 論理ドライブ1:100GB
└ 論理ドライブ2:5.359TB

この状態で改めてUbuntuインストーラを実行すると、「Storage configration」は以下の状態で認識されました。

FILE SYSTEM SUMMARY
 Mount Point :/
 SIZE:5.359TB
 TYPE:new ext4
 DEVICE TYPE:new partition of local disk

AVAILABLE DEVICES
 DEVICE:ローカルディスク1(乱数)
 └ SIZE:100.000G

USED DEVICE
 DEVICE:ローカルディスク2(乱数)
 └ partition1 new, BIOS grub spacer
   SIZE:1.000M
 └ partition2 new, to be formatted as ext4, mounted at / 
   SIZE:5.359T

どうしても5TBでパーティションを作りたいのだろうか・・・。

しかし、このままだと最初と変わらないため、以下のように変更しました。

FILE SYSTEM SUMMARY
 Mount Point :/
 SIZE:99.997G
 TYPE:new ext4
 DEVICE TYPE:new partition of local disk

AVAILABLE DEVICES
 DEVICE:ローカルディスク2(乱数)
 └ SIZE:5.359T
 
USED DEVICE
 DEVICE:ローカルディスク1(乱数)
 └ partition1 new, BIOS grub spacer
   SIZE:1.000M
 └ partition2 new, to be formatted as ext4, mounted at / 
   SIZE:99.997G

上記のように100GBの論理ドライブをルートパーティションとして使う構成にしたことで、無事にOS起動まで可能になりました

なお、OS内部では各ディスクは次のように認識しました。

root@xx:~# lsblk
NAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
sda      8:0    0  100G  0 disk
└sda1    8:1    0  100G  0 part /
└sda2    8:2    0    1M  0 part
sdb      8:16   0  5.4T  0 disk

なぜ起動できなかったのかを考える

先にお伝えすると、僕の力不足もあり今回起動できなかった明確な原因の特定はできませんでした。
ただ、調査をする中でいろいろ学びが多かったので書き残しておきます。

今回の事象の主な原因は以下2つだったと考えました。

  1. BIOSバージョンが古かった
  2. パーティションが大きすぎた(5.0TB)

主なOSの起動方式としては「Legacy Boot」と「UEFI Boot」に大別できますが、BIOSのバージョンが古いことで前者の「Legacy Boot」しか選択できない状態でした。

そして、この「Legacy Boot」はMBRパーティションでしかOSを起動できないという特徴があります。

しかし、今回OS起動に失敗していた時の構成としては、MBRではなくGPTでパーティションが組まれていました。

GPTパーティションが組まれた要因のひとつとしては「パーティションが大きすぎた」ということが考えられます。。

RAID上では約5TBの論理ドライブをひとつだけ作成しており、OSインストール時もこの論理ドライブをそのまま1つのパーティションとして利用しました。
調べてみると、Ubuntuのインストーラはディスク構成から自動的にMBRかGPTを選択 するようです。

そして、以下の条件のどれかを満たすとデフォルトでGPTを採用するみたいです。

  1. ディスクが2TB以上
  2. ディスクがすでにGPTフォーマットされている
  3. UEFIブートモードでインストーラを起動している
  4. ディスクに既存のOS(Windowsなど)がGPTでインストールされていた

今回は5TBのディスクを使用しているため、上記1の条件に該当しています。
その結果としてUbuntuのインストーラが自動的にGPTを選択した可能性が非常に高いと考えられます。

改めてgrub rescueモードでlsコマンドを実行した結果を確認してみても、GPTでパーティションが切られていることが分かります。

grub rescue> ls
(hd0) (hd0,gpt2)  (hd0,gpt1)

メモ

MBRの場合は「hd0, msdosX」のように表示される

bios_grub領域

「じゃあBIOSがGPTパーティションを認識できないから起動できなかったのかー」と一旦は腑に落ちました。

しかし、100GBの小さなパーティションを切って正常に起動するようになった状態でパーティション情報を確認すると、以下のような結果が得られました。

root@xx:~# parted /dev/sda print
Model: LSI LSI (scsi)
Disk /dev/sda: 107GB
Sector size (logical/physical): 512B/4096B
Partition Table: gpt
Disk Flags:

Number  Start   End    Size    File system  Name  Flags
1       1049kB  2097kB 1049kB               bios_grub
2       2097kB  107GB  107GB   ext4

Partition Tableが「gpt」になっており、再びGPTパーティションで構成されていることが判明。

ただ、今回は正常に起動しているという。

「BIOSはGPTをブートデバイスとして認識しないんじゃないの!?」と混乱したのですが、もう少し調べてみると「bios_grub」というパーティションの存在に気付きました。

改めて確認すると、OSインストール時のパーティション設定時から確かにいました。

partition1 new, BIOS grub spacer
partition2 new, to be formatted as ext4, mounted at /
キク

細かくチェックしないで作業してしまっているなーと反省

bios_grubは「BIOSブートパーティション」とも呼ばれ、一般的にcore.imgのみが格納されるとのこと。
これを利用している場合にはGPTであってもBIOSから起動できる模様。

メモ

core.imgの役割は、/boot/grub/grub.cfgを読み込んでGRUBメニューでカーネルを選択できるようにすること

少し話が逸れますが、bios_grubのStartが0ではなく1,049KBになっているのが気になったので調べてみました。

  • GPTパーティションテーブルを使用すると、ディスクの先頭部分(0セクターから約1MB)はGPTのメタデータ領域として予約される
  • MBRの場合においても同様に先頭部分が利用される
    この領域は「保護MBR」と呼ばれるらしく、ブートシーケンスのStage1で利用する「最小限のコード」が格納される
  • Stage1の「最小限のコード」が後続の「core.img」を読み込み(Stage1.5)、その後grub.cfgを読み込むという流れ

上記のように0セクターから約1MBの領域は言わば「予約領域」のようになっているため、bios_grubについては約1,049KBから始まるように自動的に調整されるのだと理解しました。

LBA32制限

ここまでの調査の中で「bios_grubという仕組みがあるなら、5TBパーティションの時も問題なく起動できたのでは?」と思いました。

しかし、古いBIOSやRAIDコントローラにおいては「LBA32制限」というものに引っ掛かっている可能性があるとのこと。

LBAは「Logical Block Addressing」の略で、記憶メディア上のすべてのセクタに通し番号を付与し、その番号によって記録位置にアクセスする方式のことを指します。

LBA32は、32ビットのアドレス空間を使用するLBA方式であり、扱えるストレージ容量は以下のような計算で算出することができる。

LBA32

最大アドレス可能セクタ数:232 = 4,294,967,296 (約42億)

最大容量:4,294,967,296 × 512B = 約2TiB
※1セクタ = 512バイトの場合

従って、この制限(LBA32)があるとディスクの約2TB以降の領域が読み込めないということになります。

100GBパーティションを切って正常にOSが起動できる状態のときに、以下のコマンドでディスクの認識状態を確認してみました。

root@xx:~# fdisk -l /dev/sdb
Disk /dev/sdb: 5.36 TiB, 5892623826944 bytes, 11509030912 sectors
Disk model: LSI
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes

2TB以降の領域も認識しているように見えます。
物理構成は何も変えていないので、約5TBパーティション構成(OS起動失敗)時もきちんと2TB以降の領域を認識できていたのではないかと思われます。

しかし、上記のようにOS起動後にディスクの2TB以降の領域を認識できているからと言って、OS起動時(GRUBの処理内)でも同様に2TB以降が読み取れる訳ではないみたいです。

2TB以降を認識する上では「LBA48」というものをサポートしている必要がありますが、OS起動後はOS(Linuxカーネル)がLBA48をサポートしているカーネルモジュールのストレージドライバをロードするため、基本的には2TB以降の領域も認識できるそう。

しかし、Legacy BootにおいてGRUBはBIOS経由でストレージアクセスを行うため、BIOS自身がLBA48をサポートしていなければ2TB以降の領域は認識できない。

また、BIOS自身がLBA48をサポートしていても、BIOSはOS起動時にRAIDカードのBIOSを仲介することでディスクにアクセスします。
そのため、RAID_BIOSがLBA48をサポートしていないと2TB以降を認識できない状況が発生することもあるそうです。(ややこしい)

BIOSがLBA48をサポートしているかを確認する方法のひとつとして以下のコマンドがありました。

root@xx:~# hdparm -I /dev/sda |grep LBA
root@xx:~#

「LBA48 supported」と表示されれば明確だったのですが、今回は残念ながら何も表示されませんでした。
ディスクがRAIDコントローラを経由して接続されている場合、hdparmでは直接ディスク情報の取得ができずに「何も表示されない」ことがあるようです。

また、hdparmは主にSATAデバイス用のツールであり、NVMeやSASディスクには対応していないため、この場合も「何も表示されない」となるそうです。

今回はRAIDカードを使用しているし、ディスクもSASということもあり期待した結果は得られませんでした。

LBA48について

LBA32が32ビットのアドレス空間を使用していたのに対し、LBA48では48ビットのアドレス空間を使用する拡張版のLBA方式となる。

これにより、同じく1セクタ=512バイトとした場合の最大容量は約128PiBとかなり大きくなっている

LBA48

最大アドレス可能セクタ数:248 = 281,474,976,710,656 (約281兆)

最大容量:281,474,976,710,656 × 512B = 約128PiB
※1セクタ = 512バイトの場合

整理と推察

ここまでの内容から、以下が原因ではないかと考えました。

  • BIOS(RAIDカード含む)が古くて、OS起動時に2TB以降の領域を認識できない構成だった
  • 単一の5TBパーティションにしたことで、/boot/grub/grub.cfgが2TB以降に配置されてしまい認識できなかった

しかし、ここで大きな問題に気付いてしまいました。

今回のerror: attempt to read or write outside of disk hd0.」というエラーは、core.imgが正しく読み込めなかった場合に発生することが多いということ。

もしgrub.cfgが見つからなかった場合には「error: file not found」や「error: no such device」のような異なるエラーが表示されるみたいです。
そのため、「grub.cfgが2TB以降に配置されちゃって認識できなかったから起動できなかったのかー」と思っていましたが違う可能性が高そうです。

ただ、core.imgはbios_grub領域に配置されて読み込める状態だっただろうし、なんで起動できなかったのかなというのが正直なところ。

可能性としては、Ubuntuインストーラにより自動的に実行される「grub-install」においてcore.imgそのものが適切に書き込まれていなかったり、bios_grubの配置がおかしかったということも考えられます。

仮にcore.imgが2TB以降に配置されていた場合、先述の通りBIOSから2TB以降を認識できずに結果としてエラーに繋がった可能性もあるので。

しかしながら、これはあくまでも推察であり、最初にも触れたとおり正確な原因特定まではできなかったです。

悔しい。

備忘録

これ系の話題の時によく登場する「MBRの2TB制限問題」がありますが、今回はこの問題は関係ない認識

先述の通り、MBRでパーティションを組んだ場合には先頭の512Bの領域にブートローダ(GRUBなど)やディスクのパーティション情報(パーティションテーブル)が格納される
MBRのパーティションテーブルでは最大4つのプライマリパーティションを管理できるが、仕様の関係で最大2TBまでしか認識できない

そのため、例えば5TBのディスクにMBRでパーティションを切った場合、2TB以降の領域は認識できず、実質「無駄な領域」になってしまう
ただ、今回は「GPTパーティション」が自動作成されているので、「MBR2TB制限問題」は関与していないと判断

-Linux
-