kakakakakku blog

Weekly Tech Blog: Keep on Learning!

FireLens の init プロセスで [MULTILINE_PARSER] を使う

AWS Fargate と Amazon ECS で FireLens (Fluent Bit) を使うときに「init プロセス」を活用すれば設定ファイルを Amazon S3 から自動的に読み取れるようになるよ❗️という便利機能は以下の記事にまとめてある📝

kakakakakku.hatenablog.com

しかし init プロセスには課題があって,v2.31.12 までは Fluent Bit の [MULTILINE_PARSER] が使えず「複数行ログ(Java のスタックトレースなど)」をうまく処理できなかった.もう少し詳細に説明すると,FireLens で [MULTILINE_PARSER] を使えるようにするプルリクエストは2022年11月頃に出ていたけど,今までずっと(ほぼ1年)取り込まれていなかった.僕自身も取り込む予定があるかどうかコメントしてみたこともある💨

github.com

取り込まれないままになりそうだなぁ〜と諦めていたところ,2023年10月6日にプルリクエストが取り込まれて,2023年10月21日に AWS for Fluent Bit v2.32.0 としてリリースされた❗️リリースノートには Enhancement - Support multiline parsers with the init tag. と書かれていた.

\( 'ω')/ うおおおおお

github.com

さっそく [MULTILINE_PARSER] の動作確認をする✔️

準備

以下のドキュメントに載っている [MULTILINE_PARSER] のサンプルを参考に extra.confparsers_multiline.conf を作って Amazon S3 kakakakakku-firelens-configs に置いておく.

docs.aws.amazon.com

📝 extra.conf

[SERVICE]
    parsers_file /fluent-bit/etc/parsers_multiline.conf

[FILTER]
    name multiline
    match *
    multiline.key_content log
    multiline.parser multiline-regex-test

[OUTPUT]
    Name cloudwatch_logs
    Match *
    region ap-northeast-1
    log_key log
    log_group_name /ecs/applications
    log_stream_prefix multiline/
    auto_create_group true

📝 parsers_multiline.conf

[MULTILINE_PARSER]
    name          multiline-regex-test
    type          regex
    flush_timeout 1000
    #
    # Regex rules for multiline parsing
    # ---------------------------------
    #
    # configuration hints:
    #
    #  - first state always has the name: start_state
    #  - every field in the rule must be inside double quotes
    #
    # rules |   state name  | regex pattern                  | next state
    # ------|---------------|--------------------------------------------
    rule      "start_state"   "/(Dec \d+ \d+\:\d+\:\d+)(.*)/"  "cont"
    rule      "cont"          "/^\s+at.*/"                     "cont"

次にドキュメントに載っている「複数行ログを出力するデモアプリ」のコンテナイメージ multiline-app-image を Docker Hub / Amazon ECR などに登録しておく.実装としては test.log に Java のスタックトレースを記載しておいて,Python からファイルをそのまま標準出力する.parsers_multiline.conf の正規表現をテストするときは test.log を書き換えれば良くてあると便利なデモアプリだったりする💡

📝 Dockerfile

FROM public.ecr.aws/amazonlinux/amazonlinux:latest
ADD test.log /test.log

RUN yum upgrade -y && yum install -y python3

WORKDIR /usr/local/bin

COPY main.py .

CMD ["python3", "main.py"]

📝 main.py

import os
import time
file1 = open('/test.log', 'r')
Lines = file1.readlines()

count = 0

for i in range(10):
    print("app running normally...")
    time.sleep(1)

# Strips the newline character
for line in Lines:
    count += 1
    print(line.rstrip())
print(count)
print("app terminated.")

📝 test.log

single line...
Dec 14 06:41:08 Exception in thread "main" java.lang.RuntimeException: Something has gone wrong, aborting!
    at com.myproject.module.MyProject.badMethod(MyProject.java:22)
    at com.myproject.module.MyProject.oneMoreMethod(MyProject.java:18)
    at com.myproject.module.MyProject.anotherMethod(MyProject.java:14)
    at com.myproject.module.MyProject.someMethod(MyProject.java:10)
    at com.myproject.module.MyProject.main(MyProject.java:6)
another line...

動作確認

❌ Before: aws-for-fluent-bit:init-2.31.12.20231002

Amazon ECS タスク定義

containerDefinitionslog-routerimagepublic.ecr.aws/aws-observability/aws-for-fluent-bit:init-2.31.12.20231002 を設定する.

{
    "containerDefinitions": [
        {
            "name": "multiline-app-image",
            "image": "kakakakakku/multiline-app-image",
            "cpu": 0,
            "portMappings": [],
            "essential": true,
            "environment": [],
            "mountPoints": [],
            "volumesFrom": [],
            "logConfiguration": {
                "logDriver": "awsfirelens"
            }
        },
        {
            "name": "log-router",
            "image": "public.ecr.aws/aws-observability/aws-for-fluent-bit:init-2.31.12.20231002",
            "cpu": 0,
            "portMappings": [],
            "essential": true,
            "environment": [
                {
                    "name": "aws_fluent_bit_init_s3_1",
                    "value": "arn:aws:s3:::kakakakakku-firelens-configs/extra.conf"
                },
                {
                    "name": "aws_fluent_bit_init_s3_2",
                    "value": "arn:aws:s3:::kakakakakku-firelens-configs/parsers_multiline.conf"
                }
            ],
            "mountPoints": [],
            "volumesFrom": [],
            "user": "0",
            "logConfiguration": {
                "logDriver": "awslogs",
                "options": {
                    "awslogs-create-group": "true",
                    "awslogs-group": "firelens-container",
                    "awslogs-region": "ap-northeast-1",
                    "awslogs-stream-prefix": "firelens"
                }
            },
            "firelensConfiguration": {
                "type": "fluentbit"
            }
        }
    ],
    "family": "multiline-app-image",
    "taskRoleArn": "arn:aws:iam::111111111111:role/ecsTaskRole",
    "executionRoleArn": "arn:aws:iam::111111111111:role/ecsExecutionRole",
    "networkMode": "awsvpc",
    "volumes": [],
    "placementConstraints": [],
    "requiresCompatibilities": [
        "FARGATE"
    ],
    "cpu": "512",
    "memory": "1024"
}

FireLens を実行すると Amazon CloudWatch Logs の firelens-container ロググループに以下のエラーが出てしまう🔥

Sections 'multiline_parser' and 'parser' are not valid in the main configuration file. It belongs to
the 'parsers_file' configuration files.

⭕ After: aws-for-fluent-bit:init-2.32.0

Amazon ECS タスク定義

containerDefinitionslog-routerimagepublic.ecr.aws/aws-observability/aws-for-fluent-bit:init-2.32.0 を設定する.

{
    "containerDefinitions": [
        {
            "name": "multiline-app-image",
            "image": "kakakakakku/multiline-app-image",
            "cpu": 0,
            "portMappings": [],
            "essential": true,
            "environment": [],
            "mountPoints": [],
            "volumesFrom": [],
            "logConfiguration": {
                "logDriver": "awsfirelens"
            }
        },
        {
            "name": "log-router",
            "image": "public.ecr.aws/aws-observability/aws-for-fluent-bit:init-2.32.0",
            "cpu": 0,
            "portMappings": [],
            "essential": true,
            "environment": [
                {
                    "name": "aws_fluent_bit_init_s3_1",
                    "value": "arn:aws:s3:::kakakakakku-firelens-configs/extra.conf"
                },
                {
                    "name": "aws_fluent_bit_init_s3_2",
                    "value": "arn:aws:s3:::kakakakakku-firelens-configs/parsers_multiline.conf"
                }
            ],
            "mountPoints": [],
            "volumesFrom": [],
            "user": "0",
            "logConfiguration": {
                "logDriver": "awslogs",
                "options": {
                    "awslogs-create-group": "true",
                    "awslogs-group": "firelens-container",
                    "awslogs-region": "ap-northeast-1",
                    "awslogs-stream-prefix": "firelens"
                }
            },
            "firelensConfiguration": {
                "type": "fluentbit"
            }
        }
    ],
    "family": "multiline-app-image",
    "taskRoleArn": "arn:aws:iam::111111111111:role/ecsTaskRole",
    "executionRoleArn": "arn:aws:iam::111111111111:role/ecsExecutionRole",
    "networkMode": "awsvpc",
    "volumes": [],
    "placementConstraints": [],
    "requiresCompatibilities": [
        "FARGATE"
    ],
    "cpu": "512",
    "memory": "1024"
}

FireLens を実行すると extra.conf に指定した Amazon CloudWatch Logs の /ecs/applications ロググループに複数行ログをまとめられた👏 \( 'ω')/ やったーーー❗️

Dec 14 06:41:08 Exception in thread "main" java.lang.RuntimeException: Something has gone wrong, aborting!
    at com.myproject.module.MyProject.badMethod(MyProject.java:22)
    at com.myproject.module.MyProject.oneMoreMethod(MyProject.java:18)
    at com.myproject.module.MyProject.anotherMethod(MyProject.java:14)
    at com.myproject.module.MyProject.someMethod(MyProject.java:10)
    at com.myproject.module.MyProject.main(MyProject.java:6)

まとめ

2023年10月21日にリリースされた AWS for Fluent Bit 2.32.0 から init プロセスで [MULTILINE_PARSER] を使えるようになったぞー❗️という紹介記事をまとめた.init プロセスを使えば Fluent Bit の設定ファイルを書いて挙動をカスタマイズするときに独自コンテナイメージを作る必要がなく,Amazon S3 から設定ファイルを読み込めて便利だから今後は [MULTILINE_PARSER] が必要なときでも init プロセスを選択肢に含めよう💡

関連ドキュメント

docs.fluentbit.io

docs.fluentbit.io