機械学習でのネットワークの異常検知がどれくらい難しいのか試してみる

# 0. はじめに
:::note info
この記事はシスコの有志による Cisco Systems Japan Advent Calendar 2024 （一枚目） の 22日目として投稿しています。
:::

2017年版: https://qiita.com/advent-calendar/2017/cisco
2018年版: https://qiita.com/advent-calendar/2018/cisco
2019年版: https://qiita.com/advent-calendar/2019/cisco
2020年版: https://qiita.com/advent-calendar/2020/cisco
2020年版(2枚目): https://qiita.com/advent-calendar/2020/cisco2
2021年版: https://qiita.com/advent-calendar/2021/cisco
2021年版(2枚目): https://qiita.com/advent-calendar/2021/cisco2
2022年版(1,2): https://qiita.com/advent-calendar/2022/cisco
2023年版: https://qiita.com/advent-calendar/2023/cisco
2024年版: https://qiita.com/advent-calendar/2024/cisco <=== ここ

# 1. 今年の内容は？
去年IOS-XRのAI-Driven Telemetryについて書きました。
今年も引き続きAIブームは続いていますが、機械学習を用いたNetworkの異常検知についてここ数日聞く機会がありましたので、それについて書いてみようと思います。

## 機会学習を用いたNetworkの異常検知とは？
この手の話では毎度のことになりそうですが、GPTに聞いてみました。

![anormary1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143031/ed51ce3b-698b-dbd4-04e2-97a34001ca7c.png)


Syslogなどを含めると非常に有効だと思いますが、自然言語処理が入ると一気に難しくなって私のキャパを超えてしまいそうなので、この記事ではTelemetryを用いて取得できる数字として処理できる情報を元に進めたいと思います。

# 2. まずはテレメトリを取れるように設定
これは非常に多くの記事で扱われている内容なので詳細は割愛します。
今回はIOS-XR/IOS-XEからModel Driven Telemetryでテレメトリデータを取得し、TIG(Telegraf/InfluxDB/Grafana)でテレメトリを可視化してみます。
ちなみに今回センサーパスを考えるのに、対応しているセンサーパスを機器から取得してYANG SUITEでも確認してみました。
nccで機器からセンサーパスを取得すると以下のようになります。
https://github.com/CiscoDevNet/ncc/

```
tkamata@tkamata-lab3:~/YANG-models$ python3 ~/ncc/ncc-get-all-schema -a 172.20.0.2 -u admin -p cisco
tkamata@tkamata-lab3:~/YANG-models$ ls
CISCO-ENTITY-FRU-CONTROL-MIB.yang                         Cisco-IOS-XR-freqsync-oper.yang                           Cisco-IOS-XR-ipv6-nd-oper-sub1.yang                            Cisco-IOS-XR-policy-repository-oper-sub1.yang                  Cisco-IOS-XR-um-aaa-diameter-cfg.yang                      Cisco-IOS-XR-um-traps-entity-redundancy-cfg.yang
Cisco-IOS-XR-aaa-aaacore-cfg.yang                         Cisco-IOS-XR-fretta-bcm-dpa-npu-stats-oper-sub1.yang      Cisco-IOS-XR-ipv6-nd-oper.yang                                 Cisco-IOS-XR-policy-repository-oper.yang                       Cisco-IOS-XR-um-aaa-nacm-cfg.yang                          Cisco-IOS-XR-um-traps-entity-state-cfg.yang
Cisco-IOS-XR-aaa-diameter-base-mib-cfg.yang               Cisco-IOS-XR-fretta-bcm-dpa-npu-stats-oper-sub2.yang      Cisco-IOS-XR-ipv6-new-dhcpv6d-cfg.yang                         Cisco-IOS-XR-portmode-cfg.yang                                 Cisco-IOS-XR-um-aaa-radius-server-cfg.yang                 Cisco-IOS-XR-um-traps-flash-cfg.yang
(snip)
```

YANG SUITEについても今年のAdvent Calendarで触れている記事もありますので出力結果だけ出します。
以下のように内容確認することができます。
![anormary2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143031/b5f24b60-6d19-1f76-e279-1686b825e3e0.png)


今回Routerに設定したTelemetryの設定は以下です。
```
telemetry model-driven
 destination-group COLLECTOR
  vrf Mgmt-intf
  address-family ipv4 x.x.x.x port 50002
   encoding self-describing-gpb
   protocol tcp
  !
 !
 sensor-group TRAFFIC
  sensor-path Cisco-IOS-XR-infra-statsd-oper:infra-statistics/interfaces/interface/latest/generic-counters
 !
 subscription ANALYTICS
  sensor-group-id TRAFFIC sample-interval 30000
  destination-id COLLECTOR
 !
!
 sensor-group health
  sensor-path Cisco-IOS-XR-wdsysmon-fd-oper:system-monitoring/cpu-utilization
  sensor-path Cisco-IOS-XR-nto-misc-shmem-oper:memory-summary/nodes/node/summary
  sensor-path Cisco-IOS-XR-shellutil-oper:system-time/uptime
 !
 sensor-group interfaces
  sensor-path Cisco-IOS-XR-pfi-im-cmd-oper:interfaces/interface-summary
 !
 !
 sensor-group routing
  sensor-path Cisco-IOS-XR-clns-isis-oper:isis/instances/instance/levels/level/adjacencies/adjacency
  sensor-path Cisco-IOS-XR-clns-isis-oper:isis/instances/instance/statistics-global
  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/isis/as/information
  sensor-path Cisco-IOS-XR-ipv4-bgp-oper:bgp/instances/instance/instance-active/default-vrf/process-info
 !
 sensor-group mpls-te
 sensor-path Cisco-IOS-XR-mpls-te-oper:mpls-te/tunnels/summary
 sensor-path Cisco-IOS-XR-ip-rsvp-oper:rsvp/interface-briefs/interface-brief
 sensor-path Cisco-IOS-XR-ip-rsvp-oper:rsvp/counters/interface-messages/interface-message
 
  subscription health
  sensor-group-id health strict-timer
  sensor-group-id health sample-interval 60000
  destination-id COLLECTOR
 !
 subscription interfaces
  sensor-group-id interfaces strict-timer
  sensor-group-id interfaces sample-interval 60000
  destination-id COLLECTOR
 !
 subscription routing
  sensor-group-id routing strict-timer
  sensor-group-id routing sample-interval 60000
  destination-id COLLECTOR
 !
 subscription mpls-te
  sensor-group-id mpls-te strict-timer
  sensor-group-id mpls-te sample-interval 60000

```

RouterとTIGで接続できています。

```
RP/0/RP0/CPU0:R1#show telemetry model-driven subscription
Sun Dec 22 03:16:47.380 UTC
Subscription:  health                   State: ACTIVE
-------------
  Sensor groups:
  Id                               Interval(ms)               State
  health                           60000                      Partial

  Destination Groups:
  Id                 Encoding            Transport   State   Port    Vrf                               IP
  COLLECTOR          self-describing-gpb tcp         Active  50002   Mgmt-intf                         x.x.x.x
    TLS :             False

Subscription:  mpls-te                  State: NA
-------------
  Sensor groups:
  Id                               Interval(ms)               State
  mpls-te                          60000                      Resolved

Subscription:  routing                  State: ACTIVE
-------------
  Sensor groups:
  Id                               Interval(ms)               State
  routing                          60000                      Resolved

  Destination Groups:
  Id                 Encoding            Transport   State   Port    Vrf                               IP
  COLLECTOR          self-describing-gpb tcp         Active  50002   Mgmt-intf                         x.x.x.x
    TLS :             False

Subscription:  ANALYTICS                State: ACTIVE
-------------
  Sensor groups:
  Id                               Interval(ms)               State
  TRAFFIC                          30000                      Resolved

  Destination Groups:
  Id                 Encoding            Transport   State   Port    Vrf                               IP
  COLLECTOR          self-describing-gpb tcp         Active  50002   Mgmt-intf                         x.x.x.x
    TLS :             False

Subscription:  interfaces               State: ACTIVE
-------------
  Sensor groups:
  Id                               Interval(ms)               State
  interfaces                       60000                      Resolved

  Destination Groups:
  Id                 Encoding            Transport   State   Port    Vrf                               IP
  COLLECTOR          self-describing-gpb tcp         Active  50002   Mgmt-intf                         x.x.x.x
    TLS :             False
```
IF OutだけですがGrafanaでこんな感じで見えました。
![anormary3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143031/e382587c-d811-b4d3-ef7e-a35f1c437f7c.png)

Traffic量の変化をSensor-pathを設定していないのに無事取得することができました。

# 3. ここからが本番：機械学習を使ってみる
ここで断っておきますが、このセットアップは12/22時点で作成しています。
早くから作っておけば学習結果まで出せたと思いますが、学習データの取得を考えるとこの記事の中では結果まで取り扱うことはできません。
なので、この記事ではここからは以下のRepositoryにあるデータを元に進めさせていただきます。
https;//github.com/mikemikhail/Telemetry-ML

## DatabaseのImport
まずは以下のDirectoryにあるbackup dataをImportします。
/Telemetry-ML-main/data/db_backup_210321/

```
root@ubuntu:/opt/tig/Telemetry-ML-main/data# docker exec -it influxdb /bin/bash
root@df9adac65b0f:/# influxd restore -portable -db mdt_db -newdb mdt_db_210321 /data/db_backup_210321/
2024/12/22 03:36:34 Restoring shard 6315 live from backup 20210322T012905Z.s6315.tar.gz
2024/12/22 03:36:34 Restoring shard 6328 live from backup 20210322T012905Z.s6328.tar.gz
(snip)
root@df9adac65b0f:/#
root@df9adac65b0f:/# influx
Connected to http://localhost:8086 version 1.8.4
InfluxDB shell version: 1.8.4
>
>
> auth
username: telegraf
password:
> show databases
name: databases
name
----
telegraf
_internal
mdt_db_210321
> alter retention policy "autogen" on "mdt_db_210321" duration inf
> use mdt_db_210321
Using database mdt_db_210321
> show retention policies
name    duration shardGroupDuration replicaN default
----    -------- ------------------ -------- -------
autogen 0s       6h0m0s             1        true
> show measurements
name: measurements
name
----
Cisco-IOS-XR-clns-isis-oper:isis/instances/instance/levels/level/adjacencies/adjacency
Cisco-IOS-XR-clns-isis-oper:isis/instances/instance/statistics-global
Cisco-IOS-XR-infra-statsd-oper:infra-statistics/interfaces/interface/latest/generic-counters
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/isis/as/information
Cisco-IOS-XR-ip-rsvp-oper:rsvp/counters/interface-messages/interface-message
Cisco-IOS-XR-ip-rsvp-oper:rsvp/interface-briefs/interface-brief
Cisco-IOS-XR-ipv4-bgp-oper:bgp/instances/instance/instance-active/default-vrf/process-info
Cisco-IOS-XR-mpls-te-oper:mpls-te/tunnels/summary
Cisco-IOS-XR-pfi-im-cmd-oper:interfaces/interface-summary
Cisco-IOS-XR-shellutil-oper:system-time/uptime
Cisco-IOS-XR-wdsysmon-fd-oper:system-monitoring/cpu-utilization
> exit
```

無事に取れていそうです。
GrafanaにDataSource追加してみると以下の用に見えました。十分なデータ量ありそうですね。
![anormary4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143031/2fcd28da-e767-21b0-4b1f-031642b5e1d6.png)

## TensorFlowのInstallとデータのImport
ここではTensorFlowを使って学習を行います。
PyCharmをInstallしてデータを取り込んでみます。
/Telemetry-ML-main/MLを指定して、requirement.txtの内容をpipインストールします。

```
root@ubuntu:/opt/Telemetry-ML-main/ML# pip install -r requirements.txt
Requirement already satisfied: absl-py==0.12.0 in /usr/local/lib/python3.6/site-packages (from -r requirements.txt (line 1)) (0.12.0)
Requirement already satisfied: astor==0.8.1 in /usr/local/lib/python3.6/site-packages (from -r requirements.txt (line 2)) (0.8.1)
(snip)
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
```
また、以下のDirectoryにPythonファイルが入っているのでこちらを活用します。

```
root@ubuntu:/opt/Telemetry-ML-main/ML/ML-anomaly_detection-replay-accelerated-4PM# ls -l
total 52
-rwxr-xr-x 1 root root  1463 Aug 28  2023 constants.py
-rwxr-xr-x 1 root root  5944 Aug 28  2023 monitor.py
-rwxr-xr-x 1 root root 22525 Aug 28  2023 read_df.py
-rwxr-xr-x 1 root root 13807 Aug 28  2023 tf_fn.py

root@ubuntu:/opt/Telemetry-ML-main/ML/ML-anomaly_detection-replay-accelerated-4PM# ./monitor.py
```

他のDirectoryでも並行してモデルの構築は可能ですが、環境にもよりますが私の環境では20分程度待ってみると終わりました。

## 学習結果
今回のパッケージでは通常のトラフィックパターンがどうなっているかを平日の60分毎に方向別で学習しています。
10分ごとにexperienceを更新しながら過去60分間のトラフィックパターンを元にトラフィック量を予測します。
そして、NRMSE(二乗平均平方根誤差)を元に異常を検知します。

簡単に各関数の説明を書くと以下のようになります。
constants.pyはコードの実行に使用する値を定義します。これには、データベースの認証情報、Trafficの方向、MLモデルの形状、実行する際のスリープの間隔などが含まれています。

read_df.pyには、データベースに特定の期間のデータを問い合わせたり、データをデータフレームと呼ばれるラベル付きに構造化する関数が含まれています。

tf_fn.pyには、機械学習関数、データの正規化、モデルの構築、学習と検証、損失計算、グラフ作成が含まれています。

monitor.pyは、ML学習を開始し、他のファイルで定義された関数を呼び出すドライバファイルです。これを実行することで学習を開始します。

中を見ていくと非常に多くのパラメータが存在しており、チューニングを行うのは職人技に思われますので、今回は誰かがチューニングしてくれたデフォルトの値で実行しました。

上記パッケージを走らせるとグラフの描画まで行ってくれます。
![anormary5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143031/b9ea6fa6-7825-8bfd-3d51-86db96c35181.png)

こちらの図では直近60分間隔のグラフを出してくれています。
青い線がMLモデルが予測した値で緑の戦が実際のトラフィック量をグラフ化したものです。
これを元に異常検知ができるものでしょうか。

次の図は、トレーニング/検証サイクルの結果(RMSE:二乗平均平方根誤差)のグラフです。RMSEは数値予測のモデルの良さを図る指標でモデルと実測の間に差がなければ低い値を取ります。
![anormary6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143031/978af0c9-2377-8c43-90d6-af7a32050970.png)

今回の結果ではハズレ値が大きくいくつか出ていますが、RMSEの変動が限定的であれば通常の変動、大きく変動する場合は(少なくとも学習モデルが想定できていない)異常なイベントを指します。
じゃあ、どれくらいの範囲に収まれば許容範囲なのかという点が非常に難しいポイントだと思います。。。

次のグラフは、前の図と同じRMSEを正規化したものです。
![anormary8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143031/2b96959a-eef3-906b-8f32-f42ee0c0f713.png)

青の線がトレーニングによる予測されたもの、緑の線が実測なのですが、この図としては予期しないものが発生していることを示唆していると取れます。(けど、これが本当に障害や異常なのかまでは言い切れませんね。。。)
これで一応学習データと実測値の比較が取れたかなと思います。


# 4. おわりに

機械学習によるネットワークの異常検知について試してみました。
機械学習を用いた異常検知についてツールはすでにオープン化されているレベルで揃っていると思いました。
ただし、みなさま言われていることですが、誤検知などの対応はまだまだチャレンジが続く状況ですね。
使ってみるとどう難しいのかなどイメージがつきやすいですし、なにより動かしてみて面白いので興味ある方は試してみてください。
ここまで読んでいただきありがとうございました。

おしまい

## 免責事項
本サイトおよび対応するコメントにおいて表明される意見は、投稿者本人の個人的意見であり、シスコの意見ではありません。本サイトの内容は、情報の提供のみを目的として掲載されており、シスコや他の関係者による推奨や表明を目的としたものではありません。各利用者は、本Webサイトへの掲載により、投稿、リンクその他の方法でアップロードした全ての情報の内容に対して全責任を負い、本Web サイトの利用に関するあらゆる責任からシスコを免責することに同意したものとします。