New RelicのSNMP監視でカスタムMIBを設定する方法 - ktranslate活用術

記事タイトルとURLをコピーする

みなさんこんにちは。マネージドサービス課の塩野です。

New Relicのネットワークオブザーバビリティやってみようとしたけど、標準プロファイルに情報がなくほしい情報の取得ができないということはないでしょうか。やっぱりネットワーク機器の監視で、ベンダー独自の詳細なメトリクスを取得したいことがありますよね。

標準MIBだけでは物足りない場合、カスタムMIBの設定が必要です。この記事では、MIBファイルからJSONへの変換を含めた、カスタムMIB設定の実践的な手順を解説します。

目次

概要

New RelicのSNMP監視では、ktranslateというDockerコンテナを使って実施します。

実際の作業では、標準的なプロファイルに欲しい情報がなく、ベンダーから入手したMIBファイルを解析し、必要なOIDを特定してYAMLプロファイルを作成することが多いですね。手順を追って進めれば、標準では取得できないベンダー固有のメトリクスも監視できるようになります。

SNMP監視の基本的な仕組み

SNMP(Simple Network Management Protocol)は、ネットワーク機器を監視・管理するための標準プロトコルです。ルーターやスイッチ、ファイアウォールなど、多くの機器がSNMPに対応しています。

SNMPでは、監視対象の情報を「OID(Object Identifier)」という一意の識別子で管理します。このOIDと情報の構造を定義したものがMIB(Management Information Base)です。

graph LR
    A[監視サーバー<br/>ktranslate] -->|SNMPリクエスト<br/>OID指定| B[ネットワーク機器]
    B -->|SNMPレスポンス<br/>メトリクス値| A
    A -->|データ送信| C[New Relic]

    style A fill:#1CE783
    style B fill:#00B4D8
    style C fill:#1CE783

MIBには標準MIBとカスタムMIBがあります。

標準MIBは、IF-MIBやHOST-RESOURCES-MIBなど、多くの機器で共通して使える汎用的なものです。インターフェースの統計情報やCPU使用率といった基本的なメトリクスを取得できます。

カスタムMIBは、ベンダーが独自に定義したMIBです。Cisco、Arista、Juniperなどのベンダーは、自社製品特有の機能や詳細な情報を提供するために独自のMIBを用意しています。例えば、Ciscoのメモリプール情報やAristaのBGP詳細情報などがこれに該当します。

New RelicでのSNMP監視アーキテクチャ

New RelicのSNMP監視は、ktranslateというオープンソースのDockerコンテナを使って実現されています。このコンテナ(ktranslate)がSNMPマネージャとして動作し、ネットワーク上のSNMPエージェントからメトリクスを収集してNew Relicに送信します。

graph TB
    subgraph "監視対象ネットワーク"
        D1[Router 1<br/>10.0.0.1]
        D2[Switch 1<br/>10.0.0.2]
        D3[Firewall 1<br/>10.0.0.3]
    end

    subgraph "監視基盤"
        K[ktranslate<br/>Dockerコンテナ]
        C[snmp-base.yaml<br/>設定ファイル]
        M[MIBプロファイル<br/>ディレクトリ]
    end

    subgraph "New Relicプラットフォーム"
        N[New Relic<br/>メトリクス収集]
        E[Entity<br/>デバイス管理]
    end

    D1 -->|SNMPポーリング| K
    D2 -->|SNMPポーリング| K
    D3 -->|SNMPポーリング| K
    C -.設定読み込み.-> K
    M -.MIB定義参照.-> K
    K -->|メトリクス送信| N
    N --> E

    style K fill:#00B4D8
    style N fill:#1CE783
    style E fill:#1CE783

設定の中心となるのがsnmp-base.yamlというファイルです。このファイルに監視対象のデバイス情報、SNMPの認証情報、ポーリング間隔などを記述します。

MIBプロファイルは、各ベンダーの機器に対応したYAMLファイルで、どのOIDを収集するかが定義されています。New Relicは公式のSNMPプロファイルリポジトリを提供しており、主要なベンダーの機器に対応したプロファイルが用意されています。

カスタムMIBを使う場合は、このプロファイルを自分で作成するか、既存のプロファイルをカスタマイズすることになります。

カスタムMIBの設定手順

実際にカスタムMIBを設定する手順を見ていきます。大きく分けて6つのステップがあります。

graph TD
    A[MIBファイル入手] --> B[MIBをJSONに変換]
    B --> C[JSONを解析してOID特定]
    C --> D[SNMP Walkで実機確認]
    D --> E[YAMLプロファイル作成]
    E --> F[snmp-base.yaml設定]
    F --> G[コンテナ起動]

    style A fill:#FFE5B4
    style B fill:#FFE5B4
    style C fill:#B4E5FF
    style D fill:#B4E5FF
    style E fill:#C8E6C9
    style F fill:#C8E6C9
    style G fill:#C8E6C9

ステップ1: MIBファイルの入手と配置

まず、監視したい機器のベンダーからMIBファイルを入手します。多くのベンダーは、サポートサイトやダウンロードページでMIBファイルを公開しています。

MIBファイルは通常.mib.txtという拡張子で提供されます。これらのファイルには、OIDの定義や構造が記述されています。

# MIBファイル用のディレクトリを作成
mkdir -p /opt/newrelic/snmp/mibs
mkdir -p /opt/newrelic/snmp/json

# ベンダーから入手したMIBファイルを配置
cp VENDOR-CUSTOM-MIB.mib /opt/newrelic/snmp/mibs/

ステップ2: MIBファイルをJSONに変換

MIBファイルは人間が読むには複雑な形式なので、JSONに変換して解析しやすくします。PySMIというPythonライブラリのmibdumpツールを使います。

# PySMIのインストール
pip install pysmi

# MIBをJSONに変換
mibdump --destination-format json \
  --destination-directory /opt/newrelic/snmp/json \
  VENDOR-CUSTOM-MIB

変換が成功すると、/opt/newrelic/snmp/json/VENDOR-CUSTOM-MIB.jsonというファイルが生成されます。

ステップ3: JSONファイルの解析

生成されたJSONファイルを開いて、必要なOIDを特定します。JSONファイルは以下のような構造になっています。

{
  "VENDOR-CUSTOM-MIB": {
    "meta": {
      "module": "VENDOR-CUSTOM-MIB"
    },
    "objects": {
      "deviceInfo": {
        "name": "deviceInfo",
        "oid": "1.3.6.1.4.1.9999.1.1",
        "nodetype": "node"
      },
      "deviceTemperature": {
        "name": "deviceTemperature",
        "oid": "1.3.6.1.4.1.9999.1.1.1",
        "nodetype": "scalar",
        "class": "objecttype",
        "syntax": {
          "type": "Integer32"
        },
        "maxaccess": "read-only",
        "status": "current",
        "description": "Current device temperature in Celsius"
      },
      "interfaceStatsTable": {
        "name": "interfaceStatsTable",
        "oid": "1.3.6.1.4.1.9999.1.2.1",
        "nodetype": "table",
        "class": "objecttype",
        "maxaccess": "not-accessible",
        "status": "current"
      },
      "interfaceStatsEntry": {
        "name": "interfaceStatsEntry",
        "oid": "1.3.6.1.4.1.9999.1.2.1.1",
        "nodetype": "row",
        "class": "objecttype",
        "maxaccess": "not-accessible"
      },
      "interfaceIndex": {
        "name": "interfaceIndex",
        "oid": "1.3.6.1.4.1.9999.1.2.1.1.1",
        "nodetype": "column",
        "class": "objecttype",
        "syntax": {
          "type": "Integer32"
        },
        "maxaccess": "read-only"
      },
      "interfaceName": {
        "name": "interfaceName",
        "oid": "1.3.6.1.4.1.9999.1.2.1.1.2",
        "nodetype": "column",
        "class": "objecttype",
        "syntax": {
          "type": "DisplayString"
        },
        "maxaccess": "read-only"
      },
      "interfaceErrors": {
        "name": "interfaceErrors",
        "oid": "1.3.6.1.4.1.9999.1.2.1.1.3",
        "nodetype": "column",
        "class": "objecttype",
        "syntax": {
          "type": "Counter64"
        },
        "maxaccess": "read-only",
        "description": "Total number of errors on this interface"
      }
    }
  }
}

このJSONから、以下の情報を読み取ります。

スカラーOIDの見つけ方

nodetypescalarのオブジェクトを探します。上記の例ではdeviceTemperatureがスカラーOIDです。

  • oid: 1.3.6.1.4.1.9999.1.1.1
  • syntax.type: Integer32(数値型)
  • maxaccess: read-only(読み取り専用)
  • description: 説明文

スカラーOIDは単一の値を返すため、YAMLではsymbolとして定義します。

テーブルOIDの見つけ方

nodetypetableのオブジェクトを探します。上記の例ではinterfaceStatsTableがテーブルOIDです。

テーブルには複数の行(エントリー)があり、各行には複数のカラムがあります。

  • テーブル本体: interfaceStatsTable (OID: 1.3.6.1.4.1.9999.1.2.1)
  • エントリー: interfaceStatsEntry (OID: 1.3.6.1.4.1.9999.1.2.1.1)
  • カラム:
    • interfaceIndex (OID: 1.3.6.1.4.1.9999.1.2.1.1.1) - インデックス
    • interfaceName (OID: 1.3.6.1.4.1.9999.1.2.1.1.2) - 名前(文字列)
    • interfaceErrors (OID: 1.3.6.1.4.1.9999.1.2.1.1.3) - エラー数(数値)

テーブルOIDは複数行のデータを返すため、YAMLではtableとして定義します。

データ型の確認

syntax.typeを見ると、データ型が分かります。

  • Integer32, Counter32, Counter64, Gauge32: 数値型 → メトリクスとして収集可能
  • DisplayString, OctetString: 文字列型 → タグとして使用
  • IpAddress: IPアドレス型 → タグとして使用

数値型のOIDはメトリクスとして、文字列型のOIDはタグ(ディメンション)として使うのが基本です。

ステップ4: SNMP Walkで実機確認

JSONで特定したOIDが実際の機器でサポートされているか、SNMP Walkで確認します。

# 特定のOIDツリーをWalk
snmpwalk -v2c -c public 192.168.1.100 1.3.6.1.4.1.9999 > device_snmpwalk.txt

出力例を見てみます。

SNMPv2-SMI::enterprises.9999.1.1.1.0 = INTEGER: 45
SNMPv2-SMI::enterprises.9999.1.2.1.1.1.1 = INTEGER: 1
SNMPv2-SMI::enterprises.9999.1.2.1.1.2.1 = STRING: "eth0"
SNMPv2-SMI::enterprises.9999.1.2.1.1.3.1 = Counter64: 1234
SNMPv2-SMI::enterprises.9999.1.2.1.1.1.2 = INTEGER: 2
SNMPv2-SMI::enterprises.9999.1.2.1.1.2.2 = STRING: "eth1"
SNMPv2-SMI::enterprises.9999.1.2.1.1.3.2 = Counter64: 5678

この出力から以下のことが確認できます。

  • 1.3.6.1.4.1.9999.1.1.1.0(deviceTemperature)は値45を返している
  • 1.3.6.1.4.1.9999.1.2.1(interfaceStatsTable)には2行のデータがある
    • 1行目: インデックス1, 名前"eth0", エラー数1234
    • 2行目: インデックス2, 名前"eth1", エラー数5678

JSONで見つけたOIDが実際に値を返していることが確認できました。この確認作業は重要です。MIBファイルに定義されていても、機器のファームウェアバージョンによってはサポートされていないOIDもあるためです。

ステップ5: YAMLプロファイルの作成

JSONとSNMP Walkの結果を基に、YAMLプロファイルを作成します。

# custom-device.yml
---
extends:
  - system-mib.yml

provider: kentik-default

sysobjectid:
  - 1.3.6.1.4.1.9999.*

metrics:
  # スカラーOID: デバイス温度
  - MIB: VENDOR-CUSTOM-MIB
    symbol:
      OID: 1.3.6.1.4.1.9999.1.1.1.0
      name: deviceTemperature
      poll_time_sec: 60

  # テーブルOID: インターフェース統計
  - MIB: VENDOR-CUSTOM-MIB
    table:
      OID: 1.3.6.1.4.1.9999.1.2.1
      name: interfaceStatsTable
    symbols:
      - OID: 1.3.6.1.4.1.9999.1.2.1.1.3
        name: interfaceErrors
        poll_time_sec: 60
    metric_tags:
      - column:
          OID: 1.3.6.1.4.1.9999.1.2.1.1.2
          name: interfaceName

YAMLの各項目の意味

  • extends: 継承する既存プロファイル。system-mib.ymlは標準的なシステムメトリクスを含む
  • provider: New Relicでのエンティティ識別子
  • sysobjectid: このプロファイルを適用する機器のsysObjectID(ワイルドカード可)
  • metrics: 収集するメトリクスのリスト

スカラーOIDの定義

- MIB: VENDOR-CUSTOM-MIB
  symbol:
    OID: 1.3.6.1.4.1.9999.1.1.1.0
    name: deviceTemperature
    poll_time_sec: 60
  • MIB: MIBファイル名(拡張子なし)
  • symbol.OID: JSONのoidフィールドの値 + .0(スカラーは末尾に.0が必要)
  • symbol.name: New Relicで表示されるメトリクス名(JSONのnameを使うのが一般的)
  • poll_time_sec: ポーリング間隔(秒)

symbol.OIDは、JSONに .0 が含まれていない場合の対応 ※必ずsnmpwalk/snmpget で確認すること

テーブルOIDの定義

- MIB: VENDOR-CUSTOM-MIB
  table:
    OID: 1.3.6.1.4.1.9999.1.2.1
    name: interfaceStatsTable
  symbols:
    - OID: 1.3.6.1.4.1.9999.1.2.1.1.3
      name: interfaceErrors
  metric_tags:
    - column:
        OID: 1.3.6.1.4.1.9999.1.2.1.1.2
        name: interfaceName
  • table.OID: テーブルのOID(JSONのinterfaceStatsTableoid
  • table.name: テーブル名
  • symbols: 収集する数値カラムのリスト
    • OID: カラムのOID(JSONのinterfaceErrorsoid
    • name: メトリクス名
  • metric_tags: タグとして使う文字列カラムのリスト
    • column.OID: カラムのOID(JSONのinterfaceNameoid
    • column.name: タグ名

この設定により、New Relicでは以下のようなメトリクスが記録されます。

deviceTemperature: 45
interfaceErrors{interfaceName="eth0"}: 1234
interfaceErrors{interfaceName="eth1"}: 5678

ステップ6: snmp-base.yamlの設定

作成したプロファイルを使用するように、snmp-base.yamlを編集します。

devices:
  custom_device_192.168.1.100:
    device_name: custom_device
    device_ip: 192.168.1.100
    snmp_comm: public
    oid: .1.3.6.1.4.1.9999.1.1
    mib_profile: custom-device.yml
    provider: kentik-default
    poll_time_sec: 60
    user_tags:
      environment: production
      location: datacenter-1

global:
  poll_time_sec: 60
  mib_profile_dir: /etc/ktranslate/profiles
  mibs_enabled:
    - VENDOR-CUSTOM-MIB
    - IF-MIB
    - HOST-RESOURCES-MIB

mibs_enabledセクションに、使用するカスタムMIBを追加することが重要です。ここに記載されていないMIBは、プロファイルで定義されていてもポーリングされません。

ステップ7: Dockerコンテナの起動

設定ファイルとプロファイルの準備ができたら、ktranslateコンテナを起動します。

docker run -d --name ktranslate-snmp \
  --restart unless-stopped \
  -v $(pwd)/snmp-base.yaml:/snmp-base.yaml \
  -v /opt/newrelic/snmp/profiles:/etc/ktranslate/profiles \
  -v /opt/newrelic/snmp/mibs:/etc/ktranslate/mibs \
  -e NEW_RELIC_API_KEY=$YOUR_LICENSE_KEY \
  kentik/ktranslate:v2 \
    -snmp /snmp-base.yaml \
    -nr_account_id=$YOUR_ACCOUNT_ID \
    -metrics=jchf \
    -tee_logs=true \
    -service_name=snmp-polling \
    nr1.snmp

ボリュームマウントで、設定ファイル、プロファイルディレクトリ、MIBディレクトリをコンテナ内にマッピングしています。

コンテナが正常に起動したら、ログを確認してエラーがないかチェックします。

docker logs ktranslate-snmp

正常に動作していれば、数分後にNew Relicのダッシュボードでメトリクスが表示されるようになります。

トラブルシューティングのポイント

カスタムMIBの設定でよく遭遇する問題と対処法をまとめておきます。

メトリクスが表示されない場合

まず確認すべきは、mibs_enabledセクションにカスタムMIBが追加されているかです。プロファイルで定義していても、ここに記載がないとポーリングされません。

次に、デバイスのmib_profile設定が正しいプロファイルファイルを指しているか確認します。ファイル名のタイポや拡張子の間違いがないかチェックしましょう。

SNMPの認証情報(コミュニティストリングやSNMPv3の認証情報)が正しいかも重要です。機器側のSNMP設定と一致しているか確認してください。

OIDが見つからないエラー

MIBファイルが正しく配置されていない可能性があります。コンテナ内の/etc/ktranslate/mibsディレクトリにMIBファイルが存在するか確認します。

また、MIBファイルに依存関係がある場合、必要なすべてのMIBファイルが揃っているか確認が必要です。ベンダーのMIBは、他のMIBを参照していることがよくあります。

ポーリングタイムアウト

timeout_msの値を増やすことで改善する場合があります。デフォルトは3000ミリ秒ですが、応答が遅い機器では5000〜10000ミリ秒に設定するとよいでしょう。

devices:
  slow_device:
    device_name: slow_device
    device_ip: 192.168.1.200
    timeout_ms: 10000
    retries: 2

retriesを設定することで、タイムアウト時の再試行回数を増やすこともできます。

まとめ

New RelicでカスタムMIBを使ったSNMP監視を設定する方法を紹介しました。

設定の流れをおさらいすると、まずベンダーからMIBファイルを入手し、PySMIでJSONに変換します。JSONファイルを解析してスカラーOIDとテーブルOIDを特定し、SNMP Walkで実機確認を行います。その後、YAMLプロファイルを作成してOIDとメトリクスのマッピングを定義し、snmp-base.yamlでデバイスとプロファイルを紐付け、最後にktranslateコンテナを起動するという手順でした。

標準MIBだけでは取得できないベンダー固有のメトリクスを監視できるようになると、ネットワークの可視性が大きく向上します。New Relicの公式SNMPプロファイルリポジトリには、多くのベンダーのプロファイルが公開されているので、まずはそこから自分の環境に合ったものを探してみるのがおすすめです。既存のプロファイルを見れば、YAMLの書き方の参考にもなります。

この記事がどなたかのお役に立てれば幸いです。

宣伝

弊社では、お客様環境のオブザーバビリティを加速するためのNew Relicアカウント開設を含めた伴走型のNew Relic導入支援サービスをご提供しております。もしご興味をお持ちの方は、こちらのお問合せフォームよりお問合せ頂けましたら幸いでございます。

参照

blog.serverworks.co.jp

blog.serverworks.co.jp

blog.serverworks.co.jp

blog.serverworks.co.jp

blog.serverworks.co.jp

◆ 塩野 正人
◆ マネージドサービス部 所属
◆ X(Twitter):@shioccii
◆ 過去記事はこちら

前職ではオンプレミスで仮想化基盤の構築や運用に従事。現在は運用部隊でNew Relicを使ってサービス改善に奮闘中。New Relic User Group運営