Ubuntu Weekly Recipe

第665回ホワイトボックススイッチのインストール環境であるONIEを仮想マシンに構築する

「ホワイトボックススイッチ」はユーザーが自由に[要定義]OSを入れ替えられるスイッチです。そのOSを入れ替えるための仕組みがONIE(Open Network Install Environment)です。今回は仮想マシンの上にONIEをインストールし、公開されているスイッチ用OSをインストールしてみましょう。

ホワイトボックススイッチとONIE

本記事で言う「スイッチ」とは複数の有線LANポートを持った、ネットワークに接続する、ゲームがメイン目的ではないほうのスイッチを指します[1]⁠。一般的なご家庭だと、ブロードバンドルーターから直接LANポートで機器を繋いだり、無線LAN経由で通信することが多いため、このようなスイッチを使うことはないかもしれません。それに対して会社のように多人数が有線LANを接続する際には、お世話になっていることも多いでしょう。

普段会社で使うスイッチのうちPCに近いところで使うスイッチは、ポート数が少なく、価格がそこまで高くはない機材であることが大半です。それに対して、企業や組織の基幹ネットワークや果てはISPやモバイルネットワークで使われるスイッチは、それなりに多ポートでなおかつ高額な機材となります。

やれ10GbEだ、25GbEだ、100GbEだ、400GbEだと進化し続けるネットワークの世界において、そんな高額な機材をぽんぽん買い換えられる組織はそこまで多くありません。さらに、いわゆる「プロプライエタリスイッチ」と呼ばれるものは、ハードウェアとソフトウェアがセットになっているため、ソフトウェア側の移行コストを下げようと思うと、スイッチベンダーが新しい規格に対応してくれるのを待つしかなくなります。

そこで出てくる概念が「ホワイトボックススイッチ」です。最近の高性能スイッチは、⁠LANポートのたくさんある、高性能なスイッチングLSI付きのサーバーマシン」みたいな構成のものが多く、ベースシステムだけ考えれば普通のLinuxをそのままインストールして動かせたりします。そこでいっそのこと、PCのように各スイッチベンダーはできるだけ標準的な規格で作っておき、機種依存な部分もできるだけオープンにすることで、ソフトウェア側は誰でも作れるようにしてしまおうというのがホワイトボックススイッチの考え方です[2]⁠。

ソフトウエア側はNetwork OS(NOS)と呼ばれる一種のLinuxディストリビューションとして開発します[3]⁠。ホワイトボックススイッチにはNOSをインストール・アンインストールすることに特化したONIE(Open Network Install Environment)と呼ばれるOSがインストールされているため、スイッチの購入者は好みのONIE対応NOSをインストールして使うことができるというわけです[4]⁠。

言い方を変えるとスイッチベンダーは、製造したスイッチの上にONIEのデザインスペックに準拠したイメージをインストールし、ハードウェアの仕様を提供しておくことで、さまざまなNOSベンダーがそのスイッチに対応したNOSを開発できるようになります。

これによりハードウェアとソフトウェアを独立して開発できるようになり、ベンダー側の開発コストはもちろん、スイッチユーザー側の移行リスクやコストも下げられるのです[5]⁠。

ホワイトボックススイッチ用のNOSはいろいろなところが開発していますが、その中でもソースコードが公開されていて誰でも使えるNOSのひとつが「Open Network Linux(ONL⁠⁠」です。実はこのONLはDebianベースで作られており、普通にaptコマンドでパッケージの追加インストールが可能です[6]⁠。そこで今回はQEMU環境にONIEをインストールし、さらにONLをインストールしてみることにしましょう。

実は過去に「Ubuntu CoreをONIE経由でインストールできないか」という話が出てきたことはあります(Ubuntu Weekly Topics 2015年11月27日号⁠。マーク・シャトルワースが議論に参加したこともあってか、当時それなりに話題にはなったものの、その後は特に大きな動きはないようです。実際のところ、ONIEの仕様は公開されているため、Ubuntu Coreを一般的なONIE経由でインストールするよう独自インストーラーを作ることはそこまで難しくはありません。

ビルド環境の構築とONIEイメージの作成

まずはQEMU用のONIEをビルドすることにします。ONIEはもともとスイッチベンダーが作る想定であるため、機種依存なファームウェアとなります。幸いONIE本体のソースコードには、QEMU向けの設定一式が存在するため、それをそのまま使うことにしましょう。

ビルドをするためには「Debian 9以前」の環境が必要です[7]⁠。ただ今からDebian 9環境を新規に用意するのもなんなので、Dockerイメージを用意することにしましょう。ONIEのソースツリーにはビルド用のDockerfileが用意されているのでこれを使います。

まずはDockerのインストールです。今回はUbuntu 21.04で動作確認しましたが、基本サポート中のUbuntuならどれも同じバージョンのDockerがインストールされるはずなので、どのUbuntuでも問題ないでしょう。

$ sudo apt install docker.io git
$ sudo adduser $USER docker

グループ設定を反映するために、一度ログインし直しておいてください。次にソースコードをクローンして、イメージをビルドします。

$ git clone https://github.com/opencomputeproject/onie.git
$ cd onie/contrib/build-env/
$ docker build -t debian:build-env .
(中略)
Successfully built 85940c5a622e
Successfully tagged debian:build-env

このあたりは普通のDockerの使い方ですね。次にONIE用のソースコードのビルドディレクトリを用意し、そこにONIEのソースコードをクローンします。先ほどの手順で、一度クローンしてはいるためそれをそのまま使うというのも一つの手です。ただしONIEは機種ごとにビルドツリーを持ったほうが良いため、ここでは明示的に新規にディレクトリを作成し、そこに展開しています。

今回はホームディレクトリの下に~/onie_srcとして展開しましょう。このディレクトリの下は、最終的に20GiB弱のストレージ容量を使用します。先ほど作成したDockerイメージは単にビルド環境を作っただけです。そこで適切なディレクトリをバインドマウントし、bashを起動します。

$ mkdir --mode=0777 ${HOME}/onie_src
$ docker run -it -v ${HOME}/onie_src:/home/build/src --name onie debian:build-env
build@ece6bf615181:~$ ls
clone-onie  src
build@ece6bf615181:~$ ls src/
build@ece6bf615181:~$

clone-onieスクリプトを使うと、現在空のsrc/にONIE本体のコードが展開されます。このsrc/はホスト側の${HOME}/onie_src/にバインドマウントされています。

build@ece6bf615181:~$ ./clone-onie
build@ece6bf615181:~$ cd src/onie/build-config

build-config/は機種共通のビルドスクリプト置き場です。よってまずはこのディレクトリに移動した上でmakeコマンドを実行します。

しかしながら、どうも現在のONIEは、SecureBootを有効化しているとGRUBを正しくビルド・インストールできないようです。具体的にはNOSインストール時にgrub-install: error: /usr/lib/grub/x86_64-efi/modinfo.sh doesn't exist. Please specify --target or --directory.のようなエラーメッセージが表示されます。そこでビルド前に次の手順で設定値を変更します。

$ sed -i 's/^SECURE_BOOT_ENABLE = yes/SECURE_BOOT_ENABLE = no/' ../machine/kvm_x86_64/machine.make

機種依存な情報はmachine/以下にmachine/ベンダー名/プラットフォーム名として保存されます。特定のプラットフォーム(=スイッチの機種)のイメージをビルドしたい場合はMACHINEROOT=../machine/ベンダー名 MACHINE=プラットフォーム名を指定するわけです。

今回作るQEMU向けのプラットフォームは、ベンダー名は不要で、MACHINEだけ指定すれば問題ありません。次の方法でビルドしてください。

build@ece6bf615181:~$ make -j8 MACHINE=kvm_x86_64 all
(中略)
Drive current: -outdev '/home/build/src/onie/build/images/onie-recovery-x86_64-kvm_x86_64-r0.iso'
Media current: stdio file, overwriteable
Media status : is blank
Media summary: 0 sessions, 0 data blocks, 0 data,  408g free
xorriso : UPDATE : 279 files added in 1 seconds
Added to ISO image: directory '/'='/home/build/src/onie/build/kvm_x86_64-r0/recovery/iso-sysroot'
Created: /home/build/src/onie/build/images/onie-updater-x86_64-kvm_x86_64-r0
=== Finished making onie-x86_64-kvm_x86_64-r0 master-05021132 ===

初回ビルド時はコンパイラやカーネルをダウンロード・ビルドするため、それなりのネットワーク帯域・ストレージ容量・CPU性能が必要です。Intel Core i7-8809Gでおよそ2時間ぐらいかかりました。

../build/images/に成果物が格納されます。

build@ece6bf615181:~/src/onie/build-config$ ls -l ../build/images/
total 55244
-rw-r--r-- 1 build build  7549712 May  2 11:57 kvm_x86_64-r0.initrd
-rw-r--r-- 1 build build  3966912 May  2 11:56 kvm_x86_64-r0.vmlinuz
-rw-r--r-- 1 build build  3965008 May  2 11:56 kvm_x86_64-r0.vmlinuz.unsigned
-rw-r--r-- 1 build build 28704768 May  2 11:57 onie-recovery-x86_64-kvm_x86_64-r0.iso
-rw-r--r-- 1 build build 12371831 May  2 11:57 onie-updater-x86_64-kvm_x86_64-r0

これらのファイルのうち今回使用するのは、対象のマシンにONIEをクリーンインストールするためのリカバリーイメージonie-recovery-x86_64-kvm_x86_64-r0.isoです。onie-updaterはONIEインストール済みの環境を更新する際に使用します。vmlinuzinitrdはPXEブートなどが必要な場合に使用します。

ビルド環境はもう不要なので、exitコマンドでDockerインスタンスから抜けておいてください。

仮想マシンへのONIEのインストール

QEMUを利用して仮想マシンを作成しましょう。amd64なCPUが載ったホワイトボックススイッチはおおよそUEFIに対応しているため、UEFIな仮想マシンを作ることにします。QEMUとUEFIについては第441回のQEMU/KVMでUEFIファームウェアを使うを参照してください。

まず必要なパッケージをインストールして、仮想マシン用のディスクイメージとUEFI用の変数領域を作成します。

$ sudo apt install qemu-system-x86 qemu-utils ovmf
$ mkdir ~/onie_src/qemu/ && cd $_
$ qemu-img create -f qcow2 onie.img 20G
$ cp /usr/share/OVMF/OVMF_VARS.fd .

別途作成したリカバリーイメージを指定して起動します。

$ sudo qemu-system-x86_64 --enable-kvm -m 2G \
    -name "onie" \
    -nographic \
    -boot order=cd,once=d -cdrom ../onie/build/images/onie-recovery-x86_64-kvm_x86_64-r0.iso \
    -drive if=pflash,format=raw,readonly,file=/usr/share/OVMF/OVMF_CODE.fd \
    -drive if=pflash,format=raw,file=OVMF_VARS.fd \
    -drive file=onie.img,media=disk,if=virtio,index=0 \
    -serial telnet:localhost:9000,server

QEMU 5.2.0 monitor - type 'help' for more information
(qemu) qemu-system-x86_64: -serial telnet:localhost:9000,server: info: QEMU waiting for connection on: disconnected:telnet:127.0.0.1:9000,server

4行目で先ほど作成したリカバリーイメージの一を指定しています。6行目と7行目にUEFI変数領域と作成した空のディスクイメージを指定しています。最後の行はシリアルコンソールの出力先として、telnetサーバーを9000番ポートで起動しています。誰かがこのポートに接続しない限りは仮想マシンは起動しないため、別端末からtelnetログインしましょう。

$ telnet localhost 9000

起動すると次のようなGRUBのメニューが表示されます。

図1 リカバリーイメージから起動したときのメニュー
図1

ONIE: RescueはONIE環境の動作確認・復旧用のモードです。つまりONIE経由でNOSを検出・インストールする状態になるものの、自動的にはNOSをインストールせず、単にシェルが立ち上がります。ONIE環境のデバッグなどに利用します。

ONIE: Embed ONIEはONIEそのものをインストールするモードです。既存のシステムを(インストール済みのNOSを含む)すべて削除し、ONIEをインストールします。ストレージをまっさらにしONIEをクリーンインストールするという点で、本来はスイッチベンダーが出荷前に利用します。

今回は空のストレージにONIEをインストールしたいので、⁠ONIE: Embed ONIE」を選択し、しばらく待ってください。

ONIE: Embedding ONIE ...
Platform  : x86_64-kvm_x86_64-r0
Version   : master-05021132
Build Date: 2021-05-02T11:32+00:00
Info: Mounting kernel filesystems... done.
Info: BIOS mode: UEFI
(中略)
ONIE: Success: Firmware update URL: file:///lib/onie/onie-updater
ONIE: Success: Firmware update version: master-05021132
ONIE: Rebooting...
(中略)
reboot: Restarting system

無事にインストールが完了したら再起動します。次のようなGRUBメニューが表示されます。

図2 ONIEがインストールされた状態のメニュー
図2

「ONIE: Install OS」はインストール可能なNOSイメージを、FATファイルシステムないしTFTP経由で検索しインストールするモードです。⁠ONIE: Uinstall OS」は逆にインストール済みのNOSを削除します。削除する際にランダムなデータで各パーティションで埋めるためそれなりに時間がかかります。⁠ONIE: Update ONIE」はONIE本体を更新するモードです。

特に何も指定しなければ、インストールモードになります。インストールモードでNOSをインストールするためには、別途NOSイメージを用意しなくてはなりません。そこで今回はまずEnterキーを押してシェルに入り、次のような手順で一度ONIE環境をシャットダウンしましょう。

ONIE:/ # onie-discovery-stop
NOTICE: The 'onie-discovery-stop' command is deprecated and will be removed in 2019.02.
NOTICE: Use 'onie-stop' instead.
discover: installer mode detected.
Stopping: discover... done.
ONIE:/ # halt

「Ctrl-]」を入力するとtelnetセッションを抜けるので「quit」でtelnetを終了してください。また、QEMUを起動したほうも同様にquitコマンドでインスタンスを終了します。

Open Network Linuxのインストール

Open Network Linux(ONL)はさまざまなホワイトボックススイッチに対応したDebianベースのネットワークディストリビューションです[8]⁠。ONL自体もソースコードが公開されているため、いちから自分でビルドすることが可能ではあるものの、今回はビルド済みのバイナリをそのまま使うことにします。

ビルド済みのバイナリは公式サイトDownloadからダウンロードできます。ちなみにリンクをクリックするとHTTPSにジャンプしますが、証明書が2019年10月12日期限であるため、一般的なブラウザーだと警告が表示されます。このあたりにもやる気のなさが見て取れます

とにもかくにも最新のリリースをダウンロードしましょう。ONLもONIEと同じくDebian 9以下でないとビルドできません。

$ wget http://opennetlinux.org/binaries/latest/ONL-master-ONL-OS9-2019-07-23.0153-01d1564-AMD64-INSTALLED-INSTALLER

このイメージをONIEからインストールするわけですが、ONIEがイメージを探す方法は主に5種類存在します。

  • カーネルのコマンドラインパラメーターにinstall_url=<イメージのURL>を指定して起動する
  • USBスティックなどのストレージにイメージをコピーして自動認識させる
  • DHCPのレスポンスにURLを記述する
  • ONIEが動いているマシンが接続されているネットワーク上のTFTPサーバーにイメージを置いておく
  • ONIEが起動したあと、手作業でインストールコマンドを入力する

複数台のインストールを自動化するなら、DHCPやTFTPを使うほうが良いでしょう。1台を試しにインストールしたいならコマンドラインパラメーターやUSBスティックを使う方法で十分です。

ちなみにONIEはIPv4ブロードキャストアドレスやIPv6のリンクローカルなマルチキャストアドレスにpingを打ち、応答があったIPアドレスに対して順番にNOSイメージを持っているか確認していきます。また、自動検索でインストールしたいなら、対象となるファイル名にも決まりが存在するため、ダウンロードしたファイルを適切にリネームしておきましょう。とりあえず複数の機種を考えないなら、⁠onie-installer」としておけば確実です。

今回は準備の手間を省くため、PythonでHTTPサーバーを起動しておき、手作業でインストールコマンドを実行することにしましょう。

まずはファイルの名前を変えておきます。今回は手作業でインストールするため、決まりに従わずわかりやすい名前に変更します。

$ mv ONL-master-ONL-OS9-2019-07-23.0153-01d1564-AMD64-INSTALLED-INSTALLER onl-installer.bin

Pythonのhttp.serverモジュールを使って簡易的なHTTPサーバーを立ち上げます。

$ python3 -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...

ポート番号が「8000」になっている点に注意してください。別の端末からアクセスできるか確認しておきましょう。

$ wget --spider http://localhost:8000/onl-installer.bin
スパイダーモードが有効です。リモートファイルが存在してるか確認します。
--2021-05-03 11:43:04--  http://localhost:8000/onl-installer.bin
localhost (localhost) をDNSに問いあわせています... 127.0.0.1
localhost (localhost)|127.0.0.1|:8000 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 200 OK
長さ: 256304934 (244M) [application/octet-stream]
リモートファイルが存在します。

ONIEが動く仮想マシンを起動します。今回はリカバリーイメージの指定は不要です。

$ sudo qemu-system-x86_64 --enable-kvm -m 2G \
    -name "onie" \
    -nographic \
    -drive if=pflash,format=raw,readonly,file=/usr/share/OVMF/OVMF_CODE.fd \
    -drive if=pflash,format=raw,file=OVMF_VARS.fd \
    -drive file=onie.img,media=disk,if=virtio,index=0 \
    -serial telnet:localhost:9000,server

QEMU 5.2.0 monitor - type 'help' for more information
(qemu) qemu-system-x86_64: -serial telnet:localhost:9000,server: info: QEMU waiting for connection on: disconnected:telnet:127.0.0.1:9000,server

別端末からtelnetログインしてシリアルコンソールを表示します。

$ telnet localhost 9000

「ONIE: Install OS」が自動選択されるのでそのまま放置しておきます。⁠Please press Enter to activate this console.」と表示されたらエンターキーを押してください。コマンドプロンプトが表示されるため、自動検索を停止するためにonie-stopを実行します。

Please press Enter to activate this console.
(中略)
NOTICE: ONIE started in NOS install mode.  Install mode persists
NOTICE: until a NOS installer runs successfully.

** Installer Mode Enabled **
ONIE:/ # onie-stop
discover: installer mode detected.
Stopping: discover... done.
ONIE:/ #

手動でのNOSのインストールにはonie-nos-installコマンドを利用します。今回はQEMU環境なので、ホスト側で動かしたHTTPサーバーはゲストからだとデフォルトゲートウェイのアドレスでアクセスできます。

ONIE:/ # ip route show default
default via 10.0.2.2 dev eth0
10.0.2.0/24 dev eth0  src 10.0.2.15

上記の設定だとhttp://10.0.2.2:8000/onl-installer.binがNOSイメージのアドレスというわけです。

ONIE:/ # onie-nos-install http://10.0.2.2:8000/onl-installer.bin
discover: installer mode detected.
Stopping: discover... done.
Info: Attempting http://10.0.2.2:8000/onl-installer.bin ...
Connecting to 10.0.2.2:8000 (10.0.2.2:8000)
installer            100% |*******************************|   244M  0:00:00 ETA
ONIE: Executing installer: http://10.0.2.2:8000/onl-installer.bin
(中略)
Installing for x86_64-efi platform.
Installation finished. No error reported.
(中略)
Requesting system reboot
reboot: Restarting system

インストール処理は完全に自動化されています。またインストールが完了すると自動的に再起動します。

図3 NOSがインストールされるとNOS側のGRUBメニューになる
図3

NOSがインストールされるとNOSがインストールされたパーティションのGRUBが最初に起動します。たとえばNOSをアンインストールしたい場合は、このメニューの「ONIE」を選択してください。ONIEがインストールされたパーティションのGRUBが起動するので、その先はNOSインストール前の状態と同じです。

特に何も選ばないと自動的にOpen Network Linuxが起動します。

Stopping watchdog keepalive daemon....
Starting watchdog daemon....

Open Network Linux OS ONL-master, 2019-07-23.01:53-01d1564

localhost login: root
Password:
Linux localhost 4.14.109-OpenNetworkLinux #1 SMP Tue Jul 23 04:41:51 UTC 2019 x86_64
root@localhost:~#

ログインプロンプトが表示されるため、アカウント名「root⁠⁠、パスワード「onl」でログインしてください。

root@localhost:~# cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 9 (stretch)"
NAME="Debian GNU/Linux"
VERSION_ID="9"
VERSION="9 (stretch)"
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"

root@localhost:~# onlpdump
   System Information: = {
       Product Name: ONLSIM
       Part Number: ONL
       MAC: 00:00:00:00:00:00
   }

SFPs:
There are no SFP capable ports.

Debian 9ベースとなっていることがわかりますし、スイッチとしてのハードウェアは特に存在しないこともわかります。

SONiCのインストール

ONLに対して比較的活発に開発されているNOSが、マイクロソフトのSONiCです。Apacheライセンスであるため、自由にカスタマイズが可能です。SONiCも仮想マシン用のイメージが配布されており、今回はこのイメージをインストールしてみましょう。

ONLをインストールしたディレクトリで、上記イメージをダウンロードします。

$ wget https://sonic-jenkins.westus2.cloudapp.azure.com/job/vs/job/buildimage-vs-201911/lastSuccessfulBuild/artifact/target/sonic-vs.bin

ストレージに十分な空きがあればNOSを追加インストール可能です。ただ複数のNOSを同時に使うことはないため、素直に前のNOSをアンインストールしてしまいましょう。手動でアンインストールするなら、再起動してGRUBメニューでONIEを選びます。ただ毎回GRUBメニューの表示も待つのが面倒なので、NOS側からGRUBのコマンドを使って再起動前に次回起動メニューを選択してみます。

root@localhost:~# grub-reboot ONIE
root@localhost:~# onl-onie-boot-mode uninstall
[ 1342.495457] EXT4-fs (vda2): mounted filesystem with ordered data mode. Opts: (null)
[ 1342.519414] EXT4-fs (vda3): re-mounted. Opts: (null)
[ 1342.539015] EXT4-fs (vda3): re-mounted. Opts: (null)
The system will boot into ONIE uninstall mode at the next restart.
root@localhost:~# reboot

あとは放置しておけばONLがアンインストールされたのちに、インストールモードになりますので、今度はonie-nos-installコマンドでSONiC側を選択してみましょう。

ONIE:/ # onie-stop
discover: installer mode detected.
Stopping: discover... done.
ONIE:/ # onie-nos-install http://10.0.2.2:8000/sonic-vs.bin

あとはONLと同様に放置しておけば、勝手にインストール・再起動してくれます。ログインプロンプトが表示されたらログインしましょう。初期状態で用意されているアカウント名は「admin」で、パスワードは「YourPaSsWoRd」です

Debian GNU/Linux 9 sonic ttyS0

sonic login: admin
Password:
Linux sonic 4.9.0-14-2-amd64 #1 SMP Debian 4.9.246-2 (2020-12-17) x86_64
You are on
  ____   ___  _   _ _  ____
 / ___| / _ \| \ | (_)/ ___|
 \___ \| | | |  \| | | |
  ___) | |_| | |\  | | |___
 |____/ \___/|_| \_|_|\____|

-- Software for Open Networking in the Cloud --

Unauthorized access and/or use are prohibited.
All access and/or use are subject to monitoring.

Help:    http://azure.github.io/SONiC/

admin@sonic:~$

SONiCもDebian 9ベースです。SONiCはLinuxのコマンドツリーの中にスイッチ管理用のコマンドも取り込まれています。

admin@sonic:~$ show interfaces status
  Interface            Lanes    Speed    MTU    FEC           Alias    Vlan    Oper    Admin    Type    Asym PFC
-----------  ---------------  -------  -----  -----  --------------  ------  ------  -------  ------  ----------
  Ethernet0      25,26,27,28      40G   9100    N/A    fortyGigE0/0  routed    down       up     N/A         N/A
  Ethernet4      29,30,31,32      40G   9100    N/A    fortyGigE0/4  routed    down       up     N/A         N/A
  Ethernet8      33,34,35,36      40G   9100    N/A    fortyGigE0/8  routed    down       up     N/A         N/A
 Ethernet12      37,38,39,40      40G   9100    N/A   fortyGigE0/12  routed    down       up     N/A         N/A
(後略)

ONLと同じく仮想マシン上でできることは限られてはいるものの、雰囲気を感じるくらいなら可能でしょう。

おすすめ記事

記事・ニュース一覧