FireLens(Fluent Bit)でELBヘルスチェックのログを除外してからCloudWatch Logsへログを保存してみる

Fluent BitでELBのヘルスチェックログをフィルタしてみました。
2021.08.02

本記事ではFargateで起動するFireLens(Fluent Bit)のログルーティング設定について触れます。設定例としてELBのヘルスチェックで出力されるログを除外してからCloudWatch Logsへログを送信してみます。

ECS, Fargateのカスタムログルーティングでよく名前を見聞きするFireLens

FireLnesはFluent Bitや、Fluentdを簡単に起動できる仕組みそのものです。Fluent Bit、Fluendでできることは、たとえばエラーログは即時確認したいからCloudWatch Logsへ送り、すべてのログはS3バケットに長期保存したいとか、ヘルスチェックのログは保存しないといったログ周りのあれこれ。ログの保存先の選択や、ログを見て振り分けの判定するために必要なのは主にFluent Bitか、Fluentdでの設定です。

カスタムログルーティングするにはFluent Bitか、Fluendの知識が重要になってきます。

検証環境

下記リンクで作成したFargateの環境を利用して検証します。新しいFireLens(Fluent Bit)のイメージを作成しECRへプッシュしてから、タスクを再デプロイして結果を確認します。

Fluent Bitの設定ファイル

ELBからヘルスチェックで生成されるログ(レコード)を除外してから、CloudWatch Logsへ送信するサンプルコンフィグを作成します。 ELBの配下にNginxコンテナ(コンテナ名: webapp)が起動しているだけの環境です。

  • [FILTER]Grepフィルタープラグインを利用してログをフィルタしています
  • Match webapp-firelens*webapp部分はタスク定義で指定しているコンテナ名が入ります

extra.conf

[SERVICE]
    # 取り込まれたレコードを書き出す間隔
    Flush 1
    # 終了までの待機時間
    Grace 30
    # ロギングの詳細レベル
    Log_Level info

# フィルタープラグイン名の指定
[FILTER]
    # Grepフィルタープラグインで正規表現に一致したレコードを除外できます
    Name grep
	# <コンテナ名>-firelensの形式でログが出力されます
    Match webapp-firelens*
    # ヘルスチェックのレコードパターンを除外します
    Exclude log ^(?=.*ELB-HealthChecker\/2\.0).*$


# 送信先のプラグイン名の指定
[OUTPUT]
    # CloudWatch Logsへ送信
    Name   cloudwatch_logs
    Match webapp-firelens*
    region ap-northeast-1
    log_group_name /ecs/logs/sample-test
    log_stream_name webapp
    auto_create_group true

Dockerfile

Dockerfileは作成した設定ファイル(extra.conf)をコピーしているだけです。設定ファイル名、コピー先のパスは任意ですがひとつ例外があります。

/fluent-bit/etc/fluent-bit.confFireLensで使用するため予約されています。使えないファイル名とパスがあることだけはご認識ください。

Dockerfile

FROM amazon/aws-for-fluent-bit:2.18.0
COPY ./extra.conf /fluent-bit/etc/extra.conf

/fluent-bit/etc/extra.confの設定ファイルを読み込ませるために、タスク定義で設定ファイルまでのパス指定が必要です。 作成済みの検証環境でパスを指定済みなので省略します。もちろん設定ファイルの名前、コピー先を変更した場合はタスク定義の修正が必要になります。

タスク定義抜粋

      "firelensConfiguration": {
        "type": "fluentbit",
        "options": {
          "config-file-type": "file",
          "config-file-value": "/fluent-bit/etc/extra.conf"
        }

CloudWatch Logsの出力結果

新しく作成した設定ファイルを同梱したFireLensのイメージをデプロイしました。非常にわかりにくいのですがヘルスチェックのログは記録されていません。

今回の[FILTER]箇所を未設定のときは以下のようにELB-HealthChecker/2.0が記録されます。

{
    "source": "stdout",
    "log": "10.0.2.245 - - [31/Jul/2021:07:18:55 +0000] \"GET / HTTP/1.1\" 200 612 \"-\" \"ELB-HealthChecker/2.0\" \"-\"",
    "container_id": "e6154cf1046743bbb2f00d672213f153-1393473712",
    "container_name": "webapp",
    "ecs_cluster": "sample-test-cluster",
    "ecs_task_arn": "arn:aws:ecs:ap-northeast-1:123456789012:task/sample-test-cluster/e6154cf1046743bbb2f00d672213f153",
    "ecs_task_definition": "sample-test-webapp-taskdefinition:3"
}

ヘルスチェックのログは記録されていないが、その他アクセスログなどはCloudWatch Logsに記録されているため、Grepのフィルター設定は成功したと判斷します。

おわりに

Fluent Bitまたは、Fluendの設定次第で柔軟にログをルーティング、フィルタリングできます。サイドカーで起動まではECSのタスク定義(FireLens)力、ログルーティングはFluent Bitか、Fluentd力が大切になってきます。主観ですとタスク定義はあまり難しくはないです(ややこしいけど)。ログルーティング用にFluent BitかFluendの設定を学ぶことの方が難しい気がします。その他には意図通りログをフィルタし、送信したい先へ正しくルーティングできているかのテストも含めるとなかなか時間を取られます。

参考