6
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

アプリケーションログをFluent BitでCloudWatch Logsに集約した話

Posted at

概要

今回は、EC2で稼働している弊社のアプリケーションログをCloudWatch Logsへ集約しました。
その中で調査したツールの比較や、設定方法について紹介します。

背景

弊社の主要なアプリケーションは2台のEC2で稼働しています。
これまではエラーを調査する際、

  1. EC2(A)にsshで接続してログファイルをgrepして探し、
  2. 該当エラーがない場合はEC2(B)にsshして...

とそれぞれのインスタンスを行き来することになり、調査に時間がかかっていました。

そこで、アプリケーションログをCloudWatch Logsに集約することでログを一元管理し、ブラウザからエラー調査ができるようにする必要がありました。

各ツールの比較

FireLens

ECSの場合使用可能。今回は通常のEC2なので候補から外れました。

なぜ単に Fluentd や Fluent Bit を推奨しないのですか?なぜ FireLens なのですか?

Fluentd と Fluent Bit は強力ですが、たくさんの機能セットには常に複雑さが伴います。FireLens を設計する際、2 つの主要なユーザーセグメントを想定しました。

  1. Fluentd と FluentBit を使用して、ログをどこにでも簡単に送信する方法を必要としているユーザー。
  2. Fluentd と FluentBit のフルパワーを必要としており、タスクのログをこれらのログルーターにパイプするために必要な差別化につながらない重労働は AWS に管理して欲しいユーザー。
    最初のグループに対する私たちの答えは、私たちが作成した FireLens サンプルの GitHub リポジトリによって最もよく実証されています。これらの例のほとんどは、タスク定義での設定のみを必要とし、誰でもわずかな変更だけで使用することができます。簡単であり、Fluentd や Fluent Bit の知識を必要としません。

2 番目のグループに対する私たちのソリューションは、タスク定義の FireLensConfiguration オブジェクトの options フィールドに示されています。

このように、ECSを利用している場合は後述のFluentdやFluent Bitよりも推奨されています。
FireLensを利用することで内部的にFluentdやFluent Bitが使用できます。
利点としては、設定ファイルをS3から読み込めるので、設定ファイルをイメージに含める必要がなくなるようです。

Fluentd vs Fluent Bit

それぞれ以下のような違いがあります。
拡張性を持たせたい場合はFluentdに軍配が上がりますが、そうでない場合はFluent Bitが良さそうです。

Fluentd Fluent Bit
対応 コンテナ/サーバー コンテナ/サーバー/組み込みLinux
言語 C、Ruby C
メモリ 60MB以上 1MB以下
パフォーマンス ハイパフォーマンス
依存関係 Ruby Gemとして構築されているので、一定数のGemが必要 基本なし
プラグイン 1000以上 100以上
ライセンス Apacheライセンスv2.0 Apacheライセンスv2.0

参考: https://docs.fluentbit.io/manual/about/fluentd-and-fluent-bit

AWSからも推奨されているようですね。

Fluent Bit が AWS の推奨ですが、それは Fluentd に比べてリソース使用量が大幅に少ないからです。Fluentd も何百ものプラグインが存在する定評のあるツールであり、サポートします。長期的には、FireLens がオープンソースコミュニティを活性化し、Fluentd がサポートする多くの機能とすべての送信先が Fluent Bit に追加されることを期待しています。AWS は Fluent Bit にプラグインや改善を提供し続けることで、この役割を果たしていきます。

今回のユースケースにはどちらが合うか

Fluent Bitを使用することにしました。

理由としては、

  • 今回は、単純にログをCloudWatch Logsに出力できればよかった
  • より軽量でハイパフォーマンス
  • 外部依存がない

からです。

その他の理由として、Container InsightsではFluentdは非推奨になりつつあることも挙げられます。
将来的にEC2→ECSに移行する可能性もあるため、Fluent Bitの方がより安全策とも言えますね。

Container Insights の Fluentd のサポートは現在メンテナンスモードになっています。つまり、AWS はこれ以上 Fluentd の更新を提供せず、近い将来に廃止する予定です。
さらに、Container Insights の現在の Fluentd 構成は、最新の改善およびセキュリティパッチがない古いバージョンの Fluentd Image fluent/fluentd-kubernetes-daemonset:v1.10.3-debian-cloudwatch-1.0 を使用しています。

設定方法

ここからは具体的な設定方法を紹介します。
以下の資料を参考にしています。

1. EC2のOSを確認する

まずは、Fluent BitをインストールするEC2のOSを確認します。

EC2上で、以下のコマンドを実行することで確認できます。

$ cat /etc/os-release

OSはubuntuでした。

2. Fluent Bitをインストールする

こちらから対応しているものを選択します。

今回はhttps://docs.fluentbit.io/manual/installation/linux/ubuntu を使用しました。

// fluent-bitをインストール
$ curl https://raw.githubusercontent.com/fluent/fluent-bit/master/install.sh | sh

// 有効化
$ sudo systemctl start fluent-bit

// ステータスの確認
$ systemctl status fluent-bit                                                          
● fluent-bit.service - Fluent Bit
   Loaded: loaded (/lib/systemd/system/fluent-bit.service; disabled; vendor preset: enabled)
   Active: active (running) since 水 2024-02-28 08:49:34 UTC; 1min 11s ago
     Docs: https://docs.fluentbit.io/manual/
 Main PID: 32313 (fluent-bit)
    Tasks: 4
   Memory: 13.2M
      CPU: 53ms
   CGroup: /system.slice/fluent-bit.service
           └─32313 /opt/fluent-bit/bin/fluent-bit -c //etc/fluent-bit/fluent-bit.conf

この時点では、ログはsudo tail -f /var/log/syslogで確認できます。

デフォルトでは1秒ごとにcpuのログが吐かれ続けるので、一旦止めておきます。

$ sudo systemctl stop fluent-bit

3. 出力先をCloudWatch Logsに変更

上記出力より、設定は/etc/fluent-bit/fluent-bit.confを見ていることが分かります。

このファイルを編集し、各アプリおよびnginxのログの設定をします。
以下は設定の例です。

各設定の意味は後述します。

/etc/fluent-bit/fluent-bit.conf
[INPUT]
    Name tail 
    Path /var/log/hogehoge/app_A/stdout.log
	Tag  app_A.log

[INPUT]
    Name tail 
    Path /var/log/hogehoge/app_B/stdout.log
	Tag  app_B.log

[INPUT]
    Name tail 
    Path /var/log/hogehoge/nginx/access.log
	Tag  nginx.access_log

[INPUT]
    Name tail 
    Path /var/log/hogehoge/nginx/error.log
	Tag  nginx.error_log

[OUTPUT]
    name cloudwatch_logs
    match   app_A.log
    region ap-northeast-1
    log_group_name /aws/ec2/app_A
    log_stream_name ${EC2_TAG_NAME}-${APP_A_DEPLOY_DATETIME}
    auto_create_group true
    workers 1
	log_retention_days 3
	log_key log

[OUTPUT]
    name cloudwatch_logs
    match   app_B.log
    region ap-northeast-1
    log_group_name /aws/ec2/app_B
    log_stream_name ${EC2_TAG_NAME}-${APP_B_DEPLOY_DATETIME}
    auto_create_group true
    workers 1
	log_retention_days 3
	log_key log

[OUTPUT]
    name cloudwatch_logs
    match  nginx.*
    region ap-northeast-1
    log_group_name /aws/ec2/nginx
    log_stream_prefix ${EC2_TAG_NAME}-
    auto_create_group true
    workers 1
	log_retention_days 3
	log_key log

4. configファイルをアプリごとに分離する

/path/to/fluent-bit-app_A.conf
[INPUT]
    Name tail 
    Path /var/log/hogehoge/app_A/stdout.log
	Tag  app_A.log

[OUTPUT]
    name cloudwatch_logs
    match   app_A.log
    region ap-northeast-1
    log_group_name /aws/ec2/app_A
    log_stream_name ${EC2_TAG_NAME}-${APP_A_DEPLOY_DATETIME}
    auto_create_group true
    workers 1
	log_retention_days 3
	log_key log
/path/to/fluent-bit-app_B.conf
[INPUT]
    Name tail 
    Path /var/log/hogehoge/app_B/stdout.log
	Tag  app_B.log

[OUTPUT]
    name cloudwatch_logs
    match   app_B.log
    region ap-northeast-1
    log_group_name /aws/ec2/app_B
    log_stream_name ${EC2_TAG_NAME}-${APP_B_DEPLOY_DATETIME}
    auto_create_group true
    workers 1
	log_retention_days 3
	log_key log
/path/to/fluent-bit-nginx.conf
[INPUT]
    Name tail 
    Path /var/log/hogehoge/nginx/access.log
	Tag  nginx.access_log

[INPUT]
    Name tail 
    Path /var/log/hogehoge/nginx/error.log
	Tag  nginx.error_log

 [OUTPUT]
    name cloudwatch_logs
    match  nginx.*
    region ap-northeast-1
    log_group_name /aws/ec2/nginx
    log_stream_prefix ${EC2_TAG_NAME}-
    auto_create_group true
    workers 1
	log_retention_days 3
	log_key log

上記のconfファイルを以下のように読み込みます。

/etc/fluent-bit/fluent-bit.conf
@INCLUDE /path/to/fluent-bit-wk_web.conf
@INCLUDE /path/to/fluent-bit-wvd_userui.co
@INCLUDE /path/to/fluent-bit-nginx.conf

各設定項目について

[INPUT]
    // tail -fコマンドのように、ファイル末尾をログとして吐く
    Name tail
    // ソースとなるログファイル
    Path /var/log/supervisor/vk_web/stdout.log
    // タグ名。[OUTPUT]へのルーティングのために使用する。
    Tag  vk_web.log

[OUTPUT]
    // ログ出力先にcloudwatch_logsを指定
    name cloudwatch_logs
    // [INPUT]のうち、Tagが一致するものをこのOUTPUTにルーティングする。ワイルドカード指定もできる。
    match   vk_web.log
    // リージョン指定
    region ap-northeast-1
    // ロググループ名
    log_group_name /aws/ec2/vk_web
    // ログストリーム名(詳細は後述)
    log_stream_name ${EC2_TAG_NAME}-${VK_WEB_DEPLOY_DATETIME}
    // trueの場合、ロググループを自動的に作成する
    auto_create_group true
    // cloudwatchへの出力用にスレッドを確保する。ほとんどの場合0か1で問題ない
    workers 1
    // ログストリームの保持日数
    log_retention_days 3
    // fluent-bitの出力のうちcloudwatchに送るkeyを指定、logの場合は純粋なログのみ出力する
    log_key log

上記のうち、log_stream_nameでは${EC2_TAG_NAME}-${VK_WEB_DEPLOY_DATETIME}のように${}のフォーマットで環境変数を読み込んでいます。

5. 環境変数の設定

Fluent Bitは、環境変数をwebサーバー上の/etc/default/fluent-bitから読み込みます。

今回の記事からは省略しますが、
Github Actionsの中でshellを実行し、環境変数としてデプロイ日時を設定することで
デプロイごとにログストリームが分かれるようにしています。

コストの考慮

ログの保存にも以下のようにお金がかかります。
基本的にログ調査は、当日や土日に起こったエラーの調査をすることがほとんどであり、
最悪元々のようにEC2にsshしてログファイルを直接確認することもできます。

よって、ログの保持期間は3日と設定しています。

収集 (データの取り込み)・・・0.50USD/GB

保存 (アーカイブ)・・・0.03USD/GB

分析 (Logs Insights のクエリ)・・・スキャンしたデータ 1 GB あたり 0.005USD

検出およびマスク (データ保護)・・・スキャンされたデータ 1 GB あたり 0.12USD

分析 (Live Tail)・・・0.01 USD/分

完了!

変更した設定を読み込ませるために、Fluent Bitを再起動させます。

$ sudo systemctl restart fluent-bit

アプリケーションへのアクセスがあった時、
auto_create_group trueとしているためロググループ、ログストリームが存在しなければ自動生成してくれます。

まとめ

Fluent Bitが自動でロググループやログストリームを生成してくれるのには感動しました。
今後ログ調査環境を整える際は、ぜひ使用を検討してみてください!

6
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?