Goで作るモダン・ブートサーバー Day2 - 環境構築編

この記事は「Go で作るモダン・ブートサーバー」の 2 日目の記事です。 今回はブートサーバーを開発するための開発環境を構築します。 ブートサーバーの検証をするための、 Linux 上で仮想ネットワークと仮想マシンを作る方法を紹介します。

シリーズの記事は以下のリンクからどうぞ。

環境構築

ブートサーバーの検証に物理マシンを利用しても良いのですが、仮想環境が用意できれば、デバッグや検証が捗ります。 まず想定する環境は、ブートサーバーとブートするマシン(クライアントと呼ぶ)を同じ L2 ネットワーク内に配置します。 クライアントは起動すると、IP アドレスとブート情報を、同じ L2 ネットワーク内にある DHCP サーバーに要求します。

ネットワークは 172.24.0.0/16 のネットワークアドレスを持つとします(アドレスの範囲は 172.24.0.0/16 - 172.24.255.255/16 です)。 DHCP サーバーは 172.24.0.1 という IP アドレスを持っています。 DHCP サーバーはクライアントに対して、172.24.32.0 - 172.24.32.255 の範囲のアドレスを割り当てます。

上記の構成を、仮想マシンと仮想ネットワークを使って構築します。 ブートサーバーは VM ホスト上に立てて、L2 ネットワーク上に DHCP を提供します。 この構成を作るために、以下の 3 つの準備をします。

  • ブリッジの作成
  • TAP (Terminal Access Point) の作成
  • クライアント (QEMU) の起動

図にすると以下のような構成です。

ブートサーバーの開発環境の図

ブリッジの作成

Linux にはブリッジと呼ばれる仮想的な L2 ネットワークを作成する機能があります。 ブリッジは ip コマンドから作成します(ip コマンドは多くの Linux ディストリビューションでは iproute2 パッケージから利用できます)。 まず以下のコマンドで、br0 というブリッジの作成し、ブリッジを有効にします。

# ブリッジの作成
sudo ip link add br0 type bridge
# デバイスの状態をUPに
sudo ip link set br0 up

次にブリッジにホストが利用する IP アドレスの割当です。 VM ホストから仮想ネットワークにはこのアドレスで接続します。

# アドレスを追加
sudo ip address add 172.24.0.1/16 dev br0

TAP の作成

次に TAP と呼ばれる、VM が利用する仮想ネットワークインターフェイスを作成します。 TAP も ip コマンドから作成します。 まず tap0 という TAP を作成します。

# TAPを作成
sudo ip tuntap add tap0 mode tap

そして TAP をブリッジに接続して、有効化します。

# TAPをブリッジに接続
sudo ip link set tap0 master br0
# デバイスの状態をUPに
sudo ip link set tap0 up

クライアント (QEMU) の起動

それでは作成したブリッジと TAP を使うクライアントを起動します。 クライアントは QEMU の VM で作成します。 QEMU の -netdev オプションで、作成した TAP を指定します。

# MACアドレス
mac_address="52:54:00:99:99:99"

# QEMU起動
qemu-system-x86_64 \
  -nodefaults \    # デフォルトオプションを利用しない
  -enable-kvm \    # KVMを利用する
  -boot n \        # ネットワークブート
  -nographic \	   # グラフィック出力を無効化
  -serial stdio \  # シリアル出力をstdioに
  -netdev tap,id=nic1,ifname=tap0,script=no,downscript=no \  # ネットワークデバイスを指定
  -device virtio-net-pci,netdev=nic1,mac=${mac_address}	     # NICのドライバとMACアドレスを指定

クライアントの MAC アドレスに 52:54:00:99:99:99 を割り当てます。 先頭 3 オクテット (52:54:00) は QEMU 用のベンダー ID で、QEMU で利用ときは 52:54:00:**:**:** という MAC アドレスを割り当てます。

導通テスト

上記の手順で、仮想的な L2 ネットワーク上に接続するクライアントを作成できました。 ホスト側の br0 に、クライアントから DHCP リクエストが届くか確認してみましょう。

DHCP のデバッグにはdhcpdumpというコマンドが便利です。 このコマンドでは DHCP パケットの中身を見ることができます。 -i オプションでインターフェイスを指定できます。 52:54:0:99:99:99 からの DHCP のリクエストが確認できます。

sudo dhcpdump -i br0
  TIME: 2020-03-01 16:32:47.362
    IP: 0.0.0.0 (52:54:0:99:99:99) > 255.255.255.255 (ff:ff:ff:ff:ff:ff)
    OP: 1 (BOOTPREQUEST)
 HTYPE: 1 (Ethernet)
<以下略>

お掃除

最後に作成した VM と仮想ネットワークを破棄します。 QEMU はCtrl+Cで終了できます。 TAP と作成した TAP とブリッジは以下のコマンドで削除できます

# TAPの削除
sudo ip tuntap delete tap0 mode tap
# ブリッジの削除
sudo ip link delete br0 type bridge

環境構築のスクリプト化

さて、上記のコマンドを毎回手で打つのは大変です。 そこでネットワークの作成や VM のスタートを簡単にするスクリプトを用意しました。 今後の記事では、このスクリプトを使って環境の構築をします。

https://github.com/ueokande/building-boot-server/blob/master/bin/setup

# ネットワークの作成
sudo ./setup network --name br0 --address 172.24.0.1/16

# クライアントの起動
sudo ./setup node --network br0

おわりに

この記事ではブートサーバーを開発する Linux 上の環境構築について説明しました。 次回はいよいよ、ブートサーバーを作成していきます。 まずはブートサーバーの第一ステップとして、DHCP の仕様の説明と DHCP サーバーを実装します。


Profile picture

Shin'ya Ueoka

B2B向けSaaSを提供する会社の、元Webエンジニア。今はエンジニアリング組織のマネジメントをしている。