Docker ComposeでRailsのアプリケーションログをFluentdでElasticsearchに送信する

過去の記事

前々回

前回


実現したいこと

Nginxと同じようにRailsのアプリケーションログもKibanaで参照できるようにしたい。
引き続き、過去の記事で使用した環境に変更を加えていくのでdiffを記載していく。

Rails

参考

基本的には参考サイトの通りやれば実現可能。
ただ、act-fluent-logger-railsに関してリリースされている最新の0.5.0ではRails6に対応していない。
Githubを確認したところmasterブランチには修正が適応されていたのでGemfileでGithubを指定すれば可能。

Gemfile
--- a/Gemfile
+++ b/Gemfile
@@ -47,3 +47,6 @@ end

 # Windows does not include zoneinfo files, so bundle the tzinfo-data gem
 gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
+
+gem 'act-fluent-logger-rails', git: 'https://github.com/actindi/act-fluent-logger-rails.git'
+gem 'lograge'

Gemfileを更新したのでdocker-compose build webを行っておく。

config/application.rb
--- a/config/application.rb
+++ b/config/application.rb
@@ -15,5 +15,9 @@ module Myapp
     # Application configuration can go into files in config/initializers
     # -- all .rb files in that directory are automatically loaded after loading
     # the framework and any gems in your application.
+    config.log_level = :info
+    config.logger = ActFluentLoggerRails::Logger.new
+    config.lograge.enabled = true
+    config.lograge.formatter = Lograge::Formatters::Json.new
   end
 end
config/fluent-logger.yml

ファイルを新規に作成。ひとまずdevelopmentのhostのみ設定しておく。

development:
  fluent_host:   fluentd
  fluent_port:   24224
  tag:           'rails'
  messages_type: 'string'

test:
  fluent_host:   '127.0.0.1'
  fluent_port:   24224
  tag:           'rails'
  messages_type: 'string'

production:
  fluent_host:   '127.0.0.1'
  fluent_port:   24224
  tag:           'rails'
  messages_type: 'string'

Fluentd

fluent.conf

ひとまず、Nginxの設定をほぼコピペで設定。

--- a/fluentd/fluent.conf
+++ b/fluentd/fluent.conf
@@ -14,3 +14,13 @@
   logstash_format true
   logstash_prefix nginx.access
 </match>
+
+<match rails>
+  @type elasticsearch
+  host elasticsearch
+  buffer_type memory
+  port 9200
+  type_name rails
+  logstash_format true
+  logstash_prefix rails.access
+</match>

この状態で、localhostにアクセスをしてKibanaでCreate index patternをするとrailsのログがきているはず。
f:id:arcright:20190930232653p:plain

みんなのDocker/Kubernetes

みんなのDocker/Kubernetes

  • 作者: 石澤基,五十嵐綾,大塚元央,須田一輝,稲津和磨,九岡佑介,坂部広大,青山真也,池添明宏,上岡真也
  • 出版社/メーカー: 技術評論社
  • 発売日: 2019/04/18
  • メディア: 単行本(ソフトカバー)
  • この商品を含むブログを見る

Docker LoggingにFluentdを使いforwardでNginxのログを送信する

過去の記事

実現したいこと

以前、NginxのログをFluentdを用いてElasticsearchに送信する際は、アクセスログをデータボリュームに書き出しtailで読み込んでElasticsearchに送信する方法で実現していた。
その際、オフィシャルのNginxコンテナのアクセスログの仕様について触れた。

  • docker container logsやdocker-compose upをフォアグラウンドで実行していると見ることのできるログに、各コンテナで起きたログを表示するには標準出力、標準エラー出力に内容を書く必要がある。
  • Nginxはアクセスログをログファイルに書きつつ標準出力に書き出す方法がないので、アクセスログを標準出力にシンボリックリンクすることで実現している。
  • そのため/var/log/nginx/access.logにいくらログを書いてもコンテナ内にログは残らなくなっている。
https://chulip.org/entry/2019/08/18/233205

上記仕様を回避するため、ログファイルをわざわざ別名で書き出すようにする必要があった。

しかし、そもそもデフォルトで標準出力にアクセスログが流れてくるのであればそれをそのままElasticsearchに渡してやればよいのでは?
そうすれば、ログファイルに別名を付ける必要もないし、ログを読み込むためだけにデータボリュームを用意する必要もない。

そこで、Docker Loggingを使用してNginxコンテナのログをFluentdに渡してそのままElasticsearchに送信できるようにする。

なお、過去の記事で使用した環境に変更を加えていくのでdiffを記載していく。

Fluentd

参考
--- a/fluentd/fluent.conf
+++ b/fluentd/fluent.conf
@@ -1,9 +1,7 @@
 <source>
-  @type tail
-  format ltsv
-  path /var/log/nginx/myapp_access.log
-  tag nginx
-  pos_file /var/log/nginx/myapp_access.log.pos
+  @type forward
+  port 24224
+  bind 0.0.0.0
 </source>
 
 <match nginx>

typeをforwardに変更。

Nginx

--- a/nginx.conf
+++ b/nginx.conf
@@ -24,8 +24,8 @@ server {
   listen 80;
   server_name localhost;
 
-  access_log /var/log/nginx/myapp_access.log ltsv;
-  error_log  /var/log/nginx/myapp_error.log;
+  access_log /var/log/nginx/access.log ltsv;
+  error_log  /var/log/nginx/error.log;
 
   root /myapp/public;

ログファイルのファイル名を変更して標準出力、標準エラー出力にアクセスログが出力されるように。

docker-compose.yml

参考
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -26,11 +26,16 @@ services:
     volumes:
       - .:/myapp
       - ./nginx.conf:/etc/nginx/conf.d/default.conf
-      - http-log:/var/log/nginx
     ports:
       - 80:80
     depends_on:
       - web
+      - fluentd
+    logging:
+      driver: fluentd
+      options:
+        tag: "nginx"
+        fluentd-async-connect: "true"
   elasticsearch:
     image: elasticsearch:7.3.0
     environment:
@@ -48,7 +53,6 @@ services:
   fluentd:
     build: ./fluentd
     volumes:
-      - http-log:/var/log/nginx
       - ./fluentd/fluent.conf:/fluentd/etc/fluent.conf
     ports:
       - 24224:24224
@@ -57,4 +61,3 @@ services:
 volumes:
   db-data:
   elastic-data:
-  http-log:

まず、loggingの設定を追加。
次に、ログファイルを参照する必要がなくなったのでログファイル用のデータボリューム関連を削除。

次に、fluentd-async-connect。
docker-compose upを行うと下記WARNINGが表示される。

WARNING: no logs are available with the 'fluentd' log driver

docker-compose.ymlのdepends_onでnginxは依存していることを記述しているが、
ただ単にコンテナの作成順序が保証されるだけで、サービスが起動するまで待ってくれるわけではない。
その為か、Nginxのコンテナ起動時にFluentdがavailableではないためWARNINGが表示される。

これは、FluentdとElasticsearchにも同様のことが言える。
Elasticsearchはコンテナ起動からサービスがavailableになるまでの時間が結構かかるのでFluendはすぐに接続することができない。

#0 Remaining retry: 14. Retry to communicate after 2 second(s).

logにもリトライをしている表示が出ていて、自分の環境だとだいたい16 secondsになるとようやく接続できている。
リトライの間隔は指数関数的に増えていく(1s,2s,4s,8s,16s)

上記の事から、Nginxコンテナ立ち上げ時にFluentdに接続できることは保証されていないので、
fluentd-async-connectをtrueにしておく。
ドキュメントによるとtrueだと、接続が確立できるまでメッセージをバッファリングしてくれるようである。

これで、docker-compose upしてlocalhostにアクセスすると、NginxのアクセスログがElasticsearchに送信されてKibanaで参照できる。
tailでアクセスログを読み込んでいた場合と異なり、containerのログなのでcontainer_idやcontainer_nameも一緒に送られる。
このあたりのフォーマットの調整は必要に応じてやればよいだろう。

Docker実践ガイド 第2版 impress top gearシリーズ

Docker実践ガイド 第2版 impress top gearシリーズ

AMNESIA V Edition プラチナトロフィー取得 感想/レビュー

PSPで発売された「AMNESIA」を追加要素ありでPSVitaに移植した作品。シリーズ初プレイ。

f:id:arcright:20190909220908j:plain
主人公の名前選択可能。デフォルトの名前なし。ボイスなし。

f:id:arcright:20190916210057j:plain
主人公が精霊オリオン↑と同化してしまい、その際に主人公が記憶を失ってしまう。
オリオンの助けも借りながら記憶を取り戻すために奮闘する。

主人公のボイスが無いノベルゲームっていうのはそう珍しいものではないと思うが、
主人公の台詞がこんなに少ないノベルゲームは記憶にある限りでは初めてだ。

というのも、記憶を失った主人公を助けるためにオリオンが世話を焼いてくれるのだが、
その間ずっとオリオンしか喋らない。主人公の台詞は全くない。
記憶を取り戻すまでの間、延々とオリオンが主人公の気持ちを汲み取って代弁し続ける。

なので、オリオン(男)と男キャラクターの会話をずっと見せられることになる。
記憶が戻るとオリオンがいなくなり、主人公の台詞になるがその時にはもうエンディング直前。
結果として主人公の台詞がほとんどないゲームとなっている。

女の子と男のやり取りがみたかったんだけど?

シナリオ

攻略キャラクター毎に並行世界の話なので、登場キャラクター、場所等は同じだけど関係性が全く違う。
なので、各々のルートでせっかく染み込み始めたキャラがルートが変わる度にリセットされてしまうので勿体ない。

あとは、シナリオ読んでいて自分の中で理解しきれていない部分は下記。

  • トランプのマークにはなにか意味が?
  • 冷夏のアピールをしていたけど結局何故?

見逃していたら申し訳ないが、やたらアピールしていたのにちゃんと伏線回収しなかったなと思う。

面白そうな世界観設定だと思うのだがいまいち消化しきれず、勿体ない作品だった。

AMNESIA V Edition - PS Vita

AMNESIA V Edition - PS Vita