この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
みなさん、こんにちは!
AWS事業本部の青柳@福岡オフィスです。
ECS/Fargateタスクのログ出力先をカスタマイズ(ルーティング)できる「FireLens」機能が AWS Containers Roadmap の リポジトリ でプレビューされていましたが、先日、正式リリースされました。
まだドキュメントが日本語化されていませんが、英語版ドキュメントの内容に沿って試してみました。 Custom Log Routing - Amazon ECS
従来の「CloudWatch Logs」へのログ出力
まず、従来の「CloudWatch Logs」へのログ出力を行ってみます。
全体の構成は下図のようになります。
ECSクラスターやALBの設定については省略します。(既に準備されているものとします)
アプリケーションコンテナ(今回はApache HTTP Server)を1つ含むタスク定義JSONファイルを以下のように記述します。
example-task-definition.json
{
"family": "example-task-definition-20191001",
"taskRoleArn": "arn:aws:iam::123456789012:role/ecsTaskRole",
"executionRoleArn": "arn:aws:iam::123456789012:role/ecsTaskExecutionRole",
"networkMode": "awsvpc",
"containerDefinitions": [
{
"name": "web-app",
"image": "httpd:2.4",
"portMappings": [
{
"containerPort": 80,
"hostPort": 80,
"protocol": "tcp"
}
],
"essential": true,
"entryPoint": [
"sh",
"-c"
],
"command": [
"/bin/sh -c \"echo 'FireLens Example' > /usr/local/apache2/htdocs/index.html && httpd-foreground\""
],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/firelens-example",
"awslogs-region": "ap-northeast-1",
"awslogs-stream-prefix": "ecs"
}
}
}
],
"requiresCompatibilities": [
"FARGATE"
],
"cpu": "256",
"memory": "512"
}
logConfiguration
にログ出力の設定を記述します。
logDriver
に awslogs
を指定することで、ログ出力先をCloudWatch Logsに設定することができます。
タスク定義JSONファイルを使ってタスク定義を作成します。
$ aws ecs register-task-definition --cli-input-json file://example-task-definition.json
GUI (マネジメントコンソール) で設定する場合は以下のようになります。
このタスク定義を使ってサービスを作成し、タスクを起動すると、CloudWatch Logsにログが出力されることが確認できました。
「FireLens」を使ったログ出力
「FireLens」を使う場合の構成は下図のようになります。
CloudWatch Logへのログ出力のようにアプリケーションコンテナから直接ログをログ出力先に送信するのではなく、タスク内に「FireLensコンテナ」を追加して、FireLensコンテナ経由でログを送信する仕組みです。(いわゆる「サイドカー」構成ですね)
なお、上図ではログをKinesis Data Firehose経由でS3バケットへ出力していますが、これは一例で、FireLensは他にもCloudWatch LogやFluentdなどへのログ出力に対応しています。(今回は上図の通りKinesis Data Firehose経由でS3バケットへのログ出力を行います)
ログの出力先を準備する
ログの出力先となるKinesis Data FirehoseおよびS3バケットを作成します。(特別な設定は必要ないため手順は割愛します)
また、FireLensコンテナがKinesis Data Firehoseへストリームを送れるよう、タスクロールにアクセス権限を設定します。
(タスク実行ロールではなくタスクロールの方ですので注意してください)
タスクロール ecsTaskRole
に以下のポリシーを設定します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "firehose:PutRecordBatch",
"Resource": "*"
}
]
}
タスク定義を更新する
前項のタスク定義JSONファイルをコピーして、以下のように修正します。
example-task-definition-v2.json
{
"family": "example-task-definition-20191001",
"taskRoleArn": "arn:aws:iam::123456789012:role/ecsTaskRole",
"executionRoleArn": "arn:aws:iam::123456789012:role/ecsTaskExecutionRole",
"networkMode": "awsvpc",
"containerDefinitions": [
{
"name": "web-app",
"image": "httpd:2.4",
"portMappings": [
{
"containerPort": 80,
"hostPort": 80,
"protocol": "tcp"
}
],
"essential": true,
"entryPoint": [
"sh",
"-c"
],
"command": [
"/bin/sh -c \"echo 'FireLens Example' > /usr/local/apache2/htdocs/index.html && httpd-foreground\""
],
"logConfiguration": {
"logDriver":"awsfirelens",
"options": {
"Name": "firehose",
"region": "ap-northeast-1",
"delivery_stream": "firelens-example-stream"
}
}
},
{
"name": "log-router",
"image": "906394416424.dkr.ecr.ap-northeast-1.amazonaws.com/aws-for-fluent-bit:latest",
"essential": true,
"firelensConfiguration": {
"type": "fluentbit"
},
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/firelens-example",
"awslogs-region": "ap-northeast-1",
"awslogs-stream-prefix": "firelens"
}
}
}
],
"requiresCompatibilities": [
"FARGATE"
],
"cpu": "256",
"memory": "512"
}
34~49行目の記述で、FireLensコンテナの定義を追加しています。
{
"name": "log-router",
"image": "906394416424.dkr.ecr.ap-northeast-1.amazonaws.com/aws-for-fluent-bit:latest",
"essential": true,
"firelensConfiguration": {
"type": "fluentbit"
},
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/firelens-example",
"awslogs-region": "ap-northeast-1",
"awslogs-stream-prefix": "firelens"
}
}
}
FireLensのコンテナイメージは、AWSが提供しているものを使用します。
これは、軽量ログ収集ツールである「Fluent bit」に、AWSが開発したプラグイン(Fluent bitからCloudWatch LogやKinesis Data Firehoseへ連係するためのプラグイン)を同梱したものになっています。
FireLensコンテナイメージのURLはリージョン毎に異なりますので、下記リンクを参照してください。
https://docs.aws.amazon.com/en_us/AmazonECS/latest/userguide/using_firelens.html#firelens-using-fluentbit
なお、FireLensコンテナの定義にも logConfiguration
セクションがありますが、これはFireLensコンテナ自身の動作ログの出力先の設定になります。(CloudWatch Logsを指定しています)
続いて、既存のアプリケーションコンテナの定義について、ログ出力の設定を変更します。
"logConfiguration": {
"logDriver":"awsfirelens",
"options": {
"Name": "firehose",
"region": "ap-northeast-1",
"delivery_stream": "firelens-example-stream"
}
}
26行目の logDriver
の指定を awsfirelens
に変更します。
また、28~30行目で、出力先を「firehose (=Kinesis Data Firehose)」にすること、および、Kinesis Data Firehoseに関する設定(リージョン、配信ストリーム名)を指定します。
タスク定義JSONファイルを修正しましたら、タスク定義の新しいリビジョンを作成します。
$ aws ecs register-task-definition --cli-input-json file://example-task-definition-v2.json
サービスの設定を更新し、タスク定義の新しいリビジョンでタスクを起動します。
(ログドライバーの選択肢に「FireLens」が出てこない) 今回の手順のようにタスク定義をJSONファイルを使って作成する必要があります。
ログが出力されることを確認する
ログの最終送信先であるS3バケットを確認してみましょう。
年・月・日・時のフォルダが作成され、フォルダ内にログが格納されたことが確認できました。
S3バケットに格納されたログは、AWS GlueやAmazon Athenaを使うとイイ感じに分析ができそうです。
おわりに
今回紹介したサンプルのみですと単にログ出力先をCloudWatchからKinesis Data Firehose/S3へ変更しただけということになりますが、FireLensには他にもいろいろな機能があります。
- 正規表現によるログフィルタリング
- 外部Fluentdへのログ転送
大量に動作するコンテナのログから必要なログのみを収集したり、1箇所に集めたログをツールで分析したり、ということに役立ちそうです。
AWSサービスへの対応がプラグインで提供されていたり、Fluent bitの設定をカスタマイズできたりと、今後の機能拡大にも期待です。