概要
ECS Fargate上のアプリケーションについて、
ログフォワーダーとしてFluent Bitを利用したサイドカーパターン構成を考えてみます。
ECS Fargateのログ管理方法を検討する際、プラットフォーム標準機能であるDocker Logging Driverの活用が第一候補に挙がるとおもいますが、
ここでは都合によりログの出力先をstdout, stderrに向けず、ファイル出力しているアプリケーションコンテナのログ管理を想定します。1
設定内容
ECSタスク定義、Fluent Bitの設定ファイルの内容を確認していきます。
おおよそ以下のベストプラクティスの構成と同じような形になります。
ECSタスク定義
アプリケーション + Fluent Bitの構成を設定したTerraformのリソース定義になります。
いくつかパラメータを省略しています。
resource "aws_ecs_task_definition" "this" {
family = "logforwarder-sidecar-pattern"
requires_compatibilities = ["FARGATE"]
network_mode = "awsvpc"
cpu = 1024
memory = 2048
container_definitions = jsonencode([
{
name = "application"
essential = true
image = "${var.AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/application:xxxxx"
mountPoints = [
{
"sourceVolume" = "log_directory",
"containerPath" = var.log_output_dir_path
}
]
dependencies = [{
containerName = "fluent-bit"
condition = "START"
}]
enable_cloudwatch_logging = false
log_configuration = {
logDriver = "awsfirelens"
options = {
"Name" : "cloudwatch",
"region" : var.AWS_REGION,
"log_stream_prefix" : "application",
"log_group_name" : "/aws/ecs/${var.cluster_name}/${var.service_name}",
"auto_create_group" : "true"
}
}
},
{
name = "fluent-bit"
essential = true
image = "${var.AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/custom_aws-for-fluent-bit:xxxxx"
firelens_configuration = {
type = "fluentbit"
options = {
"config-file-type" : "file",
"config-file-value" : var.fluent-bit_conf_absolute_path
}
}
mountPoints = [
{
"sourceVolume" : "log_directory",
"containerPath" : var.log_output_dir_path
}
]
},
{
name = "logrotate"
essential = true
image = "${var.AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/logrotate:xxxxx"
enable_cloudwatch_logging = false
mountPoints = [
{
"sourceVolume" = "log_directory",
"containerPath" = var.log_output_dir_path
}
]
}
])
volume {
name = "log_directory"
}
runtime_platform {
operating_system_family = "LINUX"
cpu_architecture = "X86_64"
}
}
applicationコンテナと併せてログ転送のためにfluent-bitコンテナを設定します。
また、ログローテーションのためにlogrotateコンテナ2を用意します。
applicationコンテナのログディレクトリをバインドマウントさせることで、
fluent-bitコンテナからファイルアクセスを可能にしています。
ついでにFireLensの設定をしていますが、扱いたいのは標準出力ではないので必須ではありません。
もし設定する場合、この後確認するFluent Bitの設定ファイルの絶対パスをconfig-file-value
に入れてください。
参考: https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/using_firelens.html
firelens_configuration = {
type = "fluentbit"
options = {
"config-file-type" : "file",
"config-file-value" : var.fluent-bit_conf_absolute_path
}
}
FluentBitのDockerfile
FROM public.ecr.aws/aws-observability/aws-for-fluent-bit:init-2.32.0.20231205
# https://gallery.ecr.aws/aws-observability/aws-for-fluent-bit
ARG FLUENT_BIT_CONF_PATH="/usr/local/etc/fluent-bit"
COPY ./fluent-bit.conf ${FLUENT_BIT_CONF_PATH}
AWSがメンテしているFluent Bitのイメージを利用します。Fluent Bitの設定中でECS Metadataを使用するためinitタグのイメージを選択しています。
参考: https://github.com/aws/aws-for-fluent-bit/blob/mainline/use_cases/init-process-for-fluent-bit/README.md
以下のFluent Bitの設定ファイルを用意しイメージに取り込みます。${LOG_BASEDIR}等の変数は適宜変更してください。
CMD
はベースイメージから引き継がれます。fleunt-bit起動時の設定ファイルが先のタスク定義のconfig-file-value
で指定した設定ファイルを呼び出すことで設定が有効化されます。
FireLens設定しない場合はCMD
を書き換えて用意した設定ファイルを直接読み込んで起動するようにしてみてください。
参考: https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/firelens-taskdef.html#firelens-taskdef-customconfig
@SET LOG_BASEDIR=${LOG_BASEDIR}
@SET AWS_REGION=ap-northeast-1
[SERVICE]
[INPUT]
Name tail
Tag tail.app_logs.*
Path ${LOG_BASEDIR}/*
Path_Key application_log_file_path
Read_from_Head true
[OUTPUT]
Name cloudwatch_logs
Match tail.app_logs.*
region ${AWS_REGION}
log_group_name fallback-group
log_stream_prefix fallback-stream
auto_create_group true
log_group_template /aws/ecs/${ECS_CLUSTER}/${ECS_FAMILY}/APPLICATION_LOGS
log_stream_template $application_log_file_path
Fluent Bitの設定の詳細は公式ドキュメントに記載があるため割愛します。
参考: https://docs.fluentbit.io/manual/administration/configuring-fluent-bit/classic-mode
注目したいのは以下の2点です。これらを適切に設定することで任意のパスのログファイルを任意のCloudWatchLogsのロググループ, ストリームへの転送が可能になります。
- INPUTセクションのPathパラメータでログ転送対象のログファイル名をマッチしていること
- OUTPUTセクションのlog_group_templateパラメータ、log_stream_templateパラメータでCloudWatchLogsへのログ転送先を設定していること
ロググループの指定に利用した${ECS_CLUSTER}等の利用可能な変数については以下を参考にしました。
参考: https://github.com/aws/aws-for-fluent-bit/blob/mainline/use_cases/init-process-for-fluent-bit/README.md#how-to-use-ecs-task-metadata-in-fluent-bit-config
この構成のメリット・デメリット
例えばEC2で稼働していたアプリケーションをコンテナ化する際にログ出力の見直しが必要となりますが、
この構成のメリットはアプリケーション側の改修を発生させずログ管理の外出しが可能な点にあります。
一方、Docker標準のロギング方法に沿っていないことや管理対象のコンテナが増えるため保守性が悪化すること、アプリケーションコンテナに割り当て可能なコンピューティングリソースが圧迫されてしまうことはデメリットになります。
複数種類のログが別々のフォーマットで出力されていたり、ログの識別情報がなく出力先のファイルでしか判別が難しい場合は、
標準出力に切り替えるだけではなくフィルタリングのためのログレコードの改修が必要になります。
原則としてはDocker標準の標準出力によるロギング方法に沿うのが幸せになれそうですが、
上で挙げたような改修を選択できない場合はこのような構成を検討してみてはいかがでしょうか。
-
仮想マシンで稼働しているアプリケーションをコンテナ化したい場合などを想定してください。 ↩
-
なにかしらの組織にメンテされているイメージが見当たらなかったため自前で用意します。
参考: https://qiita.com/minarai/items/45121d5c06a1098e9a1c ↩