ゴール
ECS on Fargateでfluentbitを利用してログを複数箇所に送信する
前提条件
- ECS on Fargate
- Ruby on Rails (今回の箇所に関係ないですが)
- 既に標準出力にログをはいており、awslogsドライバーを利用してcloudwatchにログを送信している
- 環境はecs-cliを利用している(書き方がecs-cliによっているので必要に応じて利用しているもので読み替えていただければ)
達成条件
- APM(Datadog)にログを送信したいモチベーションが出てきたので以下の2箇所に同時にログを送信する構成を取りたい
- CloudWatch Logs
- Datadog
今回はDatadogさんの話によった話は書きませんがAPMやインフラ監視を一元管理してくれるsaasサービスになります
まとめ
- fluentbit をサイドカーとして立ち上げてCloudWatchLogsとDatadogに送信するようにする
- アプリケーションログをfluentbitに連携するにあたり AWS FireLens を利用する
- アプリケーションのログドライバーでFireLensを指定
driver: awsfirelens
- アプリケーションのログドライバーでFireLensを指定
- 複数箇所にログを送信するためにはfluentbitに対して自前でconfigファイルを書く必要がある(単一箇所に送信する場合はFireLensの設定だけで可能そう)
- AWS FireLensの設定でconfigのパスを指定する方法として「ローカルファイルの参照」「S3上のファイルの参照」の二つがあるがFargateではローカルファイルの参照しかサポートしていない (参考)
- fluentbitのcontainer内にconfigファイルを注入する必要があるのでfluentbitのイメージをラップしたimageを自前で用意する必要がある
fluentbitイメージの用意
複数箇所にログを送信する場合はFireLensの設定のみでは実現できず、自前でconfigファイルを用意する必要があります。
ただしconfigファイルのパスをFireLens側で指定すればfluentbitがいい感じに動いてくれるとのこと
(やったことないのですがfluentbit側でこれを設定すると大変なのかな?)
FireLensからconfigファイルを指定する方法として二つあるがFargateには一つしか選択肢がない、、、、、
-
file: fluentbitコンテナ内のファイルパスを指定する => Fargateはこちらのみ -
s3: S3のファイルパスを指定する
AWS Fargate でホストされるタスクは、file 設定ファイルタイプのみをサポートします。
ここは早く改修されてほしいTT (FireLensからの指定の仕方は後述)
なんとかしてfluentbit container内にローカルファイルを置かないといけないので悲しいDockerfileを爆誕させた
(fluentbitは現時点の最新でとってるので適宜変更するのが良さそうです)
FROM amazon/aws-for-fluent-bit:2.23.3
COPY ./extra.conf /fluent-bit/etc/extra.conf
confファイルは参考程度に
秘匿情報をどうしようと模索していたのですが ${...} でいい感じに読み込んでくれました
[OUTPUT]
Name cloudwatch
Match *
region ap-northeast-1
log_group_name sample-application
log_stream_prefix rails
[OUTPUT]
Name datadog
Match *
Host http-intake.logs.datadoghq.com
TLS on
compress gzip
apikey ${DD_API_KEY}
dd_service your-service-name
dd_source your-source-name
provider ecs
これをデプロイ時に新しく作成したECRにpushして使ってます
AWS FireLensを利用してfluentbitにログを流す
ここはecs-cliの書き方によっていると思うので適宜ドキュメントを見てください
docker-composeでfluentbitのサイドカーコンテナを追加してアプリケーションのlogging周りを変更
version: "3"
services:
app: # 既存のRailsアプリケーション
...
depends_on: # fluentbitが立ち上がるまで待つ
- log_router
logging:
driver: awsfirelens # 今までawslogsを指定していたのをFireLensに変更
log_router: # fluentbitのcontainerを追加
image: {ECRのパス}
build:
context: ./fluentbit # fluentbit用のDockerfileのパス(今回はfluentbitディレクトリに押し込んだ)
restart: always
logging:
driver: awslogs # fluentbit自体のログはawslogsドライバーでCloudWatchLogsに投げる
options:
awslogs-group: {...}
awslogs-region: ap-northeast-1
awslogs-stream-prefix: {...}
task_definition:
...
services:
...
log_router:
...(cpu/memoryなどは適宜設定)
firelens_configuration:
type: fluentbit
options:
config-file-type: "file"
config-file-value: "/fluent-bit/etc/extra.conf" # Dockerfileで指定したパス
secrets:
- value_from: {...} # 今回はDatadog用のAPIキーを入れたので追加しましたが必要に応じて無視してください
name: DD_API_KEY
fluentbitからCloudWatch Logsにログを書き込むための権限を追加
fluentbitからCloudWatch Logsにログを書き込むためにタスクロールにポリシーの追加が必要でした
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": ["{書き込み先のパスを列挙}"]
}
コメント
FargateからもS3でのファイル指定ができるようになればconfをS3配置して公式のイメージが使えるのでDockerfileを用意してECRにプッシュしてみたいな作業が不要になるので待ち遠しいです。。。
これがベストかはわからないので気づいた点があればコメントお願いします
参考