Upgrade to Pro — share decks privately, control downloads, hide ads and more …

PythonツールであるpygnmiをSONiCのgNMIに対して使ってみた

 PythonツールであるpygnmiをSONiCのgNMIに対して使ってみた

PythonツールであるpygnmiをSONiCのgNMIに対して使ってみた
APRESIA Systems株式会社
長尾剛樹

SONiC Workshop Japan 2025
https://sonic.connpass.com/event/345182/

Tweet

More Decks by SONiC Users Group Japan

Other Decks in Technology

Transcript

  1. 4 ◆コマンドライン ◊sshなどで接続し、LinuxコマンドやSONiC CLIを使用した、機器の設定や状態確認 ◆SNMP ◊ネットワーク機器から定期的なポーリングを通して稼働情報などを収集 ◆REST API(RESTCONF) ◊HTTP プロトコルを通じたデバイス情報の取得、設定の変更

    ◆gNMI ◊ストリーミングによるTelemetryが可能 ◊gRPC/プロトコルバッファにより、異なる言語間でもデータの構造が常に同じである ことが保証される SONiCがサポートするネットワーク管理技術
  2. 5 ◆以下の理由から、複雑化したネットワークでは、リアルタイム性、柔軟性がある管理技術 が求められる ◊手動から運用自動化への切り替わりによる効率化、迅速化、ミス削減の要求 ◊コントローラによる集中管理、構成管理ツール (Ansible, etc.) の普及 ネットワーク管理技術比較 項目

    SNMP (Simple Network Management Protocol) REST API (RESTCONF) gNMI (gRPC Network Management Interface) データ収集 ポーリング (クライアント主導) ポーリング (HTTP GET) / 通知 (Webhookなど) ストリーミング (サーバーPush可能) リアルタイム性 △ (ポーリング間隔依存) 〇 (ポーリング間隔依存 or 通知方 式による) ◎ (高い、ストリーミング) データ構造 MIB (複雑、ベンダー依存性) YANG model (構造化・標準化) YANG model(構造化・標準化) 操作 Get, Set (限定的) CRUD (Get, POST, PUT, DELETE) 〇 Get, Set, Subscribe (ストリー ミング) ◎ 通信効率 △ (UDP、テキストベース) 〇 (HTTP/S、JSON/XML) ◎ (gRPC/HTTP2)
  3. 6 ◆YANGはデータモデリング言語 ◊ネットワーキングデータモデルの記述を 目的にIETFにて標準化 ◊監視ツールとネットワーク機器の両方で YANG modelにベースにしてデータを保 持しているため、gNMIやREST APIで情 報のやり取りが可能

    ◊そのため、異なる機器でも共通のYANG モデルに対応していれば、監視ツールは 機器の差分を気にする必要がなくなる YANG model とは module: openconfig-interfaces +--rw interfaces +--rw interface* [name] +--rw name -> ../config/name +--rw config | +--rw name? string | +--rw type identityref | +--rw mtu? uint16 | +--rw loopback-mode? boolean | +--rw description? string | +--rw enabled? boolean +--ro state | +--ro name? string | +--ro type identityref | +--ro mtu? uint16 | +--ro loopback-mode? boolean | +--ro description? string | +--ro enabled? boolean | +--ro ifindex? uint32 | +--ro admin-status enumeration | +--ro oper-status enumeration | +--ro last-change? oc-types:timeticks64 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +--ro carrier-transitions? oc-yang:counter64 +--ro last-clear? oc-types:timeticks64 YANG model ネットワーク機器(Server) 監視ツール(Client) REST API gNMI 例として、openconfig-interfaces.yangをツリー構造にして表示したもの YANG model
  4. 7 ◆読み方:ピーワイジーエヌエムアイ ◆最新版 0.8.15 (2025/3月更新) ◆主機能: ◊デバイスへの接続 (TLS/SSLサポート) ◊gNMI 操作

    (Capabilities, Get, Set, Subscribe) をシンプルな API で提供 ◆pyGNMI により自動化可能なもの ◊状態監視 ◊設定変更 ◊リアルタイムデータの収集(ストリーミングテレメトリ) ◆現状の対応 Network OS ◊テスト済みOS:Arista EOS, Nokia SR OS, Cisco IOS XR, Juniper JUNOS, Nokia SRLinux, Cisco NX-OS ◊テスト段階:Broadcom SONiC pyGNMI概要 github.com/akarneliuk/pygnmi/
  5. 8 ◆監視ツールとSONiCでの情報交換は以下のように行われる。 ◊Python(pyGNMI)を例に記載 pyGNMIとSONiCの通信アーキテクチャ gNMI/Telemetry Client (from pyGNMI) Redis DB

    gNMI/Telemetry server Vender ASIC SAI API syncd Subscribe (poll/stream) Get gRPC Redis API SONiC(Server) 監視ツール(Client) Python apps Python library other app components YANG modelに準じたデータ制御
  6. 9 ◆Client ◊Ubuntu22.04 LTS ◊Python3.10 (venvを使った仮想環境) −以下を事前にインストール • grpcio twine

    pytest coverage dictdiffer pylint flake8 protobuf −pipを使用してpyGNMIをインストール ◆Server ◊Community SONiC-vs 202305/202311/202405/202411 ◊AS7726-32X + Community SONiC 202305/202311 今回pyGNMIを実験した環境
  7. 10 ◆Server(SONiC)側で実施 ◊ 証明書作成 − 以下のリンクを参考に作成しました − https://karneliuk.com/2023/01/automation-19-enabling-ocp-sonic-to-be-managed-via-gnmi-with-pygnmi/ ◆Telemetry(gNMI)コンテナにてUser作成、証明書を使用したgNMI_serverの起動 sudo

    openssl req -x509 -newkey rsa:4096 -keyout dsmsroot.key -out dsmsroot.cer -sha256 -days 365 -nodes -subj '/CN=lab-ca’ sudo openssl req -new -newkey rsa:4096 -nodes -keyout server.key -out server.csr -subj "/CN=sonic" sudo openssl x509 -req -in server.csr -CA dsmsroot.cer -CAkey dsmsroot.key –CAcreateserial -out server.cer -days 365 -sha512 pyGNMIでSONiCにTLS/SSLを使ってアクセスするための認証設定 自己署名証明書 秘密鍵 (dsmsroot.key) と証明書 (dsmsroot.cer) クライアントの秘密鍵 (server.key) 証明書署名要求 (CSR) (server.csr) 署名された証明書 を生成 (streamingtelemetryserver.cer) [admin$sonic] sudo docker exec -ti gnmi bash [root$gnmi] uesradd admin [root$gnmi] /usr/sbin/telemetry -logtostderr --ca_crt dsmsroot.cer --server_crt server.cer --server_key server.key --port 50051 --allow_no_client_auth -v=2 --gnmi_translib_write
  8. 11 ◆SONiCが対応しているyang modelを取得する gnmi_capability スクリプト from pygnmi.client import gNMIclient import

    json if __name__ == "__main__": with gNMIclient( target=(host["ip_address"], host["port"]), username=host["username"], password=host["password"], path_root="ca.pem", path_cert="server.pem", path_key="server.key", override="sonic", ) as gc: result = gc.capabilities() print(json.dumps(result,indent=4)) Server側で生成した認証ファイルを 事前にClientにコピーしておく YANG modelを取得する関数
  9. 12 ◆Capabilityの操作により、SONiCが対応しているyang modelを確認 { "supported_models": [ { "name": "openconfig-acl", "organization":

    "OpenConfig working group", "version": "1.0.2" }, { "name": "openconfig-acl", "organization": "OpenConfig working group", "version": "" }, { "name": "openconfig-sampling-sflow", "organization": "OpenConfig working group", "version": "" }, { "name": "openconfig-interfaces", "organization": "OpenConfig working group", "version": "" }, { "name": "openconfig-lldp", "organization": "OpenConfig working group", "version": "1.0.2" }, { "name": "openconfig-platform", "organization": "OpenConfig working group", "version": "1.0.2" }, { "name": "openconfig-system", "organization": "OpenConfig working group", "version": "1.0.2" }, { "name": "ietf-yang-library", "organization": "IETF NETCONF (Network Configuration) Working Group", "version": "2016-06-21" }, { "name": "sonic-db", "organization": "SONiC", "version": "0.1.0" } ], "supported_encodings": [ "json", "json_ietf", "proto" ], "gnmi_version": "0.7.0" } gnmi_capability 結果
  10. 13 ◆YANG modelであるopenconfig-interfacesを使用したgetスクリプト例 gnmi_get スクリプト from pygnmi.client import gNMIclient import

    json if __name__ == "__main__": with gNMIclient( target=(host["ip_address"], host["port"]), username=host["username"], password=host["password"], path_root="ca.pem", path_cert="server.pem", path_key="server.key", override="sonic“ ) as gc: result = gc. get(path=['openconfig-interfaces:interfaces’]) print(json.dumps(result,indent=4)) 指定されたYANG modelのデータを取得する関数
  11. 14 ◆実行結果からGet操作が可能なことを確認 ◊以下は、取得したEthernet0 interface データの抜粋 gnmi_get 結果 {"update": [ {

    "path": "openconfig-interfaces:interfaces/interface[name=Ethernet0]", "val": { "openconfig-interfaces:interface": [ { "config": { "enabled": true, "mtu": 9100, "name": "Ethernet0" }, "openconfig-if-ethernet:ethernet": { "config": { "port-speed": "openconfig-if-ethernet:SPEED_100GB" },
  12. 15 ◆YANG modelであるopenconfig-interfacesを使用したsubscribeスクリプト例 gnmi_sub スクリプト subscribe = { "subscription": [

    { "path": "openconfig:/interfaces", "mode": "sample", “sample_interval”: 30000000000 },], "mode": "stream", "encoding": "json“ } if __name__ == "__main__": with gNMIclient(…省略…) as gc: result = gc.subscribe(subscribe=subscribe) print(json.dumps(result,indent=4)) 指定されたYANG modelのデータを取得する関数 この例は30秒間隔のストリーミングテレメトリ (1000000000以上(1s)を指定可能)
  13. 16 ◆Subscribeの実行結果でも、mtuやspeedの設定や統計情報を取得可能 gnmi_sub 結果 {'update': {'update’: [ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {'path': 'name',

    'val': 'Ethernet0'}, {'path': 'state/counters/out-errors', 'val': 0}, {'path': 'state/counters/out-unicast-pkts', 'val': 25812}, {'path': 'subinterfaces/subinterface[index=0]/index', 'val': 0}, {'path': 'ethernet/state/counters/in-oversize-frames', 'val': 0}, {'path': 'ethernet/config/port-speed', 'val': 'SPEED_100GB'}, {'path': 'state/counters/out-multicast-pkts', 'val': 0}, {'path': 'subinterfaces/subinterface[index=0]/config/index', 'val': 0}, {'path': 'config/mtu', 'val': 9100}, {'path': 'state/counters/out-broadcast-pkts', 'val': 0}, {'path': 'subinterfaces/subinterface[index=0]/state/index', 'val': 0}, {'path': 'ethernet/state/port-speed', 'val': 'SPEED_100GB'}, {'path': 'ethernet/state/counters/in-distribution/in-frames-65-127-octets', 'val': 0}, {'path': 'state/counters/in-errors', 'val': 0}, {'path': 'state/counters/in-octets', 'val': 0}, {'path': 'state/counters/in-pkts', 'val': 0}, {'path': 'state/counters/out-pkts', 'val': 25812}, {'path': 'state/enabled', 'val': True}, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 'timestamp': 1744347247156379177, 'prefix': 'openconfig- interfaces:interfaces/interface[name=Ethernet0]’} } ※出力結果は見やすいよう編集しており、本来は改行されていません。 ▪ mtu/speedのconfig/state ▪ 統計情報
  14. 17 ◆YANG modelであるsonic-portを使用した、setスクリプト例 gnmi_set スクリプト例 update_cfg = [ ( "sonic-port:sonic-port/PORT/PORT_LIST[ifname=Ethernet0]",

    { "sonic-port:PORT_LIST": [ { "admin_status": "up", "alias": "hundredGigE1", "ifname": "Ethernet0", "index": 1, "lanes": "1,2,3,4", "mtu": 1500, }]})] if __name__ == “__main__”: with gNMIclient(…省略…) as gc: config_result = gc.set(update=update_cfg, encoding="json_ietf") print(f"{config_result}") 指定されたconfigをsetする関数
  15. 18 ◆vs版では設定操作不可だったため、実機環境(AS7726-32X + SONiC 202305 /202311)で検証 ◊反応は正常に返るが、SONiC redisDBには設定反映されていない。 ◊原因: sonic-gnmi

    issues#20 (gNMIのsetが未対応) gnmi_set 結果 Client Server I1218 18:32:26.061647 330 common_app.go:547] transformer.XlateToDb() returned result DB map - map[UPDATE:map[4:map[PORT:map[Ethernet0:"mtu": "1500" "admin_status": "up" "alias": "hundredGigE1" "index": "1" "lanes": "1,2,3,4" ]]]] Default value DB Map - map[] Aux DB Map - map[] I1218 18:32:26.061703 330 common_app.go:582] Result Tables List[PORT] I1218 18:32:26.061885 330 common_app.go:376] processUpdate:path =/sonic-port:sonic- port/PORT/PORT_LIST[ifname=Ethernet0] I1218 18:32:26.061907 330 common_app.go:609] Proceeding to perform DB operation I1218 18:32:26.061943 330 utils.go:50] cvlSortDepTblList = [] I1218 18:32:26.061956 330 common_app.go:642] Returning from processCommon() - success ~/pygnmi$ python3 set.py {'timestamp': 0, 'prefix': None, 'response': [{'path': 'sonic-port:sonic- port/PORT/PORT_LIST[ifname=Ethernet0]', 'op': 'UPDATE'}]}
  16. 19 ◆結果 ◊Capability/Get/Subscribeは正常に動作 ◊Set操作は下記環境では動作確認が不可 −SONiC-vs 202305/202311/202405/202411, −SONiC 202305/202311 (+ AS7726-32X)

    ※202405以降は別問題により実験不可 ◆わかったこと ◊SONiCのTelemetryコンテナの起動オプションに --insecureを有効にした場合には、す べての操作を確認できなかったため、認証関連の設定が必要 ◊Get,Subscribeについては、仮想SONiCとPython(pyGNMI)で手軽に試すことが可能 pyGNMIをCommunity SONiCに使ってみた結果まとめ