先日DHCPとmatchboxというOSSを利用してNetbootを行ったので、その時のメモを残しておきます。
前提として私はネットワーク初心者ですので、誤りがある場合は優しく指摘していただけると助かります。
また一般的にはNetbootを行う際はDHCPによるIPの払い出しは行わないと思います...。
実現したいこと
物理マシンの電源を入れてしばらく待つと自動でUbuntu Serverがインストールされて利用可能状態になっていること
環境について
今回は学習目的(興味本位)で、物理マシンと仮想マシンの両方で同一手法によるNetbootを試してみました。
基本的にここで説明している手順は実験環境2で利用したものになっています。(IPアドレスなど)
実験環境1 (物理マシン)
- Thinkpad 2台(研究室の備品を借りたため執筆時に手元にないため型番はわかりません...)
ネットワークアドレスを192.168.10.0/24とし、サーバー役に192.168.10.150を割り当てました。
サーバ役にはOSとしてUbuntu Desktop 22.04を用いました。
実験環境2 (仮想マシン)
ハイパーバイザーとしてProxmoxを利用し、そのうえにVMを2つ立てて検証しました。
- DHCPサーバ(10.10.10.12/24)
- OS: Ubuntu Server 22.04
- CPU: 4 cores
- RAM: 4GB
- HDD: 32GB
- クライアント(dhcp)
- CPU: 4 cores
- RAM: 6GB
- HDD: 32GB
DHCPサーバを準備する
DHCPサーバーとしてisc-dhcp-serverを利用しました。
インストール
以下のコマンドでインストールしました。
$ sudo apt install -y isc-dhcp-server
設定
dhcpd.conf
を作成し、以下のように記述しました。
$ nano dhcpd.conf
DHCPARGS="ens18";
option domain-name-servers 8.8.8.8;
default-lease-time 600;
max-lease-time 7200;
subnet 10.10.10.0 netmask 255.255.255.0 {
range 10.10.10.10 10.10.10.200;
option routers 10.10.10.254;
option broadcast-address 10.10.10.255;
if exists user-class and option user-class = "iPXE" {
filename "http://10.10.10.12:80/boot.ipxe";
} elsif substring(option vendor-class-identifier, 0, 9) = "PXEClient" {
filename "undionly.kpxe";
}
}
コンフィグファイルについては、多少のネットワークの知識があれば読み解けるようになっていると思います。
また、今回はBIOSのみを想定しています。UEFIの場合はもう少し別の設定を入れる必要があります。
if exists user-class and option user-class = "iPXE" {
filename "http://10.10.10.12:80/boot.ipxe";
} elsif substring(option vendor-class-identifier, 0, 9) = "PXEClient" {
filename "undionly.kpxe";
}
この部分はDHCPのDiscoverにあるOption 60を見て送信元がPXEかiPXEか判定しています。
filename で指定しているURLは後述するmatchboxのURLです。
設定の上書き
$ sudo cp dhcpd.conf /etc/dhcp/dhcpd.conf
isc-dhcp-serverは/etc/dhcp/dhcpd.conf
を参照しているため、手元のdhcpd.confで上書きしておきます。
起動
$ sudo systemctl restart isc-dhcp-server
起動後、以下コマンドで起動できているか確認します。
$ sudo systemctl status isc-dhcp-server
active になっていれば問題なく設定ができています。
TFTPサーバを準備する
PXEからiPXEにチェーンロードするために、後述するundionly.kpxeというバイナリを提供する必要があります。
PXEはTFTPによるファイルの取得が行えるため、TFTPサーバを用意します。DHCPサーバと別に用意してもいいですが、今回はDHCPサーバと兼任させることにしました。
インストール
$ sudo apt install -y tftpd-hpa
インストール出来れば、設定ファイルが作成されるので確認します。
$ cat /etc/default/tftpd-hpa
# /etc/default/tftpd-hpa
TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/srv/tftp"
TFTP_ADDRESS=":69"
TFTP_OPTIONS="--secure"
デフォルトでは/srv/tftp/
をもとにファイルを提供するようなので、作成していない場合はこのディレクトリを作成しておきます。
$ sudo mkdir /srv/tftp
起動
$ sudo systemctl restart tftpd-hpa
undionly.kpxe を準備する
undionly.kpxeはPXEからiPXEにチェーンロードするために必要になるバイナリです。
ダウンロード
$ wget https://boot.ipxe.org/undionly.kpxe
TFTPのディレクトリに配置する
$ sudo mv undionly.kpxe /srv/tftp/undionly.kpxe
matchboxを準備する
matchboxは公式サイトで以下のように説明されています。
Matchbox is a service that matches bare-metal machines to profiles that PXE boot and provision clusters.
Matchboxは、ベアメタルマシンと、PXEブートとクラスタのプロビジョニングを行うプロファイルをマッチングするサービスです。(DeepL翻訳)
よくわからなかったので、matchboxが提供するエンドポイントにリクエストを送信すると事前定義したプロファイルに基づき、対応したネットブート設定を吐き出してくれるサービスと私は認識しました。
インストール
matchboxのGitHubから最新のリリースを取得します
$ wget https://github.com/poseidon/matchbox/releases/download/v0.10.0/matchbox-v0.10.0-linux-amd64.tar.gz
$ tar -zxvf matchbox-v0.10.0-linux-amd64.tar.gz
解凍すると、その中にmatchboxという名前のバイナリがあるので、適当にパスを通してください。
基本ディレクトリの作成
matchboxでは以下のディレクトリをデフォルトで利用するので、作成しておきましょう。
- /var/lib/matchbox/
- /var/lib/matchbox/assets/
- /var/lib/matchbox/groups/
- /var/lib/matchbox/profiles/
グループの作成
グループではプロファイルに一致させるためのセレクターなどを記述します。
今回はMACアドレスをベースにマッチングを行いました。
/var/lib/matchbox/groups/
にnode-1.json
を作成します。
{
"id": "node-1",
"name": "Install node 1",
"profile": "node-1-install",
"selector": {
"mac": "対象のMACアドレス"
}
}
matchboxではこのグループにマッチした場合、profile
というキーをもとに/var/lib/matchbox/profiles/
内にあるプロファイルを自動選択します。
プロファイルの作成
プロファイルではネットブートについて定義します。
/var/lib/matchbox/profiles/
にinstall-node-1.json
を作成します。
{
"id": "node-1-ubuntu-install",
"name": "Install Ubuntu on node-1",
"boot": {
"kernel": "/assets/ubuntu/2004/vmlinuz",
"initrd": [
"/assets/ubuntu/2004/initrd"
],
"args": [
"autoinstall",
"ip=dhcp",
"ds=nocloud-net;s=http://10.10.10.12/assets/",
"url=http://10.10.10.12/assets/ubuntu/2004/ubuntu-22.04.6-live-server-amd64.iso"
]
}
}
Ubuntuを起動する場合は引数に、ip=dhcp
を指定する必要があります。
Ubuntu起動後にcloud-initによる自動化を図る場合は、autoinstall
とds=nocloud-net;s=http://10.10.10.12/assets/
を引数に指定する必要があります。
注意点ですが、ds=nocloud-net;s={URL}
でURLを指定する場合は、最後が/
で終わっている必要があります。
また、URL先にはcloud-initの仕様としてmeta-data
とuser-data
が格納されている必要があります。
- 参考: Ubuntu Manpage: casper
- 参考: Netbooting the server installer on amd64 | Ubuntu
- 参考: Bug #1848018 “[solved] PXE boot/nfsboot broken; Eoan Ermine; 19...” : Bugs : casper package : Ubuntu
- 参考: pxe - Deploying Ubuntu 22.04 with PXEBoot using Syslinux - Super User
assetsの用意
先ほど作成したプロファイルに記述があったisoファイルと、その中にあるvmlinuz、initrdを取り出してassetsディレクトリに用意しておきます。
$ sudo mkdir -p /var/lib/matchbox/assets/ubuntu/2004/
$ cd $_
ISOのダウンロードとマウント
$ sudo wget https://releases.ubuntu.com/focal/ubuntu-20.04.6-live-server-amd64.iso
$ sudo mkdir /mnt/ubuntu2004/
$ sudo mount -t iso9660 -o loop ubuntu-20.04.6-live-server-amd64.iso /mnt/ubuntu2004/
必要なファイルをコピー
$ sudo cp /mnt/ubuntu2004/casper/vmlinuz /var/lib/matchbox/assets/ubuntu/2004/vmlinuz
$ sudo cp /mnt/ubuntu2004/casper/initrd /var/lib/matchbox/assets/ubuntu/2004/initrd
これで準備は終わりです。
cloud-init のデータを用意する
cloud-initによる自動化を行うため、user-dataを作成します。
$ nano user-data
#cloud-config
autoinstall:
version: 1
identity:
hostname: ubuntu-server
password: "$6$exDY1mhS4KUYCE/2$zmn9ToZwTKLhCw.b4/b.ZRTIZM30JZ4QrOQ2aOXJ8yk96xpcCof0kxKwuX1kqLG/ygbJ1f8wxED22bTL4F46P0"
username: ubuntu
パスワードはubuntu
です。
また、meta-dataも作成しておきます。
meta-dataの中身は空っぽのままで大丈夫です。
$ touch meta-data
これら二つを/var/lib/matchbox/assets/
直下に移動しておきます。
$ sudo mv user-data /var/lib/matchbox/assets/user-data
$ sudo mv meta-data /var/lib/matchbox/assets/meta-data
複数のディストリビューションなどをインストールする場合は、別ディレクトリに移動すべきですが今回はUbuntuのみを想定しているので問題ありません。
matchboxを起動する
$ sudo matchbox --address=10.10.10.12:80
クライアントを起動する
すべての準備が終わったので、ターゲットとなるクライアントPCの電源を入れます。
全行程が問題なく終わっていれば、PXEからiPXEにチェーンロードします。
その後、Ubuntuが起動し、cloud-initが走ります。
しばらく待つと、ubuntu-serverというホスト名でUbuntuが起動しているはずです。
もし、ISOファイル取得中にno space left on device
と表示され処理が中断された場合は、メモリが足りません。
VMの場合は割り当てを増やしましょう。
[余談] 奇妙なバグが起きた
今回はUbuntu20.04, 22.04でNetbootが正しく行えるかチェックしました。
Ubuntu20.04は物理マシンも仮想マシンもどちらも正常にNetboot + cloud-initを完了することができました。
しかし、仮想マシンでUbuntu22.04をNetbootした場合のみ、cloud-initが実行されませんでした。
仮想マシンでUbuntu22.04を起動した場合、Netbootまでは正常に動作しましたが、cloud-initを行う段階においてds=nocloud-net
で指定しているURLにリクエストを送信しないというバグが発生しました。
できる範囲で調査は行ったのですが、原因らしい原因は見つけることができませんでした。
また、物理マシンにおいてもUbuntu22.04はcloud-initによる設定がUbuntu20.04のときよりも処理に時間が掛かっていました。
時間がなかったため、時間の測定などは十分に行えていないので検証すべき点はたくさんあります...。
おわりに
以上がDHCPサーバとmatchboxを使ってUbuntuをNetbootしたときのメモ書きです。
Ubuntu 20.04では正常に動作したものが22.04で動作しなかったのは少モヤモヤしますが、やりたいことは実現できたのでよかったです。
原因はいつか解明したいと思います。