fluentdでElasticsearchにnginxアクセスログを流してみる
fluentdでElasticsearchにNginxログを流してみたメモです。
以前、LogstashとBeatsを利用してElasticsearchにデータ投入を試したので、
fluentdでも試してみようと思います。
Nginxのアクセスログをfluentdを利用してElasticsearchに流してみます。
下記のバージョンで試してみます。
- Ubuntu 16.04
- td-agent 0.12.4(fluentd-0.12.40)
- Elasticsearch 6.1.1
- Kibana 6.1.2
- nginx 1.12.2
Elasticsearch
Elasticsearch 6.1.1をインストールして起動します。
$ curl -L -O https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.1.1.tar.gz $ tar -xvzf elasticsearch-6.1.1.tar.gz $ cd elasticsearch-6.1.1/ $ ./bin/elasticsearch
Kibana
Kibana 6.1.2をインストールして起動します。
以前書きましたが、ホストOSからゲストOS(Ubuntu)上のKibanaにアクセスするために
config/kibana.ymlのserver.hostにゲストOSのIPを追記して起動します。
$ wget https://artifacts.elastic.co/downloads/kibana/kibana-6.1.2-linux-x86_64.tar.gz $ tar -xzf kibana-6.1.2-linux-x86_64.tar.gz $ cd kibana-6.1.2-linux-x86_64/ $ ifconfig $ vi config/kibana.yml server.host: 10.0.2.15 $ ./bin/kibana
td-agent
fluentdの配布パッケージであるtd-agentを利用します。
td-agentを利用することでfluentdの安定版が使え、システムのRuby環境を汚さずにfluentdを利用することが出来ます。
ディストリビューションごとにインストーラが異なるので、下記のページから自分の環境用(Ubuntu)のコマンドを探します。
https://docs.fluentd.org/v0.12/articles/install-by-deb
Ubuntu16では下記のコマンドでインストールします。
$ curl -L https://toolbelt.treasuredata.com/sh/install-ubuntu-xenial-td-agent2.sh | sh
確認
$ td-agent --version
td-agent 0.12.4
status
起動確認
$ /etc/init.d/td-agent status ● td-agent.service - LSB: data collector for Treasure Data Loaded: loaded (/etc/init.d/td-agent; bad; vendor preset: enabled) Active: active (running) since 日 2018-01-14 20:22:12 JST; 2h 0min ago Docs: man:systemd-sysv-generator(8) Process: 29470 ExecStart=/etc/init.d/td-agent start (code=exited, status=0/SUCCESS) Main PID: 29495 (ruby) Tasks: 9 Memory: 65.0M CPU: 3.242s CGroup: /system.slice/td-agent.service tq29495 /opt/td-agent/embedded/bin/ruby /usr/sbin/td-agent --log /var/log/td-agent/td-agent.log --daemon /var/run/td-agent/td-agent.pid mq29498 /opt/td-agent/embedded/bin/ruby /usr/sbin/td-agent --log /var/log/td-agent/td-agent.log --daemon /var/run/td-agent/td-agent.pid 1月 14 20:22:11 ubuntu16 systemd[1]: Starting LSB: data collector for Treasure Data... 1月 14 20:22:12 ubuntu16 td-agent[29470]: Starting td-agent: * td-agent 1月 14 20:22:12 ubuntu16 systemd[1]: Started LSB: data collector for Treasure Data.
stop
停止。
$ sudo /etc/init.d/td-agent stop [ ok ] Stopping td-agent (via systemctl): td-agent.service. $ sudo /etc/init.d/td-agent status ● td-agent.service - LSB: data collector for Treasure Data Loaded: loaded (/etc/init.d/td-agent; bad; vendor preset: enabled) Active: inactive (dead) since 日 2018-01-14 22:23:25 JST; 2s ago Docs: man:systemd-sysv-generator(8) Process: 29716 ExecStop=/etc/init.d/td-agent stop (code=exited, status=0/SUCCESS) Process: 29470 ExecStart=/etc/init.d/td-agent start (code=exited, status=0/SUCCESS) Main PID: 29495 (code=exited, status=0/SUCCESS) 1月 14 20:22:11 ubuntu16 systemd[1]: Starting LSB: data collector for Treasure Data... 1月 14 20:22:12 ubuntu16 td-agent[29470]: Starting td-agent: * td-agent 1月 14 20:22:12 ubuntu16 systemd[1]: Started LSB: data collector for Treasure Data. 1月 14 22:23:24 ubuntu16 systemd[1]: Stopping LSB: data collector for Treasure Data... 1月 14 22:23:25 ubuntu16 td-agent[29716]: Stopping td-agent: * td-agent 1月 14 22:23:25 ubuntu16 systemd[1]: Stopped LSB: data collector for Treasure Data.
start
起動。
$ sudo /etc/init.d/td-agent start [ ok ] Starting td-agent (via systemctl): td-agent.service. $ sudo /etc/init.d/td-agent status ● td-agent.service - LSB: data collector for Treasure Data Loaded: loaded (/etc/init.d/td-agent; bad; vendor preset: enabled) Active: active (running) since 日 2018-01-14 22:23:51 JST; 2s ago Docs: man:systemd-sysv-generator(8) Process: 29716 ExecStop=/etc/init.d/td-agent stop (code=exited, status=0/SUCCESS) Process: 29794 ExecStart=/etc/init.d/td-agent start (code=exited, status=0/SUCCESS) Main PID: 29819 (ruby) Tasks: 9 Memory: 65.1M CPU: 327ms CGroup: /system.slice/td-agent.service tq29819 /opt/td-agent/embedded/bin/ruby /usr/sbin/td-agent --log /var/log/td-agent/td-agent.log --daemon /var/run/td-agent/td-agent.pid mq29822 /opt/td-agent/embedded/bin/ruby /usr/sbin/td-agent --log /var/log/td-agent/td-agent.log --daemon /var/run/td-agent/td-agent.pid 1月 14 22:23:51 ubuntu16 systemd[1]: Starting LSB: data collector for Treasure Data... 1月 14 22:23:51 ubuntu16 td-agent[29794]: Starting td-agent: * td-agent 1月 14 22:23:51 ubuntu16 systemd[1]: Started LSB: data collector for Treasure Data.
fluent-plugin-elasticsearch install
fluentdでは入出力、フィルター、変換などがplugin形式で提供されており、それらを組み合わせて組み込むことが出来ます。
デフォルトで利用できるplugin以外はインストールする必要があります。
今回Elasticsearchに出力するためにfluent-plugin-elasticsearchをインストールします。
(td-agent3系だとデフォルトで入っているようです)
$ sudo td-agent-gem install fluent-plugin-elasticsearch --version="1.13.1"
確認
$ td-agent-gem list | grep elastic elasticsearch (6.0.0) elasticsearch-api (6.0.0) elasticsearch-transport (6.0.0) fluent-plugin-elasticsearch (1.13.1)
nginx
nginxを下記の手順でインストールします。
https://www.nginx.com/resources/wiki/start/topics/tutorials/install/#official-debian-ubuntu-packages
$ sudo vi /etc/td-agent/td-agent.conf $ wget -qO - https://nginx.org/keys/nginx_signing.key | sudo apt-key add - $ sudo vim /etc/apt/sources.list.d/nginx.list deb http://nginx.org/packages/ubuntu/ xenial nginx deb-src http://nginx.org/packages/ubuntu/ xenial nginx $ sudo apt-get update $ sudo apt-get install nginx $ sudo nginx -v nginx version: nginx/1.12.2 $ sudo /etc/init.d/nginx start [ ok ] Starting nginx (via systemctl): nginx.service.
nginx.confはインストール時のままです。
$ cat /etc/nginx/nginx.conf user nginx; worker_processes 1; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; #tcp_nopush on; keepalive_timeout 65; #gzip on; include /etc/nginx/conf.d/*.conf; }
td-agent設定
td-agent.confを設定します。
sourceディレクティブでtail inputプラグインの設定を記述します。
$ sudo vi /etc/td-agent/td-agent.conf # input from nginx access_log <source> @type tail path /var/log/nginx/access.log format nginx tag nginx.access pos_file /var/log/nginx/access.log.pos </source>
- path: 読み込み対象のファイルを指定。
- format: nginxを指定。
- tag: 何でもいいですが、nginx.accessを指定。この名前をmatchディレクティブで使用します。
- pos_file: tail inputプラグインがどこまで読み込んだかを記録しておくファイルです。ファイルの出力先を指定。
matchディレクティブでElasticsearchに出力する設定を記述します。
# output to elasticsearch <match nginx.access> @type elasticsearch logstash_format true logstash_prefix nginx host localhost port 9200 type_name accesslog </match>
- logstash_format: trueに指定して、インデックス名がlogstash-YYYY.MM.DDになります。
- logstash_prefix: nginxを指定することで、logstash_formatがnginx-YYYY.MM.DDになります。
- host,port: Elasticsearchのhostとportを指定。
- type_name: ElasticsearchのTypeを指定します。ここではaccesslogにしました。
普通にtd-agentを実行すると、nginxのアクセスログが読めなかったり、
posファイルが書き込めなかったりするので、簡単のためにtd-agentのユーザをrootに変更してしまいます。
TD_AGENT_USER=rootに変更
$ sudo vi /etc/init.d/td-agent #!/bin/sh export PATH=/sbin:/usr/sbin:/bin:/usr/bin TD_AGENT_NAME=td-agent TD_AGENT_HOME=/opt/td-agent TD_AGENT_DEFAULT=/etc/default/td-agent #TD_AGENT_USER=td-agent TD_AGENT_USER=root TD_AGENT_GROUP=td-agent TD_AGENT_RUBY=/opt/td-agent/embedded/bin/ruby TD_AGENT_BIN_FILE=/usr/sbin/td-agent TD_AGENT_LOG_FILE=/var/log/td-agent/td-agent.log TD_AGENT_PID_FILE=/var/run/td-agent/td-agent.pid TD_AGENT_OPTIONS="--use-v1-config"
td-agent再起動
$ sudo service td-agent restart
Elasticsearch mapping定義
Elaticsearchのmappingを定義します。
mappingファイルを作成し、フィールドの型を定義します。
defaultのマッピング(text)以外のフィールドだけ定義します。
$ vi nginx_mapping.json { "template": "nginx*", "mappings": { "accesslog": { "properties": { "remote": {"type": "ip"}, "code": {"type": "integer"}, "size": {"type": "integer"}, "@timestamp": {"type": "date", "index": "false"} } } } }
PUTでmappingを登録します。
が、下記のようなエラーが出てしまいました。
$ curl -X PUT 'http://localhost:9200/nginx_access_log/' -d @nginx_mapping.json {"error":"Content-Type header [application/x-www-form-urlencoded] is not supported","status":406}
どうやらElasticsearch6からContent-Typeヘッダが必要となったようです。
という事でContent-Typeを指定して再実行すると登録出来ました。
$ curl -X PUT -H "Content-Type: application/json" 'http://localhost:9200/nginx_access_log/' -d @nginx_mapping.json [2018-01-29T02:40:37,822][INFO ][o.e.c.m.MetaDataCreateIndexService] [V3FBp3U] [nginx_access_log] creating index, cause [api], templates [], shards [5]/[1], mappings [nginx] {"acknowledged":true,"shards_acknowledged":true,"index":"nginx_access_log"}
下記のエンドポイントにアクセスし、mapping定義を確認。
$ curl -X GET 'localhost:9200/nginx_access_log/?pretty' { "nginx_access_log" : { "aliases" : { }, "mappings" : { "accesslog" : { "properties" : { "@timestamp" : { "type" : "date", "index" : false }, "code" : { "type" : "integer" }, "remote" : { "type" : "ip" }, "size" : { "type" : "integer" } } } }, "settings" : { "index" : { "creation_date" : "1517328346452", "number_of_shards" : "5", "number_of_replicas" : "1", "uuid" : "ldnnJY0rQ_OClhGB7tGrqA", "version" : { "created" : "6010199" }, "provided_name" : "nginx_access_log" } } } }
確認
curlでnginxにアクセスしてログを流してみます。
$ curl -s http://localhost/index.html > /dev/null
すると、下記のようにwarnになってしまいました。
どうやらfluentdのnginxのログ形式とaccess_logの形式が合ってないようです。
$ sudo tail -f /var/log/td-agent/td-agent.log 2018-01-31 01:34:52 +0900 [warn]: pattern not match: "127.0.0.1 - - [31/Jan/2018:01:34:52 +0900] \"GET /index.html HTTP/1.1\" 200 612 \"-\" \"curl/7.47.0\" \"-\""
そのため、
①nginxのログ形式をfluentdのpattern matchの定義に合わせる。
または
②fluentdのpattern matchの定義をnginxの形式に変更して合わせる。
のどちらかが必要そうです。
①が簡単そうです。
nginxをインストールするとデフォルトのlog_formatがmain形式になっているので、defaultで定義されているcombined形式に変更します。
http://nginx.org/en/docs/http/ngx_http_log_module.html
combined(default)形式 nginx.conf
log_format combined '$remote_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent ' '"$http_referer" "$http_user_agent"';main形式 nginx.conf
log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"';combined(default)形式 ログ
$ cat /var/log/nginx/access.log 127.0.0.1 - - [02/Feb/2018:02:23:16 +0900] "GET /index.html HTTP/1.1" 200 612 "-" "curl/7.47.0"main形式 ログ
$ cat /var/log/nginx/access.log.1 | grep -v 400 127.0.0.1 - - [31/Jan/2018:01:34:52 +0900] "GET /index.html HTTP/1.1" 200 612 "-" "curl/7.47.0" "-"
access_logのフォーマット形式を消せばcombined形式が利用されます。
$ sudo vi /etc/nginx/nginx.conf http { include /etc/nginx/mime.types; default_type application/octet-stream; # access_log /var/log/nginx/access.log main; access_log /var/log/nginx/access.log; sendfile on; #tcp_nopush on; keepalive_timeout 65; #gzip on; include /etc/nginx/conf.d/*.conf; }
nginx再起動
$ sudo /etc/init.d/nginx restart [ ok ] Restarting nginx (via systemctl): nginx.service.
再度ログを流してみます。
$ curl -s http://localhost/index.html
うまくいきました。
$ sudo tail -f /var/log/td-agent/td-agent.log 2018-01-31 01:48:45 +0900 [info]: Connection opened to Elasticsearch cluster => {:host=>"localhost", :port=>9200, :scheme=>"http"}
②fluentdのpattern matchの定義をnginxの形式に変更して合わせる
でもやってみます。
nginxのaccess_logのフォーマット形式を元のmain形式に戻します。
$ sudo vi /etc/nginx/nginx.conf http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; #tcp_nopush on; keepalive_timeout 65; #gzip on; include /etc/nginx/conf.d/*.conf; }
下記を参考にtd-agent.confのtail inputプラグインのformatを変更します。
https://joppot.info/2017/03/10/3480
$ sudo vi /etc/td-agent/td-agent.conf # input from nginx access_log <source> @type tail path /var/log/nginx/access.log format /^(?<remote>[^ ]*) (?<host>[^ ]*) (?<user>[^ ]*) \[(?<timestamp>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^ ]*) +\S*)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)" "(?<forwarder>[^\"]*)")?/ tag nginx.access pos_file /var/log/nginx/access.log.pos </source>
td-agent再起動
$ sudo /etc/init.d/td-agent restart
再度ログを流してみます。
$ curl -s http://localhost/index.html
うまくいきました。
$ sudo tail -f /var/log/td-agent/td-agent.log 2018-01-31 01:48:45 +0900 [info]: Connection opened to Elasticsearch cluster => {:host=>"localhost", :port=>9200, :scheme=>"http"}
posファイルを確認してみます。
fluentdでログが読み込まれるとposファイルも更新されています。
$ cat /var/log/nginx/access.log.pos /var/log/nginx/access.log 00000000000005f2 000000000002168e $ curl -s http://localhost/index.html > /dev/null $ curl -s http://localhost/service/index.html > /dev/null $ curl -s http://localhost/service/list.html > /dev/null $ curl -s http://localhost/service/detail.html?id=21 > /dev/null $ curl -s http://localhost/index.html > /dev/null $ curl -s http://localhost/service/index.html > /dev/null $ curl -s http://localhost/service/list.html > /dev/null $ curl -s http://localhost/service/detail.html?id=21 > /dev/null $ cat /var/log/nginx/access.log.pos /var/log/nginx/access.log 000000000000094e 000000000002168e
Kibana確認
Kibanaで確認してみます。
http://localhost:5601でkibanaにアクセスし、
左のManagementからIndex patternにnginx*を入力
Time Filter field nameはそのまま@timestampを選択。
作成したindex patternが表示される。
左のDiscoverから作成したnginx*のindex patternを表示。
うまく表示出来ています。
おわり。