9
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

AWSAdvent Calendar 2021

Day 19

Fargateコンテナの特定ログをFireLensを使って別々に振り分けようとしたけどボツった話

Last updated at Posted at 2021-12-19

この記事は、「AWS Advent Calendar 2021」の19日目の記事です。

背景

弊社で開発しているとあるプロダクトでFargateで起動しているコンテナのアプリログの中で特定のログを収取集計してcsvなどに出力できたらいいなという要望があり、Fargateログの振り分けならFireLensがあったよなということでそれを調査検証してみるというタスクがありました。

色々調査していく過程で、別の方法でいいかもという結論となったのでここで供養させる。

FireLensとは

デプロイメントスクリプトを修正したり、手動で追加のソフトウェアをインストールしたり、追加コードを書き込んだりすることなく、コンテナログをストレージや分析ツールに直接追加できます。Amazon ECS または AWS Fargate の設定をいくつか更新することにより、必要な場所にコンテナログを送信することを FireLens に指示するため、宛先を選択し、オプションでフィルターを定義します。FireLens は Fluent Bit または Fluentd と動作します。このことは、それらのオープンソースのプロジェクトによりサポートされた宛先にログを送信できることを意味します。

通常、Fargateのコンテナログはawslogsを用いてCloudWatchlogsに転送されますが、FireLensを用いることでCloudWatchlogsだけでなく、S3やKinesisに直接送ることが出来るようになりました。タスク定義にてFireLensの使用を設定する事で、コンテナログをサイドカーとして配置されたFluentdまたはFluent Bitに転送され、それらを経由することでS3やKinesisなどに直接振り分けるという仕組みです。

やろうとしたこと

  1. 既存のログはそのままCloudWatchlogsに転送したい
  2. タスク定義にはWebとApp用のコンテナがあり、それぞれ別のロググループに転送したい
  3. 出力されるコンテナログの中でも特定文字列を含むログに関するものだけを別の出力先に送って分析/csv出力したい。

③ではS3にログを転送して、Athenaでクエリ打ってcsv出力を考えておりました。

スクリーンショット 2021-12-19 17.44.39.png

FireLensによるログ振り分け

FireLens用コンテナイメージ作成準備

下記ファイルをそれぞれ用意する

├── Dockerfile
├── fluent-bit-custom.conf
└── stream_processor.conf
  • Dockerfile
Dockerfile.
FROM amazon/aws-for-fluent-bit:2.16.1

COPY ./fluent-bit-custom.conf /fluent-bit/custom.conf
COPY ./stream_processor.conf /fluent-bit/etc/stream_processor.conf

RUN ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
stream_processor.conf
[STREAM_TASK]
    Name s3tag
    Exec CREATE STREAM s3tag WITH (tag='s3tag') AS SELECT log FROM TAG:'*-firelens-*' ;
fluent-bit-custom.conf
[SERVICE]
    Flush 1
    Grace 30
    Streams_File stream_processor.conf

[FILTER]
    Name grep
    Match s3tag
    Regex log <マッチさせたい値(正規表現)>

[OUTPUT]
    Name cloudwatch
    Match <コンテナ名1>-firelens-*
    region ap-northeast-1
    log_group_name <ロググループ1>
    log_stream_prefix from-fluentbit/
    auto_create_group true
    log_key log

[OUTPUT]
    Name cloudwatch
    Match <コンテナ名2>-firelens-*
    region ap-northeast-1
    log_group_name <ロググループ2>
    log_stream_prefix from-fluentbit/
    auto_create_group true
    log_key log

[OUTPUT]
    Name s3
    Match s3tag
    region ap-northeast-1
    bucket <S3 バケット名>
    total_file_size 1M
    upload_timeout 1m
    json_date_key false

Firelensを使用する場合、コンテナのログはコンテナ名-firelens-タスクIDというタグが付与されるため、例えばコンテナ名がappでタスクIDがabcdefghijklmnopqrstuvwxyz123456の場合はのタグはapp-firelens-abcdefghijklmnopqrstuvwxyz123456となる。

つまり、それぞれのタグに対してOUTPUTにてロググループを設定する事でコンテナログをそれぞれ別のロググループに転送する事が出来ます。

その際に、logの部分だけを出力させたいのでlog_keyパラメータにlogを指定する。この指定が無いと下記の様にJSONでログが出力がされ、やや情報過多に

log.json
{
    "container_id": "f186706ff1bd4fe8885d79030d05b5b9-527074092",
    "container_name": "app",
    "ecs_cluster": "sample-cluster",
    "ecs_task_arn": "arn:aws:ecs:ap-northeast-1:xxxxxxxxxxxx:task/sample-cluster/f186706ff1bd4fe8885d79030d05b5b9",
    "ecs_task_definition": "sample-front:1",
    "log": "> npx blitz start --port 80",
    "source": "stdout"
}

また、ログの中にある特定文字列を含む場合、S3へ転送としたいのでFILTERとGrepを使って抽出させる。その際に、Cloudwatchlogsに転送するログにはFILTERが適用させないために、StreamProcessorに専用のタグを付与してそのタグにだけFILTERを適用させる。

FireLens用コンテナイメージ作成

  • ビルド
docker build -t ${AWS_ACCOUNT_ID}.dkr.ecr.${REGION}.amazonaws.com/${REPOSITORY_NAME}:v1.0 .
  • ECRにログイン
aws ecr get-login-password --profile ${PROFILE} | docker login --username AWS --password-stdin https://{AWS_ACCOUNT_ID}.dkr.ecr.${REGION}.amazonaws.com
  • コンテナイメージPush
docker push {AWS_ACCOUNT_ID}.dkr.ecr.${REGION}.amazonaws.com/${REPOSITORY_NAME}:v1.0

タスク定義設定

IAMロール

既存の設定がCloudwatchlogsへ転送のみで、今回S3への転送が増えましたのでECSタスクロールに対象S3への書き込み権限を追加しました。

sample-firelens-s3.json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "firelens",
            "Effect": "Allow",
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::<S3 バケット名>"
        }
    ]
}

### ログルータの統合(FireLensの使用)

  • タスク定義の設定下部のログルータの統合より、FireLens統合を有効にするにチェックを入れる
  • タイプfluentbitイメージにECRにPushしたコンテナイメージを指定(例:xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/fluentbit:v1.0)する。
  • 適用を押下する

FireLensコンテナが更新されました。の表示がでればOK

また、コンテナの項目でlog_routerのコンテナが追加されているのが、分かる

FireLens用ロググループの作成

アプリのログとFireLensのログが混在しないようにFireLens単独のロググループを、Cloudwatchlogsに任意の命名(例:/ecs/firelens)で作成します。

web/appコンテナのログ出力設定

  • web/appそれぞれのコンテナを選択してログ設定項目のログドライバーをawslogsからawsfirelensに変更して更新を押下する

  • 何故かログオプションが空にならないので、再度web/appそれぞれのコンテナを選択して、ログオプションでxを押下して空にした状態で更新を押下する。

FireLensログ出力設定

  • log_routerのコンテナを選択する
  • FireLens自身はawslogsのログドライバーを使用
  • ログをプションをそれぞれ指定して更新を押下する
Key Value
awslogs-group /ecs/firelens
awslogs-region ap-northeast-1
awslogs-stream-prefix firelens

JSONによる設定

コンテナイメージに配置したカスタム定義を読み込ませます。

  • ボリューム項のJSONによる設定をクリックする

  • firelensConfiguration部分を下記のように編集して保存を押下する
            "firelensConfiguration": {
                "type": "fluentbit",
                "options": {
                    "config-file-type": "file",
                    "config-file-value": "/fluent-bit/custom.conf"
                }
            },

  • それぞれ完了したら、タスク定義作成画面最下部より作成を押下する。

サービスの更新

作成したリビジョンを指定してサービスを更新

  • web/app/log_routerのコンテナがそれぞれRUNNINGであることを確認

  • web/app/log_routerがそれぞれのロググループにログが転送されていることを確認

  • S3にログが転送されていることを確認

最終的に

FireLensによるログ転送を調査してきた訳ですが、最終的にはlog Insightを用いる事となりました。理由としては以下になります。

  • FireLensによるログ転送にはlog_router用のコンテナが必須であり、検証当時コスト削減も丁度課題に上がり始めていた事もあって、より低コストで実現できる方式が望ましかった。
  • 自分の調査不足かもしれませんが、「特定文字列を含むログは別ターゲットに転送」をFireLensに当初期待していたが、どうやら、上記方法の場合「指定したロググループにコンテナログが吐き出される」それに+して「指定した文字列にマッチした物は別ターゲットにも転送」という形式であった
  • ログ転送自体が目的ではなく、その先の分析が出来ればいい
  • そういった事もあって、S3+AthenaではなくCloudWatchlogs内で完結できるlog Insightでよくないかととなり、こんな感じでlog Insightで出来るんだけどこれで十分だったりする?と改めてプロダクトチームに相談したところ、それでOKとなった。

log Insight

CloudWatch Logs Insights では、Amazon CloudWatch Logs のログデータをインタラクティブに検索して分析できます。クエリを実行することで、運用上の問題に効率的かつ効果的に対応できます。
問題が発生した場合は、CloudWatch Logs Insights を使用して潜在的原因を特定し、デプロイした修正を検証できます。 CloudWatch Logs Insights には専用のクエリ言語といくつかのシンプルで強力なコマンドが含まれています。また、サンプルクエリ、コマンドの説明、クエリの自動補完、ログフィールドの検出を使用して CloudWatch Logs Insights を開始できます。サンプルクエリは、AWS のサービスの複数のログタイプ向けに用意されています。

要するに、logsに格納されているログに対してクエリを実行して分析できる機能。
ログのクエリ分析はS3+Athenaがメジャーだが態々S3にログをエクスポートしなくてもlogsだけで完結できるのが利点で、CSV出力も可能

まとめ

結果的にFireLensを使う事は無かったですが、調査の過程で複数コンテナを持つタスクにおけるFluent-bitでのロググループの振り分けであったり、log_keyの指定やフィルタリング、S3への転送、log Insightでのクエリなど様々な知見が得られました。今後Firelensを使う場面が得られたらこれである程度出来るはず。

参考

[詳解 FireLens – Amazon ECS タスクで高度なログルーティングを実現する機能を深く知る]
(https://aws.amazon.com/jp/blogs/news/under-the-hood-firelens-for-amazon-ecs-tasks/)
[Fluent Bit: Official Manual / Fluent Bit + SQL / WHERE Condition]
(https://docs.fluentbit.io/manual/stream-processing/getting-started/fluent-bit-sql#where-condition)
[Fluent Bit: Official Manual / Grep]
(https://docs.fluentbit.io/manual/pipeline/filters/grep)

9
1
2

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
9
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?