はじめに
以前、SONiCの機能が動かないときの調査方法という記事を書きましたが、より実践的な内容になります。
SONiC(master branch)はちゃんと動いてくれない
ホワイトボックススイッチ用のNOSというかソフトウェアコレクションとして公開されているSONiCですが、githubのmasterブランチからビルドしたものはあまり安定していません。開発ブランチなので、これ自体はしかたないと考えます。
といっても何を動かそうとしてもいつもなんかおかしいダメダメだと言ったような感じではなく、commitが加わるとたまに特定機能の動作がおかしくなることがある、と言ったことが多いです。あるいは、うっかり秘孔をついてしまい(設定パラメータの値を変に指定するなどして)、プロセスが異常終了することもあります。ひどいときはビルドが通らないこともありますが、本稿ではビルド自体はできることを前提とします。
デバッグその前に: ベンダーのサポートは受けられる?
公開版SONiCは基本的にコミュニティによって無償でさまざまな問題に対応しています。スイッチベンダーによるサポートは軽くWeb検索したところ見つけることができたのは
- https://www.dell.com/ja-jp/work/shop/povw/sonic
- https://support.edge-core.com/hc/en-us/categories/360002134713-Edgecore-SONiC
このくらいでした。しっかり探せばもっとあるかもしれません。もちろんスイッチベンダーさんと個別にコンタクトできればそれなりにお話はできるかと思います。(金銭面その他条件あるかと思いますが)頼りにできるのであれば頼っていいと思います。
さまざまな事象
いろいろあります。
- プロセスが落ちる
- コンテナが予期せず終了した
- スイッチがシャットダウン処理している
- 設定が反映されない
- 設定パラメータの一部が伝わっていない
- 想定していた動作をしてくれない
- 機能がサポートされていない
- 表示が崩れる
個人的にはいずれも経験しています。
対応1 showコマンドで状況確認する
showコマンドを使うと、SONiCの持つ各機能について設定や状態を確認することができます。
show interfaces status
SONiCが管理するフロントポートの情報を表示します。IPアドレスの付与とは関係なく、リンクアップダウンといった情報を得ることができます。
admin@sonic:~$ show interfaces status
Interface Lanes Speed MTU FEC Alias Vlan Oper Admin Type Asym PFC
----------- --------------- ------- ----- ----- --------------- ------ ------ ------- --------------- ----------
Ethernet0 1,2,3,4 100G 9100 rs hundredGigE1/1 routed up up QSFP28 or later N/A
Ethernet4 5,6,7,8 100G 9100 rs hundredGigE1/2 trunk up up QSFP28 or later N/A
Ethernet8 9,10,11,12 100G 9100 rs hundredGigE1/3 routed up up QSFP28 or later N/A
(以下略)
operの項目がN/Aだった場合、なんらかの不具合が発生しています。また、不具合によってはまったくなにも表示されないことも起こりえます。Type欄にはQSFP28 or laterやSFP/SFP+/SFP28といったようなトランシーバー情報が表示されます。表示されるはずです。表示されなかったらxcvrdが動いていないかを確認してみてください。
show ip interfaces
SONiCが管理するインタフェースにIPアドレスを付与すると、それがフロントポートか管理ポートかVLANかはたまたループバックかにかかわらず、show ip interfacesコマンドの一覧に表示されるはずです。
admin@sonic:~$ show ip interfaces
Interface Master IPv4 address/mask Admin/Oper BGP Neighbor Neighbor IP
----------- -------- ------------------- ------------ -------------- -------------
Ethernet0 172.21.0.1/24 up/up N/A N/A
Ethernet12 10.0.0.3/31 up/up N/A N/A
Loopback0 10.1.0.1/32 up/up N/A N/A
Vlan2002 10.0.2.1/31 up/up N/A N/A
docker0 240.127.1.1/24 up/down N/A N/A
eth0 xxx.xxx.xxx.xxx/24 up/up N/A N/A
lo 127.0.0.1/16 up/up N/A N/A
admin@sonic:~$
IPアドレスを設定したはずのインタフェースが表示されない場合、致命的な問題が発生していると言えます。
show services
SONiCで提供されている各機能はサービスという単位でdockerコンテナにまとめられています。show servicesを使うと、SONiCが管理しているコンテナのうち動作しているものの一眼を表示させることができます。最低限、
- database docker
- swss docker
は動いていないといけません。BGPが必要であればbgp docker、NATが必要であればnat dockerが動いているかどうかを確認するといいでしょう。もちろんdocker psコマンドを使っても確認できます。
対応2 ログを見る
ログを見る前にswssloglevel
SONiCのログは通常NOTICEレベルまでしか記録されていませんが、より詳細な情報を得るためにログレベルをINFOあるいはDEBUGに変更することができます。
admin@sonic:~$ swssloglevel -l INFO -c orchagent
どんなログが出るのが正常ルートか、どういうログが出たらどこがおかしいのかといった知見はソースコードとにらめっこして得るしかないのがつらいところです。
show logging
動きがおかしいと思ったとき、まず最初に確認するのはログです。show loggingで確認できるので眺めます。コマンドのパラメータを記述ミスしているときは、これで気づくこともあります。しかし、SONiCを構成するプロセスの動作がおかしいこともあり、ログを見るとその痕跡を発見できたりします。
いくつか例を挙げると
- NATの設定が一切ハードウェアに反映されていない
-
syncdがSAIのエラーを受けてスイッチのシャットダウン処理が走った -
orchagentの中で例外が発生し、SIGABRTでプロセスが落ちた
といったことをログから把握できたりします。たとえば下記のような感じです(あくまで例です。このログは実際には発生しません)。
Oct 5 11:44:37.717490 sonic INFO swss#orchagent: :- addDnatToNhCache: Adding to NH cache indexed by translated ip 172.21.0.2, the DNAT entry with ip 10.0.2.1
Oct 5 11:44:37.719109 sonic INFO swss#supervisord: intfmgrd RTNETLINK answers: File exists
Oct 5 11:44:37.719109 sonic INFO swss#supervisord: orchagent terminate called after throwing an instance of 'std::logic_error'
Oct 5 11:44:37.719109 sonic INFO swss#supervisord: orchagent what(): basic_string::_M_construct null not valid
swss.rec, sairedis.rec
SONiCは設定情報を内部でやり取りするのにredis dbを使っています。このDBの情報を直接読むにはsonic-db-dumpを使うなどするのですが、それでは変更履歴をたどることができません。幸いSONiCはDBに加えられた変更をログファイルとして残しておくように作られていて、それがswss.recとsairedis.recです。
どちらのファイルも/var/log/swss/に置かれています。swss.recにはAPPL_DBに書かれた内容、sairedis.recにはASIC_DBに書かれた内容が時系列順に記録されています。
内容を突き合わせることで、本来設定されているべきデータがどこまで処理されているかを推測することができます。たとえば、
- NATの設定をする
-
swss.recにNATの設定が記録されている -
sairedis.recにNATの設定が記録されていない
といった場合、orchagentに何らかの問題があることが推測できます。同様にもしswss.recにも何も記録されていない場合、orchagentより前段となるcfgmgr(NATの場合はnatmgrd)に何らかの問題があると推測できます。
また、swss.recやsairedis.recには細かなパラメータ情報も記録されていますので、指定したはずのパラメータの値が反映されていないと言った状況も確認することができます。
対応3 プロセスが動いているか確認する
ログを見てプロセスがSIGABRTを受けて終了した、と言った状況がわかれば改めて確認する必要はないのですが、動いているべきプロセスが動いていないために最終的な動作もおかしいと言ったことは十分ありえます。
SONiCの設定を動作に反映させるため最低限必要なプロセスとして
orchagentsyncd
は欠かせません。これらのプロセスが動いていないとSONiCは正しく動きません。psやshow servicesなどで確認しましょう。
cfgmgrの各種プロセスも重要です。実際、ある日気づくとNATの設定が動作に反映されず、しかも全くログに残らないことがあったのですが、これはnatmgrdが動いていないことが直接の原因でした。これに関して解説すると
- 元々
natmgrdはswss dockerで動いていた - ある日の更新で新たにNAT用にnat dockerが用意され、
natmgrdはそちらで動かすよう変更された -
config_db.jsonにはどのコンテナを有効化するかの設定があるがnat dockerの設定はなかった - nat dockerが起動しないため、
natmgrdも動いていなかった
ということでした。これはsudo config feature nat enabledで解決しました。
対応4 gdbによるデバッグ
起動時は問題がないのになにか設定するとプロセスが落ちる、と言ったときの調査方法を紹介します。変な動作をしているときも、あたりをつけてbreakpointを設定することで対応できることもあります。原始的なprintfデバッグでももちろん大丈夫ですが、gdbを使うほうが楽ではないかと思います。
デバッグビルド
rules/configにINSTALL_DEBUG_TOOLS=yを加えてビルドします。通常よりもビルド時間が増えますので気長に待ちましょう。
ソースコードを展開する
デバッグビルドのSONiCにはソースコードをtar.gzで固めたものが含まれています。広げないとgdbが読めませんので、あらかじめ広げておきます。
admin@sonic:~$ sudo tar -C / -xvf /src/sonic_src.tar.gz
gdbでプロセス監視を開始する
通常gdbは、gdb デバッグ対象コマンドという形式で対象コマンドのデバッグを開始するのですが、すでに動いているプロセスをデバッグ対象に指定することもできます。-p プロセス番号です。
admin@sonic:~$ docker exec -it swss bash
# cd /src/sonic-swss/orchagent
# ps ax|grep orch
43 pts/0 Sl 0:00 /usr/bin/orchagent -d /var/log/swss -b 8192 -m xx:xx:xx:xx:xx:xx
310 pts/1 S+ 0:00 grep orch
# gdb -p 43
(gdb) c
breakpointを設定するときはcontinueする間に設定しておきます。
(gdb) b routeOrch->getNextHopEntry
(gdb) c
/var/coreにプロセス異常終了時のcoreが出力されていることがありますので、それを使って追うことができる場合はわざわざプロセス監視するまでもないかもしれません。
なお、gdbは各コンテナ内に用意されていますがホストには置かれていませんのでご注意ください。
問題を発生させgdbでデバッグ
別窓でSONiCにログイン、設定します。orchagentがSIGSEGVしたりSIGABRTしたり、あるいは事前に設定しておいたbreakpointに到達するとgdbのプロンプトが戻ってくるので、btやpコマンドなどを使い、状況確認していくといいでしょう。
対応(番外) bcmsh, bcmcmd (Broadcomの場合)
swss.recやsairedis.recは問題ない、ログを見ても設定は反映されていそう、でも動いてないと言った場合、プラットフォームがBroadcomであればSAIよりハードウェアに近いレベルでの状態確認が可能です。それがbcmshとbcmcmdです。
bcmshはパラメータ無しで起動します。表示に従いEnterを押すとプロンプトが出て、内蔵コマンドを使っていろいろな状態確認ができ、機能によってはスイッチASICへの設定も可能です。ただし細かいコマンド解説はありませんので、手探りで使うには限度があります。
admin@sonic:~$ bcmsh
Press Enter to show prompt.
Press Ctrl+C to exit.
NOTICE: Only one bcmsh or bcmcmd can connect to the shell at same time.
drivshell>?
?
help: "??" or "help" for summary
Commands common to all modes:
? ?? ASSert Attach BackGround
break BroadSync CASE CD ClearScreen
CONFig CONSole CoPy CPUDB CTEcho
CTInstall CTSetup DATE DBDump DBParse
DeBug DELAY DEVice DIR DISPatch
Echo EXIT EXPR FLASHINIT FLASHSYNC
FOR Help HISTory IF IPROCRead
IPROCWrite JOBS KILL LED LOCal
LOG LOOP LS M0 MCSCmd
MCSDump MCSLoad MCSMsg MCSStatus MCSTimeStamp
MKDIR MODE MORe MoVe NOEcho
Pause PCIEPHY PortMod PRINTENV PROBE
PSCAN PWD QUIT RCCache RCLoad
REBOOT REName RESET RM RMDIR
RPC SAVE SET SETENV SHell
SLeep TIME Version
Commands for current mode:
AGE ALPM ASF Attach Auth
BIST BPDU BTiMeout BUFfer CABLEdiag
CACHE CanCun CHecK CLEAR COLOR
COMBO COS CounTeR CustomSTAT DDRMemRead
DDRMemWrite DDRPhyRead DDRPhyTune DDRPhyWrite DELete
DETach DMA DmaRomTest DMIRror DPLL
DSCP DTAG Dump EditReg EGRess
EthernetAV EXTernalTuning EXTernalTuning2EXTernalTuningSumFieldProcessor
FLEXport FlowDb FlowTracker FlowTrackerMON FlowTrackerRemoteMON
Getreg GPORT H2HIGIG H2HIGIG2 HASH
HashDestinationHeaderMode HSP IbodSync INIT
Insert INTR IPFIX IPG IPMC
KNETctrl L2 L2LEARN L2MODE L3
LATency LINKscan LISTmem Listreg LLS
OOKup MCAST MemFirst MemNext MemSCAN
MemWatch MIM MIRror MODify ModMap
Modreg MPLS MSPI MTiMeout MultiCast
OAM PacketWatcher PBMP PHY PKTIO
POP PORT PortRate PortSampRate PortStat
PROBE PUSH PUTREG PVlan RATE
RateBw RegCMp RegWatch REMove ResTest
RXCfg RXInit RXMon SCHan SEArch
SER Setreg SHOW SOC SRAM
SramSCAN STACKMode StackPortGet StackPortSet STG
STiMeout STKMode StkTask SW_AN SwitchControl
SystemSnake TCAM TeCHSupport TestClear TestList
TestMode TestParameters TestRun TestSelect TMCheck
TMDumpMem TMShow TRUNK TX TXBeacon
TXCount TXSTArt TXSTOp VLAN WARMBOOT
WLAN Write XAUI
Dynamic commands for all modes:
BCMSAI
drivshell>
bcmcmdは、bcmshが提供するコマンドを1行で実行するものです。
admin@sonic:~$ bcmcmd 'l3 nat_egress show'
l3 nat_egress show
IDX TYPE ID IP MASK L4Port RefCount
1 SNAT 2 10.0.2.1 255.255.255.255 0 1
drivshell>
admin@sonic:~$
この例では、スイッチASICにSNATの設定(送出側)が入っていることが確認できます。
対応5 ソースコードの変更とビルド
ソースコードの展開
SONiCのソースコードは本体のリポジトリとgit submoduleのリポジトリに分割して管理されています。前出のorchagentやsyncdはsubmodule内にソースコードが格納されていますので、変更が必要であれば本体をcloneしたあとはmake initでsubmoduleを広げておきましょう。
buildhost$ git clone https://github.com/Azure/sonic-buildimage
buildhost$ cd sonic-buildimage
buildhost$ make init
ソースコードの編集
ビルド
デバッグ時は何度もビルドすることがありますが、一度ビルドが完了したあとはmake cleanしておかないと再ビルドしてくれませんのでご注意ください。(makeとは……)
buildhost$ make configure PLATFORM=broadcom
buildhost$ make clean
buildhost$ make all
Broadcomがターゲットの場合はPLATFORM=broadcom、MellanoxであればPLATFORM=mellanoxとします。
対応6 イメージ更新と動作確認
新しいイメージをインストールして再起動
sonic-installerコマンドを使えば/etc/sonic/config_db.jsonの内容は新しいイメージに引き継がれますので、これを使って更新することにします。ONIEで更新する場合はconfig_db.jsonの内容を予め保存しておかないと最初から設定しなおしになりますのでご注意ください。
% scp sonic-xxxxx.bin admin@xxx.xxx.xxx.xxx:
% ssh admin@xxx.xxx.xxx.xxx
admin@xxx.xxx.xxx.xxx's password:
Linux sonic 4.19.0-9-2-amd64 #1 SMP Debian 4.19.118-2+deb10u1 (2020-06-07) 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/
Last login: Thu Oct 8 08:06:01 2020 from yyy.yyy.yyy.yyy
admin@sonic:~$ sonic-installer install -y sonic-xxxxx.bin
(snip)
admin@sonic:~$ sudo shutdown -r now
注意点
resolv.confとsshのホスト鍵
事前に準備しておかないと失われます。
気にしないのであれば特に言うことはありません。たとえばマネジメントポートでDHCPクライアントを動かしてIPアドレスを取得しているのであれば、/etc/resolv.confを保持する必要はないでしょう。sshのホスト鍵が変わってもそれに追従すればいいだけであれば、ssh-keygen -Rで消してしまえばいいだけです。
/etc/config-setup/にバックアップとリストアのためのスクリプトを置くことで、更新前の設定を引き継ぐことができます。無保証ですが、下記のようなものを用意します。
https://github.com/iMasaruOki/sonic-config-setup-hooks
いちいち用意するのが面倒であれば、/host/に単純にコピーしておいて、新しいイメージで起動後にログインし、/host/からコピーで書き戻せばそれでも大丈夫です。
バージョン名の重複
SONiCのイメージにはビルド時に付与されるバージョン文字列があります。ビルドログを残しておくとわかりますが
"SONIC_IMAGE_VERSION" : "master.0-dc6b388"
といったものです。同じバージョンがすでにインストール済みだとSONiCはすでにあるものとみなしてビルドしなおしたイメージをインストールすることができません。
デバッグ時は何度もイメージをビルドしてはインストールを繰り返すことになりますが、手順次第ではバージョン番号が変わりませんのでご注意ください。
すでに(見かけ上)同じバージョンのSONiCがインストールされている場合の対応方法ですが、下記になります。
-
sonic-installer set-next-bootを使い、次に起動するバージョンを別のものにする - rebootし、別バージョンが起動したら
sonic-installer removeでもう片方を消す - (見かけ上)同じバージョンのSONiCを
sonic-installer installでインストールする - rebootする
最後に
やや備忘録気味ですが、SONiCのデバッグ手法についておおまかに解説しました。
しかし、実際のところorchagentやsyncdの挙動、APPL_DBやASIC_DBの構造、SAIライブラリの挙動などがわからないとどうにも手がつけられないと思います。うっかりデバッグする羽目になったら大変と思います。ベンダー提供のSAIライブラリ内の挙動に左右されどうにもできないこともあると思います。がんばれないこともあると思いますが、がんばりましょう。応援します。