【ECS Fargate】FireLensを使用してDatadogとS3にコンテナログを転送するタスク定義をCFnで作成する

container

こんにちは、エンジニアの田代です。
今回は以前投稿した下記の記事と同様、ECS+Fargateの環境をCloudFormationで構築します。
こちらの記事で解説している部分は今回の記事では割愛しているので、併せて参考にしてみて下さい。 blog.tech-monex.com

はじめに

FireLensとはAWS ECSの環境において、Fluentd或いはFluent Bitのコンテナをタスク定義に含め、ログドライバーとして動作させることでコンテナログを種々の宛先へ転送させることが出来る機能です。
今回はAWSが提供しているFluent Bitのイメージを基にして、nginxコンテナのログをDatadogとS3へ転送してみます。
尚、CloudFormationテンプレートを使って構築しますが、CLIを使ってタスク定義を作成する際にも参考にして頂ける内容かと思います。 aws.amazon.com

やりたいこと

diagram

上図のように、nginxとFluent Bitのコンテナを1つずつ含むタスク定義を作成し、nginxコンテナの標準出力をDatadog及びS3に転送させられるようにすることが今回のゴールです。

前提事項

当記事ではタスク定義の作成をメインに扱うので、ECRリポジトリや、タスクを動作させるためのクラスター及びサービスと付随する各リソースについては既に用意されているものとします。
そちらについての情報を求めている方は冒頭のリンク先の記事もご覧頂ければと思います。

Fluent Bitコンテナの作成

まずFluent BitコンテナをビルドしてECRにプッシュします。
今回のようにログ転送先を複数指定する場合は独自のFluent Bit設定ファイルが必要となるため、logDestinations.confを用意します。

FROM amazon/aws-for-fluent-bit:latest
ADD logDestinations.conf /logDestinations.conf
[OUTPUT]
    Name datadog
    Match *
    Host http-intake.logs.datadoghq.com
    TLS on
    compress gzip
    apikey ${DD_API_KEY}
    dd_service sample_nginx_service
    dd_source nginx
    dd_tags environment:sample_env
    provider ecs

[OUTPUT]
    Name s3
    Match *
    region ap-northeast-1
    bucket ${S3_BUCKET}
    total_file_size 10M
    upload_timeout 1m
    store_dir /tmp/fluent-bit/s3
    s3_key_format /fluent-bit-logs/$TAG/%Y/%m/%d/%H/%M/%S
    use_put_object On

各項目は必要であれば公式ドキュメントを参考に適宜書き換えて頂ければと思います。
また、Datadogのapikeyと転送先S3バケットの値は実行時にSSMパラメーターから取得するため、ここでは環境変数名を指定しています。 docs.fluentbit.io

各ファイルが用意出来たら、CLIから下記のコマンドを実行してDockerイメージをECRにプッシュします。

$ aws ecr get-login-password --region {YOUR_REGION}
$ docker login -u AWS -p {YOUR_TOKEN} https://{YOUR_ECR_URL}.amazonaws.com
$ # -> Login Succeeded
$ docker build -t sample-log-router .
$ docker tag sample-log-router:latest {YOUR_ECR_URL}.amazonaws.com/sample-log-router:latest
$ docker push {YOUR_ECR_URL}.amazonaws.com/sample-log-router:latest

タスク定義の作成

続いてタスク定義を作成します。
CloudFormationテンプレートを実行する前に、まずはSSMパラメータストアにDatadog apikey(datadog_api_key)とS3バケット名(fluent_bit_bucket)をSecureStringとして登録しておきましょう。

ssm
SSMパラメータストアに環境変数用の値を登録

登録が出来たら、CloudFormationでsample_nginx_task.yamlを実行してタスク定義を作成します。
FirelensConfigurationで事前に用意したlogDestinations.confを設定ファイルとして指定しています。

AWSTemplateFormatVersion: "2010-09-09"

Parameters:
  FluentBitImageUri:
    Type: String
  TaskExecutionRoleArn:
    Type: String
  TaskRoleArn:
    Type: String  

Resources:
  SampleNginxTaskDefinition:
    Type: AWS::ECS::TaskDefinition
    Properties:
      ContainerDefinitions:
        # nginxコンテナの設定
        - Name: 'NginxContainer'
          Essential: true
          # 公式のnginxイメージを利用
          Image: 'public.ecr.aws/nginx/nginx:latest'
          # ログ出力先にFireLensを指定
          LogConfiguration:
            LogDriver: 'awsfirelens'
          PortMappings:
            - HostPort: 80
              Protocol: 'tcp'
              ContainerPort: 80
        # Fluent Bitコンテナの設定
        - Name: 'FluentBitContainer'
          DependsOn:
            - Condition: 'START'
              ContainerName: 'NginxContainer'
          Essential: true
          # FireLensの設定
          FirelensConfiguration:
            Options:
              enable-ecs-log-metadata: true
              # logDestinations.confを設定ファイルとして指定
              config-file-type: 'file'
              config-file-value: '/logDestinations.conf'
            Type: 'fluentbit'
          Image: !Ref FluentBitImageUri
          LogConfiguration:
            # Fluent BitコンテナのログはCloudWatchに保管
            LogDriver: 'awslogs'
            Options:
              awslogs-group: '/ecs/SampleNginxTask'
              awslogs-region: !Ref 'AWS::Region'
              awslogs-stream-prefix: 'ecs'
          Secrets:
            # SSMパラメーターの値を環境変数に設定
            - Name: 'DD_API_KEY'
              ValueFrom: 'datadog_api_key'
            - Name: 'S3_BUCKET'
              ValueFrom: 'fluent_bit_bucket'
      Cpu: 256
      ExecutionRoleArn: !Ref TaskExecutionRoleArn
      Family: 'SampleNginxTask'
      Memory: 512
      NetworkMode: 'awsvpc'
      RequiresCompatibilities:
        - 'FARGATE'
      TaskRoleArn: !Ref TaskRoleArn

スタック作成が完了したら、予め用意しておいたサービスでタスクを実行し、nginxにアクセスしてみます。

nginx
nginxにアクセス

nginxのデフォルトページが表示されました。
最後に、アクセスログがDatadogとS3に転送されているかを確認します。

datadog
Datadog
s3
S3

ねらい通りDatadogとS3にそれぞれログが転送されました。
Datadogのタグや、S3の保管先プレフィックスもlogDestinations.confで設定した通りになっていますね。

まとめ

以上で、 CloudFormationのテンプレートを使って、コンテナログを複数の宛先へ転送するタスク定義を作成することが出来ました。
Fluent BitやFireLensが備える機能の一部の紹介に留まりましたが、今回の記事がECSを運用する上での参考になれば嬉しいです。

田代 侑大システム開発部 マネックス・ラボ