GoでgRPCを使ってIOS XRからTelemtryを収集する
Telemetryの取得方法は様々あり、最近ではOSSのcollectorが作られていることもあって、こと統計情報取得に関してはSNMPから置き換わる日も遠くなさそうである。
とはいえ、ElasticsearchやinfluxDB等、成熟した製品があるデータストアと比べ、TelemetryのCollectorは発展途上なのも事実。
Pythonを使った手法は以前、ネットワークプログラマビリティ勉強会で紹介したので、今回はGoを用いて、CiscoのIOS XRからDial outでModel Driven Telemetryを取得する方法を紹介する。(pipelineがまさしくGoで書かれたCollectorそのものだが、枝葉が多くて読み解きにくいので)
なお、エラーハンドリングなどは完全に省略しているので、必要に応じて追加して頂きたい。
手軽にIOS XRを試すには、AWSでXRv 9000を立てればいい。
Telemetry用には以下のようなconfigを投入する。
telemetry model-driven
destination-group gollector
address-family ipv4 192.168.1.100 port 2103
encoding self-describing-gpb
protocol grpc no-tls
!
!
sensor-group Perf
sensor-path Cisco-IOS-XR-wdsysmon-fd-oper:system-monitoring/cpu-utilization
!
subscription PerfStats
sensor-group-id Perf sample-interval 5000
destination-id gollector
source-interface MgmtEth0/RP0/CPU0/0
!
!
ここでは、XRvからサーバ(192.168.1.100)のport 2103宛に、CPU使用率の情報を投げる設定を入れている。お試しなので、TLSは使わず、トランスポートにgRPC、データフォーマットにGPBを使う。
サーバ側はなんでもいいが、今回CentOS8.2を使った。SELinuxとfirewalldの設定を変えておく。
setenforce 0
systemctl stop firewalld
また、Goをインストールしてパスを通しておく。
wget http://golang.org/dl/go1.15.2.linux-amd64.tar.gz
tar -C /usr/local -zxf go1.15.2.linux-amd64.tar.gz
export PATH=$PATH:/usr/local/go/bin
目的に則したGo用のファイル郡はすでに用意されており、今回はDial out用のファイルを参照する。このファイルでserver apiは以下のように定義されていることから、
type GRPCMdtDialoutServer interface {
MdtDialout(GRPCMdtDialout_MdtDialoutServer) error
}
MdtDialout
メソッドを実装すればよいことがわかる。以下のような感じ。
package main
import (
dialout "github.com/cisco/bigmuddy-network-telemetry-proto/proto_go/mdt_grpc_dialout"
)
type server struct{}
func (s *server) MdtDialout(stream dialout.GRPCMdtDialout_MdtDialoutServer) error {
//ここに受け取ったデータに対する処理を書く
}
次に、gRPCのserverを立てる。
package main
import (
"net"
"google.golang.org/grpc"
dialout "github.com/cisco/bigmuddy-network-telemetry-proto/proto_go/mdt_grpc_dialout"
)
type server struct{}
func (s *server) MdtDialout(stream dialout.GRPCMdtDialout_MdtDialoutServer) error {
//ここに受け取ったデータに対する処理を書く
}
func main() {
listen, _ := net.Listen("tcp", "0.0.0.0:2103")
s := grpc.NewServer()
dialout.RegisterGRPCMdtDialoutServer(s, &server{})
s.Serve(listen)
}
Model Driven Telemetryは、このファイルに記載された形式で送られてくる。(Dial outで受け取った戻り値のMdtDialoutArgsに含まれるData []byteがこの形式)
そこで、その定義に従いUnmarchalしてやる。また、self-describing gpbの場合、DataGpbkvにTelemetryデータが格納される。それらを勘案して、以下のようにすればデータを取得できる(大量のデータが送られてくるので注意)。
package main
import (
"fmt"
"net"
"google.golang.org/grpc"
"github.com/golang/protobuf/proto"
telem "github.com/cisco/bigmuddy-network-telemetry-proto/proto_go"
dialout "github.com/cisco/bigmuddy-network-telemetry-proto/proto_go/mdt_grpc_dialout"
)
type server struct{}
func (s *server) MdtDialout(stream dialout.GRPCMdtDialout_MdtDialoutServer) error {
for {
msg, _ := stream.Recv()
telem := &telem.Telemetry()
err := proto.Unmarshal(msg.Data, telem)
if telem.DataGpbkv != nil {
fmt.Println(telem.DataGpbkv)
}
}
}
func main() {
listen, _ := net.Listen("tcp", "0.0.0.0:2103")
s := grpc.NewServer()
dialout.RegisterGRPCMdtDialoutServer(s, &server{})
s.Serve(listen)
}
ここで注意が必要なのは、google.golang.org/protobuf/proto
ではなく、 github.com/golang/protobuf/proto
を使わなければならないということろである。エディタの補完では前者になってしまうことがあるので、明示的に後者を指定すること。
あとは、telem.DataGpbkv
をいい感じにパースして、目的にデータストアに投げればいい(ここはsensor pathに応じて異なる処理が必要になるので割愛する)。
ちなみに、gRPC serverと接続しているとき、XRv側では以下のようにステータスを確認できる。
RP/0/RP0/CPU0:xrv#show telemetry model-driven subscription PerfStats
Sun Sep 20 00:17:49.074 JST
Subscription: PerfStats
-------------
State: ACTIVE
Source Interface: MgmtEth0_RP0_CPU0_0(Up 0x60000000)
Sensor groups:
Id: Perf
Sample Interval: 5000 ms
Sensor Path: Cisco-IOS-XR-wdsysmon-fd-oper:system-monitoring/cpu-utilization
Sensor Path State: Resolved
Destination Groups:
Group Id: gollector
Destination IP: 192.168.1.100
Destination Port: 2103
Encoding: self-describing-gpb
Transport: grpc
State: Active
No TLS
Total bytes sent: 0
Total packets sent: 0
Collection Groups:
------------------
Id: 1
Sample Interval: 5000 ms
Encoding: self-describing-gpb
Num of collection: 0
Collection time: Min: 0 ms Max: 0 ms
Total time: Min: 0 ms Avg: 0 ms Max: 0 ms
Total Deferred: 0
Total Send Errors: 0
Total Send Drops: 0
Total Other Errors: 0
No data Instances: 0
Last Collection Start:2020-09-20 00:17:49.516345779 +0900
Last Collection End: 2020-09-20 00:17:44.511967965 +0900
Sensor Path: Cisco-IOS-XR-wdsysmon-fd-oper:system-monitoring/cpu-utilization
以上
Discussion