この記事は GRIPHONE Advent Calendar 2019 14日目の記事です。
こんにちは、SREの川野です。今回はGrafana LokiをDockerコンテナを使って試してみたので、ご紹介します!
Grafana Lokiについて
Lokiは、Prometheusにインスパイアされた、水平方向にスケーラブルで可用性の高いマルチテナントログ集約システムです。
https://github.com/grafana/loki
Prometheusがメトリックを対象としていることに対して、Lokiはログを対象にしています。また、ログの配信方法がPrometheusがプル型なのに対し、Lokiではプッシュ型です。Datadogのように監視対象のサーバーにエージェントをインストールすることでそのエージェントからログが配信されるようになります。
Lokiのロギングスタックは以下の3つのコンポーネントで構成されています。
- ログを収集してLokiに送信するエージェント
- ログの保存とクエリの処理を行うメインサーバー
- ログの照会、表示を行う監視ツール
今回の環境構成について
今回はDockerを使って環境を構築します。テスト用のログとして、Nginxコンテナを作成しアクセスログを使用したいと思います。
ロギングスタックの構成は以下の形になります。
- Fluentd : ログを収集してLokiに送信するエージェント
- Loki : ログの保存とクエリの処理を行うメインサーバー
- Grafana : ログの照会、表示を行う監視ツール
↓今回作成する環境
https://github.com/Takashi-Kawano/fluentd-out-loki-sample
環境構築
これから作成する設定ファイルの全体のディレクトリ構成は以下のようになっています。
$ tree .
.
├── docker-compose.yaml
├── fluent.conf
├── host_logs
└── plugin
└── out_loki.rb
2 directories, 3 files
では、作成の手順について説明していきます。
手順1. 以下のdocker-compose.yml
を作成します。
loki, grafana, fluentd, nginxの4つのコンテナを作成するための設定をします。
version: "3"
networks:
loki:
services:
loki:
image: grafana/loki:v1.2.0
ports:
- "3100:3100"
command: -config.file=/etc/loki/local-config.yaml
networks:
- loki
grafana:
image: grafana/grafana:6.5.2
ports:
- "3000:3000"
networks:
- loki
fluentd:
image: fluentd:v1.6.2-1.0
environment:
FLUENT_CONF: /fluentd/etc/fluent.conf
networks:
- loki
volumes:
- ./host_logs:/var/log
- ./fluent.conf:/fluentd/etc/fluent.conf
- ./plugin:/etc/fluent/plugin
nginx:
image: nginx:1.17.6
volumes:
- ./host_logs:/var/log/nginx
ports:
- "8080:80"
手順2. ログを送信するためのFluentdの設定ファイルfluent.conf
を作成します。
match
ディレクティブ
Lokiプラグインを使用してendpoint_url
にhttp://loki:3100
を指定しています。FluentdコンテナからLokiサーバーへはDockerのlokiネットワークを介して接続できることに注意です。また、ここでGrafanaで見るとき用のラベリングを行います。
parse
ディレクティブ
Nginxプラグインを使ってNginxログをパースするようにしています。
<source>
@type tail
path /var/log/*.log
tag nginx.test
<parse>
@type nginx
expression /^(?<remote>[^ ]*) (?<host>[^ ]*) (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^\"]*?)(?: +\S*)?)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)"(?:\s+(?<http_x_forwarded_for>[^ ]+))?)?$/
time_format %d/%b/%Y:%H:%M:%S %z
</parse>
</source>
<match **>
@type loki
endpoint_url http://loki:3100
labels {"env":"prod","farm":"a"}
</match>
手順3. plugin
ディレクトリを作成して、その配下にLokiプラグインとしてout_loki.rb
を作成します。
Lokiプラグインの実装は以下をご確認ください。
https://github.com/Takashi-Kawano/fluentd-out-loki-sample/blob/master/plugin/out_loki.rb
手順4. Nginxログをコンテナ上にマウントするためにhost_logs
というディレクトリを作成します。
こちらのディレクトリは、docker-compose.yml
を見ていただくとわかるかと思うのですが、Nginxコンテナの/var/log/nginx
をホストのhost_logs
にマウントしています。また、host_logs
をFluentdコンテナにもマウントしているので、Fluentdコンテナ上でNginxアクセスログをFluentdのエージェントが収集して、Lokiコンテナへ送信することができます。
手順5. 各設定ファイルが準備できましたら、コンテナを起動します。
$ docker-compose up -d
4つのコンテナが起動できていることを確認します。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4934b5481895 grafana/loki:v1.2.0 "/usr/bin/loki -conf…" 28 seconds ago Up 23 seconds 80/tcp, 0.0.0.0:3100->3100/tcp loki_loki_1
c9969a515fd1 fluentd:v1.6.2-1.0 "tini -- /bin/entryp…" 28 seconds ago Up 26 seconds 5140/tcp, 24224/tcp loki_fluentd_1
90562c989133 grafana/grafana:6.5.2 "/run.sh" 28 seconds ago Up 26 seconds 0.0.0.0:3000->3000/tcp loki_grafana_1
195bc71c1d05 nginx:1.17.6 "nginx -g 'daemon of…" 28 seconds ago Up 23 seconds 0.0.0.0:8080->80/tcp loki_nginx_1
手順6. ログを送信するためにNginxに適当にリクエストを投げておきます。
$ while true; do curl -I http://localhost:8080; sleep 1; done > /dev/null 2>&1
つづいて、Lokiコンテナへ保存されているNginxログをGrafanaを使って確認してみます。
手順7. ブラウザでhttp://localhost:3000
にアクセスし、ログインします。(初回は、ユーザー名とパスワードはそれぞれadminです)
手順8. ログインしたら、トップページに表示されている「Add data source」を押下し、表示されるリストから「Loki」を選択します。
手順9. HTTP URLにhttp://loki:3100
を入力します。コンテナ間のネットワークはlokiで名前解決しているので、ドメイン名は、localhostではなくlokiとなります。他のフォームは空欄のままで下の緑の「Save & Test」ボタンを押下します。
手順10. 以下のようなエラーが出る場合がございますが、データソースは作成されているので、気にせず左のサイドバーの「Explore」を押下します。
Data source connected, but no labels received. Verify that Loki and Promtail is configured properly.
手順11.「Log lables」をクリックするとfluent.conf
で設定したenvラベルとfarmラベルが表示されていることがわかります。
手順12. envのprodを選択してみると、ログを確認することができます。
Nginxプラグインを使ったパースも反映されていることを確認できます。
終わりに
如何でしたでしょうか。
ログ収集するエージェントとしてはFluentdの他にpromtailやFluentBitなどを使用できます。はじめにFluentBitをチャレンジしましたが、中々上手くいきませんでした。今回のも終わってみれば簡単そうに見えるのですが、やっているときは試行錯誤が多く結構難しく感じました。あとDockerの勉強にもなりました。
個人的な次ステップとしては、以下のように考えています。
- promtailをKubernetesクラスタにインストールさせてログを送信
- Prometheusとサービスディスカバリと連携
最後まで読んでいただき、ありがとうございました。