Prometheus SNMP Exporterでトラフィック取得する

Prometheus の SNMP Exporter 使ってネットワーク機器のトラフィックを取得しようとしたときに手間取りあれこれ対処した時のメモ
(ネットワークシュミレータで確認)

# やりたかったこと
- ネットワーク機器からifInOctetsとifOutOctetsのMIBをSNMPで取得してトラフィック取得
- トラフィック量と合わせて、インターフェース名(ifDescr)や装置名(sysName)をPrometheusのメトリクスとして取得

今回、ifInOctetsやifOutOctetsのメトリクスにsysNameの情報を付与するのに手間取りましたが、`prometheus.yml`内のRulesで対応

## 今回の確認環境
- 各バージョン
  - トラフィック取得サーバ：Ubuntu 24.04.1 LTS
    - Prometheus, version 2.45.3
    - SNMP Exporter, version 0.25.0
    - grafana-server, Version 11.5.1
  - SNMPの監視対象：VyOS 1.5-rolling-202411070006
- ネットワークシュミレータ上の構成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3043279/e14fa9ca-2763-ac1e-36a9-384c0eb53ac8.png)
- 取得したトラフィックグラフ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3043279/4404f414-3507-80ec-5420-1523997d1db5.png)

# 事前準備
## Prometheus, SNMP Exporterのインストール
以下を実施
```:Prometheus, SNMP Exporterのインストール
apt update
apt -y install prometheus prometheus-snmp-exporter
```

一緒にnode-exporterもインストールされるが今回不要なためdisableする
```:node-exporterのdisable
systemctl disable prometheus-node-exporter.service
```
## Grafanaのインストール
以下を実施
```:Grafanaのインストール
wget -q -O /usr/share/keyrings/grafana.key https://packages.grafana.com/gpg.key
echo "deb [signed-by=/usr/share/keyrings/grafana.key] https://packages.grafana.com/oss/deb stable main" | tee -a /etc/apt/sources.list.d/grafana.list
apt update
apt -y install grafana
```

Grafanaの設定変更、ローカル環境なので https ではなく http でログインできるように変更
`/etc/grafana/grafana.ini`内の`;protocol = http`を`protocol = http`に変更
```:Grafanaの設定変更(/etc/grafana/grafana.ini)
# diff grafana.ini grafana.ini.org
32c32
< protocol = http
---
> ;protocol = http
#
```
Grafanaの起動と再起動時も自動で起動するようにenableする
```:Grafanaの起動
systemctl start grafana-server.service
systemctl enable grafana-server.service
```
## VyOSの設定
SNMP監視対象としてVyOSにSNMP設定を行う、以下の設定をいれるだけです。(今回はコミュニティ名を`public`としてます)
```:VyOSのSNMP設定
set service snmp community public
```
今回はそれ以外に、インターフェースへのIP設定とホストネーム(SNMPでのsysName)を設定してます
```:VyOSに設定した内容
set interfaces ethernet eth0 address '10.0.0.2/24'
set system host-name 'VyOS-1'
set service snmp community public
```

# Prometheus の設定
`/etc/prometheus`内の以下2つのファイル`snmp.yml`と`prometheus.yml`を編集
- `snmp.yml` 
  - 取得対象のコミュニティ名や取得したいMIBを定義。今回は、コミュニティは`public`、MIBはifTable全体とsysNameを取得しその中の`ifInOctets`・`ifOutOctets`・`sysName`をメトリクスとして取得するように設定、`ifInOctets`・`ifOutOctets`はインターフェース識別子`ifIndex`とインターフェース名`ifDescr  `をラベルとして付与する
(ここでsysNameもラベルとして付与したかったがなかなかできず諦めました)
- `prometheus.yml`
  - `job_name: "snmp"`の部分でSNMP監視対象や、`snmp.yml`で定義しているモジュール名(今回は`module_ifOctets`)を指定する
  - `rule_files`の箇所で`ifInOctets`・`ifOutOctets`に`sysName`を結合させたメトリクス定義するファイル`snmp_rules.yml`を指定
```:snmp.yml
auths:
  public_v2:
    version: 2  # SNMP バージョン 2 を使用
    community: public  # SNMP コミュニティ

modules:
  module_ifOctets:  # SNMP モジュール名
    walk:  # SNMPのwalk（OIDツリーをたどる）
      - 1.3.6.1.2.1.2.2.1  # インターフェース情報（ifTable全体）
      - 1.3.6.1.2.1.1.5.0  # sysName（デバイス名）のOID

    metrics:  # 取得するメトリクス
      - name: sysName  # デバイスのsysName（ホスト名）
        oid: 1.3.6.1.2.1.1.5.0  # sysNameのOID
        type: DisplayString  # 文字列として表示

      - name: ifInOctets  # インターフェースの受信バイト数
        oid: 1.3.6.1.2.1.2.2.1.10  # ifInOctetsのOID
        type: counter  # カウンター型メトリクス（増加し続ける値）
        indexes:  # インターフェースのインデックス（識別子）
          - labelname: ifIndex
            type: Integer32
        lookups:  # インデックス情報を人間が読めるように変換
          - labelname: ifDescr  # インターフェースの説明（名前）
            labels: [ifIndex]
            oid: 1.3.6.1.2.1.2.2.1.2  # ifDescr（インターフェース名）のOID
            type: DisplayString  # 文字列として表示

      - name: ifOutOctets  # インターフェースの送信バイト数
        oid: 1.3.6.1.2.1.2.2.1.16  # ifOutOctetsのOID
        type: counter  # カウンター型メトリクス
        indexes:  # インターフェースのインデックス
          - labelname: ifIndex
            type: Integer32
        lookups:  # インターフェースの名前を取得
          - labelname: ifDescr  # インターフェースの説明（名前）
            labels: [ifIndex]
            oid: 1.3.6.1.2.1.2.2.1.2  # ifDescrのOID
            type: DisplayString  # 文字列として表示
```


```:prometheus.yml
global:
  scrape_interval:     15s # メトリクスの収集間隔を15秒に設定（デフォルトは1分）
  evaluation_interval: 15s # ルール評価の間隔を15秒に設定（デフォルトは1分）

rule_files:
  - "snmp_rules.yml" # SNMPのIF情報のsysNameを追加するルールを適用

scrape_configs:
  - job_name: "snmp"  # SNMP監視用のジョブ名
    scrape_interval: 30s  # 30秒間隔でメトリクスを収集
    static_configs:
      - targets:
        - 10.0.0.2  # 監視対象のSNMPエージェント
        # - 10.0.1.2  # 監視対象のSNMPエージェント(複数台SNMPで監視する場合に追加)
    metrics_path: /snmp  # SNMP Exporterが提供するメトリクスのエンドポイント
    params:
      module: [module_ifOctets] # SNMP Exporterの設定で使用するモジュール名
    relabel_configs:
      - source_labels: [__address__]  # ターゲットアドレスを取得
        target_label: __param_target  # SNMP Exporter用のtargetパラメータに設定
      - source_labels: [__param_target]  # 変換後のターゲットアドレスを取得
        target_label: instance  # instanceラベルとして設定
      - target_label: __address__
        replacement: 127.0.0.1:9116  # SNMP Exporterが動作するローカルアドレスを指定

```

`/etc/prometheus`に`snmp_rules.yml`を作成し以下の内容で保存すると、IF情報のsysNameを追加されたメトリクスが作られる
```:snmp_rules.yml
groups:
  - name: snmp_rules  # SNMP関連のルールグループ
    interval: 30s  # ルールの評価間隔（30秒ごとに計算）

    rules:
      - record: ifInOctets_sysName  # 受信バイト数（ifInOctets）にsysNameを付与した新しいメトリクスを記録
        expr: |
          ifInOctets * on(instance) group_left(sysName) sysName
        # ifInOctetsに対応するsysName（ホスト名）を付与
        # `on(instance)` で `instance` ラベルが一致するデータを結合
        # `group_left(sysName)` を使って、sysNameを追加（sysNameは一意であるため）

      - record: ifOutOctets_sysName  # 送信バイト数（ifOutOctets）にsysNameを付与した新しいメトリクスを記録
        expr: |
          ifOutOctets * on(instance) group_left(sysName) sysName
        # ifOutOctetsに対応するsysName（ホスト名）を付与
        # 記録ルールを適用して、sysNameごとの送信バイト数を管理しやすくする

```
# Prometheus で確認
## 設定反映
変更した内容を反映させるため、Prometheus と SNMP Exporter をリスタートさせる
```:restart
systemctl restart prometheus.service
systemctl restart prometheus-snmp-exporter.service
```
## PrometheusのWeb-GUIで確認

`http://[サーバのIP]:9090/`をブラウザに入力してPrometheusのWeb画面を開き、`Graph`の
画面で、設定したメトリクス`ifInOctets_sysName`・`ifOutOctets_sysName`が表示されていることを確認して`Execute`で確認する

- PrometheusのWeb画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3043279/8f2fddd6-07ce-49d4-b2ab-bd97a5b400d3.png)

- `Execute`で確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3043279/92d68fb3-65d1-50d8-9fee-22fc5bf37f97.png)

# Grafana で確認
詳細は省略しますが、「Prometheusと連携」と「ダッシュボードの作成」の作成は以下を参考にしてください

https://qiita.com/k-maki/items/21ee627c2ecbf0f9360c#grafana%E4%B8%8A%E3%81%A7%E3%81%AE%E8%A8%AD%E5%AE%9A

ダッシュボードの編集画面だけ貼り付けておきます
① `rate(ifInOctets_sysName{ifDescr=~"eth.*"}[$__rate_interval]) * 8`
② `rate(ifOutOctets_sysName{ifDescr=~"eth.*"}[$__rate_interval]) * 8`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3043279/20c07e7a-4577-f9f4-52f2-c605654f884e.png)


表示されるトラフィックグラフ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3043279/4404f414-3507-80ec-5420-1523997d1db5.png)

以上