うちの会社では複数あるサーバのログ集約に Fluentd を使っている。 サーバが多数あってもログファイルが1個のサーバに集まっていればログを確認するときに便利だ。 いままではなんとなく見よう見まねで使っていたが、ここいらで一つ本家ドキュメントを読んでおこう。
ここだな…
Fluentd とは
- ログ集約と配布をやってくれるミドルウェア。
- 多様な入力と出力の機能や、フィルタリングや、バッファリングの機能がある。
- それぞれプラグインがあって、どこと繋げるとか抽出の機能を外付けできる。
設定でよく見かける 24224 ポートは forward というプラグインのデフォルトのポートだ。これはfluentd 間の通信で使われる。 例えば これ はJavaのロガーでロガーがfluentdサーバにログメッセージを送る。
でもこれ直接使うとアプリケーションから org.fluentd.logger.FluentLogger を直接使うことになるから、何らかのロガーのアペンダーとして提供されているほうが出力先を切り替えたいときに楽かもね。
Dockerも fluentd の機能を持っている。設定を入れると指定されたfluentdのサーバにログメッセージを送れる。https://docs.docker.com/config/containers/logging/fluentd/
1個のログメッセージをfluentdでは event と呼んでいる。event は タグと時刻とメッセージ内容で構成される。時刻はそのまま時刻だ。タグは eventの分類に使われる。メッセージはJSON形式になるらしい。https://docs.fluentd.org/quickstart/life-of-a-fluentd-event#event-structure
docker-compose でのサンプルを動かしてみる
うむうむなるほど。ドキュメントには動作するサンプルもあるな。https://docs.fluentd.org/container-deployment/docker-compose やってみよう。
これは EFK Stackの例らしい。 ElasticSearch, Fluentd, Kibanaでの分析基盤が動かせるのだな。 コードはここにあるからcloneして…と。
>docker-compose up -d
Creating elasticsearch ... done
Creating fluentd-elastic-kibana_kibana_1 ... done
Creating fluentd-elastic-kibana_fluentd_1 ... done
Creating fluentd-elastic-kibana_web_1 ... error
ERROR: for fluentd-elastic-kibana_web_1 Cannot start service web: failed to initialize logging driver: dial tcp [::1]:24224: connect: connection refused
ERROR: for web Cannot start service web: failed to initialize logging driver: dial tcp [::1]:24224: connect: connection refused
ERROR: Encountered errors while bringing up the project.
>
エラーになった。どうしてだ? web から fluentd に繋げないのか。 docker-compose.yaml はどうなっているかというと…
version: "3"
services:
web:
image: httpd
ports:
- "80:80"
links:
- fluentd
logging:
driver: "fluentd"
options:
fluentd-address: localhost:24224
tag: httpd.access
fluentd:
build: ./fluentd
volumes:
- ./fluentd/conf:/fluentd/etc
links:
- "elasticsearch"
ports:
- "24224:24224"
- "24224:24224/udp"
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:7.13.1
container_name: elasticsearch
environment:
- "discovery.type=single-node"
expose:
- "9200"
ports:
- "9200:9200"
kibana:
image: docker.elastic.co/kibana/kibana:7.13.1
links:
- "elasticsearch"
ports:
- "5601:5601"
web のログ設定が
logging:
driver: "fluentd"
options:
fluentd-address: localhost:24224
tag: httpd.access
になっているな。これはさっき見たような docker が直接ログドライバーとして fluentd サーバにログを送る設定だ。 接続先と流すタグの設定をしている。
設定を変えて動かしてみる
接続先が localhost とはどういう意味だろう?というか、links を使っていてあまりよろしくないかもな。サービス全部同じネットワークに入れて、fluentd のIPアドレスを固定するように設定すればよいだろう。やってみよう。
https://docs.docker.com/compose/compose-file/compose-file-v3/#links
<<ドタドタバタリ>>
よしこれでどうだ。 linksやめて、efk_stack_network というネットワーク設定してIPアドレスを 10.10.10.10 に固定したぜ!(重要なところだけ記載。)
version: "3"
services:
web:
image: httpd
ports:
- "80:80"
logging:
driver: "fluentd"
options:
fluentd-address: 10.10.10.10:24224
tag: httpd.access
networks:
efk_stack_network:
fluentd:
build: ./fluentd
volumes:
- ./fluentd/conf:/fluentd/etc
networks:
efk_stack_network:
ipv4_address: 10.10.10.10
(略)
networks:
efk_stack_network:
ipam:
driver: default
config:
- subnet: 10.10.10.0/24
起動してみよう。
>docker-compose up -d
Creating network "fluentd-elastic-kibana_efk_stack_network" with the default driver
Creating fluentd-elastic-kibana_kibana_1 ... done
Creating fluentd-elastic-kibana_web_1 ... error
Creating fluentd-elastic-kibana_fluentd_1 ... done
Creating elasticsearch ... done
ERROR: for fluentd-elastic-kibana_web_1 Cannot start service web: failed to initialize logging driver: dial tcp 10.10.10.10:24224: i/o timeout
ERROR: for web Cannot start service web: failed to initialize logging driver: dial tcp 10.10.10.10:24224: i/o timeout
ERROR: Encountered errors while bringing up the project.
>
つながらない。いやいやいやそんなことはないぞ。試しに ping 打ってみるか。web がコケてるから一旦ログドライバー設定消して、もう一度起動しよう。まずは ping をインストールしてと…
>docker exec -it fluentd-elastic-kibana_web_1 /bin/bash
root@b15fc9396cf2:/usr/local/apache2# apt-get update
Get:1 http://deb.debian.org/debian bullseye InRelease [116 kB]
(略)
Processing triggers for libc-bin (2.31-13+deb11u2) ...
root@b15fc9396cf2:/usr/local/apache2# ping 10.10.10.10
PING 10.10.10.10 (10.10.10.10) 56(84) bytes of data.
64 bytes from 10.10.10.10: icmp_seq=1 ttl=64 time=0.123 ms
64 bytes from 10.10.10.10: icmp_seq=2 ttl=64 time=0.050 ms
64 bytes from 10.10.10.10: icmp_seq=3 ttl=64 time=0.035 ms
64 bytes from 10.10.10.10: icmp_seq=4 ttl=64 time=0.100 ms
64 bytes from 10.10.10.10: icmp_seq=5 ttl=64 time=0.036 ms
^C
--- 10.10.10.10 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4184ms
rtt min/avg/max/mdev = 0.035/0.068/0.123/0.036 ms
root@b15fc9396cf2:/usr/local/apache2#
ping 通るな…
もっと設定を変えて動かしてみる
じゃあなんでつながらない?コンテナの起動タイミング的な何かかな? 設定オプションでそれっぽいのないだろうか?
<<ドタドタバタリ>>
あ、 fluentd-async てのがあるな。メッセージはコネクションが確立されるまでバッファされます。か。
https://docs.docker.com/config/containers/logging/fluentd/#fluentd-async
設定してみよう。
logging:
driver: "fluentd"
options:
fluentd-address: 10.10.10.10:24224
tag: httpd.access
fluentd-async: "true"
さあどうかな?
>docker-compose up -d
Creating network "fluentd-elastic-kibana_efk_stack_network" with the default driver
Creating fluentd-elastic-kibana_web_1 ... done
Creating fluentd-elastic-kibana_kibana_1 ... done
Creating elasticsearch ... done
Creating fluentd-elastic-kibana_fluentd_1 ... done
>
おお起動した!その後のhttp アクセスもちゃんとKibana に拾われているぞ。これでいいんだ。

うーむなるほど。EFKの構成もこのぐらいの docker-compose.yml で作れるなら学習にもとっつきやすそうだ。
localhostはどこなのか
それにしても…もともとの設定だと接続先が localhost だったがこれはどういう意味なのだろう? web コンテナで fluentd のサービスなんか動いてないのに。
logging:
driver: "fluentd"
options:
fluentd-address: localhost:24224
tag: httpd.access
<<ドタドタバタリ>>
わかった!この記事によると localhost ってホスト側のOSを指すらしい。https://blg.dai-it-system.com/2021/09/docker_log_fluentd/ それで、ポートバインディングでホストのポート24224とfluentd のポート24224を繋いでいる。つまり通信が一旦 docker の外にでているのだ。そういうことだったのか!
fluentd:
build: ./fluentd
volumes:
- ./fluentd/conf:/fluentd/etc
links:
- "elasticsearch"
ports:
- "24224:24224"
- "24224:24224/udp"
まとめ
とにかく動かすことができた。設定ファイルの書式もわかってきた。次はfluentdをテスト用AWSアカウントで実際に立ててみよう。
続きはまた別の機会に。
