1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Grafana MCP×Codexでマルチベンダーネットワークの障害を調査してみた

1
Posted at

はじめに

オープンソースで公開されているGrafana MCP Serverを、Arista cEOS、Juniper cJunosEvolved、SONiC VMで構成したマルチベンダー環境で試しました。

Grafanaにメトリクスやログが集まっていても、目的に合うクエリやダッシュボードを作り、複数機器の情報を時系列で確認するには手間がかかります。特にマルチベンダー環境では、機器ごとにインターフェース名やログ形式が異なります。

今回はCodexから自然言語で、次の3つを行いました。

  • 入出力トラフィックのグラフ作成
  • 全機器のsyslogを横断したBGP状態調査
  • リンク障害の原因とトラフィックへの影響調査

Grafana MCPを使うことで、ダッシュボードの作成から、設定変更、インターフェース状態、BGP切断、トラフィック迂回、復旧状況までを一連の対話で確認できました。

本記事は検証環境での実施例です。表示内容は環境によって異なります。

実際に、CodexからGrafana MCP Serverを介して調査を依頼した結果の一部を、以下の画像に示します。

image.png

Grafana MCPで何ができるのか

MCP(Model Context Protocol)は、AIクライアントが外部のツールやデータソースを共通の方法で利用するための仕組みです。

Grafana MCP Serverを利用すると、CodexのようなMCPクライアントから、Grafanaのダッシュボード、データソース、メトリクス、ログなどを扱えます。

権限を付与した構成では、既存データの調査だけでなく、Grafanaダッシュボードの作成や更新も可能です。

今回の構成全体を簡略化すると、次のようになります。

image.png

今回のObservability構成

今回使用するObservability関連ノードは次のとおりです。

Observability
├─ gNMIc
├─ Prometheus
├─ Vector
├─ Loki
├─ Grafana
└─ Grafana MCP Server

それぞれの関係は、大きく次の3つに分かれます。

メトリクス収集経路

ネットワーク機器
    ↓ gNMIストリーミングテレメトリ
gNMIc
    ↓ Prometheus形式でメトリクスを公開
Prometheus
    ↓ PromQL
Grafana

ネットワーク機器からgNMI Subscribeで取得する仕組みを、ここでは「gNMIストリーミングテレメトリ」と表記します。

その中で取得されるインターフェースカウンター、パケット数、エラー数などの数値データを「メトリクス」と呼びます。

つまり、テレメトリは収集方式、メトリクスは収集されるデータという関係です。

ログ収集経路

ネットワーク機器
    ↓ syslog
Vector
    ↓ ログの整形・転送
Loki
    ↓ LogQL
Grafana

Vectorは各ネットワーク機器からsyslogを受信し、ホスト名やデバイス名などのラベルを付けてLokiへ転送します。

Lokiはログを保存し、GrafanaからLogQLを使って検索できるようにします。

AIからの調査経路

利用者
    ↓ 自然言語
Codex
    ↓ MCP
Grafana MCP Server
    ↓ Grafana API・データソースへのクエリ
Grafana
    ├─ Prometheus
    └─ Loki

CodexがPrometheusやLokiへ直接接続するのではなく、Grafana MCP Serverを通じてGrafana上のデータソースを利用します。

検証環境の構成

今回のネットワーク部分は、次の3台で構成します。

ノード ネットワークOS 役割
ceos1 Arista cEOS ルーター/スイッチ
cjunosevo1 Juniper cJunosEvolved ルーター
sonic1 SONiC VM ルーター/スイッチ

各ネットワーク機器には、通信確認用のLinuxクライアントを1台ずつ接続します。

image.png

ネットワーク機器間は三角形に接続し、eBGPで経路交換を行い、1本のリンクが停止しても別経路へ迂回できる構成としています。

セットアップ

事前準備:ネットワークOSイメージを準備する

今回のトポロジーでは、次のDockerイメージを使用します。

ノード containerlabのkind Dockerイメージ
ceos1 arista_ceos ceos:4.36.1F
cjunosevo1 juniper_cjunosevolved cjunosevolved:25.4R1.13-EVO
sonic1 sonic-vm vrnetlab/sonic_sonic-vs:202511

containerlabが対応するネットワークOSはkindで区別されます。現在の対応一覧には、arista_ceos、juniper_cjunosevolved、sonic-vmが含まれています。

最初に、イメージがすでに登録されているか確認します。

docker image ls

最終的に、次の3つのイメージが表示される状態にします。

REPOSITORY                   TAG
ceos                         4.36.1F
cjunosevolved                25.4R1.13-EVO
vrnetlab/sonic_sonic-vs      202511

ネットワークOSの利用条件やライセンスは、各ベンダーやプロジェクトの条件に従ってください。

Arista cEOSを準備する

Arista cEOSのイメージは、通常の公開Dockerイメージとして自由にpullするのではなく、Aristaのダウンロードサイトから入手します。

Aristaのアカウントでログインし、使用するEOSバージョンのcEOS-labアーカイブをダウンロードします。

今回使用したバージョンは4.36.1Fです。

ファイル名は、次のような形式になります。

cEOS64-lab-4.36.1F.tar.xz

ダウンロードしたアーカイブをDockerへ登録します。

docker import cEOS64-lab-4.36.1F.tar.xz ceos:4.36.1F

containerlabの公式ドキュメントでも、Aristaから取得したcEOSのアーカイブをdocker importで登録する手順が案内されています。

登録されたことを確認します。

docker image ls ceos

次のように表示されれば準備完了です。

REPOSITORY   TAG
ceos         4.36.1F

今回のトポロジーファイルでは、次のように指定しています。

ceos1:
  kind: arista_ceos
  image: ceos:4.36.1F
  mgmt-ipv4: 172.20.20.21
  startup-config: network/ceos1.cfg

containerlabで起動したcEOSでは、管理インターフェース、ホスト名、gNMI、NETCONF、eAPIなどが初期設定されます。標準の管理ユーザーはadmin、パスワードはadminです。

Juniper cJunosEvolvedを準備する

今回使用するのは、containerlabのjuniper_cjunosevolvedに対応するcJunosEvolvedイメージです。

cJunosEvolvedは、Juniperがコンテナ形式で提供するJunos OS Evolvedの検証用イメージです。

Juniperの配布サイトから、利用するバージョンのイメージをダウンロードします。

今回使用したバージョンは次のとおりです。

25.4R1.13-EVO

配布されるファイル名や圧縮形式はリリースによって異なる可能性があります。

Dockerイメージをtar形式で入手した場合は、次のように読み込みます。

docker image load -i <ダウンロードしたcJunosEvolvedイメージ>

登録されたイメージを確認します。

docker image ls | grep cjunosevolved

トポロジーファイルで使用する名前とタグが異なる場合は、docker tagで付け直します。

docker tag \
  <読み込まれたイメージ名>:<タグ> \
  cjunosevolved:25.4R1.13-EVO

最終的に次のように表示されることを確認します。

REPOSITORY        TAG
cjunosevolved     25.4R1.13-EVO

今回のトポロジーファイルでは、次のように指定しています。

cjunosevo1:
  kind: juniper_cjunosevolved
  image: cjunosevolved:25.4R1.13-EVO
  mgmt-ipv4: 172.20.20.22
  startup-config: network/cjunosevo1.cfg
  env:
    CPTX_COSIM: "BX"

CPTX_COSIMには、エミュレートするプラットフォームを指定しています。

BX = PTX10002-36QDD
BT = PTX10001-36MR

今回の環境ではBXを指定しています。
標準の管理ユーザーはadmin、パスワードはadmin@123です。

cJunosEvolvedは起動に時間がかかる場合があります。デプロイ直後にSSH接続できない場合は、docker logs -fで起動状況を確認してください。

SONiC VMを準備する

今回使用するSONiC VMは、SONiC VSの仮想マシンイメージをvrnetlabでDockerイメージ化して使用します。

全体の流れは次のとおりです。

sonic-vs.img.gz
       ↓
vrnetlabでビルド
       ↓
vrnetlab/sonic_sonic-vs:202511

vrnetlabを取得する

git clone https://github.com/srl-labs/vrnetlab.git
cd vrnetlab/sonic

SONiC VSイメージを取得する

SONiCのビルド成果物から、使用するリリースのsonic-vs.img.gzを取得します。

今回は202511に対応するSONiC VSイメージを使用しています。

ダウンロードしたファイルを、vrnetlabのsonicディレクトリへ配置します。

cp ~/Downloads/sonic-vs.img.gz .

実際の保存場所に合わせてパスを変更してください。

Dockerイメージを作成する

make docker-image

作成されたイメージを確認します。

docker image ls | grep sonic

作成されたタグがトポロジーファイルと異なる場合は、タグを付け直します。

docker tag \
  vrnetlab/sonic_sonic-vs:<作成されたタグ> \
  vrnetlab/sonic_sonic-vs:202511

次のように表示されれば準備完了です。

REPOSITORY                    TAG
vrnetlab/sonic_sonic-vs       202511

今回のトポロジーファイルでは、次のように指定しています。

sonic1:
  kind: sonic-vm
  image: vrnetlab/sonic_sonic-vs:202511
  mgmt-ipv4: 172.20.20.23
  startup-config: network/sonic1-config_db.json
  binds:
    - network/sonic1-config_db.json:/etc/sonic/config_db.json:ro
    - network/sonic-backup.sh:/backup.sh:ro

SONiC VMでは、containerlab側のインターフェースとSONiC内部のポート名が異なります。

今回の環境では、概ね次のように対応します。

containerlab側 SONiC内部
eth0 管理インターフェース
eth1 Ethernet0
eth2 Ethernet4
eth3 Ethernet8

そのため、トポロジーファイルでsonic1:eth1と記述していても、SONiC内部ではEthernet0として操作します。

検証環境をセットアップする

今回は、次のGitHubリポジトリに環境を準備しています。

各ネットワークOSの設定内容や、gNMI、syslog、Prometheus、Loki間の収集設定については、別の記事で詳しくまとめる予定です。

1. リポジトリを取得する

git clone --depth=1 https://github.com/katsumi2018/clab-multivendor-observability.git
cd clab-multivendor-observability/

2. セットアップスクリプトを実行する

./setup.sh

セットアップスクリプトでは、データ保存用ディレクトリの作成や、必要な権限の設定などを行います。

3. containerlabでトポロジーをデプロイする

sudo containerlab deploy -t multivendor-observability.clab.yml

containerlabは、トポロジーファイルに記述されたノードを起動し、指定されたエンドポイント間に仮想リンクを作成します。

cJunosEvolvedやSONiC VMは、コンテナが起動してから内部の仮想マシンが利用可能になるまで時間がかかる場合があります。

起動状況は、次のように確認できます。

docker logs -f clab-multivendor-observability-cjunosevo1
docker logs -f clab-multivendor-observability-sonic1

トポロジーファイル

今回使用したトポロジーの主要部分は次のとおりです。

各サービスへの接続を確認する

デプロイ完了後、GrafanaとGrafana MCP Serverへ到達できることを確認します。

今回の検証環境では、containerlabを実行しているLinuxホストのIPアドレスが192.168.100.199です。

  • Grafana:http://192.168.100.199:3000/
  • Prometheus:http://192.168.100.199:9090/
  • Grafana MCP:http://192.168.100.199:8000/mcp

192.168.100.199の部分は、自分の環境のIPアドレスに読み替えてください。

Codexを動かしている端末から、Grafanaの3000番ポートとGrafana MCP Serverの8000番ポートへ到達できる必要があります。

Grafanaを確認する

ブラウザーで次のURLを開きます。

http://192.168.100.199:3000/

今回の検証環境では、初期ログイン情報として次を使用します。

ユーザー名:admin
パスワード:admin

初期ログイン後に新しいパスワードの設定を求められますが、今回はadminで設定

admin / adminはローカルの検証環境だけで使用してください。外部から到達可能な環境や継続利用する環境では、必ず十分に強いパスワードへ変更してください。

Grafanaへログインしたら、PrometheusとLokiがデータソースとして登録されていることを確認します。

CodexにGrafana MCP Serverを登録する

Codexの設定画面を開き、[プラグイン]からMCPサーバーの設定を開きます。

Grafana MCP ServerのURLとして、次を登録します。

http://192.168.100.199:8000/mcp

image.png

今回のローカル検証環境では、Bearerトークンや追加ヘッダーを設定していません。

認証情報が必要な環境では、Grafana MCP Server側の構成に合わせて設定してください。

本番環境では、通信の暗号化、サービスアカウント、最小権限、シークレットの安全な保管を検討してください。Grafana MCP Serverでは、Streamable HTTP接続自体をTLS化するためのサーバー証明書も設定できます。

ここまでセットアップが終了になります

試してみる

試してみる1:入力・出力データ量のグラフを作る

最初に、インターフェースのトラフィックを可視化するダッシュボードをCodexに作ってもらいました。

Codexへ次のように指示します。

入力と出力データ量のグラフを作って、1つのグラフで同時に表示できるようにして。インターフェース名に「/」がある場合もあるので気をつけてください。

インターフェース名について補足したのは、Juniperのet-0/0/0のようにスラッシュを含む名前も、フィルターやクエリで正しく扱ってもらうためです。

マルチベンダー環境では、インターフェース名が次のように異なります。

Arista:Ethernet1
Juniper:et-0/0/0
SONiC:Ethernet0

処理が終わったら、ブラウザーでGrafanaを確認します。

http://192.168.100.199:3000/

Grafanaを確認すると、Network Interface Trafficダッシュボードが作成されていました。

デバイスとインターフェースを選択でき、入力と出力の系列が1つのグラフへまとめられています。

image.png

画面上で対象機器を切り替えられるため、同じダッシュボードを複数機器の確認に利用できます。

自然言語の指示から、PromQLの作成だけでなく、デバイスやインターフェースを選択するための変数を含むダッシュボードまで作成できたのが印象的でした。

試してみる2:syslogからBGPの状態を調査する

次に、全機器のsyslogを横断してBGPの状態変化を調べてもらいます。

Codexへ次のように指示しました。

全ての機器でBGPの状態変化を調査して

Codexは、Lokiに保存されている機器ごとのBGP関連ログを検索し、状態変化、エラー、復旧状況を時系列で整理しました。

image.png

今回の結果では、起動直後に次の事象が確認できました。

  • ceos1がsonic1から想定外のAS番号を受信し、接続を拒否した
  • sonic1でBGPプロセスが再起動した
  • cjunosevo1側では接続のリセットが記録された
  • その後はBGPセッションが確立した
  • 継続するDown、Idle、Ceaseは見つからなかった

1台ずつログインしてログを確認する代わりに、複数機器のsyslogを横断して時系列で確認できました。

単にエラーを列挙するだけでなく、その後にセッションが復旧したかどうかまで追えている点が重要です。

試してみる3:直近の障害とトラフィックへの影響を調査する

最後に、意図的にリンク障害を発生させ、Codexが原因と影響をどこまで追えるかを確認しました。

1. 継続的な通信を発生させる

client1からclient2へpingを送信し続けます。

今回の構成では、client2のIPアドレスは192.168.102.1です。

docker exec -it \
  clab-multivendor-observability-client1 \
  ping 192.168.102.1

トラフィックがgNMIcとPrometheusへ反映されるよう、しばらく通信を継続します。

今回は約3分待ちました。

2. ceos1のインターフェースを停止する

別のターミナルからceos1へSSHで接続します。

ssh admin@clab-multivendor-observability-ceos1

今回の環境でのパスワードはadminです。

cjunosevo1向けのEthernet1をshutdownします。

ceos1> enable
ceos1# configure terminal
ceos1(config)# interface ethernet 1
ceos1(config-if-Et1)# shutdown

これにより、次のリンクが停止します。

ceos1 Ethernet1
        ↓
cjunosevo1 et-0/0/0

3. 直近5分の異常を調べる

リンクを停止した直後、Codexへ次のように指示しました。

直近の5分の異常があったら内容と原因を教えて

image.png

Codexの回答では、次のイベントが時系列で関連付けられていました。

  • ceos1 Ethernet1がDown
  • 同時刻にBGP peerがEstablishedからIdleへ遷移
  • cjunosevo1側でもHold Timerが満了
  • BGPセッションが切断

以上から、管理操作によってEthernet1を停止したことが、BGPセッション断の原因と判断されました。

次の情報を、1本の時間軸で結び付けられています。

管理者の操作ログ
        ↓
インターフェースのDown
        ↓
ceos1側のBGP状態変化
        ↓
cjunosevo1側のHold Timer満了
        ↓
BGPセッション切断

4. トラフィックへの影響を確認する

続けて、同じ対話の中で質問しました。

トラフィックはどうなってますか?

image.png

結果を見ると、通信全体は停止せず、別経路へ迂回していると判断されました。

ログ調査だけで分かるのは、「リンクとBGPセッションが落ちた」という制御プレーン上の状態です。

さらにPrometheusのメトリクスを確認することで、次のことまで整理できました。

  • 通信は全断していない
  • 代替経路へトラフィックが切り替わった
  • BGPによる経路切り替えが動作した

ログとメトリクスを組み合わせる意味

ネットワーク障害を調査する場合、ログとメトリクスはそれぞれ異なる情報を持っています。

ログから分かること

  • インターフェースがいつDownしたか
  • BGPセッションがどの状態へ遷移したか
  • その後セッションが復旧したか

メトリクスから分かること

  • 別インターフェースのトラフィックが増加したか
  • 通信が継続しているか
  • 障害前後でトラフィックがどのように変化したか

ログとメトリクスを組み合わせることで、まず何が起きたのかを把握し、その原因を調べたうえで、影響がどの機器まで広がったのか、通信にどのような影響が出たのかを確認できます。
さらに、現在は復旧しているのか、問題が継続しているのかまで一連の流れとして調査できます。

環境を停止する

検証が終わったら、次のコマンドで環境を削除できます。

sudo containerlab destroy -t multivendor-observability.clab.yml

永続化しているGrafana、Prometheus、Lokiのデータは、dataディレクトリに残ります。

すべての保存データも削除する場合は、内容を確認したうえで対象ディレクトリを削除してください。

sudo rm -rf data/grafana/*
sudo rm -rf data/prometheus/*
sudo rm -rf data/loki/*

rm -rfを実行する前に、現在のディレクトリと削除対象を必ず確認してください。

まとめ

実際に使って分かったこと

自然言語からダッシュボードを作成できる

表示したいデータと条件を文章で伝えるだけで、入力・出力トラフィックを同時に表示するダッシュボードを作成できました。

Grafanaのダッシュボード作成方法を知らなくても、自然言語で取得したい内容を伝えることで、学習コストをかけずに複数のデータを組み合わせ、運用時に見やすいダッシュボードを作成できる点が大きなメリットだと感じました。

複数機器のログを時系列で調査できる

syslogを確認することで、いつから異常が発生しているかを把握できます。

また、大量のログから問題を特定する際も、MCPを通じてAIと一緒に調査することで、不具合の原因を効率的に突き止められる点が大きなメリットだと感じました。

ログとメトリクスなど複数の情報を組みあわせて調査できる

「異常の原因」に続けて「トラフィックはどうなったか」と質問することで、制御プレーンのBGP状態と、データプレーンの通信状況を同じ文脈で確認できました。

障害原因と利用者への影響を切り分けるうえで有効です。

さいごに

Grafana MCP ServerをCodexへ登録することで、マルチベンダーのネットワーク監視データに対して、次の操作を自然言語から行えました。

  • インターフェースの入力・出力トラフィックを可視化するダッシュボードの作成
  • Arista、Juniper、SONiCのsyslogを横断したBGP状態変化の調査
  • BGPセッション切断原因の推定
  • 障害後のトラフィック迂回の確認

今回、取得するメトリクスはインターフェースのカウンターのみでしたが、メーカによって異なりますが、IF状態・BGP状態・経路数など、多くの情報を取得することが可能です。

利用するネットワーク構成やプロトコルに合わせて複数のメトリクスを取得することで、大規模なネットワーク内でも、問題が発生している箇所や発生時刻を特定するうえで大きな武器になると感じました。

参考リンク

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?