iSCSIブートで苦戦した記録

目次

iSCSIブートでお遊び環境を作ろうと思ったら難しくて、モヤモヤしながら代替策をとりまくってとりあえず起動させたメモ

背景

お遊び用に壊したりスナップショットを取ったり複製したりが自由にできるWindowsの物理マシンが欲しかったので、iSCSIブートを試してみた。

綺麗に上手くできた環境のまとめではなく、妥協に妥協を重ねて何とか起動させたメモ。

苦戦

iSCSIターゲット (サーバ)

自宅にはWindows Serverがあるので、iSCSIターゲットサーバ機能を有効化して仮想ディスク(VHDXファイル)をiSCSIで公開してみたが、自分の要件にはあわなかったため、Hyper-VでLinuxサーバを立ち上げてそのサーバをiSCSIターゲットサーバとすることにした。

具体的には、Windows ServerのiSCSIターゲットサーバでは、SCSIのUNMAPを有効化させることができないようで、HDDとして認識されるためクライアント側のOSをWindowsとした時に自動デフラグが走ってしまったり(PowerShellでがんばってみたが無効化できなかった…)、UNMAPができないためシンプロビジョニングのVHDXファイルを使っている際に最適化(縮小)させる時の作業が面倒だった。

Linuxサーバ側の準備は単純で、Ubuntu 26.04の場合は以下のような感じだった。

公開したいディスクのpathを確認

ls -al /dev/disk/by-path/

必要なパッケージのインストールと設定

sudo apt install targetcli-fb
sudo targetcli
cd /backstores/block/
create name=<backend_name> dev=/dev/disk/by-path/.....

cd <backend_name>
set attribute is_non_rot=1
set attribute emulate_tpu=1
set attribute emulate_tpws=1
set attribute unmap_zeroes_data=1

cd /iscsi
create iqn.<target iqn>

cd iqn.<target iqn>/tpg1
portals/ create
luns/ create /backstores/block/<backend_name>
acls/ create <initiator iqn>

set attribute default_cmdsn_depth=128

saveconfig
exit

Windows 11 (イニシエーター/クライアント)

iSCSIディスクに DISM /Apply-Image でWindows 11を展開して、 DISM /Add-Driver でNICのドライバを追加してみたが、Windowsへ制御が移った段階でiSCSIターゲットへの接続が上手く行えず、Inaccessible_Boot_Device (0x7B) になってしまった。

せっかくWindows Serverがあるので Windows Deployment Services (WDS) を使おうと思ったが、WDSのサポートは既に終了しておりWindows 10時代のboot.wimを使うなど、ちょっと面倒くさそうだったので今回は見送り。いつか実施してみたい。

結果的に、適当なディスクをPCにつないで普通にWindows 11を起動、NICをインストールした上でP2VによるVHDX化をすることで起動できた。

NICのiSCSIブート機能

NICはIntel X540を利用しているため、NICの機能で直接iSCSIブートができるらしいが、民生品のマザーボードを使っているせいかファームウェアを焼いてもオプションROMを焼いても、iSCSIブートのconfigを出すことができなかった。

そこで、今回は UEFI HTTP Boot でiPXEを立ち上げて、そこからiSCSIブートを行うことにした。

Ubuntu 26.04の場合は以下のような感じだった。

必要なパッケージのインストール

sudo apt install kea-dhcp6-server nginx

/etc/kea/kea-dhcp6.conf はだいたいこんな感じ。なお、IPv6でUEFIブートをする場合は、DHCPv6サーバからアドレスの払い出しも行う必要がある。ただし、RAにMフラグを立てる必要はない。

{
"Dhcp6": {
    "interfaces-config": {
        "interfaces": [ "eth1" ]
    },
    "option-data": [
        {
            "name": "dns-servers",
            "data": "fe80::1"
        }
    ],
    "subnet6": [
        {
          "id": 1,
          "subnet": "fd00::/64",
          "interface": "eth1",
          "pools": [
            {
              "pool": "fd00::101-fd00::1ff"
            }
          ]
        }
    ],
    "client-classes": [
      {
        "name": "uefi HTTP Clients",
        "test": "substring(option[16].hex,6,21) == 'HTTPClient:Arch:00016'",
        "option-data": [
          {
            "name": "vendor-class",
            "csv-format": false,
            //"data": "343, HTTPClient"
            "data": "00000157000a48545450436c69656e74"
          },
          {
            "space": "dhcp6",
            "name": "bootfile-url",
            "code": 59,
            "data": "http://[fd00::100]/ipxe/x86_64-sb/snponly-shim.efi"
          }
        ]
      }
    ],
    "loggers": [
    {
        "name": "kea-dhcp6",
        "output-options": [
            {
                "output": "stdout",
                "pattern": "%-5p %m\n",
            }
        ],
        "severity": "INFO",
        "debuglevel": 99
    }
  ]
}
}

nginxは初期設定のまま、 /var/www/html の下にiPXEのバイナリ https://github.com/ipxe/ipxe/releases/latest を配置する。

今回は Secure Bootを有効化したまま起動するため、 x86_64-sb の下のバイナリを利用した。

自動起動できるように、バイナリと同じディレクトリに boot.ipxe.cfg を用意する。

set keep-san 1
sanboot iscsi:[fd00::100]::::iqn.<target iqn>

Windows 11からL2でiSCSI接続ができなくなる

推測が混じっているので別OSをiSCSIブートしてみて挙動を確認しようと思っている部分。

恐らくWindows 11のセキュリティ機能 コア分離 (メモリ整合性) が影響していると思うが、ブート中にiSCSIターゲットへ接続するときのMACアドレスが、物理NICのアドレスではなくHyper-VっぽいMACアドレスになる様子だった。 結果として、iPXEの段階では全く問題がないのに、Windowsへ制御が移った段階でiSCSIターゲット側(Ubuntu 26.04)が正しい宛先(Windows 11)へiSCSIの応答を送信できず、Inaccessible_Boot_Device (0x7B)になってしまう問題が発生した。

回避方法は(納得できない方法だが)間にUbuntu 24.04を挟んでL3接続にすることで正常に接続できるようになった。

ルーティングしているマシンがUbuntu 24.04で、iSCSIターゲットのUbuntu 26.04とは異なるため、Ubuntu 26.04側の問題という可能性もある気はする。

まとめ

ということでいろいろ苦労しながら、妥協を重ねながら、無事にiSCSIブートができるようになった。 まだまだ試したいことは色々あるので遊ぼうと思うが、ひとまず安定しているため、一旦メモを書いてみた。