ECS×FireLens(Fluent Bit v1.8.3)でSIGSEGV──回避のためのpreflightログ戦略
TL;DR
- Datadogとlog-router(FireLens/FluentBit)でログ送信するバックエンドサービスのデプロイ時、初回のログ送信でlog-routerが稀にクラッシュする事象があった
- デプロイ時のコンテナ起動を工夫し、preflightでログ送信が安全にできるかを確認し、その
SUCCESS
を待ってからバックエンドサービスを起動する運用にした - 環境:ECSFargate、DatadogAgent7.31.0、aws-for-fluent-bit2.19.0(FluentBitv1.8系)
備考:“preflight”はCORS文脈で利用される言葉だが、ここでは公開前の下準備という意味で使用
想定される読者
- デプロイ直後の“初回のみ不安定”を回避したい人
背景
当該バックエンドサービスはALB配下で公開されている。
1つのECSタスク内にlog-router(FireLens/FluentBit)、DatadogAgent、バックエンドサービス本体の3コンテナを同居させており、ログ送信は各コンテナが起動後、バックエンドサービスがRunningになってから始まる設計だった。
問題は、バックエンドサービスがRunningになった時点でALBがそのタスクをターゲットとして扱い始める一方、初回のログ送信タイミングでlog-routerがクラッシュすることがあった点にある。
log-routerはessential:true
で定義していたため、log-routerが落ちるとタスク全体が停止し、同一タスク内のDatadogAgentやバックエンドサービスも巻き添えで終了する。
タスク停止時にはALB側でターゲットがDRAINING状態となる。この間にたまたま該当ターゲットへ接続したユーザーのリクエストは502で失敗する、という挙動が発生していた。
なお自環境の観測ではこのクラッシュは初回のログ送信時に限って発生し、2回目以降では再現しなかった。
やったこと
- preflight用の一時コンテナで数回ログを送ってlog-router(FireLens/FluentBit)経路を事前確認
- preflight用の一時コンテナの
SUCCESS
を待ってバックエンドサービスを起動 -
dependsOn
で起動順制御、preflightはessential:false
- サービス側はデプロイ・サーキットブレーカーを有効化(失敗時ロールバック)
補足: dependsOnとessentialの要点(AWS公式要約)
dependsOn(コンテナ依存関係)
コンテナの起動順や完了待ちを条件で指定できる。
条件はSTART
/COMPLETE
/SUCCESS
/HEALTHY
があり、SUCCESS
は「ゼロ終了コードでの完了」を待つ。
essential
essential:trueとしてマークされたコンテナが停止するとタスク全体が停止する
実装(抜粋)
preflight一時コンテナ
{
"name": "log-router-preflight",
"image": "public.ecr.aws/amazonlinux/amazonlinux:2023-minimal",
"essential": false,
"command": ["sh","-c","for i in $(seq 1 3); do echo preflight alive; sleep 10; done"],
"dependsOn": [
{ "containerName": "log-router", "condition": "START" },
{ "containerName": "dd-agent", "condition": "START" }
]
}
バックエンドサービス
{
"name": "app",
"dependsOn": [
{ "containerName": "log-router-preflight", "condition": "SUCCESS" }
]
}
結論/結果
-
バックエンドサービス公開前にログ送信経路を確認することで、初回のみ発生していたlog-routerクラッシュに伴うDRAINING→502を実運用で解消できた
-
preflightはessential:false、本体はdependsOn:SUCCESSで起動順を明示するため、失敗しても公開前で止められた
-
これは安全策であり、根本原因への対応は別途必要です
Discussion