spacelyのブログ

Spacely Engineer's Blog

AWS Firelensでfargateログをdatadogに集約する

どこでもかんたんVRスペースリー」のインフラを担当しています佐藤です.

スペースリーではメインのRailsアプリのアプリケーションログをdatadogで管理していますが,
新たにAWS ECS Fargate上でアプリを実行・運用するときでも,
アプリケーションログはdatadogに集約して監視・運用したいという要件があります.
これを実現する方法として AWS Firelensを導入したのでその詳細についてまとめました.

1. 前提

Firelens とは

FirelensAWSが提供するログ転送エージェントです.

従来AWSにおけるログ転送手段としては,AWS CloudWatch logsに転送する方法のみがサポートされていました.
Amazon Kinesisやdatadogのような別のログ基盤に転送するためには,一度CloudWatch logsを経由するか自前でログ転送の仕組みを実装する必要がありました.
CloudWatch logsを経由する場合,一時的にCloudWatch logsに蓄積してCloudWatch logsからlambdaで転送処理を実行するコスト,
転送の仕組みのメンテナンスコストおよびCloudWatch logsを経由することによる遅延などの課題がありました.
自前でログ転送の仕組みを実装する場合,特にコンテナ(ECS)にはログ転送の仕組みが備わっているにもかかわらずそれを利用できないという無駄がありました.

こういった課題を解決するため,コンテナなどのクラウドネイティブな技術としてデファクトで利用されているfluentdおよびfluent-bitを拡張し,
AWSがサポートする仕組みとしてFirelensが 2019/11に発表されました

スペースリーにおけるECSログの取り扱い

スペースリーでは各種ログ(アクセスログ,アプリケーションログ)の蓄積と分析にdatadogを採用しています.
今後ECS(Fargate)におけるアプリの実行・運用を想定していますが,これに関連するログについてもdatadogに転送して合わせて管理したいと考えています.

幸いなことにAWSでもFirelensを用いたdatadogへのログ転送を想定し,
サンプルコードを提供しています.
これを利用し,実際にdatadogへのログ転送を検証・実装します.

2. ログ収集要件

改めてログ基盤の要件すると以下になります.

  • ログはdatadogで一元管理したい
  • ログの永続化はS3を利用したい
  • 開発時には logs tailでログを参照したい

3. 設計

ECSからログは単にdatadogに転送します.
datadogからS3にログをアーカイブする仕組みになっているので,
別途ここで永続化のために直接S3に転送する実装はしないことにしました.
ただし,すべてのログをdatadogに転送するとコストが高くなります.
datadog log managementのコストが課題になってきたら要検討としました.

また,開発時にはdatadogでログを確認するのではなく,cliからECSのログを確認したいという要件があります.
これを実現するため,開発環境におけるコンテナ定義ではfirelensによるdatadog転送は利用せず,
単にCloudWatch logsに転送するようにしました.
これによりaws cliのv2であればCloudWatch logsをtailして参照することができます.

4. 実装

ECSの採用例となる視線分析アプリにおける実装例は以下のような感じです.

{
  "family": "gaze-heatmap",
  "taskRoleArn": "arn:aws:iam::<アカウントID>:role/ECSTaskGazeHeatmap",
  "executionRoleArn": "arn:aws:iam::<アカウントID>:role/ECSTaskExecutionRole",
  "networkMode": "awsvpc",
  "containerDefinitions": [
    {
      "name": "gaze-heatmap",
      "image": "<アカウントID>.dkr.ecr.ap-northeast-1.amazonaws.com/gaze-heatmap:latest",
      "essential": true,
      "logConfiguration": {
        "logDriver": "awsfirelens",
        "options": {
          "Name": "datadog",
          "Host": "http-intake.logs.datadoghq.com",
          "TLS": "on",
          "dd_service": "gazeheatmap",
          "dd_source": "gazeheatmap",
          "dd_tags": "Env:development",
          "provider": "ecs"
        },
        "secretOptions": [{
          "name": "apikey",
          "valueFrom": "arn:aws:secretsmanager:ap-northeast-1:<アカウントID>:secret:<datadog-api-key>"
        },
        {
          "name": "GCP_SERVICE_ACCOUNT",
          "valueFrom": "arn:aws:secretsmanager:ap-northeast-1:<アカウントID>:secret:<gcp-service-account>"
        }]
      }
    },
    {
      "name": "logrouter",
      "image": "906394416424.dkr.ecr.ap-northeast-1.amazonaws.com/aws-for-fluent-bit:latest",
      "essential": true,
      "firelensConfiguration": {
        "type": "fluentbit",
        "options": {
          "enable-ecs-log-metadata": "true"
        }
      },
      "logConfiguration": {
        "logDriver": "awslogs",
        "options": {
          "awslogs-group": "/aws/ecs/gaze-heatmap",
          "awslogs-region": "ap-northeast-1",
          "awslogs-stream-prefix": "gaze-heatmap",
          "awslogs-create-group": "true"
        }
      }
    }
  ],
  "requiresCompatibilities": [
    "FARGATE"
  ],
  "cpu": "256",
  "memory": "512"
}

視線分析アプリではGCP上の視線データを利用しているため,
datadogと合わせて認証情報を SecretsManager に保管して実行時に注入しています.
このとき,タスク実行ロールには追加で SecretsManager への参照権限が必要になります.
SSM パラメタストアを利用する場合も同様です.
(参考: Amazon ECS タスクで秘密情報や機密情報をコンテナに安全に渡す方法を教えてください。)

datadogで参照すると以下のような感じです.
ログはもちろん,指定したタグもきちんと反映されているので
他のアプリのログと合わせて一元管理する場合でも簡単に識別・分析することができます.
f:id:morita_spacely:20201111162008p:plain

5. 実装の注意点

ログ転送コンテナの追加

アプリケーションログの転送設定は対象アプリの logConfiguration に記載しますが
実際のログ転送はログ転送コンテナが実行するため,logrouterコンテナを追加する必要があります.
このコンテナがcloudwatchやfirehoseに転送するためのプラグインを実装しており,
datadogに転送する場合も同様にこのコンテナが必要になります. 始めはdatadogの転送設定はfirelensのコンテナに指定するものだと思っていましたが, アプリのコンテナに指定が必要です. 複数のアプリコンテナを実行する場合はその度にdatadogへの転送設定を指定する必要があります.

ECSメタデータ

ECSの実行時メタデータも合わせて出力されます.
デフォルトが有効で enable-ecs-log-metadata の値により無効化することもできますが,
特に無効化する理由はないのでそのまま利用します.

有効にするとこのようなタグが生成されます.
f:id:morita_spacely:20201111162217p:plain

無効にするとこのようなタグ生成になります.
f:id:morita_spacely:20201111162238p:plain

Container Insightsによるリソース状況可視化

CloudWatch Container Insightsを利用することでECSのリソース利用状況を可視化できます.
試しに有効にした場合の出力結果は以下の通りです(クラスタのメトリクスとタスクのメトリクスを表示).
現時点では動作確認までなのでどの程度の粒度で情報が取得できるか確認できていません.

f:id:morita_spacely:20201111162300p:plain

f:id:morita_spacely:20201111162524p:plain

上記メトリクスの課題として,タスクのリソース利用状況は確認できてもコンテナ別リソース利用状況が確認できません.
これではDockerイメージの取得時間などのリードタイムが計測できません.
加えて,監視をdatadogに集約できず,CloudWatchを利用する必要があります
(別途datadogにデータ転送することはできると思いますが).

datadogもメトリクス収集要のコンテナを配置する方法を提供していますが,これらの課題をすべて解決できそうにはなさそうです.
これらの監視方法などについては別途検討が必要です.

We are hiring

スペースリーの研究開発チームは,新しいもの好きな一緒に働くエンジニアを大募集しています!

興味がある方はぜひ,お気軽にお問合せください。

問い合わせ採用ページ
採用担当:recruiting@spacely.co.jp