ECS(Fargate)のnginxログをFireLensでs3へ転送する
はじめに
今回はECS(Fargate)で動かしているnginxのログをFireLensでs3へ転送してみたので、そのメモを記載します。
FireLensとはECSのログドライバの1つです。(他にはawslogs
等がある)
実体はサイドカーでFluentBit or Fluentdコンテナが起動し、そのコンテナがログルーティングを行うといったものになっております。
イメージ図
検証
流れとしては
- AWSリソース準備
- Firehoseに書き込むためのタスクロール設定
- タスク定義設定
となります。
AWSリソース準備
各種AWSリソースを用意します。
Firehoseに書き込むためのポリシーであったり、Firehose用のS3に書き込むためのポリシーであったり、IAM周りのリソース作成に注意しましょう。
Firehoseに書き込むためのタスクロール設定
タスクのfirelensコンテナがFirehoseに書き込むため、タスクロールを設定します。
⭕ タスクロール
❌ タスク実行ロール
です。混同しないように気をつけましょう。
タスクのポリシーは以下のようにしておけばOKです。
{
"Statement": [
{
"Action": [
"firehose:PutRecordBatch",
"firehose:PutRecord"
],
"Effect": "Allow",
"Resource": "<deliverystream arn>",
"Sid": ""
}
],
"Version": "2012-10-17"
}
タスク定義設定
FireLensを使用する場合のサンプルはこちらに記載があります。
[
{
"name": "nginx",
"image": "nginx:latest",
// 略
"LogConfiguration": {
"logDriver": "awsfirelens",
"options": {
"Name": "firehose",
"region": "ap-northeast-1",
"delivery_stream": "my-firehose-stream"
}
}
},
{
"essential": true,
"image": "public.ecr.aws/aws-observability/aws-for-fluent-bit:stable",
"name": "log_router",
"firelensConfiguration": {
"type": "fluentbit"
},
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/logs/firelens",
"awslogs-region": "ap-northeast-1",
"awslogs-stream-prefix": "firelens"
}
},
"memoryReservation": 50
}
]
ポイントは以下です。
- ログを飛ばしたいコンテナで
"logDriver": "awsfirelens"
を設定する - firelens用のコンテナを追加する
- firelens自体のログはcloudwatch logsに保存する
- 今回はfluentbitを使用するため、
firelensConfiguration
で指定する。
動作確認①
問題なければs3にログが飛びます。
年月日で階層化されて、delivery_stream名
-<ランダム文字列>というフォーマットで定期的に出力されるようです。
s3bucket/
└── yyyy
└── mm
└── dd
└── hh
└── logfile
動作確認②
firehoseのdelivery_streamのメトリクスも確認してみます。
特に問題はなさそうです。
動作確認③
ファイルの中身を確認します。
curl -I
でリクエストを投げたところ、このようなログで記録されていました。
FluentBit形式のログになっているようです。
{"container_id":"<コンテナランタイム ID>","container_name":"<コンテナ名>","ecs_cluster":"<ECSクラスタ>","ecs_task_arn":"<ECSタスクARN>","ecs_task_definition":"<タスク定義名>","log":"10.10.2.75 - - [17/Jul/2023:08:37:02 +0000] \"HEAD / HTTP/1.1\" 200 0 \"-\" \"curl/7.81.0\" \"<グローバルIP>\"","source":"stdout"}
- container_id:コンテナランタイムID
- container_name:コンテナ名
- ecs_cluster:ECSクラスタ名
- ecs_task_arn:ECSタスクARN
- ecs_task_definition:タスク定義名
- log:nginxが吐いたログ。プライベートIPはALBのもの
- source:不明なので今度調べる。おそらくコンテナの標準出力であることを表している。
なにはともあれ、このようにFirelens経由でログがs3に吐かれていることが確認出来ました!
ハマったメモ
name
と指定する
① コンテナ定義でこのようなログが出力され、タスクが起動しませんでした。
InternalError: unable to generate fireLens config file: unable to generate fireLens config content: unable to generate fluent config output section: unable to apply log options of container nginx to fireLens config: missing output key Name which is required for fireLens configuration of type fluentbit. Launch a new task to retry.
コンテナ定義でのFirelens設定を確認すると
"LogConfiguration": {
"logDriver": "awsfirelens",
"options": {
"name": "firehose",
"region": "ap-northeast-1",
"delivery_stream": "xxxxxxxxxxx"
}
}
となっていました。
正しくは
"LogConfiguration": {
"logDriver": "awsfirelens",
"options": {
- "name": "firehose",
+ "Name": "firehose",
"region": "ap-northeast-1",
"delivery_stream": "xxxxxxxxxxx"
}
}
なので注意しましょう。
他のオプションが小文字であるため、混同してしまう可能性はありそうです。
② Firehoseへログを書き込む権限が足りない
このようなログがfirelensサイドカーから出てきたらログ転送先への書き込み権限が足りていません。
タスクロール、ポリシーを適切に設定することで対応しましょう。
time="2023-07-17T07:44:25Z" level=error msg="[firehose 0] PutRecordBatch failed with AccessDeniedException: <taskrole arn> is not authorized to perform: firehose:PutRecordBatch on resource: <firehose-stream> because no identity-based policy allows the firehose:PutRecordBatch action\n\tstatus code: 400, request id: xxxyyyzzz123
こちらにサンプルを記載しています。
おわりに
次は複数の宛先にログルーティングするやり方を調査したいと思います。
参考
Discussion