designetwork

ネットワークを軸としたIT技術メモ

Speedtest CLI & Elastic Stackで回線速度を可視化・監視する

Ookla Speedtest CLIにより定期的にスピードテストを実行して、結果ログをFilebeat→Logstash→Elasticsearchと格納して、Kibanaで可視化する。インターネットが遅いときはPraeco (ElastAlert)でSlack通知することもできるようになる。

Kibanaダッシュボード

Slackアラート

監視構成

構成概要はこのようになっている。

Speedtest CLI

中核となるSpeedtest CLIスピードテストができるサイトはUSEN、Measurement Lab、Netflix fast.comなど各種あるが、Ooklaから、Webブラウザ不要・各種OSでコマンド実行可能なSpeedtest CLIが提供されている。

www.speedtest.net

初回実行時にEnd User License Agreementに同意する。

C:\app\ookla-speedtest>speedtest
==============================================================================

You may only use this Speedtest software and information generated
from it for personal, non-commercial use, through a command line
interface on a personal computer. Your use of this software is subject
to the End User License Agreement, Terms of Use and Privacy Policy at
these URLs:

        https://www.speedtest.net/about/eula
        https://www.speedtest.net/about/terms
        https://www.speedtest.net/about/privacy

==============================================================================

Do you accept the license? [type YES to accept]: YES
License acceptance recorded. Continuing.

CLIからも同意可能

speedtest --accept-license

今回は、一般ユーザ環境のWindows PCで実行する。タスクスケジューラで定期実行させるためにbatファイルを作成する。

@echo off
set YYYY=%date:~0,4%
set MM=%date:~5,2%
set YYYYMM=%YYYY%%MM%

C:\app\ookla-speedtest\speedtest.exe -f json -v -s 48463 >> C:\app\ookla-speedtest\log\PC-speedtest_%YYYYMM%.log 2>&1
オプション 内容
-f json 結果ログをJSON形式で出力させる。
-v エラー発生時などログが追いやすくなる。
-s 48463 テスト先を固定する。自動選択だとエラー率高い...

このような結果が得られる。(整形済み)

{
  "type": "result",
  "timestamp": "2022-04-29T11:57:36Z",
  "ping": {
    "jitter": 0.16800000000000001,
    "latency": 7.2350000000000003
  },
  "download": {
    "bandwidth": 25663582,
    "bytes": 233639723,
    "elapsed": 9102
  },
  "upload": {
    "bandwidth": 32094379,
    "bytes": 188270165,
    "elapsed": 5909
  },
  "packetLoss": 0,
  "isp": "Softbank BB",
  "interface": {
    "internalIp": "x.x.x.x",
    "name": "",
    "macAddr": "xx:xx:xx:xx:xx:xx",
    "isVpn": false,
    "externalIp": "x.x.x.x"
  },
  "server": {
    "id": 48463,
    "host": "speed.udx.icscoe.jp",
    "port": 8080,
    "name": "IPA CyberLab 400G",
    "location": "Tokyo",
    "country": "Japan",
    "ip": "219.100.92.228"
  },
  "result": {
    "id": "56bf915e-c442-4524-b2ee-a05203a8a4d2",
    "url": "https://www.speedtest.net/result/c/56bf915e-c442-4524-b2ee-a05203a8a4d2",
    "persisted": true
  }
}

テスト先サーバは speedtest --servers で確認できる。

>speedtest -v --servers
Closest servers:

    ID  Name                           Location             Country
==============================================================================
 20976  GLBB Japan                     Tokyo                Japan
 21569  i3D.net                        Tokyo                Japan
 38241  BudgetVM                       Tokyo                Japan
 28910  fdcservers.net                 Tokyo                Japan
 24333  Rakuten Mobile, Inc            Tokyo                Japan
 44988  Misaka Network, Inc.           Tokyo                Japan
 48463  IPA CyberLab 400G              Tokyo                Japan
 14623  IPA CyberLab                   Bunkyo               Japan
  8407  Allied Telesis Capital Corporation Sagamihara           Japan
  6087  Allied Telesis Capital Corporation Fussa-shi            Japan

ログローテーションの仕組みは割愛し、月次にしてファイル数を少なく抑える。

タスクスケジューラ

Windowsのタスクスケジューラでbatを5分間隔で定期実行する。Linuxの場合はshellスクリプトをcronなどで実行すればよい。
※数百MBのダウンロード/アップロードが発生し回線を圧迫する恐れがあるので注意。

Filebeat

Filebeatでbat実行で出力されるログを読み、Logstashに送信する。(インストール手順は割愛)

C:\app\filebeat
---
filebeat.yml
---
filebeat.config:
  modules:
    path: ${path.config}\\modules.d\\*.yml
    reload.enabled: false

filebeat.inputs:
- type: log
  enabled: true
  paths:
    - C:\app\ookla-speedtest\log\PC-speedtest_*.log
  fields:
    log_system: intra
    log_type: speedtest

output.logstash:
  hosts: ["<LOGSTASH>:5044"]
  ssl.enabled: true
  ssl.verification_mode: certificate
  ssl.certificate_authorities: [C:\app\filebeat\certs\elasticsearch-ca.pem]

logging:
  level: info
  to_files: true
  to_syslog: false
  json: true
  files:
    path: C:\app\filebeat\log
    name: 'filebeat'
    keepfiles: '7'
    permissions: '0644'
  metrics.enabled: false

name: PC
monitoring.enabled: true
monitoring.cluster_uuid: <UUID>
monitoring.elasticsearch:
  hosts: ["<ELASTICSEARCH>:9200"]
  username: "beats_system"
  password: "PASSWORD"
  protocol: "https"
  ssl.enabled: true
  ssl.verification_mode: certificate
  ssl.certificate_authorities: [C:\app\filebeat\certs\elasticsearch-ca.pem]

Logstash

LogstashでログをElasticsearch用にフィールド分けする。ログ形式をJSONとしているため、grokで正規表現によるパースは不要。Pipeline-to-Pipelineの機能でfilter設定ファイルを分割することで運用性を向上させている。

beats_server.conf

input {
  beats {
    port => 5044
    ssl => true
    ssl_verify_mode => none
    ssl_key => "/etc/logstash/certs/logstash.p8.key"
    ssl_certificate => "/etc/logstash/certs/logstash.crt"
  }
}

output {
  if [fields][log_system] == "intra" {
    } else if [fields][log_type] == "speedtest" {
      pipeline {
        send_to => "intra.speedtest"
      }
    }
  }
}

結果ログのdownload.bandwidth, upload.bandwidthBytes per secのため、8倍してbits per secにする。

intra.speedtest.conf

input {
  pipeline {
    address => "intra.speedtest"
  }
}

filter {
  if [fields][log_type] == "speedtest" {
    json {
      source => "message"
    }
    if [download][bandwidth] {
      ruby {
        code => "
          event.set('[download][bps]',event.get('[download][bandwidth]').to_i*8)
          event.set('[upload][bps]',event.get('[upload][bandwidth]').to_i*8)
        "
      }
    }
  }

  mutate {
    add_field => { 
      "[ecs][version]" => "1.10.0"
      "[event][kind]" => "event"
      "[event][category]" => "network"
      "[event][type]" => "info"
      "[event][outcome]" => "unknown"
    }
  }
  date {
    match => ["timestamp", "ISO8601", "MMM dd HH:mm:ss yyyy", "MMM  d HH:mm:ss yyyy"]
    target => "@timestamp"
    #timezone => "Asia/Tokyo"
  }
}

output {
  elasticsearch {
    ssl => true
    ssl_certificate_verification => true
    cacert => "/etc/logstash/certs/elasticsearch-ca.pem"
    ilm_enabled => true
    ilm_rollover_alias => "intra.speedtest"
    ilm_policy => "intra.speedtest"
    hosts => ["<ELASTICSEARCH>:9200"]
    user => "elastic"
    password => "${ES_PWD}"
    manage_template => true
    ecs_compatibility => "v1"
  }
}

Elasticsearch

個別の設定は不要。数値が期待通り扱われないような場合はIndex Templateでフィールド設定を調整する。

Kibana

冒頭の通り、このようなダッシュボードを作成した。

Windows Updateが配信されて急激にインターネット網が輻輳しており、朝7時から速度が低下していき、9時には2Mbps程度しか出ていない。輻輳はプロバイダー網内で発生していたため、従来のSNMPMRTGによる帯域監視では、ただトラフィックが少ないようにしか見えない。NetFlowなどを活用すればコネクションが長時間化したり、TCP再送が増えていそう。

アクセス元回線グローバルIPの通り、回線を切り替えることで輻輳している網を回避した。

パネル 対象フィールド 備考
ダウンロード速度[bps] download.bps 最新値 existsでフィルタしてエラー回避
アップロード速度[bps] upload.bps 同上
ダウンロード速度[bps] download.bps 平均値
アップロード速度[bps] upload.bps 平均値
パケットロス packetLoss
Ping遅延[ms] ping.latency
Pingゆらぎ[ms] ping.jitter
テスト先サーバ server.host
アクセス元回線グローバルIP interface.externalIp
warning: テスト失敗 level テストに失敗状況を可視化

テスト結果リンク

Speedtest CLIでのテスト結果は result.url から通常のWebブラウザ版と同様に確認できる。

このダッシュボードでは下記のScripted fieldsにより result.link としている。

Scripted fieldsの機能で Format: Urlとすることでクリック可能なリンクのフィールドとなる。(deprecatedになっていますが...)

エラー時は result.link は空になるので、存在チェックした上で取得。

if (doc['result.url'].size() == 0) {
    return ""
} else {
    return doc['result.url'].value
}

Praeco (ElastAlert)

情シスでイントラ環境を監視する場合、ユーザより先にインターネット遅延に気付く必要があるので、download.bpsしきい値Slackアラートする。

Praecoについてはこちら ※記事中のバージョンは古いので最新版を要確認

designetwork.daichi703n.com

生成されるElastAlert設定はこちらの通り。

filter:
  - query:
      query_string:
        query: 'download.bps:*'
index: intra.speedtest
metric_agg_key: download.bps
metric_agg_type: avg
min_threshold: 100000000
name: intra.speedtest.download.bps_slow
query_key: agent.hostname

まとめ - Speedtest CLI & Elastic Stackで回線速度を可視化・監視する

Ookla Speedtest CLIを定期実行し、結果をElastic Stackに集約することで、インターネット回線の速度を可視化・監視することができるようになる。従来のSNMPMRTG・NetFlowなどによる監視とは異なり、よりユーザ目線での監視ができるのが画期的で、ネットワークの運用レベル向上が期待できる。