fluent-plugin-telemetry-iosxeの紹介

# はじめに

この記事はCiscoの有志による[Cisco Systems Japan Advent Calendar 2018](https://qiita.com/advent-calendar/2018/cisco)の18日目です。

この記事では、拙作の`fluent-plugin-telemetry-iosxe`を紹介します。

`fluent-plugin-telemetry-iosxe`は、その名前から推測できるとおり、IOS XEのModel Driven TelemetryのためのFluentdのInputプラグインです。

**[Github] tetsusat/fluent-plugin-telemetry-iosxe**
https://github.com/tetsusat/fluent-plugin-telemetry-iosxe

昨年のAdvent Calenderの頃に公開したプラグインですが、今回の投稿を執筆するにあたって、以下の機能拡張を行ってます。

- Chunked Framingに対応 (https://tools.ietf.org/html/rfc6242#section-4.2)
- 複数サブスクリプションのサポート

# そもそもIOS XEのModel Driven Telemetry？

IOS XEのModel Driven Telemetryは、現在、IETF Telemetryのプレスタンダード版`draft-ietf-netconf-yang-push`に準拠してます。
IOS XEのModel Driven Telemetry自体については、昨年のCisco Advent Calenderのために執筆した以下の記事を参考にしてください。

**[Qiita] IOS XEのModel Driven Telemetryを試してみた**
https://qiita.com/tetsusat/items/eae0f79f445e54ef662f

# デバイスの設定

デバイス側の設定は超簡単です。

まずは、YANGに対応したNETCONFを有効にします。

```
Router(config)#netconf-yang
```

加えて、NETCONFでアクセスするためのアカウントを作成します。`privilege`レベルは`15`にする必要があります。

```
Router(config)#username admin privilege 15 password admin
```

これだけです。

# fluent-plugin-telemetry-iosxeの設定

まずは、標準出力に出力する例です。

```
<source>
  @type telemetry_iosxe
  server 192.0.2.1
  port 830
  user admin
  password admin
  xpath_filters /process-cpu-ios-xe-oper:cpu-usage/cpu-utilization/five-seconds
  tag cpu-usage-five-seconds
  period 500
  @label @telemetry
</source>
<label @telemetry>
  <match **>
    @type stdout
  </match>
</label>
```

TelemetryのNotificationを受けると、以下のような感じで標準出力に出力されます。

```
2018-12-14 03:30:54.000000000 +0000 cpu-usage-five-seconds: {"cpu_usage":{"cpu_utilization":{"five_seconds":1}}}
2018-12-14 03:30:59.000000000 +0000 cpu-usage-five-seconds: {"cpu_usage":{"cpu_utilization":{"five_seconds":2}}}
2018-12-14 03:31:04.000000000 +0000 cpu-usage-five-seconds: {"cpu_usage":{"cpu_utilization":{"five_seconds":1}}}
...
```

次に、InfluxDBに出力する例です。
InfluxDBに出力するために`fluent-plugin-influxdb`を使います。
それと、Grafanaで可視化することを想定して、`fluent-plugin-flatten-hash`で階層化されたデータをフラット化しておきます。

**[Github] fangli/fluent-plugin-influxdb**
https://github.com/fangli/fluent-plugin-influxdb

**[Github] kazegusuri/fluent-plugin-flatten-hash**
https://github.com/kazegusuri/fluent-plugin-flatten-hash

`fluent-plugin-telemetry-iosxe`の解説からは脱線しますが、`fluent-plugin-influxdb`の設定で`auto_tags`を`true`にしておくと、値が文字列なフィールドをタグにしてくれます。そうすると、Grafanaのクエリーで`WHERE`によるフィルタや`GROUP BY`による集約に使えるようになります。

```
<source>
  @type telemetry_iosxe
  server 192.0.2.1
  port 830
  xpath_filters /process-cpu-ios-xe-oper:cpu-usage/cpu-utilization/five-seconds
  user admin
  password admin
  tag cpu-usage-five-seconds
  period 500
  @label @telemetry
</source>
<label @telemetry>
  <filter **>
    @type flatten_hash
    separator .
  </filter>
  <match **>
    @type influxdb
    host localhost
    port 8086
    dbname telemetry
    user admin
    password admin
    time_precision s
    auto_tags true
  </match>
</label>
```

すると、以下のような感じでInfluxDBにレコードができます。

```
> select * from "cpu-usage-five-seconds" limit 5
name: cpu-usage-five-seconds
time                cpu_usage.cpu_utilization.five_seconds
----                --------------------------------------
1544759262000000000 1
1544759267000000000 2
1544759272000000000 1
1544759277000000000 2
1544759282000000000 1
```

# 応用

およそ1年前にこのプラグインを公開して以来、複数の対象にサブスクライブするにはどうしたらいいのか、ということをしばしば聞かれました。

2つやり方があります。

1つ目のやり方は、`xpath_filters`におけるXPathの指定にユニオンオペレータ(|)を使います。こうすると、一つのサブスクリプションで複数の対象にサブスクライブできます。

```
<source>
  @type telemetry_iosxe
  ...
  xpath_filters /interfaces/interface[name="GigabitEthernet1"]/statistics/in-octets|/interfaces/interface[name="GigabitEthernet1"]/statistics/out-octets
  ....
</source>
```

この場合、一つのNotificationに集約されて通知されてきます。

```
2018-12-14 04:02:34.000000000 +0000 interface-stats: {"interfaces":{"interface":{"name":"GigabitEthernet1","statistics":{"in_octets":7935445674,"out_octets":27392586}}}}
2018-12-14 04:02:39.000000000 +0000 interface-stats: {"interfaces":{"interface":{"name":"GigabitEthernet1","statistics":{"in_octets":7935459283,"out_octets":27458631}}}}
2018-12-14 04:02:44.000000000 +0000 interface-stats: {"interfaces":{"interface":{"name":"GigabitEthernet1","statistics":{"in_octets":7935472426,"out_octets":27459313}}}}
...
```

もう一つのやり方は、`xpath_filters`において対象を配列として指定します。こうすると、複数のサブスクリプションで複数の対象にサブスクライブできます。

```
<source>
  @type telemetry_iosxe
  ...
  xpath_filters [
    "/interfaces/interface[name=\"GigabitEthernet1\"]/statistics/in-octets",
    "/interfaces/interface[name=\"GigabitEthernet1\"]/statistics/out-octets"
  ]
  ....
</source>
```

この場合、サブスクリプションが複数なので、複数のNotificationが通知されてきます。

```
2018-12-14 04:19:53.000000000 +0000 interface-stats: {"interfaces":{"interface":{"name":"GigabitEthernet1","statistics":{"in_octets":7937904353}}}}
2018-12-14 04:19:53.000000000 +0000 interface-stats: {"interfaces":{"interface":{"name":"GigabitEthernet1","statistics":{"out_octets":27901067}}}}
2018-12-14 04:19:58.000000000 +0000 interface-stats: {"interfaces":{"interface":{"name":"GigabitEthernet1","statistics":{"in_octets":7937919099}}}}
2018-12-14 04:19:58.000000000 +0000 interface-stats: {"interfaces":{"interface":{"name":"GigabitEthernet1","statistics":{"out_octets":27968448}}}}
2018-12-14 04:20:03.000000000 +0000 interface-stats: {"interfaces":{"interface":{"name":"GigabitEthernet1","statistics":{"in_octets":7937933134}}}}
2018-12-14 04:20:03.000000000 +0000 interface-stats: {"interfaces":{"interface":{"name":"GigabitEthernet1","statistics":{"out_octets":27970140}}}}
...
```

おしまい