Filebeat→Logstash→Elasticsearch→KibanaでNginxのログを可視化する
面白そうだったので
- Filebeat – 軽量ログ収集ツール
- Logstash – データを変換し一元化してくれるツール
- ElasticSearch – 全文検索や統計を取ってくれるツール
- Kibana – ブラウザでアクセスして上記を可視化したり設定変更できるGUI
全て同じElastic社が作っているので連携がスムーズです。
ホストOSのNginxのログをfilebeatで収集→Logstashで加工→ElasticSearchで統計→Kibanaで表示するDocker composeを作ります。
Nginxの設定
Nginx設定ファイルの編集
Cloudflare(CDN)用のreal ip取得(使用している人のみ)
プロキシを挟んでいても相手の正しいIPが取得できるように下記をhttpブロックに追記しておきます。
CloudflareとNGINXと公式のIP rangeを参考に、下記プロキシからのアクセスのみreal_ip_headerを取得
set_real_ip_from 103.21.244.0/22;
set_real_ip_from 103.22.200.0/22;
set_real_ip_from 103.31.4.0/22;
set_real_ip_from 104.16.0.0/12;
set_real_ip_from 108.162.192.0/18;
set_real_ip_from 131.0.72.0/22;
set_real_ip_from 141.101.64.0/18;
set_real_ip_from 162.158.0.0/15;
set_real_ip_from 172.64.0.0/13;
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 188.114.96.0/20;
set_real_ip_from 190.93.240.0/20;
set_real_ip_from 197.234.240.0/22;
set_real_ip_from 198.41.128.0/17;
set_real_ip_from 2400:cb00::/32;
set_real_ip_from 2606:4700::/32;
set_real_ip_from 2803:f800::/32;
set_real_ip_from 2405:b500::/32;
set_real_ip_from 2405:8100::/32;
set_real_ip_from 2c0f:f248::/32;
set_real_ip_from 2a06:98c0::/29;
real_ip_header CF-Connecting-IP;
Kibana&Elasticsearch&Logstash&Filebeatのインストール
Docker composeファイルの作成
さくさくっと全部入ったDocker composeを作成します。
公式Dockerイメージを使用します。バージョンは適切に設定して下さい。
docker-compose.yamlと同じフォルダにdocker.env
、elasticsearch.yml
、kibana.yml
、filebeat.yml
ファイルを作成します。
es-data
フォルダも生成し書き込み権限を持たせておきます。一応sudo docker network create mynetwork
で作成したネットワークを使用しています。
docker-compose.yaml
version: '3'
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:8.9.1
environment:
- "discovery.type=single-node"
- "xpack.security.enabled=true"
- "ELASTIC_PASSWORD=${ELASTIC_PASSWORD}"
- "ELASTIC_USER=${ELASTIC_USER}"
ports:
- "9200:9200"
volumes:
- ./es-data:/usr/share/elasticsearch/data
- ./elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml:ro
networks:
- mynetwork
restart: always
kibana:
image: docker.elastic.co/kibana/kibana:8.9.1
ports:
- "5601:5601"
environment:
- "ELASTICSEARCH_HOSTS=http://elasticsearch:9200"
- "XPACK_REPORTING_KIBANASERVER_HOSTNAME=localhost"
volumes:
- ./kibana.yml:/usr/share/kibana/config/kibana.yml:ro
networks:
- mynetwork
restart: always
logstash:
image: docker.elastic.co/logstash/logstash:8.9.1
environment:
- "ELASTICSEARCH_HOST=http://elasticsearch:9200"
volumes:
- ./logstash/pipeline:/usr/share/logstash/pipeline
- ./logstash/conf.d:/etc/logstash/conf.d
- ./logstash.yml:/usr/share/logstash/config/logstash.yml:ro
networks:
- mynetwork
depends_on:
- elasticsearch
restart: always
filebeat:
image: docker.elastic.co/beats/filebeat:8.9.1
volumes:
- ./filebeat.yml:/usr/share/filebeat/filebeat.yml:ro
- /var/log/nginx:/var/log/nginx
networks:
- mynetwork
depends_on:
- elasticsearch
restart: always
networks:
mynetwork:
driver: bridge
docker.env
Elasticsearchのユーザー名とパスワードを設定します。Kibanaのコンソールにログイン時に使用します。
ELASTIC_PASSWORD=elasticのパスワード
ELASTIC_USER=elasticのユーザー名
作成したらsudo docker compose up -d
でコンテナを起動します。
ElasticSearchの設定
elasticsearch.yml
基本デフォルトのままなので特に弄らなくて良いかもです。
cluster.name: "docker-cluster"
network.host: 0.0.0.0
http.port: 9200
トークンの生成
Docker経由でコマンドを打ってElasticsearchでelastic/kibanaのアクセストークンを生成します。
sudo docker exec -it kibana-elasticsearch-1 bash -c "bin/elasticsearch-service-tokens create elastic/kibana my-token"
このトークンをkibana.ymlに入力します。
Kibanaの設定
上記で生成したトークンを記述します。32文字以上のフレーズは適当なジェネレーターで生成しました。
kibana.yml
server.host: "0.0.0.0"
server.shutdownTimeout: "5s"
# 作成したアクセストークンを入力
elasticsearch.hosts: [ "http://elasticsearch:9200" ]
elasticsearch.serviceAccountToken: "生成したトークン"
xpack.security.encryptionKey: "32文字以上のフレーズ"
xpack.reporting.encryptionKey: "32文字以上のフレーズ"
xpack.encryptedSavedObjects.encryptionKey: "32文字以上のフレーズ"
xpack.security.session.idleTimeout: "1h"
xpack.reporting.kibanaServer.hostname: "kibana"
Nginxの設定
例として「https://ドメイン:23232/」にアクセスしたらKibanaのコンソールにアクセスするように設定します。今回は許可したIPアドレスからのみ接続できるようにしています。
/etc/nginx/conf.d/kibana-proxy.confを作成して下記を入力します。
kibana-proxy.conf
server {
listen 23232 ssl;
server_name ドメイン名;
ssl_certificate 証明書.pem;
ssl_certificate_key 証明書鍵.pem;
location / {
allow 許可するIP;
allow 127.0.0.0/24;
deny all;
proxy_pass http://localhost:5601; # Kibanaのアドレス
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
できたらsudo systemctl restart nginx
でNginxを再起動し、Dockerも再起動してコンソール「https://ドメイン:23232/」にアクセスしてみます。ログイン画面が出てくれば成功です。
データ収集&加工
Filebeatの設定
/var/log/nginx/*.jsonに保存されたデータを収集します。
filebeat.yml
Firebeatでログを収集し、Logstashへデータを送ります。
type: log
は非推奨になりtype: filestream
を使用するようにと公式ドキュメントにあるのでそれを使用します。
filebeat.inputs:
- type: filestream
paths:
- /var/log/nginx/*.json
tags: ["nginx", "json"]
parsers:
- ndjson:
target: ""
add_error_key: true
output.logstash:
hosts: ["logstash:5044"]
Logstashの設定
公式サイト を参考にKibanaでLogstashを動かすためのロールとユーザーを作成します。


このユーザー名とパスワードをlogstash.confファイルに記述します。
logstash
フォルダを作成し、更にその下にpipeline
フォルダを作成し、その下にlogstash.conf
ファイルを作成します。ここに基本設定を記入します。
logstash/pipeline/logstash.conf
ベースの設定をします。
input {
beats {
port => 5044
}
}
output {
elasticsearch {
hosts => ["http://elasticsearch:9200"]
index => "%{[@metadata][beat]}-%{[@metadata][version]}-%{+YYYY.MM.dd}"
user => logstash_internal
password => 設定したパスワード
}
}
Logstashでのデータ加工
こちらのサイトのfilter-nginx.confとlog-json.confをそのまま使用させて頂きました。
filter-nginx.confファイルをpipeline
フォルダの中に入れます。
log-json.confの内容をホストOSの/etc/nginx/nginx.conf
のhttpブロックに追記し、更に下記を追記します。
access_log /var/log/nginx/global-access.json json;
error_log /var/log/nginx/global-error.log;
これでjson形式の細かいログが取れます。
あとはNginxとDockerを再起動します。
実行
Discoverを開いて上手くデータが流れ込んできていれば成功です。やったね。

ufwやfail2banの設定ファイルも公開されている方がいるので使ってみたいところ。アクセスログだけでなくMetricbeatでシステム情報もロギングしたいです。