ELK Stackでシステム監視 MetricbeatでNginxのステータス情報を取得+グラフ化

この前のMetricbeatのインストール記事にも書いたけど、どうにもMetricbeatのモジュールとMetricSetの関係がわからない。公式サイトのドキュメントでは例えばNginxはモジュールでそのMetricSetはstubstatusとなっているし、Nginxモジュールを使って実際に出力したデータもそうなっている。だけど、デバッグ表示ではNginxモジュールというのは存在しなくて nginx/stubstatus というMetricSetだけが存在するということになっている。だからなのかモジュールの有効化・無効化がドキュメントどおりにできない。 MetricSetの方もたとえばSystemモジュールで利用可能な筈の system/uptime を使おうとするとレジストされてないので使えないと表示されるけどレジストってなんじゃらほい状態。system/uptimeはデバッグ表示で見ても表示されてないから使えないんだろうけど、elastic社の公式サイトのドキュメントではFreeBSDでも利用可能な表示になってるんだけどねぇ。
ちなみにportsでビルドして /usr/ports/sysutils/beats/work/beats-6.2.2/metricbeat/module/system/uptime を見るとそこにuptimeのソースはあるのでなんだかなぁ状態。


2018-03-12T09:36:11.884+0900 DEBUG [modules] beater/metricbeat.go:80 Register [ModuleFactory:[docker, mongodb, mysql, postgresql, system, uwsgi], MetricSetFactory:[aerospike/namespace, apache/status, ceph/cluster_disk, ceph/cluster_health, ceph/cluster_status, ceph/monitor_health, ceph/osd_df, ceph/osd_tree, ceph/pool_disk, couchbase/bucket, couchbase/cluster, couchbase/node, docker/container, docker/cpu, docker/diskio, docker/healthcheck, docker/image, docker/info, docker/memory, docker/network, dropwizard/collector, elasticsearch/node, elasticsearch/node_stats, etcd/leader, etcd/self, etcd/store, golang/expvar, golang/heap, graphite/server, haproxy/info, haproxy/stat, http/json, http/server, jolokia/jmx, kafka/consumergroup, kafka/partition, kibana/status, kubernetes/container, kubernetes/event, kubernetes/node, kubernetes/pod, kubernetes/state_container, kubernetes/state_deployment, kubernetes/state_node, kubernetes/state_pod, kubernetes/state_replicaset, kubernetes/system, kubernetes/volume, logstash/node, logstash/node_stats, memcached/stats, mongodb/collstats, mongodb/dbstats, mongodb/status, mysql/status, nginx/stubstatus, php_fpm/pool, postgresql/activity, postgresql/bgwriter, postgresql/database, prometheus/collector, prometheus/stats, rabbitmq/node, rabbitmq/queue, redis/info, redis/keyspace, system/core, system/cpu, system/diskio, system/filesystem, system/fsstat, system/load, system/memory, system/network, system/process, system/process_summary, system/raid, uwsgi/status, vsphere/datastore, vsphere/host, vsphere/virtualmachine, zookeeper/mntr]]


デバッグログ表示でモジュールとMetricSetのリストを見る。

ここから本題。今回はNginxのステータスをMetricbeatで取得する。基本的な仕組みはcollectdでNginxのステータスを取得するのと同じ。

Nginxでステータス表示

Nginxの設定 /usr/local/etc/nginx/nginx.conf
1
2
3
4
5
#前略
http {
#中略
        include /usr/local/etc/nginx/vhosts/*.conf;
}

/usr/local/etc/nginx/vhostsにnginxのバーチャルホストの設定を置くとする。
そして/usr/local/etc/nginx/vhosts/にある*.conf設定ファイルをインクルードする設定を追加。

/usr/local/etc/nginx/vhosts/localhost.conf
1
2
3
4
5
6
7
server {
    listen 127.0.0.1:80;
    location /ngstat {
        stub_status on;
        access_log off;
    }
}

Nginxのバーチャルホストの1つとして127.0.0.1:80で待ち受けるものを作成する。
その/ngstatにアクセスすることでNginxのステータスを取得する。
なので、Nginxのhttp_stub_statusモジュールが使える状態でないと当然動かない。
ローカルホスト専用なのでアクセス制限は考えなくてOK.

上の2つの設定は以前の記事そのまま。

# service nginx reload            #←Nginx設定再読み込み
# curl http://127.0.0.1/ngstat
Active connections: 3
server accepts handled requests
 2760 2760 2979
Reading: 0 Writing: 1 Waiting: 2

このように表示(もちろん数値は違う筈)されればNginx側は準備完了。

Metricbeatの設定

前のMetricbeatインストールの記事と大部分同じ設定であるとする。

/usr/local/etc/metricbeat.yml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
metricbeat.config.modules:
  path: ${path.config}/beats/metric_*.yml     #ここが初期値と変わってるので注意
  reload.enabled: false

#output.elasticsearch:                        #elasticsearchには出力しない
#  hosts: ["localhost:9200"]

output.logstash:
  hosts: ["localhost:5044"]

logging.level: debug                          #ログ出力をデバックレベルにする
logging.selectors: ["*"]
logging.to_syslog: false
logging.to_files: true                        #ログファイルを出力する
logging.files:
  path: /var/log                              #ログファイルのPath
  name: metricbeat.log                        #ログファイル名
↑ここは字下げする(2行)

ログファイル/var/log/metricbeat.logにデバックログを出力する設定にしたのが前回と違う点。

/usr/local/etc/beats/metric_nginx.yml (新規ファイル)
1
2
3
4
5
6
- module: nginx
  metricsets: ["stubstatus"]
  enabled: true
  period: 60s                               #←1分間隔
  hosts: ["http://127.0.0.1"]
  server_status_path: "ngstat"

portsをビルドしたときのファイルが残っているなら /usr/ports/sysutils/beats/work/beats-6.2.2/metricbeat/modules.d に各種モジュールの設定ファイルの雛形があるのでそれをコピーする手もある。
その場合はファイル名を変更する。metricbeat.ymlで指定したインクルードするファイル名はmetric_*.ymlなのでそれに沿ったファイル名にする。(例: nginx.yml.disabled → metric_nginx.yml)

公式サイトの役に立ちそうであまりそうでもないMetricbeatのモジュール関係のドキュメントも参照。

確認

# service metricbeat restart
Metricbeatを再起動する。
/var/log/metricbeat.log
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
2018-03-12T09:42:11.953+0900    DEBUG   [publish]       pipeline/processor.go:275       Publish event: {
  "@timestamp": "2018-03-12T00:42:11.952Z",
  "@metadata": {
    "beat": "metricbeat",
    "type": "doc",
    "version": "6.2.2"
  },
  "metricset": {
    "name": "stubstatus",
    "module": "nginx",
    "host": "127.0.0.1",
    "rtt": 507
  },
  "nginx": {
    "stubstatus": {
      "requests": 2931,
      "hostname": "127.0.0.1",
      "reading": 0,
      "handled": 2712,
      "accepts": 2712,
      "current": 1,
      "waiting": 0,
      "active": 1,
      "writing": 1,
      "dropped": 0
    }
  },
  "beat": {
    "version": "6.2.2",
    "name": "hoge.localnet",
    "hostname": "hoge.localnet"
  }
}

ログを確認し、Nginxモジュールが出力したデータがあることを確認する。 上の出力例の8行目から13行目の部分を探すが、 hage:{hoge} は並び順が決まっておらず入れ替わりまくりなので上の出力例の順番に表示されるとは限らない。つまり8〜13行目にあるとは限らない。

Timelionでグラフにする

今回は抽出条件をhostで対象ホスト、metricset.moduleをnginxでNginxモジュールにする。値となるのはnginx.stubstatus.HOGEでHOGEの部分はrequests, reading, handled, accepts, current, waiting, active, writing, dropedとなる。 nginx.stubstatus.hostname は扱わない。この内、accepts, handled, requestsの3つは累積値なので例によって1分前の値との差を出す。その際に敢えて差分がマイナス値になるようにして下向けの折れ線グラフにする。
その他の値は累積値ではないので単純に折れ線グラフにする。
kibana6になって1分毎に取得した値を単純にグラフ化すると何故かそれが殆ど表示されなくなったので、.es(interval='1m', hoge)というようにインターバル指定を追加している。それが下。

1
2
3
4
5
6
7
8
9
.es(interval='1m', q='host:hoge.localnet AND metricset.module:nginx' , metric='max:nginx.stubstatus.accepts', offset='-1m').subtract(.es(q='host:hoge.localnet AND metricset.module:nginx' , metric='max:nginx.stubstatus.accepts')).lines(width=1, fill=1).label('accepts: ↓'),
.es(interval='1m', q='host:hoge.localnet AND metricset.module:nginx' , metric='max:nginx.stubstatus.handled', offset='-1m').subtract(.es(q='host:hoge.localnet AND metricset.module:nginx' , metric='max:nginx.stubstatus.handled')).lines(width=1, fill=1).label('handled: ↓'),
.es(interval='1m', q='host:hoge.localnet AND metricset.module:nginx' , metric='max:nginx.stubstatus.requests', offset='-1m').subtract(.es(q='host:hoge.localnet AND metricset.module:nginx' , metric='max:nginx.stubstatus.requests')).lines(width=1, fill=1).label('requests: ↓'), 
.es(interval='1m', q='host:hoge.localnet AND metricset.module:nginx' , metric='max:nginx.stubstatus.current').lines(width=1, fill=1).label('current: ↑'),
.es(interval='1m', q='host:hoge.localnet AND metricset.module:nginx' , metric='max:nginx.stubstatus.active').lines(width=1, fill=1).label('active: ↑'), 
.es(interval='1m', q='host:hoge.localnet AND metricset.module:nginx' , metric='max:nginx.stubstatus.dropped').lines(width=1, fill=1).label('dropped: ↑'), 
.es(interval='1m', q='host:hoge.localnet AND metricset.module:nginx' , metric='max:nginx.stubstatus.reading').lines(width=1, fill=1).label('reading: ↑'), 
.es(interval='1m', q='host:hoge.localnet AND metricset.module:nginx' , metric='max:nginx.stubstatus.waiting').lines(width=1, fill=1).label('waiting: ↑'), 
.es(interval='1m', q='host:hoge.localnet AND metricset.module:nginx' , metric='max:nginx.stubstatus.writing').lines(width=1, fill=1).label('writing: ↑')

最初の3行は差分、それ以外は単純な線グラフ。個別に書いて並べるので面倒だけど簡単ではある。

MetricbeatでNginxのステータス情報を表示する

こんな感じ。

関連記事:

ELK Stackでシステム監視 FreeBSDのportsでELK Stack6系をインストール

FreeBSDのportsのelasticsearch5にJNAへのシンボリックリンクの貼り間違いバグがあって、それの修正をお願いしたら同じバグを持っていたelasticsearch6も一緒に修正された。
そして一昨日、待ちに待ったlogstash6のportsも登場した。
そこでこの機会にelasticsearch, logstash, kibanaをそれぞれ5系から6系に変えることにした。この3点は少なくともメジャーバージョンは合わせておいた方がトラブらないという話を聞いていたが、logstash6がなかなか登場しないので5系を使っていた。特にLogstashとKibanaはX-Packの関係で同じバージョンが良さげ。

elasticsearch6とkibana6のインストール

# cd /usr/ports/textproc/elasticsearch6
# make install
# cd /usr/ports/sysutils/logstash6
# make install
# /usr/ports/textproc/kibana6
# make install
/etc/rc.conf (追記3行 ただし5系を入れていたなら変更無し)
1
2
3
4
5
elasticsearch_enable="YES"
elasticsearch_login_class="root"
logstash_enable="YES"
logstash_log="YES"            #インストールから様子見の期間だけ
kibana_enable="YES"

elasticsearch6の設定と起動

elasticsearch6の設定と起動は前回と同じで問題なし。

/usr/local/etc/elasticsearch/elasticsearch.yml
1
2
3
4
5
6
7
8
path.data: /var/db/elasticsearch
path.logs: /var/log/elasticsearch
path.scripts: /usr/local/libexec/elasticsearch
network.host: localhost
http.port: 9200

xpack.ml.enabled: false          #以下2行X-Packで使わない(使えない)機能を指定
xpack.security.enabled: false

X-Packインストールまでにelasticsearchを起動するなら最後の2行はコメントにしておく。

/usr/local/etc/elasticsearch/jvm.options
1
2
-Xms2g
-Xmx2g

メモリの割当てだけ変えておく。初期値の1GBはあまりにも小さすぎる。

elasticsearch6にX-Packをインストール

elasticsearch5にはX-Packをインストールするためのports (elasticsearch5-x-pack)が用意されていたのでそれを入れるだけだったが、elasticsearch6のportsにはそのようなportsが用意されていないので手動でインストールすることになる。

で、X-Packプラグインをインストールするためのツールは/usr/local/lib/elasticsearch/binにあるelasticsearch-plugin。 portsで入れると何故か /usr/local/bin/elasticsearch-plugin があるのでそれが使えそうに見えるが、同じディレクトリに elasticsearch-env が無いので使えない。 /usr/local/lib/elasticsearch/bin/elasticsearch-env を /usr/local/bin/ にコピーするか /usr/local/lib/elasticsearch/bin に移動してからそこの elasticsearch-plugin を実行する。(たぶんportsの考慮漏れ)
elasticsearch-plugin は同じディレクトリの elasticsearch-env を呼ぶが、それを見ると初期値ではx-packなどの設定置き場が /usr/local/lib/elasticsearch/config になっているみたい。
そこで /usr/local/lib/elasticsearch/config を作成してからX-Packをインストールする。
portsバージョンelasticsearch6-6.2.2_6で修正された模様

# mkdir /usr/local/lib/elasticsearch/config
# /usr/local/lib/elasticsearch/bin/elasticsearch-plugin install x-pack
# cd /usr/local/lib/elasticsearch/bin
# wget https://artifacts.elastic.co/downloads/packs/x-pack/x-pack-6.x.x.zip  (正しいバージョン指定)
# ./elasticsearch-plugin install file:///usr/local/lib/elasticsearch/bin/x-pack-6.x.x.zip
-> Downloading x-pack from elastic
[=================================================] 100%
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@     WARNING: plugin requires additional permissions     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
* java.io.FilePermission \\.\pipe\* read,write
* java.lang.RuntimePermission accessClassInPackage.com.sun.activation.registries
* java.lang.RuntimePermission getClassLoader
* java.lang.RuntimePermission setContextClassLoader
* java.lang.RuntimePermission setFactory
* java.net.SocketPermission * connect,accept,resolve
* java.security.SecurityPermission createPolicy.JavaPolicy
* java.security.SecurityPermission getPolicy
* java.security.SecurityPermission putProviderProperty.BC
* java.security.SecurityPermission setPolicy
* java.util.PropertyPermission * read,write
See http://docs.oracle.com/javase/8/docs/technotes/guides/security/permissions.html
for descriptions of what these permissions allow and the associated risks.

Continue with installation? [y/N]y
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@        WARNING: plugin forks a native controller        @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
This plugin launches a native controller that is not subject to the Java
security manager nor to system call filters.

Continue with installation? [y/N]y
Elasticsearch keystore is required by plugin [x-pack-security], creating...
-> Installed x-pack with: x-pack-core,x-pack-deprecation,x-pack-graph,x-pack-logstash,x-pack-ml,x-pack-monitoring,x-pack-security,x-pack-upgrade,x-pack-watcher

2018年4月12日追記:
Kibanaは以前からプラグインコマンドからプラグイン名指定でX-Packをインストールしようとすると失敗していたが、ElasticSearchでも6.2.3からはプラグイン名指定ではX-Packのインストールが失敗するようになったので先にX-Packのファイルをダウンロードしてファイル名指定でインストールするという方法に変更した。

kibana6の設定

kibana6の設定も以前の記事と基本的に同じ。つまり、やらなければならないことも同じ。

/usr/local/etc/kibana.yml
1
2
3
4
5
6
7
server.port: 5601
#server.host: "localhost"
server.host: "192.168.52.20"  #Kibanaの動いているホストの(監視側セグメントの)IPアドレス
elasticsearch.url: "http://localhost:9200"
path.data: /var/db/kibana     #←無い筈なので追加 (重要)
xpack.ml.enabled: false
xpack.security.enabled: false

X-Packインストールまでにkibanaを起動するなら最後の2行はコメントにしておく。


# mkdir /var/db/kibana

kibana6にX-Packをインストール

kibana5にはX-Packをインストールするためのports (kibana5-x-pack)が用意されていたのでそれを入れるだけだったが、kibana6のportsにはそのようなportsが用意されていないので手動でインストールすることになる。
2018年3月6日現在のportsではMakefileが間違っているのでkibanaの関連ツールがインストールされない。
/usr/ports/textproc/kibana6/work/kibana-6.2.2-linux-x86_64/bin にある以下2つのファイルを/usr/local/www/kibana6/bin にコピーする。(面倒なのでディレクトリごと)。

  • kibana-keystore
  • kibana-plugin

また、/usr/local/www/kibana6/config/kibana.ymlを必要とするようなのでディレクトリを作成して/usr/local/etc/kibana.ymlにシンボリックリンクを張る。portsバージョンkibana6-6.2.2_2で修正された模様

# cp -pR /usr/ports/textproc/kibana6/work/kibana-6.2.2-linux-x86_64/bin /usr/local/www/kibana6/
# mkdir /usr/local/www/kibana6/config
# ln -s /usr/local/etc/kibana.yml /usr/local/www/kibana6/config/kibana.yml

なお、インストールした後にmake cleanしていて /usr/ports/textproc/kibana6/work以下が掃除済み(存在しない)の場合は、以下を実行でファイルが出来る。

# cd /usr/ports/textproc/elasticsearch6
# make fetch        (ファイル取得済みの筈なので今回は不要)
# make extract      ←今回はこれだけ
# make patch        (今回欲しいファイルがパッチ対象ではないので不要)
# make configure    (今回はビルド無しで良いので不要)
# make build        (今回はビルド無しで良いので不要)

kibana-pluginを実行してX-Packをインストールする。elastic社のサイトのドキュメントでは bin/kibana-plugin install x-pack を実行するとある。そこで、以下。

# /usr/local/www/kibana6/bin/kibana-plugin install x-pack
DeprecationWarning: os.tmpDir() is deprecated. Use os.tmpdir() instead.
Attempting to transfer from x-pack
Attempting to transfer from https://artifacts.elastic.co/downloads/kibana-plugins/x-pack/x-pack-6.2.2.zip
Transferring 269704442 bytes..............

上手く行くようで何故かファイルの転送中に停まってしまうみたいで何時間もこのままに。
中断して以下。

# cd /tmp
# wget https://artifacts.elastic.co/downloads/kibana-plugins/x-pack/x-pack-6.2.2.zip
# /usr/local/www/kibana6/bin/kibana-plugin install file:///tmp/x-pack-6.2.2.zip
Attempting to transfer from file:///tmp/x-pack-6.2.2.zip
Transferring 269704442 bytes....................
Transfer complete
Retrieving metadata from plugin archive
Extracting plugin archive
Extraction complete
Optimizing and caching browser bundles...
Plugin installation complete
# chown -R www:www /usr/local/www/kibana6

好みの問題かも知れないけどkibana6ディレクトリ以下のオーナーを変更。

Logstash6の設定

/usr/local/etc/logstash/logstash.conf
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
input {
        #Beats
        beats {
                port => 5044
        }

        #Collectd
        udp {
                port => 25826
                buffer_size => 262144
                workers => 4
                queue_size => 8192
                codec => collectd { }
                type => "collectd"
        }
}

output {
        elasticsearch {
                hosts => [ "localhost:9200" ]
        }
}
/usr/local/logstash/config/jvm.options (変更)
1
2
-Xms1g
-Xmx1g

上の2つの値は初期値。必要に応じて増やす。データの流量が少なくて簡単なことしかしなければ初期値で十分。

Logstash6にX-Packをインストール

Logstashのファイルは/usr/local/logstash/にある。portsでインストールすると実行用のファイルに実行権限が付いてしないのでそれを付けるところから。

# chmod +x /usr/local/logstash/bin/benchmark.sh
# chmod +x /usr/local/logstash/bin/cpdump
# chmod +x /usr/local/logstash/bin/dependencies-report
# chmod +x /usr/local/logstash/bin/ingest-convert.sh
# chmod +x /usr/local/logstash/bin/logstash-keystore
# chmod +x /usr/local/logstash/bin/logstash-plugin       ← 今回使うのはこれ
# chmod +x /usr/local/logstash/bin/logstash.lib.sh         ← logstash-pluginから呼び出される
# chmod +x /usr/local/logstash/bin/pqcheck
# chmod +x /usr/local/logstash/bin/ruby
# chmod +x /usr/local/logstash/bin/system-install

# /usr/local/logstash/bin/logstash-plugin install x-pack
expr: illegal option -- C
expr: usage: expr [-e] expression

Downloading file: https://artifacts.elastic.co/downloads/logstash-plugins/x-pack/x-pack-6.2.2.zip
Downloading [=============================================================] 100%
Installing file: /tmp/studtmp-fe4cc2f4d060d661a2cdc1a53b50f56c125fbf33c63fc2ca412ce6cce245/x-pack-6.2.2.zip
Install successful
/usr/local/etc/logstash/logstash.yml (追加) (logstash.confじゃない)
1
2
3
xpack.monitoring.elasticsearch.url: http://localhost:9200
xpack.monitoring.elasticsearch.username: 
xpack.monitoring.elasticsearch.password:

今回はusernameとpasswordは指定しない。

ELK Stackの起動

# service elasticsearch start
# service logstash start
# service kibana start

Kibanaは起動コマンド実行後ブラウザで利用可能になるまで数分ほど待たされるかも。
特にKibanaはX-Packを入れた後の初起動は利用可能になるまで15分以上かかるかも。

X-Pack ライセンス投入

ライセンス投入は以前のELK Stackインストールの記事参照。

初稿ではKibanaのX-Packインストール後にKibanaが動かないと思って確認すると書いたが、時間がかかるだけだったよう。

KibanaでX-Packを確認
X-PackをインストールするとKibanaのメニューに[Monitoring]が表示されてX-Packをインストールしたアプリケーションが表示される。この記事ではelasticsearchとKibanaとLogstashにX-Packをインストールしたのでそれが表示されている。

関連記事:
Up