ECSにデプロイしたDockerコンテナからfluentbitでログ出力する

以前、こちらの記事で簡単なExpress.jsアプリのDockerイメージを作り、ECSにデプロイする方法を説明しました。

この記事では、アプリからのログ出力について書きます。

最も簡単なログ出力

lib/cdk-stack.tsを下記のようloggingecs.AwsLogDriverを指定すると、CloudWatchにログ出力が行われます。アプリからは、console.log()など標準出力にログが出るようにしておけば大丈夫です。

taskDefinition.addContainer('MyAppContainer', {
  image: ecs.ContainerImage.fromEcrRepository(repository, versionTag),
  logging: new ecs.AwsLogDriver({
    streamPrefix: 'hello-ecs',
    mode: ecs.AwsLogDriverMode.NON_BLOCKING
  }),
  portMappings: [
    {
      containerPort: 3000,
    }
  ],
})

ただ、この方法だとCloudWatchの代わりにS3にログを出すとか、ログの内容によって出し分けるといったことができません。

FireLensでfluentbitを使う

fluentbitはfluentdの軽量版で、ECSからのログ出力の方法として、AWSではFireLensとして公式にサポートされています。
FireLensはfluentbitコンテナをサイドカーとして起動して、アプリが動作しているコンテナからログを収集し、fluentbitの様々な設定に基づいてログ出力を行います。

まず、FireLensを使ってCloudWatchにログ出力する方法を説明します。

lib/cdk-stack.tsを下記のようにします。

import * as s3 from 'aws-cdk-lib/aws-s3'
import * as assets from 'aws-cdk-lib/aws-s3-assets'

export class CdkStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // 中略

    const extraConfAsset = new assets.Asset(this, 'ExtraConfAsset', {
      path: path.join(__dirname, 'extra.conf')
    })

    taskDefinition.addFirelensLogRouter('MyLogRouter', {
      firelensConfig: {
        type: ecs.FirelensLogRouterType.FLUENTBIT,
      },
      environment: {
        aws_fluent_bit_init_s3_1: `arn:aws:s3:::${extraConfAsset.s3BucketName}/${extraConfAsset.s3ObjectKey}`
      },
      image: ecs.ContainerImage.fromRegistry(
        'public.ecr.aws/aws-observability/aws-for-fluent-bit:init-latest'
      ),
      logging: ecs.LogDriver.awsLogs({
        streamPrefix: 'log-router'
      })
    })

    taskDefinition.defaultContainer = taskDefinition.addContainer('MyAppContainer', {
      image: ecs.ContainerImage.fromEcrRepository(repository, versionTag),
      logging: ecs.LogDrivers.firelens({
        options: {}
      }),
      portMappings: [
        {
          containerPort: 3000,
        }
      ]
    })

    // 後略

fluentbitの設定ファイルは、extra.confcdk-stack.tsと同じディレクトリに作成し、それをS3のアセットとして管理します。(S3へのアップロードはcdk deploy時に自動的に行われます。)

アプリのコンテナは、taskDefinition.defaultContainerとして指定するように変更します。

extra.confは、下記のようなものです。

[OUTPUT]
    Name    cloudwatch
    Match   *
    region  ap-northeast-1
    log_group_name  /hello/ecs
    log_stream_prefix ecs-fluentbit-
    auto_create_group true

この設定でCloudWatchに/hello/ecsというロググループが自動的に作成され、ログ出力が行われます。

今回はここまでです。次回の記事で、ログの出し分けについて説明します。

この記事を書いた人

井上 研一

株式会社ビビンコ代表取締役、ITエンジニア/経済産業省推進資格ITコーディネータ。AI・IoTに強いITコーディネータとして活動。画像認識モデルを活用したアプリや、生成AIを業務に組み込むためのサービス「Gen2Go」の開発などを行っている。近著に「使ってわかった AWSのAI」、「ワトソンで体感する人工知能」。日本全国でセミナー・研修講師としての登壇も多数。