さくらのアドベントカレンダー2022 8日目の記事です。
この記事は、SONiCをつかった検証環境が急に欲しくなった人向けに、「さくらのクラウドだけで作れるよ!」という内容のネタ記事です。
SONiCとは
紹介記事などがたくさんあるため、詳しい説明は他の解説記事を参照していただきたいのですが、SONiCはホワイトボックススイッチ向けのオープンソースなOSです。基本的にはホワイトボックススイッチにインストールして利用しますが、検証用として仮想マシン上でも利用が可能です。
さくらのクラウドとSONiC
さくらのクラウドはIaaSなクラウドサービスなので、一般的にはサーバーOSをインストールして利用することが多いかと思いますが、今回はこのさくらのクラウド上にSONiCをデプロイし、SONiCの検証環境を構築することを目指します。
やってみる
SONiCイメージのダウンロード
SONiCのビルド済みイメージは以下のサイトにて一覧でまとめられており、ダウンロードが可能です。
様々なプラットフォーム向けのイメージがありますが、sonic-vs.img.gz
が仮想マシン用イメージですので、これをダウンロードします。今回は ブランチ 202205
を利用しました。
SONiCイメージの変換
ダウンロードしたSONiCのイメージはgzipで圧縮されているので、まずはgunzipで伸長します。しかしながら配布されているイメージはqcow2フォーマットなので、そのままではさくらのクラウドにインポートできません。そのため qemu-img
コマンドを使ってrawフォーマットに変換します。
gunzip sonic-vs.img.gz
qemu-img convert -f qcow2 -O raw sonic-vs.img sonic-vs.raw
さくらのクラウドでアーカイブを作成する
さくらのクラウドでは、rawイメージをアップロードしてクラウドインスタンスとして実行することができる機能がありますので、以下ドキュメントを参考にrawイメージのアップロードを行います。rawイメージは16GB程度あったので、今回は余裕をもって40GBのブランクアーカイブを作成しました。
コントロールパネル上でブランクのアーカイブを作成するとcurlコマンドのサンプルが表示されるので、このままファイル名だけ変更してコピペすると簡単にアップロードできます。
サーバーを作成する
SONiCイメージのアーカイブができたら、サーバーを作成します。今回は2Core 2GBプランで作成しました。
作成したSONiCのアーカイブは、「マイアーカイブ」で選択できます。
サーバー作成するときに注意点
NICの準仮想化モードを無効化しておきます。準仮想化モードでもSONiC上でインターフェースはみえるのですが、スピード表示がおかしくなったりするので無効化するのが良いと思います。
またNICはサーバー作成後に追加するので、とりあえず「切断」しておきます。
もう1点、デフォルトでは「その他のオプション」の箇所に「作成後すぐに起動」のチェックボックスが有効になっていますが、前述した通りサーバー作成後にNICを追加するのでチェックを外しておきます。(サーバー起動中はNICの追加ができないため)
スイッチの作成
SONiCサーバー(さくらのクラウドにデプロイされたものということで、あえてサーバーと呼びます)に接続するためのスイッチを作成します。さくらのクラウドにおいては、サーバーとサーバーを直結することができないため、SONiCサーバー同士を直結したいのであれば、直結したいリンク数分のスイッチを作成しておきます。
スイッチの作成では難しいところはありません。
NICの追加
作成したSONiCサーバーにNICを追加し、前項で作成したスイッチの接続を行います。サーバーへのNIC追加についても難しいところは無いと思います。
NIC追加における注意点
仮想マシンのSONiCイメージでは、先頭のNICがマネジメントポート(eth0
)として認識されます。そのため、さくらのクラウドでNICを作成する場合でもその点を念頭においた上でNICを追加してください。
SONiC内部での認識名との対応は以下のようになります。
SONiCでの認識名 | クラウドコンパネで表示される番号 |
---|---|
eth0 | 0 |
Ethernet0 | 1 |
Ethernet4 | 2 |
Ethernet8 | 3 |
Ethernet12 | 4 |
Ethernet16 | 5 |
起動
NICが追加できたら起動です!「電源操作」ボタンからサーバーを起動しましょう。起動後はコンソールからSONiCの操作ができます。なおデフォルトのユーザー名とパスワードは以下のドキュメントに記載していますので参考にしてください。
https://github.com/sonic-net/SONiC/blob/master/doc/SONiC-User-Manual.md
起動後
あとは自由にSONiCを使うだけです!... というわけにはいかず、さくらのクラウドで利用するためにはSONiCでいくつかの設定が必要です。
MACアドレスの罠
さくらのクラウドでは、NICを追加すると固定のMACアドレスが割り振られます。
SONiCのデフォルトでは、 eth0
のMACアドレスが Ethernet0
や Ethernet4
といったインターフェースのMACアドレスとして利用されるようなのですが、前述した通り eth0
は先頭のNIC、Ethernet0
は先頭から2番めのNICですので、送信元MACアドレスがさくらのクラウドによってアサインされたものと異なることになってしまい、結果パケットがSONiCサーバーから出ていけません。
まとめると、起動直後の初期状態では以下のようになります。
SONiCでの認識名 | クラウドコンパネで表示される番号 | MACアドレス |
---|---|---|
eth0 | 0 | クラウドコンパネ番号に応じたMACアドレス |
eth1 | 1 | クラウドコンパネ番号に応じたMACアドレス |
eth2 | 2 | クラウドコンパネ番号に応じたMACアドレス |
Ethernet0 | 1 | eth0と同じMACアドレス |
Ethernet4 | 2 | eth0と同じMACアドレス |
MACアドレスを変更しよう
さくらのクラウドで利用するにあたっては、 Ethernet***
インターフェースのMACアドレスがマズいことがわかりましたので、これを変更しましょう。MACアドレスの変更は、 config
コマンドでは行えないようなので、/etc/sonic/config_db.json
を直接編集する必要があります。
$ cat /etc/sonic/config_db.json
(途中略)
"INTERFACE": {
"Ethernet0": {
"mac_addr": "12:34:56:78:90:ab"
},
"Ethernet4": {
"mac_addr": "11:22:33:44:55:66"
},
"Ethernet8": {
"mac_addr": "aa:bb:cc:dd:ee:ff"
}
},
(後略)
設定後はリロードして反映させます。
$ sudo config reload -y
設定反映後 ip link
コマンド等でMACアドレスを確認すると、変更されたことが確認できるかと思います。
さらなるMACアドレスの罠
EthernetインターフェースのMACアドレス変更により、パケットがSONiCから出ていけるようになりました!
あとは自由にSONiCを使うだけです! ... というわけにもいかず、なんだか挙動がおかしい状態となっています。
pingを実行してみよう
この状態で、シンプルに以下のように接続し、pingを実行してみます。
┌────────────────┐ ┌────────────────┐
│ SONiC │ │ Ubuntu │
│ 192.168.1.1/24 ├───────────────┤ 192.168.1.2/24 │
└────────────────┘ └────────────────┘
Ubuntu側から実行すると2つ応答があります。おかしいですね、直結しているはずなのに。
ubuntu@ubuntu:~$ ping 192.168.1.1
PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data.
64 bytes from 192.168.1.1: icmp_seq=1 ttl=64 time=1.34 ms
64 bytes from 192.168.1.1: icmp_seq=1 ttl=64 time=1.34 ms (DUP!)
64 bytes from 192.168.1.1: icmp_seq=2 ttl=64 time=0.695 ms
64 bytes from 192.168.1.1: icmp_seq=2 ttl=64 time=0.748 ms (DUP!)
64 bytes from 192.168.1.1: icmp_seq=3 ttl=64 time=0.580 ms
ためしにUbuntu側から1つだけ投げ、SONiC側でパケットキャプチャしてみると、
ubuntu@ubuntu:~$ ping -c1 192.168.1.1
PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data.
64 bytes from 192.168.1.1: icmp_seq=1 ttl=64 time=6.79 ms
--- 192.168.1.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 6.793/6.793/6.793/0.000 ms
ubuntu@ubuntu:~$
確かにSONiC側から2つのreplyが返されているようです。おかしいですね。
admin@sonic:~$ sudo tcpdump -nei Ethernet0 icmp
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on Ethernet0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
08:00:39.254735 9c:a3:ba:29:e7:33 > 9c:a3:ba:2b:79:20, ethertype IPv4 (0x0800), length 98: 192.168.1.1 > 192.168.1.2: ICMP echo reply, id 36, seq 1, length 64
08:00:39.254923 9c:a3:ba:2b:79:20 > 9c:a3:ba:29:e7:33, ethertype IPv4 (0x0800), length 98: 192.168.1.2 > 192.168.1.1: ICMP echo request, id 36, seq 1, length 64
08:00:39.254947 9c:a3:ba:29:e7:33 > 9c:a3:ba:2b:79:20, ethertype IPv4 (0x0800), length 98: 192.168.1.1 > 192.168.1.2: ICMP echo reply, id 36, seq 1, length 64
これは eth1
でキャプチャしてみても同様です。
admin@sonic:~$ sudo tcpdump -nei eth1 icmp
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), snapshot length 262144 bytes
08:00:57.316927 9c:a3:ba:2b:79:20 > 9c:a3:ba:29:e7:33, ethertype IPv4 (0x0800), length 98: 192.168.1.2 > 192.168.1.1: ICMP echo request, id 37, seq 1, length 64
08:00:57.317258 9c:a3:ba:29:e7:33 > 9c:a3:ba:2b:79:20, ethertype IPv4 (0x0800), length 98: 192.168.1.1 > 192.168.1.2: ICMP echo reply, id 37, seq 1, length 64
08:00:57.317407 9c:a3:ba:29:e7:33 > 9c:a3:ba:2b:79:20, ethertype IPv4 (0x0800), length 98: 192.168.1.1 > 192.168.1.2: ICMP echo reply, id 37, seq 1, length 64
この挙動、pingだけならまだしも?、たとえばBGPで接続しようとしたときに、SONiC側からackとrstが同時に返ってくるみたいな動きになります。こわい!
回避策
結論からいうと、上記の場合 Ethernet0
に対応した eth1
インターフェースのMACアドレスを手動で変更すると改善します。SONiCのインターフェースを介してのethインターフェースのMACアドレス変更方法は不明だったため、ip link
コマンドで変更しました。
$ sudo ip link set dev eth1 address ff:ee:dd:cc:bb:aa
eth1
のMACアドレスを変更することで、 Ethernet0
からの応答が1つになりました。
ubuntu@ubuntu:~$ ping -c 1 192.168.1.1
PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data.
64 bytes from 192.168.1.1: icmp_seq=1 ttl=64 time=1.20 ms
--- 192.168.1.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 1.202/1.202/1.202/0.000 ms
admin@sonic:~$ sudo tcpdump -nei Ethernet0 icmp
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on Ethernet0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
08:02:09.401079 9c:a3:ba:2b:79:20 > 9c:a3:ba:29:e7:33, ethertype IPv4 (0x0800), length 98: 192.168.1.2 > 192.168.1.1: ICMP echo request, id 38, seq 1, length 64
08:02:09.401170 9c:a3:ba:29:e7:33 > 9c:a3:ba:2b:79:20, ethertype IPv4 (0x0800), length 98: 192.168.1.1 > 192.168.1.2: ICMP echo reply, id 38, seq 1, length 64
eth1
でキャプチャしても1つで見えます。
admin@sonic:~$ sudo tcpdump -nei eth1 icmp
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), snapshot length 262144 bytes
08:02:17.292052 9c:a3:ba:2b:79:20 > 9c:a3:ba:29:e7:33, ethertype IPv4 (0x0800), length 98: 192.168.1.2 > 192.168.1.1: ICMP echo request, id 39, seq 1, length 64
08:02:17.292469 9c:a3:ba:29:e7:33 > 9c:a3:ba:2b:79:20, ethertype IPv4 (0x0800), length 98: 192.168.1.1 > 192.168.1.2: ICMP echo reply, id 39, seq 1, length 64
どうも IPアドレスをアサインした Ethernet0
に加えて eth1
からも応答を返しているように見えなくもない挙動ですが、実際のところ原因はわかりません。もし詳しい方がいらっしゃいましたら教えてください...。
ともあれ
MACアドレスの罠はあったものの、これでさくらのクラウド上でSONiCが利用できるようになりました!
さくらのクラウド上でSONiCによるIP Closな検証環境もちゃんと作れます。
ただ、普通にGNS3とかeve-ngとか使うほうが私はいいと思います。