EKSからCloudwatch logsへのログ転送を FluentD から Fluent Bit に移行する
サマリー
EKSのアプリケーションログをCloudwatchに転送するのに使っていたFluentDをFluent Bitに置き換えました。
この時に、公式ドキュメントだけでは痒い所に手が届かない情報しか載っていなかったので苦労した部分を共有します。
FluentDからFluent Bitへの移行が推奨されています
数年前にEKSクラスタ上で動かすアプリケーションのログを、FluentDを使ってCloudwatchに集約できるようにしました。その時の記事は↓↓↓です。
この設定をしてから約3年半ずっとログはこれで取れていました。
ところが先日、EKSのKubernetesのバージョンを1.22から1.25まで上げたところ、ログがとれない状態に。
原因を調べている中で、今はもうFluentDを使うことが非推奨になっていることを知ります。
ログがとれない原因究明は時間の無駄になりそうなのでやめて、先にFluent Bitへの移行を進めることにしました。
Container Insights の FluentD のサポートは現在メンテナンスモードになっています。つまり、AWS はこれ以上 FluentD の更新を提供せず、近い将来に非推奨にする予定です。
(中略)
可能な限り Container Insights で FluentBit を使用するように移行することを強くお勧めします。Container Insights のログフォワーダとして FluentBit を使用すると、パフォーマンスが大幅に向上します。
(オプション) CloudWatch Logs へログを送信する DaemonSet として FluentD を設定する
Fluent Bitへの移行について
移行手順
基本的には公式ドキュメント
がベースになりますが、ちょっとこれだけだと融通がきかないです。
公式ドキュメントでは、Fluent Bit用の設定ファイルを直接適用するように書かれています。
次のいずれかのコマンドを実行して、Fluent Bit daemonset をクラスターにダウンロードしてデプロイします。
しかし、このファイルをそのまま適用すると不便なところがあります。そこで、いきなり適用するのではなく手を入れることにします。
ドキュメントには「より Fluentd に似ている Fluent Bit の設定」という候補があるのですが、少なくとも私の環境では全く似ていなかったので、「Fluent Bit 最適化設定」の方を使いました。
まずは、次のファイルをダウンロードしましょう。
ログのパース方法を変える
デフォルトでは、ログは「CRI形式」で出力されます。
これはAWSの配っているサンプルの設定では、単なるテキストとして集約されます。
なのでこれをパースして、構造化されたデータにします。
parsers.conf
を設定している部分に
[PARSER]
Name cri
Format regex
Regex ^(?<time>[^ ]+) (?<stream>stdout|stderr) (?<logtag>[^ ]*) (?<log>.*)$
Time_Key time
Time_Format %Y-%m-%dT%H:%M:%S.%L%z
というのを足します。
そして、application-log.conf
を設定している部分で、docker
を利用している部分を全てcri
に置き換えます。
Parser docker
を
Parser cri
に。
参考リンク:
ログストリーム名を変える
「Fluent Bit 最適化設定」では、デフォルトで
kubernetes-nodeName-application.var.log.containers.kubernetes-podName_kubernetes-namespace_kubernetes-container-name-kubernetes-containerID
という名前になります。
私の希望としては、Podを跨いで同じアプリケーションのログは同じログストリームに集約したいです。エラーログを確認したいときにコンテナのIDごとにログストリームが分かれていると探すのが大変だからです。(本来ならElasticsearchとかで集約すべきなんでしょうか?)
[OUTPUT]
Name cloudwatch_logs
Match application.*
region ${AWS_REGION}
log_group_name /aws/containerinsights/${CLUSTER_NAME}/application
log_stream_prefix ${HOST_NAME}-
log_stream_template $kubernetes['labels'] ['app'].$kubernetes['namespace_name'] // ここ!
auto_create_group true
extra_user_agent container-insights
答えとしては、log_stream_template
というのを指定します。
ただし、フォールバック用にlog_stream_name
またはlog_stream_prefix
の指定を残しておく必要はあります。
log_stream_template
は、Record Accessor
という書き方をすることになります。
ドキュメント中には記載がないのですが、ハイフンの使用には制限があるようです。
本来なら、アプリ名
-環境名
でログを集約したかったのですが、アプリ名
.環境名
としました。
まとめ
そして最後に、
kubectl apply -f fluent-bit.yaml
で設定を適用すれば、望むログストリーム名でパースされたログがFluent BitによってCloudwatchに転送されます。
あとは、FluentDのDaemonSetを消しましょう。
関連記事
Discussion