内部実装¶
gNMI / OpenConfig の内部実装は、telemetry コンテナの中に gNMI server があり、translib / sonic-mgmt-common 経由で YANG → CONFIG_DB / APPL_DB / STATE_DB に変換するという縦の流れを押さえると整理できます。GET / SET / SUBSCRIBE で経路がそれぞれ違うのが特徴です。
データフロー¶
flowchart LR
CLIENT[gNMI client] -->|gRPC TLS| GNMI[telemetry / gnmi server<br/>sonic-gnmi]
GNMI --> TRANSLIB[translib / sonic-mgmt-common]
TRANSLIB --> YANG[sonic-yang-models]
GNMI -->|GET/SET| CONFIG[(CONFIG_DB)]
GNMI -->|GET/SUBSCRIBE| APPL[(APPL_DB / STATE_DB / COUNTERS_DB)]
GNMI -->|on_change subscribe| REDIS_PSUB[Redis keyspace notifications]
GNMI -->|sample/streaming| POLL[poll loop]
GNMI -->|gNOI| HOST[host service<br/>sonic-host-service]
GNMIGET[GNMIGet] --> ZMQ[orchagent ZMQ endpoint]
主要 daemon / コンポーネントの責務¶
| コンポーネント | 主な実体 | 責務 |
|---|---|---|
telemetry container |
sonic-gnmi(旧 sonic-telemetry)/ gnmi_server |
gNMI / gNOI / gNSI gRPC server。TLS / mTLS 終端 |
translib (sonic-mgmt-common/translib/) |
translib.go、transformer/ |
YANG path ↔ Redis テーブルの双方向変換、ocyang バインドを使う |
transformer |
per-module transformer(translib/transformer/xfmr_*.go) |
OpenConfig path から SONiC YANG / Redis テーブルへの mapping 規則 |
sonic-yang-mgmt / sonic-yang-models |
yang-models/*.yang |
SONiC 独自 YANG。CONFIG_DB との整合の根拠 |
dialin / dialout server |
telemetry/dialin.go / dialout.go |
dial-in (subscribe) と dial-out collector |
gNOI services |
gnoi/system、gnoi/file、gnoi/os |
Reboot、Time、Ping、SetPackage 等。host service 経由で OS 操作 |
gNSI services |
gnsi/certz、gnsi/authz、gnsi/pathz |
証明書ローテーション / 認可ポリシー |
SAI 属性使用¶
gNMI server は SAI 属性を直接触りません。代わりに COUNTERS_DB の counter(port / queue / PG / buffer pool)、STATE_DB の運用状態を読み取り側として参照します。SAI 属性は flexcounter が裏で populate しています(→ 08 章 / 20 章)。
書き込み側で gNMI SET から SAI に到達する経路は:
gnmi SET→ translib transformer →CONFIG_DBCONFIG_DB変更 →*mgrd/orchagent→ SAI
であり、gNMI server から直接 ASIC_DB を叩く経路はありません。
Redis テーブル参照関係¶
gNMI Path Redis target
/sonic-port:sonic-port/PORT/... ─> CONFIG_DB:PORT
/sonic-port:sonic-port/PORT_TABLE/ ─> APPL_DB:PORT_TABLE
/openconfig-interfaces:interfaces/... ─> transformer 経由で CONFIG_DB:PORT + APPL_DB:PORT_TABLE 合成
/openconfig-system:system/processes/ ─> STATE_DB / proc
counters subtree ─> COUNTERS_DB:COUNTERS:<oid>
SUBSCRIBE は target が STATE_DB か COUNTERS_DB かによって on_change(keyspace notifications)と sample(poll)を選びます。OpenConfig path の場合、transformer が複数 DB をまたぐためにキャッシュ + 仮想的な change-set を作って notify します。
ZMQ / Redis pub/sub の使用¶
- Redis keyspace notifications(
__keyspace@*__)を gNMI server が subscribe して on_change を出します。 - ZMQ: GNMIGet / GNMISet の一部経路で、orchagent との直結 RPC を行う実装が追加されました(
gnmi-native-write系の HLD)。これにより CONFIG_DB を経由しない write が一部のテーブルで可能です。 - dial-out: collector への gRPC push(poll/on_change の結果)。
- gNOI の
Reboot/Ping等は host service(sonic-host-service)に DBus / Unix socket で投げ、root 権限の操作はコンテナ外で行います。
既知の実装上の制約¶
- OpenConfig path は
transformerが個別に実装する必要があり、未実装の path は SET / GET が NotFound になります。すべての OC モジュールが網羅されているわけではありません。 - gNMI Set の transaction 境界は単一 SetRequest 内のみ。複数 path で一部失敗すると rollback ロジックがあるが、CONFIG_DB に書き込んだ後の orchagent / SAI 反映を待たないため、SET が成功しても ASIC への反映までは別の subscribe で確認する必要があります。
- TLS 設定は
DEVICE_METADATA系ではなくGNMI/TELEMETRY_CLIENTテーブルで管理し、CONFIG_DB のTELEMETRY|gnmiなどのキー構造で証明書パスを指定します。CLI/UI がconfig gnmi系で揃っていない箇所がある点に注意です。 - gNSI の certz は
sonic-host-serviceに証明書ローテーションを依頼する経路で、OS 側/etc/sonic/telemetry/のファイル更新まで含めて atomicity を担保する設計です(途中失敗で telemetry が起動できなくなる事故が過去 issue にあります)。 - Subscribe の
samplemode で interval を極端に短く(例: 100ms)すると、counter 読み出し(flexcounter polling は通常 10s)と整合せず、同じ値を返し続けることがあります。
認証 / 認可の内部経路¶
gNMI server の認証は CONFIG_DB の TELEMETRY / GNMI / TELEMETRY_CLIENT テーブルを起点に、複数経路で行われます。
| 認証方式 | 入口 | 確認先 |
|---|---|---|
| TLS client cert | mTLS handshake | /etc/sonic/telemetry/dsmsroot.cer 等 |
password |
gRPC metadata | /etc/sonic/dsms_users または PAM |
cert_username |
TLS CN / SAN | gNSI authz policy で確認 |
| JWT | gRPC metadata | gnsi/authz の policy 評価 |
gnsi/authz の policy は protobuf テキストで、SetRequest の rotate API でローテーションする設計です。policy が壊れていると gNMI 自体が起動できない fail-closed 設計です。
性能観点¶
- subscribe sample interval の下限は flexcounter polling と整合させるのが安全で、port counter は 10s、queue / PG は 10s、buffer pool は 60s が標準です。100ms 等は無意味(同じ値を返す)です。
- GET の最大サブツリー深さには実質制限が無く、
/interfaces全体を 1 度に取ると数千 OID の Redis 読み出しが直列で走り、数秒〜数十秒かかります。client 側でリスト要素を絞るのが定石です。 - dial-out は collector への gRPC で QoS / retry の制御が薄く、collector 側がオフラインのときに gNMI server のメモリが膨らむ報告があります。
TELEMETRY_CLIENTのqueue_sizeで抑えます。
translib transformer の責務分担¶
translib/transformer/ 配下の per-module ファイル(xfmr_<module>.go)は、OpenConfig YANG path を SONiC YANG path に変換する mapping を提供します。
| transformer | 対象 |
|---|---|
xfmr_interfaces.go |
/openconfig-interfaces/interfaces ↔ PORT / PORT_TABLE |
xfmr_network_instance.go |
/openconfig-network-instance ↔ VRF / BGP_NEIGHBOR / etc |
xfmr_acl.go |
/openconfig-acl ↔ ACL_TABLE / ACL_RULE |
xfmr_qos.go |
/openconfig-qos ↔ QUEUE / SCHEDULER / WRED_PROFILE |
xfmr_system.go |
/openconfig-system ↔ DEVICE_METADATA / SYSLOG / etc |
未実装の transformer がある OC path に対して GET / SET を投げると、translib 層で NotFound を返す動作で、HLD と実装の乖離が出やすいポイントです。
GNMIGet (ZMQ direct write) 経路¶
gnmi-native-write 系の改善で、いくつかのテーブル(DASH_* 系、APP_DB:GENERIC_CONFIG_UPDATER_TABLE 等)は GNMISet → orchagent の ZMQ endpoint に直接届く経路が追加されました。これにより CONFIG_DB を経由しないため、CONFIG_DB rewrite race / 大量更新時の Redis 単一スレッド bottleneck を回避できます。
| 項目 | 通常経路 | ZMQ direct |
|---|---|---|
| Entry point | CONFIG_DB write | orchagent ZMQ socket |
| Atomicity | Redis transaction (MULTI/EXEC) |
ZMQ message + orchagent task |
| Failure feedback | STATE_DB から間接的 | gNMI response に直接 |
| 対象 | 全テーブル | DASH 等の opt-in テーブルのみ |
CONFIG_DB を bypass するため、config save / config reload の永続化対象には入りません。再起動後に再投入する責任は外部 controller 側にあります。