はじめに
こんにちは。前回に続いてログの扱いをあれこれ調べてました。今回はログ集約をやってみたくてFluentdについてです。Docker上に構築したLaravelだとどうやるのかを調べています。
環境
- PHP 7.3.6
- Laravel 5.8.29
Fluentdについて
冒頭にもあるように、ログ集約のためのミドルウェアで、Ruby製OSSです。サーバ上ではnginx,Apache,MySQL,Redis,postfixなど様々なミドルウェアと、その上に構築・実装したアプリケーションが都度ログを吐き出しています。通常はあちこちに散ってるログを一括して受けつけ、任意の形式・場所にまとめて出力してくれるのがFluentdです。
もう少し短く言うと「ログの入出力を一本化するミドルウェア」になるでしょうか。
今まで関わったプロジェクトのサーバで「なんかログ集めるやつが動いてる」という雑な認識しかしておらず、自分で構築やチューニングした経験はありませんでした。
目的
- DockerでFluentdを動作させたい
- Laravelのアプリから吐き出したログをFluentdで受け付けたい
nginxのログをFluentdに出力する記事はすぐ見つかったんですが、Laravelのログはどうすれば?というのが見当たらなかったので、入門がてら調べてみたのが今回の記事になります。
Fluentd本体はdocker-composeで導入
公式がイメージを用意してくれていますので、docker-compose.ymlに記述すれば使えるようになります。
以下、nginx+PHP-FPM+MariaDB+Fluentd全ての設定を記述したファイルです。それぞれ説明を後述します(全項目はさすがに説明しきれませんが…)。
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 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | version: "3" services: fluentd: build: ./fluentd command: > /usr/bin/fluentd -c /fluentd/etc/fluent.conf -v ports: - "127.0.0.1:24224:24224" - "127.0.0.1:24224:24224/udp" volumes: - ./fluentd/logs:/fluentd/log - ./fluentd/my_fluentd.conf:/fluentd/etc/my_fluentd.conf environment: FLUENTD_CONF: my_fluentd.conf TZ: Asia/Tokyo db: image: mariadb:latest ports: - 3306:3306 environment: MYSQL_ROOT_PASSWORD: root MYSQL_USER: test MYSQL_PASSWORD: test MYSQL_DATABASE: testdb volumes: - ./db-data:/var/lib/mysql app: build: ./php volumes: - .:/var/www/html depends_on: - db web: image: nginx:mainline-alpine ports: - 80:80 volumes: - ./web/default.conf:/etc/nginx/conf.d/default.conf - .:/var/www/html depends_on: - app links: - app logging: driver: fluentd options: fluentd-address: "localhost:24224" tag: "docker.{{.Name}}" |
fluentd
Fluentdの最新は1.6系ですが、stableとlatestは1.3系です。基本はAlpine Linuxで、別途debian版もあります。
以下、fluentdビルド用のDockerfileです。イメージからコンテナを作るだけでなく、コンテナ内であれこれしたい場合は
build
で指定したパスにDockerfileを置きます。
apk add --update
でパッケージ全体を更新した後で、
apk add --update --no-cache
でパッケージを個別にインストールしています。bashはコンテナ内でCUIを操作しないのであれば不要です。
tzdataはApline Linuxのデフォルトが
UTC+0
なので、日本のタイムゾーンに合わせるためです。
1 2 3 4 5 | FROM fluent/fluentd:latest RUN apk add --update && \ apk add --update --no-cache build-base curl curl-dev git zip unzip vim bash tzdata && \ cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \ echo "Asia/Tokyo" > /etc/timezone |
以下、
FLUENTD_CONF
で指定して差し替えているFluentdの設定ファイルです。
source
でFluentdへの入力、
match
で出力を制御しています。
各オプションについてはまだ理解しきれていませんが、こちらを参考にさせてもらい、作成しました。
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 | <source> @type forward @id input1 @label @mainstream port 24224 </source> <filter **> @type stdout </filter> <label @mainstream> <match docker.**> @type file @id output_docker1 path /fluentd/log/docker.*.log symlink_path /fluentd/log/docker.log append true time_slice_format %Y%m%d time_slice_wait 1m time_format %Y%m%dT%H%M%S%z </match> <match **> @type file @id output1 path /fluentd/log/data.*.log symlink_path /fluentd/log/data.log append true time_slice_format %Y%m%d time_slice_wait 3m time_format %Y%m%dT%H%M%S%z </match> </label> |
db
データベースのコンテナです。今回はDBログには触れてないのと、docker-compose.ymlに書いてある以上のことはしていないため、割愛します。
app
PHP-FPMが稼働するコンテナです。Fluentd導入に際して特別なことはしていませんが、ビルド用のDockerfileは以下のとおりです。
docker-compose up -d
の後、コンテナの中で
composer create-project --prefer-dist laravel/laravel testapp
を実行してLaravelをインストールしています。
1 2 3 4 5 6 7 8 9 10 11 12 13 | FROM php:7.3-fpm-alpine RUN apk add --update && \ apk add --update --no-cache build-base curl curl-dev git zip unzip vim bash tzdata RUN cd /usr/bin && curl -sS https://getcomposer.org/installer | php && ln -s /usr/bin/composer.phar /usr/bin/composer && \ apk add libxml2-dev $PHPIZE_DEPS && \ pecl install xdebug && \ docker-php-ext-install pdo_mysql mbstring xml curl session tokenizer json && \ docker-php-ext-enable pdo_mysql mbstring xml curl session tokenizer json xdebug && \ cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \ echo "Asia/Tokyo" > /etc/timezone && \ apk del tzdata # CMD crond -l 1 -b WORKDIR /var/www/html |
web
nginxコンテナです。
logging
セクション以下でログドライバとしてfluentdを指定し、ログの出力先とタグを指定しています。
タグはFluentdの基本機能で、受け付けたログの出し分けに使います。本筋から外れるのと、私がまだきちんと理解しきれていないので、参考ページの紹介に留めます…
今回の主旨はLaravelのログ出力ですが、nginxのログも以下のように出力しています(見やすく整形)。
1 2 3 4 5 6 | { "container_name":"/20190725_web_1", "source":"stdout", "log":"192.168.144.1 - - [24/Jul/2019:10:19:58 +0000] \"GET /register HTTP/1.1\" 200 4905 \"http://localhost/login\" \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36\"", "container_id":"f10447b18f1b515bac3a2afc29fe17f4c1a552b737514e7ff598cd5c95f322cd" } |
LaravelからログをFluentdに出力する
パッケージ導入
Laravelデフォルトでは
storage/logs
以下にログファイルがデイリーで生成されていきます。
また、LaravelはロガーとしてMonologを使用しており、Monolog用のログハンドラがパッケージとして公開されていますので、有り難く使わせていただきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | bash-4.4# composer require dakatsuka/monolog-fluent-handler Do not run Composer as root/super user! See https://getcomposer.org/root for details Using version ^1.2 for dakatsuka/monolog-fluent-handler ./composer.json has been updated Loading composer repositories with package information Updating dependencies (including require-dev) Nothing to install or update Generating optimized autoload files > Illuminate\Foundation\ComposerScripts::postAutoloadDump > @php artisan package:discover --ansi Discovered Package: beyondcode/laravel-dump-server Discovered Package: fideloper/proxy Discovered Package: laravel/tinker Discovered Package: nesbot/carbon Discovered Package: nunomaduro/collision Package manifest generated successfully. |
PHPコード例
Laravelからは以下のように出力します。5.6以降は
config/logging.php
に記述することでもっとスマートに書けるかなと思うのですが、一応動くコードです。
1 2 3 4 5 6 7 8 9 10 11 12 | use Dakatsuka\MonologFluentHandler\FluentHandler; use Monolog\Logger; trait RegistersUsers { public function showRegistrationForm() { $logger = new Logger('example'); $logger->pushHandler(new FluentHandler()); $logger->debug('laravel', ['message' => 'from testapp to docker-fluent']); return view('auth.register'); } |
これでFluent側のログには以下のように出力されます。
見やすいように改行を入れてますが、実際は1行です。
なお出力先は前述したFluentdの設定ファイル(my_fluentd.conf)の
match docker.**
内で指定したパスになります。
1 2 3 4 5 6 7 | 2019-07-24T20:17:56+09:00 docker.20190725_web_1 { "source":"stderr", "log":"2019/07/24 11:17:56 [error] 7#7: *4 FastCGI sent in stderr: \"PHP message: Fluent\\Logger\\FluentLogger example.laravel: {\"message\":\"from testapp to docker-fluent\",\"level\":\"DEBUG\"}\" while reading response header from upstream, client: 192.168.144.1, server: , request: \"GET /register HTTP/1.1\", upstream: \"fastcgi://192.168.144.4:9000\", host: \"localhost\", referrer: \"http://localhost/login\"", "container_id":"f10447b18f1b515bac3a2afc29fe17f4c1a552b737514e7ff598cd5c95f322cd", "container_name":"/20190725_web_1" } |
さいごに
昔から知ってはいたFluentdですが、いざ触ってみると自由度が高く、出力先としてS3やBigQueryを選べたり、夢が広がります。引き続き学習して使いこなせるようになりたいです。