Docker上でWebサービス+Fluentd+Elasticsearchでアクセスログ管理
docker-compose.yml
KibanaからElasticsearchに接続する際は`kibana_system`を使う構成です。後述のスクリプトでパスワードを設定しています。
webappのloggingのtagの値でfluentdのフィルター等は構成します。後述の設定ファイルで定義します。
version: "3"
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:8.12.2
container_name: analytics-demo-elasticsearch
environment:
- discovery.type=single-node
- xpack.security.enabled=true
- ELASTIC_PASSWORD=password
ports:
- 9200:9200
volumes:
- esdata:/usr/share/elasticsearch/data
fluentd:
build: ./fluentd
container_name: analytics-demo-fluentd
volumes:
- ./fluentd/conf:/fluentd/etc
- ./fluentd/log:/fluentd/log
ports:
- 24224:24224
- 24224:24224/udp
kibana:
image: docker.elastic.co/kibana/kibana:8.12.2
container_name: analytics-demo-kibana
environment:
- ELASTICSEARCH_URL=http://elasticsearch:9200
- ELASTICSEARCH_USERNAME=kibana_system
- ELASTICSEARCH_PASSWORD=password
ports:
- 5601:5601
webapp:
image: analytics-demo-app
container_name: analytics-demo-app
environment:
- FLUENTD_HOST=fluentd
- FLUENTD_PORT=24224
ports:
- 3000:3000
logging:
driver: fluentd
options:
fluentd-address: localhost:24224
tag: webapp
volumes:
esdata:
fluentd/Dockerfile
シンプルな構成は以下です。GeoIPを使う場合などはここで他のプラグインもインストールします。
FROM fluent/fluentd:v1.16-debian-2
USER root
RUN fluent-gem install fluent-plugin-elasticsearch --no-document
USER fluent
fluentd/conf/fluent.conf
以下はWebサービスのログ形式がApache2の形式を想定していますが、フィルターはWebサービスのログ形式に合わせる必要があります。
`@timestamp`の上書きを行わないとElasticsearchのドキュメントに反映されませんでした。
<system>
log_level debug
workers 2
</system>
<source>
@type forward
port 24224
bind 0.0.0.0
</source>
<filter webapp>
@type parser
key_name log
<parse>
@type regexp
expression /^(?<host>[^ ]*) [^ ]* (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>(?:[^\"]|\\.)*?)(?: +\S*)?)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>(?:[^\"]|\\.)*)" "(?<agent>(?:[^\"]|\\.)*)")?$/
time_format %d/%b/%Y:%H:%M:%S %z
</parse>
</filter>
<filter webapp>
@type record_transformer
enable_ruby
<record>
host_param "#{Socket.gethostname}"
size ${record["size"] == "-" ? 0 : record["size"]}
@timestamp ${time.strftime('%Y-%m-%dT%H:%M:%S%z')}
</record>
remove_keys log
</filter>
<match webapp>
@type copy
<store>
@type elasticsearch
host elasticsearch
port 9200
user elastic
password password
index_name fluentd-${tag}
flush_interval 1s
</store>
<store>
@type stdout
</store>
</match>
ElasticsearchのIndex Template
ダッシュボードで可視化する際などに使える`keyword`を追加したりしています。
`text`だけではグラフを作成する際の軸のフィールドとして選択出来ません。
{
"index_patterns": ["fluentd-*"],
"template": {
"settings": {
"number_of_shards": 1,
"number_of_replicas": 1
},
"mappings": {
"properties": {
"host": { "type": "ip" },
"user": { "type": "keyword" },
"method": { "type": "keyword" },
"path": {
"type": "text",
"fields": {
"keyword": { "type": "keyword", "ignore_above": 256 }
}
},
"code": { "type": "integer" },
"size": { "type": "integer" },
"referer": {
"type": "text",
"fields": {
"keyword": { "type": "keyword", "ignore_above": 256 }
}
},
"agent": {
"type": "text",
"fields": {
"keyword": { "type": "keyword", "ignore_above": 256 }
}
},
"host_param": { "type": "keyword" },
"@timestamp": { "type": "date" }
}
}
}
}
起動スクリプト
`kibana_system`のパスワードも設定したく、各サービスが起動した状態で起動順序を制御したかったのでスクリプトを作成しました。
環境構築時に起動・停止を繰り返す場合は`docker-compose down -v`のように、`-v`を付けておくことで関連するリソース(docker volumeなど)も削除してくれます。
#!/bin/bash
# Docker Build
docker-compose build --no-cache
# Elasticsearchの起動
echo "Starting Elasticsearch..."
docker-compose up -d elasticsearch
# Elasticsearchが起動するのを待つ
echo "Waiting for Elasticsearch to be ready..."
until $(curl -s -f -u "elastic:password" -o /dev/null "http://localhost:9200/_cluster/health?wait_for_status=yellow&timeout=50s"); do
printf '.'
sleep 5
done
echo "Elasticsearch is ready."
# kibana_systemのパスワード設定
curl -s -u "elastic:password" -X POST "http://localhost:9200/_security/user/kibana_system/_password" -H "Content-Type: application/json" -d "{\"password\":\"password\"}";
# Templateの適用
curl -s -u "elastic:password" http://localhost:9200/_index_template/template_fluentd -H "Content-Type: application/json" -d @elasticsearch/template/fluentd.json
# Kibanaの起動
echo "Starting Kibana..."
docker-compose up -d kibana
# Fluentdの起動
echo "Starting Fluentd..."
docker-compose up -d fluentd
# Fluentdが起動するのを待つ
echo "Waiting for Fluentd to be ready..."
until nc -z localhost 24224; do
printf '.'
sleep 1
done
sleep 5 # Fluentdの起動を待つために適切な待ち時間を設定する
echo "Fluentd is ready."
# Webappの起動
echo "Starting Webapp..."
docker-compose up -d webapp
echo "All services have been started."
この記事が気に入ったらサポートをしてみませんか?