105
109

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

GrafanaとInfluxDBでネットワークリソースの視覚化

Last updated at Posted at 2016-04-10

Rubyスクリプトで、CiscoルータにSSHでログインして、CLIから10秒間隔でshow interface叩いて、実行結果から必要な値を正規表現で抜き出して、InfluxDBに保存して、Grafanaで視覚化してみました。

GrafanaとInfluxDBでネットワークリソースを視覚化してみました。データベースはInfluxDB、ビジュアライゼーションツールはGrafana、データ取得はRubyスクリプト+expect4rライブラリで実装しています。
本記事はUsing InfluxDB + Grafana to Display Network Statisticsを参考にしています。データ取得にInfluxsnmpを利用していますが、今回は自作のRubyスクリプトで実行しています。
範囲を選択_032.png
カスタマイズすると上図のようにできます。今回はデータの視覚化までの基本的なところを説明します。

目的

ルータのトラフィックなどのネットワークリソースの視覚化することを目的としています。

従来はSNMPとRRDtoolなどを組み合わせて視覚化していました。ただし、トラフィック以外に取得項目が増えた場合や、取得間隔の変更など、手間がかかりました。そこで、代替ツールとしてInfluxDB+Grafanaを試用してみました。

今回は時系列データベースのInfluxDBを使います。メリットとして、スキーマレスのため、取得項目が増えた場合でも、データベース側で設定変更不要です。ガンガン監視項目の追加やルータの台数を増やすことができます。
視覚化ツールはGrafanaを使って、表示時間の変更や一度に複数の項目を表示などができます。ダイナミックに時間を変更でき、かっこ良く表示できます。

ネットワークリソースの値取得はSNMPが標準的ですが、今回はSSHからCLIでshowコマンドを実行し、その結果をデータベースに保存しています。想定はSNMPに対応していない値やSNMPできない環境を想定しています。

仕組み

データ取得・保存・表示は下記の仕組みで実現します。
スクリーンショット 2016-04-12 7.35.31.png

準備

今回はDockerHub上のイメージを使ってInfluxDBとGrafanaを使います。

※Grafana v3.0.0-beta1がInfluxDB v0.11以降に対応していないため、今回はInfluxDB v0.10を利用します。

ルータの準備

Cisco VIRLで下記の環境を構築します。擬似トラフィックを流すため、両端にlxc-iperf-1/2間でiperfでトラフィックを流しています。
VM Maestro _031.png

Ubuntu/Dockerの準備

InfluxDBとGrafanaをDocker上で動かすため、Dockerをインストールします。Ubuntu14.04で提供されているdocker.ioパッケージをインストールします。バージョンはv1.6.2です。

$ cat /etc/lsb-release 
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=14.04
DISTRIB_CODENAME=trusty
DISTRIB_DESCRIPTION="Ubuntu 14.04.4 LTS"
$ sudo apt install docker.io

InfluxDBの準備

InfluxDBは時系列データベースです。スキーマレスのため、動的に保存する項目を増やしたりできます。
今回はInfluxDB v0.10をDockerHubのコンテナイメージを使って利用します。データベースは$HOME/influxdbに保存するよう設定します。InfluxDBはTCPポート8083,8086を使用します。TCP8083はWeb管理インタフェース、TCP8086はAPIのポートです。

# InfluxDB v0.10のコンテナイメージを取得
$ sudo docker pull tutum/influxdb:0.10

# InfluxDBのコンテナ起動
$ sudo docker run -d --name=influxdb --volume=$HOME/influxdb:/data -p 8083:8083 -p 8086:8086 tutum/influxdb:0.10

# InfluxDBが起動しているか確認
$ sudo docker ps
CONTAINER ID        IMAGE                 COMMAND             CREATED             STATUS              PORTS                                            NAMES
cb5e24f3065a        tutum/influxdb:0.10   "/run.sh"           4 minutes ago       Up 4 minutes        0.0.0.0:8083->8083/tcp, 0.0.0.0:8086->8086/tcp   influxdb            

# コンテナを停止したい場合に実行
$ sudo docker stop influxdb

# 停止したコンテナを起動
$ sudo docker start influxdb

InfluxDBでデータベースの作成

続いて、Web管理インタフェースからInfluxDB上でデータベースを作成します。今回はtraffic1というデータベース名で、4週間データを保存する設定をします。

DockerホストのTCPポート8083をWebブラウザで表示し、下記のクエリを発行し、データベースの作成とポリシーを設定します。

# データベースの作成
CREATE DATABASE traffic1
# 作成済みのデータベース確認
SHOW DATABASES

# デフォルトのポリシーtrafficを設定、4週間保存する
CREATE RETENTION POLICY traffic ON traffic1 DURATION 4w REPLICATION 1 DEFAULT
# ポリシーの確認
SHOW RETENTION POLICIES ON "traffic1"

今回は192.168.122.103のDockerホスト上で動作しているため、Web管理インタフェースはhttp://192.168.122.103:8083/ となります。WebブラウザでWeb管理インタフェースを開き発行したいクエリを「Query」フォームに入力し、Enterで確定します。問題なければ、Success!が表示されます。
範囲を選択_001.png

上記のデータベース作成とポリシーを設定すると、下記のとおりとなります。
範囲を選択_002.png

データ取得用のRubyスクリプト

今回はSNMPを使わずに手製スクリプトでルータにSSHして、データを取得しています。想定としてはSNMPでは取得できないメトリクスや、そもそもSNMPできないルータに対して、CLIからコマンドを実行して、値を保存する方法を想定しています。

CiscoルータにSSHし、show interfaceコマンドの実行結果をデータベースに保存します。データベースはtraffic1で、SQLデータベースで言ういわゆるテーブル名はcisco_showintとしていします。InfluxDBでは、テーブル名はシリーズ名と言われます。

show interfaceから正規表現を利用して下記のパラメータを抽出します。抽出した結果は、ホスト名とインタフェース名を組み合わせたportというタグをつけてデータベースに保存します。

  • interface: インタフェース名
  • out_drops: 送信ドロップ数
  • in_packets: 受信パケット数
  • in_bytes: 受信バイト数
  • in_errors: 受信エラーパケット数
  • out_packets: 送信パケット数
  • out_bytes: 送信バイト数
  • out_errors: 送信エラーパケット数
  • lost_carriers: Ethernetキャリア信号の喪失回数

expect4rライブラリを使って、CiscoルータにSSHしています。詳細はRubyのexpect4rでCiscoルータにTelnet/SSHしてコマンド実行するを見てください。

collector.rb
require 'expect4r'
require 'awesome_print'
require 'clockwork'
require 'influxdb'
require 'parallel'
require 'yaml'

# InfluxDBの設定
influxdb = InfluxDB::Client.new 'traffic1', host: '192.168.122.103'

# 取得先ホスト
hosts = YAML.load(<<EOL)
- :hostname: iosv-1
  :host: 172.16.1.205
- :hostname: iosv-2
  :host: 172.16.1.206
EOL

# show interfaceの結果から値を抜き出す正規表現
REGEX_SHOWINT = %r{
  ^(?<interface>[\w\.\/]+)\ is
  .+?
  Total\ output\ drops:\ (?<out_drops>\d+)
  .+?
  (?<in_packets>\d+)\ packets\ input,\ (?<in_bytes>\d+)\ bytes
  .+?
  (?<in_errors>\d+)\ input\ errors,
  .+?
  (?<out_packets>\d+)\ packets\ output,\ (?<out_bytes>\d+)\ bytes
  .*?
  (?<out_errors>\d+)\ output\ errors,
  .+?
  (?<lost_carriers>\d+)\ lost\ carrier
}xm
# 上記の正規表現は下記のshow interfaceの結果をインタフェース単位に抽出する
# GigabitEthernet0/2 is up, line protocol is up 
#   Hardware is iGbE, address is fa16.3e59.cd19 (bia fa16.3e59.cd19)
#   Description: to iosv-2
#   Internet address is 10.0.0.9/30
#   MTU 1500 bytes, BW 1000000 Kbit/sec, DLY 10 usec, 
#      reliability 255/255, txload 1/255, rxload 1/255
#   Encapsulation ARPA, loopback not set
#   Keepalive set (10 sec)
#   Full Duplex, Auto Speed, link type is auto, media type is RJ45
#   output flow-control is unsupported, input flow-control is unsupported
#   ARP type: ARPA, ARP Timeout 04:00:00
#   Last input 00:00:07, output 00:00:00, output hang never
#   Last clearing of "show interface" counters never
#   Input queue: 0/75/0/0 (size/max/drops/flushes); Total output drops: 842948
#   Queueing strategy: fifo
#   Output queue: 0/40 (size/max)
#   5 minute input rate 115000 bits/sec, 171 packets/sec
#   5 minute output rate 2092000 bits/sec, 172 packets/sec
#      3475718 packets input, 286108879 bytes, 0 no buffer
#      Received 0 broadcasts (0 IP multicasts)
#      0 runts, 0 giants, 0 throttles 
#      0 input errors, 0 CRC, 0 frame, 0 overrun, 0 ignored
#      0 watchdog, 0 multicast, 0 pause input
#      3517278 packets output, 5302646275 bytes, 0 underruns
#      0 output errors, 0 collisions, 3 interface resets
#      0 unknown protocol drops
#      0 babbles, 0 late collision, 0 deferred
#      0 lost carrier, 0 no carrier, 0 pause output
#      0 output buffer failures, 0 output buffers swapped out

hosts.each do |host|
  ios = Expect4r::Ios.new_ssh(
    host: host[:host], user: 'cisco',
    pwd: 'cisco', enable_password: 'cisco'
  )
  # 10秒間隔で定期的に実行する
  Clockwork.every(10.seconds, "#{host[:hostname]} collector") do
    ios.login

    # Ciscoルータでshow interfaceを実行し、
    # 正規表現でメトリクスを抜き出す
    response = ios.exec('show interface').join.delete("\r")
    response.scan(REGEX_SHOWINT) do
      m = Regexp.last_match
      data = {
        values: {
          out_drops:     m[:out_drops].to_i,
          in_packets:    m[:in_packets].to_i,
          in_bytes:      m[:in_bytes].to_i,
          in_errors:     m[:in_errors].to_i,
          out_packets:   m[:out_packets].to_i,
          out_bytes:     m[:out_bytes].to_i,
          out_errors:    m[:out_errors].to_i,
          lost_carriers: m[:lost_carriers].to_i
        },
        tags: {
          port: "#{host[:hostname]} #{m[:interface]}"
        }
      }

      # InfluxDBにメトリクスを保存
      influxdb.write_point('cisco_showint', data)
      ap data
    end
  end
end

データ取得用のRubyスクリプトの実行

上記のRubyスクリプトは定期実行するためにclockworkを利用して、10秒間隔で実行します。

実行結果
$ clockwork collector.rb 
I, [2016-04-10T11:30:36.846900 #1318]  INFO -- : Starting clock for 2 events: [ iosv-1 collector iosv-2  collector ]
I, [2016-04-10T11:30:36.847066 #1318]  INFO -- : Triggering 'iosv-1 collector'
{
    :values => {
            :out_drops => 0,
           :in_packets => 744202,
             :in_bytes => 45856886,
            :in_errors => 0,
          :out_packets => 780556,
            :out_bytes => 126581158,
           :out_errors => 0,
        :lost_carriers => 1
    },
      :tags => {
        :port => "iosv-1 GigabitEthernet0/0"
    }
}
{
    :values => {
            :out_drops => 0,
           :in_packets => 5049224,
             :in_bytes => 7628494232,
            :in_errors => 0,
          :out_packets => 4034600,
            :out_bytes => 332766793,
           :out_errors => 0,
        :lost_carriers => 1
    },
      :tags => {
        :port => "iosv-1 GigabitEthernet0/1"
    }
}
{
    :values => {
            :out_drops => 988441,
           :in_packets => 4029369,
             :in_bytes => 332510281,
            :in_errors => 0,
          :out_packets => 4080969,
            :out_bytes => 6136203204,
           :out_errors => 0,
        :lost_carriers => 0
    },
      :tags => {
        :port => "iosv-1 GigabitEthernet0/2"
    }
}

InfluxDBでデータ保存結果の確認

データが保存されているか、InfluxDBのWeb管理インタフェースで確認します。
右上から対象のデータベースtraffic1を選択し、下記のクエリを実行します。

select * from cisco_showint where port = 'iosv-1 GigabitEthernet0/1' order by desc

InfluxDB - Admin Interface - Mozilla Firefox_004.png

cURLコマンドでデータ一覧を取得することができます。APIのエンドポイントはhttp://192.168.122.103:8086/query となります。パラメータにデータベースとクエリを指定します。結果はJSONとなります。詳細はInfluxDB Querying Dataを参照してください。

$ curl -G "http://192.168.122.103:8086/query?pretty=true" --data-urlencode "db=trffic1" --data-urlencode "q=SELECT * FROM cisco_showint WHERE port = 'iosv-1 GigabitEthernet0/1' order by desc limit 2"
{
    "results": [
        {
            "series": [
                {
                    "name": "cisco_showint",
                    "columns": [
                        "time",
                        "in_bytes",
                        "in_errors",
                        "in_packets",
                        "lost_carriers",
                        "out_bytes",
                        "out_drops",
                        "out_errors",
                        "out_packets",
                        "port"
                    ],
                    "values": [
                        [
                            "2016-04-10T02:51:33Z",
                            7.628494232e+09,
                            0,
                            5.049224e+06,
                            1,
                            3.32786237e+08,
                            0,
                            0,
                            4.034858e+06,
                            "iosv-1 GigabitEthernet0/1"
                        ],
                        [
                            "2016-04-10T02:51:23Z",
                            7.628494232e+09,
                            0,
                            5.049224e+06,
                            1,
                            3.32786087e+08,
                            0,
                            0,
                            4.034856e+06,
                            "iosv-1 GigabitEthernet0/1"
                        ]
                    ]
                }
            ]
        }
    ]
}

Grafanaの準備

ビジュアライゼーションツールのGrafanaを設定します。今回はv3.0.0の正式リリース前だったため、v3.0.0-beta1を使用します。
$HOME/grafanaに設定データを保存するよう設定します。TCP3000ポートで稼働します。

# Grafana v3.0.0-beta1のコンテナイメージを取得
$ sudo docker pull grafana/grafana:3.0.0-beta1

# Grafanaのコンテナ起動
sudo docker run -d --name=grafana --volume=$HOME/grafana/:/var/lib/grafana -p 3000:3000 grafana/grafana:3.0.0-beta1

# InfluxDBとGrafanaが起動しているか確認
$ sudo docker ps
CONTAINER ID        IMAGE                         COMMAND             CREATED             STATUS              PORTS                                            NAMES
813046bdf50e        grafana/grafana:3.0.0-beta1   "/run.sh"           6 seconds ago       Up 6 seconds        0.0.0.0:3000->3000/tcp                           grafana             
cb5e24f3065a        tutum/influxdb:0.10           "/run.sh"           58 minutes ago      Up 58 minutes       0.0.0.0:8083->8083/tcp, 0.0.0.0:8086->8086/tcp   influxdb            

# コンテナを停止したい場合に実行
$ sudo docker stop grafana

# 停止したコンテナを起動
$ sudo docker start grafana

Grafanaにログイン

Grafanaの設定をするために、WebブラウザからGrafanaを表示します。
Webブラウザでhttp://192.168.122.103:3000 を開くと、ログイン画面が表示されます。デフォルトは、ユーザ名:admin、パスワード:adminでログインできます。
範囲を選択_006.png

Grafanaでデータソースの指定

ログイン後、最初にデータソースの設定をします。データソースにInfluxDBを使用するよう指定します。

左上のGrafanaアイコンをクリックし、メニューが表示されたら、Data Sourcesリンクをクリックし、Data Sources画面に移動します。
範囲を選択_007.png

Data Sources画面でAdd data sourceボタンをクリックします。
範囲を選択_008.png

Add data source画面で下記のパラメータを入力します。

  • Name: traffic1 ※データベース名と同じ名前を設定します。
  • Default: ON
  • Type: InfluxDB ※データベースにInfluxDBを指定。指定すると入力項目がInfluxDBに合わせて変化します
  • Http Settings
    • Url: http://192.168.122.130:8086 ※InfluxDBのTCP8086を指定します。
    • Access: direct ※ブラウザから直接アクセスするように指定します。
  • InfluxDB Details
    • Database: traffic1 ※InfluxDBで作成したデータベースを指定
    • User: admin ※入力必須項目のためダミーで入力
    • Password: admin ※入力必須項目のためダミーで入力

Addボタンをクリックし、データソースを追加します。
範囲を選択_009.png

追加後にテスト接続し、問題ないことを確認するため、Test Connectionボタンをクリックし、Successと表示がでることを確認します。問題なければ、Saveボタンで保存します。
範囲を選択_010.png

Grafanaダッシュボードの作成

Grafanaアイコン => Dashboards => Newからダッシュボード作成画面に移動します。
Screenshot from 2016-04-10 13:06:32.png

新しいダッシュボードを作成したら、グラフパネルを追加します。ROWアイコン => Add Panel => Graphからグラフパネル作成画面に移動します。
ワークスペース 1_020.png

メトリクスの追加は下記のYouTubeの動画のとおりに設定します。
Grafanaの設定
※追記:動画ではGraph Metricsでfill(null)となっていますが、fill(none)に変更が必要です。fill(null)で表示時間を変更した場合、うまく表示されない場合があります。

Graph Generalの設定。グラフのタイトルを設定します。
範囲を選択_023.png

Graph Metricsの設定。データベースを選択し、表示対象のメトリクスを設定します。
トラフィックの場合、累積カウンタとなるため、直前の値と差分を取る必要があります。non_negative_derivative(1s)関数を使用し、直前との差分の1秒間隔の平均をグラフにプロットします。ただし、ラップアラウンドは考慮されていません。値がバイトのため、ビットに変換するためにmath(*8)関数を使用して、8倍しています。GROUP BYでfill(none)を選択します。
範囲を選択_029.png

Graph Axesの設定。X-Y軸の設定をします。Unit(単位)をbits/sec、Y-Minを0、Right YをOFFに設定します。
範囲を選択_026.png

Graph Legendの設定。判例の設定をします。判例に最大と現在の値を表示するよう設定します。
範囲を選択_027.png

最後にダッシュボードを保存します。
Screenshot from 2016-04-10 13:44:35.png

今回は必要最小限の設定のみ説明しました。今回説明していないTemplatingを使うことで、動的にポートを選択できるようになります。詳しくはUsing InfluxDB + Grafana to Display Network Statisticsを参照してください。

参考文献

105
109
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
105
109

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?