On the last two videos, we went over the basic concepts of model-driven telemetry and presented a demo using pipeline and other tools.
🤖 Here’s what we used:
- XRv IOS-XR 6.4.2 (xrv9k-fullk9-x-6.4.2.ova) 3GB RAM / 1×2 CPU / 45GB HD
- BIRD Routing Daemon v1.6.0
- Pipeline v1.0.0
- InfluxDB v1.7 (container)
- Grafana v4.2.0 (container)
XRv IOS-XR
This is the XRv configuration, notice I cared to configure NTP, this is because I want to make sure the telemetry data goes out with the correct UTC timestamp, which will make our lives easier when working with InfluxDB and Grafana:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
ntp server 74.117.214.2 prefer ! interface GigabitEthernet0/0/0/0 ipv4 address 10.0.0.2 255.255.255.0 ! route-policy BGP-EXPORT-POLICY pass end-policy ! route-policy BGP-IMPORT-POLICY pass end-policy ! router ospf BACKBONE area 0 interface GigabitEthernet0/0/0/0 ! ! ! router bgp 64002 bgp router-id 10.0.0.2 address-family ipv4 unicast redistribute connected ! neighbor 10.0.0.56 remote-as 64056 shutdown address-family ipv4 unicast route-policy BGP-IMPORT-POLICY in route-policy BGP-EXPORT-POLICY out ! ! ! telemetry model-driven max-containers-per-path 0 destination-group PIPELINE-DGROUP address-family ipv4 10.0.0.56 port 5432 encoding self-describing-gpb protocol tcp ! ! sensor-group EVENT-SENSORS sensor-path Cisco-IOS-XR-infra-syslog-oper:syslog/messages/message ! sensor-group SENSORS-FOR-PIPELINE sensor-path Cisco-IOS-XR-wdsysmon-fd-oper:system-monitoring/cpu-utilization sensor-path Cisco-IOS-XR-infra-statsd-oper:infra-statistics/interfaces/interface/latest/data-rate sensor-path Cisco-IOS-XR-infra-statsd-oper:infra-statistics/interfaces/interface/latest/generic-counters sensor-path Cisco-IOS-XR-ip-rib-ipv4-oper:rib/vrfs/vrf/afs/af/safs/saf/ip-rib-route-table-names/ip-rib-route-table-name/protocol/bgp/as/information sensor-path Cisco-IOS-XR-ip-rib-ipv4-oper:rib/vrfs/vrf/afs/af/safs/saf/ip-rib-route-table-names/ip-rib-route-table-name/protocol/ospf/as/information ! subscription SUBSCRIPTION sensor-group-id SENSORS-FOR-PIPELINE sample-interval 5000 sensor-group-id EVENT-SENSORS sample-interval 0 destination-id PIPELINE-DGROUP ! ! |
Also, notice the sensor-group called EVENT-SENSORS, when referenced under the subscription, is configured with a sample-interval of 0, this means it will behave like an “event-driven” sensor, which is why we’re using it for our syslog. In the videos referenced above, we had our event-sensors inside an additional subscription that was referencing the same destination-group, which achieves the same outcome, so, as you can see, there’s some good flexibility within the [telemetry model-driven] hierarchy.
Note: You can quickly see the YANG models available in your IOS-XR device by looking in the /pkg/yang directory from the router shell:
0 1 |
RP/0/RP0/CPU0:XRv#run [xr-vm_node0_RP0_CPU0:~]$ls /pkg/yang |
BIRD Routing Daemon
The strategy for BIRD will be to import all the routes under [protocol static] and then use filters to split the ones that we’re going to advertise via BGP and the ones advertised via OSPF. For BIRD to acknowledge our static routes, they have to be in the format of “route prefix/prefix-length next-hop“, so we can use this Python3 script to generate the route files:
And then:
0 |
$python3 routegen.py 20000 15000 |
The above will generate 20K 10.44.X.X and 15K 10.88.X.X routes in files called bird.bgp and bird.ospf respectively.
And this is the configuration file we’re using for BIRD:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
define bgp_pl = [ 10.44.0.0/16+ ]; define ospf_pl = [ 10.88.0.0/16+ ]; filter bgp_filter { if net ~ bgp_pl then accept; else reject; } filter ospf_filter { if net ~ ospf_pl then accept; else reject; } protocol static { import all; include "/home/paan/bird-router/bird.bgp"; include "/home/paan/bird-router/bird.ospf"; } protocol ospf { tick 2; rfc1583compat yes; area 0.0.0.0 { stub no; interface "ens*" { hello 10; retransmit 5; cost 10; transmit delay 5; dead count 4; dead 40; wait 40; type broadcast; authentication none; }; }; export filter ospf_filter; } protocol bgp { description "My BGP Link"; local as 64056; neighbor 10.0.0.2 as 64002; hold time 240; startup hold time 240; connect retry time 120; import all; export filter bgp_filter; } |
The official site has good documentation that will help you get started if this is your first time working with BIRD.
Pipeline
I found the telemetry tutorials on xrdocs to be the most helpful when it comes to getting started with pipeline, the links to the specific articles are listed at the end of this post.
This is the pipeline configuration file, the xport_input section called [fromRouters] matches the settings of the destination-group we configured previously in the XRv router:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
[default] id = pipeline [fromRouters] stage = xport_input type = tcp encap = st listen = :5432 logdata = off keepalive_seconds = 3 [toInflux] stage = xport_output type = metrics file = metrics.json output = influx influx = http://localhost:8086 database = xrvdb |
As far as the
metrics.json file, pipeline comes with a few sensors already defined, so I’ve excluded those from this gist, for brevity:
InfluxDB and Grafana
Pipeline comes with a shell script to quickly spin up a Grafana and Prometheus containers, so I got rid of the Prometheus line and added one for InfluxDB instead, the shell script is called run.sh and can be found under bigmuddy-network-telemetry-pipeline/tools/monitor :
0 1 2 3 |
docker rm -fv graf4ppl 2>/dev/null || echo "No grafana instance to kill" docker rm -fv influxdb 2>/dev/null || echo "No influxdb instance to kill" docker run -d -i --net=host -v ${PWD}/data_graf4ppl:/var/lib/grafana --name graf4ppl grafana/grafana:4.2.0 docker run -d --net=host -v ${PWD}/data_influxdb:/var/lib/influxdb --name influxdb influxdb:1.7 |
Notice we are not doing any port publishing -p because the network type –net is set to host, so the ports exposed in the respective container images will be automatically exposed to the host’s network (my 10.0.0.0/24 LAN).
InfluxDB
The shell script will start the container exposing port 8086 and will save it with an id/tag of “influxdb“. Then we can go inside the container and do what we need to do using the Influx CLI:
0 1 2 3 4 |
$ docker container exec -it influxdb bash # influx > CREATE USER "fipy" WITH PASSWORD "pass" > CREATE DATABASE "db" > GRANT ALL ON "db" TO "fipy" |
This is an example query from Postman, using the timestamp to query like this comes handy, especially when trying to figure out if the telemetry data is making it into the database:
Grafana
Grafana by default will be exposed on port 3000, so you can simply browse to it after spinning up the container. Make sure you configure the data source as an InfluxDB type and be mindful of the HTTP access type (direct/proxy) if you’re reaching the Grafana URL from an external machine and not from localhost.
Here are a few query strings I’m using for the dashboard that I showed in the demo:
References and Resources
Everything you need to know about Pipeline
Filtering in Telemetry. Where to apply and why?
Using Pipeline: Integrating with InfluxDB