「車輪の再実装」って言葉が好き(実践はできてない)

ネットワークへの接続状況を監視してみる (Prometheus on Docker on ラズパイ)

github pagesを畳んだので、そこにあった記事の転載

現在一人暮らし中なので、自宅の回線はモバイルルーターを契約しているのだが、近頃回線がものすごく遅くなるときがある。 google.comとか1.1.1.1とかにpingを飛ばすとロス率が70%を越したり、レイテンシが500msとかになったりする。今どき地球の裏側の方がちゃんと繋がりそうだなぁなんて思いつつ、いい機会なので死活監視をしてみようと思うので記録。

ところでレイテンシといえば、Latency Numbers Every Programmer Should Knowってページを思い出した。ちなみにこのページによると、CA(カリフォルニア?)とオランダ間でのRTTは150ms程らしい。この手のレイテンシとかのオーダーの話は稀によく耳にするけど、いまいち感覚が身についている気がしない。ちゃんと覚えないとなぁ...

使用するツール

  • Prometheus
  • Docker / Docker Compose
  • RaspberryPi(3B+)

Prometheus

監視ツールというとDatadogとかMackerelとかを聞くことが多い気がするけど、そもそも内側から見たいのでこれらを含めたSaaSは候補から除外、OSSが好きなのと、勢いがありそうだったので?Prometheusを使うことにした。

Docker/ Docker Compose

PrometheusはGolang製の単一バイナリでそのまま動くらしいので使う理由もあまりないけど、単純に趣味

強いて理由を上げるとすれば、そのうちデータベースと連携してデータを保存したりする場合にまとめて管理するのが楽そうかな〰という気分。

RaspberryPi(3B+)

24時間監視しようと思うと、普段遣いのノートPCだと辛いし、消費電力とかもヤバそうなので、ラズパイを使うことに決定。

1. ラズパイの設定

しばらく使ってなかったら、調子が悪くなっていたので、OSをクリーンインストール

  • OSをインストール

  • パスワード設定

  • SSHを有効化

  • Dockerのインストール

cf. 最近のRaspberry Piイメージ(Raspbian)をインストールするメモ

今回初めて知ったけれど、mDNSという仕組みがあり、それを使えばIPを固定しなくても同じLANでraspberrypi.localという名前でラズパイを参照できるらしい、これまで何度か /etc以下設定ファイルを書き換えたりしてたけど、そんな必要なかったのか〰(便利なので良いけれど)。

2. Prometheusを動かしてみる

まずはPrometheusの概要を学んでみようということで、Qiitaで以下の記事を発見

10分で理解する Prometheus

Prometheusは雑に解釈すると、以下の2種類のプログラムからなるらしい

  1. exporter:

    • 監視対象のサーバーで動作するプログラム。
    • 監視するリソース毎に準備
    • WebAPIの感覚で、情報をテキストベースで公開する
  2. prometheus:

    • 監視サーバーのプログラム

    • 定期的に巡回してexporterから情報を収集する

というわけで、早速試してみる。

PrometheusのGETTING STARTED

を参考にしつつ、Dockerを使いたいのでPrometheusのDockerイメージを落としてくる。

 $ docker pull prom/prometheus
 $ docker inspect prom/prometheus
 ~~~前略~~~
             "Cmd": [
                "--config.file=/etc/prometheus/prometheus.yml",
                "--storage.tsdb.path=/prometheus",
                "--web.console.libraries=/usr/share/prometheus/console_libraries",
                "--web.console.templates=/usr/share/prometheus/consoles"
            ],
            "ArgsEscaped": true,
            "Image": "sha256:b452ed1aa226459ac89e04859fa746c0f15861534109fc0c9155596f0244ec22",
            "Volumes": {
                "/prometheus": {}
            },
            "WorkingDir": "/prometheus",
            "Entrypoint": [
                "/bin/prometheus"
            ],
~~~後略~~~

なんとなくPrometheusの使い方がわかったところで、

Getting Started に従い、prometheus.ymlを作成

$ mkdir -p ~/workspace/prometheus
$ cd ~/workspace/prometheus
$ cat > prometheus.yml <<EOF
global:
  scrape_interval:     15s
  external_labels:
    monitor: 'codelab-monitor'
scrape_configs:
  - job_name: 'prometheus'
    scrape_interval: 5s
    static_configs:
      - targets: ['localhost:9090']
EOF

というわけで、さて動かすぞ!と思ったらエラー

$ docker run -p 9090:9090 -v prometheus.yml:/etc/prometheus.yml prom/prometheus
standard_init_linux.go:207: exec user process caused "exec format error"

いろいろ試してみたけど、動かない。

多分イメージがx86向けなんだなぁ(動くものしかpullできないと思ってた...)

というわけで、自分でイメージを作って実行してみる

# dockerfile
FROM armhf/alpine AS build-env

RUN apk update && apk add ca-certificates wget &&\
      wget https://github.com/prometheus/prometheus/releases/download/v2.9.2/prometheus-2.9.2.linux-armv7.tar.gz &&\
      tar -xzf prometheus-2.9.2.linux-armv7.tar.gz

FROM scratch
COPY --from=build-env /prometheus-2.9.2.linux-armv7/* /
ENTRYPOINT ["/prometheus"]
CMD ["--config.file=/prometheus.yml",\
     "--storage.tsdb.path=/data",\
     "--web.console.libraries=/usr/share/prometheus/console_libraries",\
     "--web.console.templates=/usr/share/prometheus/consoles"\
     ]
$ mkdir build
$ cd build
$ vim Dockerfile # 上の内容を記述
$ docker build . -t arm-prometheus
$ docker run --rm -p 9090:9090 arm-prometheus

raspberrypi.local:9090を開いてみる。

f:id:progrunner17:20191014134706j:plain

良さそうだ

Exporterを導入する

Prometheusの概要のところでも少し触れたが、Prometheusでは、監視するリソース毎にexporterと呼ばれるプログラムを動かす。

今回はGithubで公開されているczerwonk/ping_exporterを使ってみる。

こちらは本当にconfigなしでも動くので、とりあえず動かしてみる。

$ wget https://github.com/czerwonk/ping_exporter/releases/download/0.44/ping_exporter-0.4.4_linux_arm
$ mv ping_exporter-0.4.4_linux_arm ping_exporter
$ chmod +x ping_exporter
$ ./ping_exporter 1.1.1.1
$ curl localhost:9427/metrics
# HELP ping_loss_percent Packet loss in percent
# TYPE ping_loss_percent gauge
ping_loss_percent{ip="1.1.1.1",ip_version="4",target="1.1.1.1"} 0
# HELP ping_rtt_best_ms Best round trip time in millis
# TYPE ping_rtt_best_ms gauge
ping_rtt_best_ms{ip="1.1.1.1",ip_version="4",target="1.1.1.1"} 88.44157409667969
# HELP ping_rtt_mean_ms Mean round trip time in millis
# TYPE ping_rtt_mean_ms gauge
ping_rtt_mean_ms{ip="1.1.1.1",ip_version="4",target="1.1.1.1"} 188.0380859375
# HELP ping_rtt_ms Round trip time in millis (deprecated)
# TYPE ping_rtt_ms gauge
ping_rtt_ms{ip="1.1.1.1",ip_version="4",target="1.1.1.1",type="best"} 88.44157409667969
ping_rtt_ms{ip="1.1.1.1",ip_version="4",target="1.1.1.1",type="mean"} 188.0380859375
ping_rtt_ms{ip="1.1.1.1",ip_version="4",target="1.1.1.1",type="std_dev"} 84.13036346435547
ping_rtt_ms{ip="1.1.1.1",ip_version="4",target="1.1.1.1",type="worst"} 348.2742004394531
# HELP ping_rtt_std_deviation_ms Standard deviation in millis
# TYPE ping_rtt_std_deviation_ms gauge
ping_rtt_std_deviation_ms{ip="1.1.1.1",ip_version="4",target="1.1.1.1"} 84.13036346435547
# HELP ping_rtt_worst_ms Worst round trip time in millis
# TYPE ping_rtt_worst_ms gauge
ping_rtt_worst_ms{ip="1.1.1.1",ip_version="4",target="1.1.1.1"} 348.2742004394531

良さそうだ。

exporterとprometheusを連携するため、prometheus.ymlを書き換える

global:
  scrape_interval:     15s
  external_labels:
    monitor: 'codelab-monitor'
scrape_configs:
  - job_name: 'prometheus'
    scrape_interval: 5s
    static_configs:
      - targets: ['localhost:9090']
  - job_name: 'ping_exporter'
    scrape_interval: 5s
    static_configs:
      - targets: ['172.17.0.1:9427']

さて、ここの172.17.0.1は実際にはlocalhostを指すのだが、詳しい説明は長くなるので省略。

(dockerのネットワークのホストやブリッジ等を調べるとよい) (なお、実行時に、 --network="host"というオプションをつけると、localhostでも接続可能 )

さて、もう一度prometheusを実行してみる。

$ docker run --rm  -p 9090:9090 -v prometheus.yml:/prometheus.yml arm-prometheus

raspberrypi.local:9090を開き、ping_rtt_msをクエリとしてグラフを表示させてみると以下のようになった。

f:id:progrunner17:20191014134744j:plain

うまく表示できた。

しばらくpingのデータだけだと物足りない気もするが、疲れたので今日はおしまい。

しばらくデータを記録してみようとおもう。