🔊

EKSからCloudwatch logsへのログ転送を FluentD から Fluent Bit に移行する

2023/08/24に公開

サマリー

EKSのアプリケーションログをCloudwatchに転送するのに使っていたFluentDをFluent Bitに置き換えました。
この時に、公式ドキュメントだけでは痒い所に手が届かない情報しか載っていなかったので苦労した部分を共有します。

FluentDからFluent Bitへの移行が推奨されています

数年前にEKSクラスタ上で動かすアプリケーションのログを、FluentDを使ってCloudwatchに集約できるようにしました。その時の記事は↓↓↓です。

https://qiita.com/k5trismegistus/items/9675d90a22746dd030cf

この設定をしてから約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への移行について

移行手順

基本的には公式ドキュメント

https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/Container-Insights-setup-logs-FluentBit.html

がベースになりますが、ちょっとこれだけだと融通がきかないです。

公式ドキュメントでは、Fluent Bit用の設定ファイルを直接適用するように書かれています。

次のいずれかのコマンドを実行して、Fluent Bit daemonset をクラスターにダウンロードしてデプロイします。

しかし、このファイルをそのまま適用すると不便なところがあります。そこで、いきなり適用するのではなく手を入れることにします。

ドキュメントには「より Fluentd に似ている Fluent Bit の設定」という候補があるのですが、少なくとも私の環境では全く似ていなかったので、「Fluent Bit 最適化設定」の方を使いました。

まずは、次のファイルをダウンロードしましょう。

https://raw.githubusercontent.com/aws-samples/amazon-cloudwatch-container-insights/latest/k8s-deployment-manifest-templates/deployment-mode/daemonset/container-insights-monitoring/fluent-bit/fluent-bit.yaml

ログのパース方法を変える

デフォルトでは、ログは「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

に。

参考リンク:
https://progret.hatenadiary.com/entry/2022/04/24/102737

ログストリーム名を変える

「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という書き方をすることになります。

https://docs.fluentbit.io/manual/administration/configuring-fluent-bit/classic-mode/record-accessor

ドキュメント中には記載がないのですが、ハイフンの使用には制限があるようです。
本来なら、アプリ名-環境名でログを集約したかったのですが、アプリ名.環境名としました。

まとめ

そして最後に、

kubectl apply -f fluent-bit.yaml

で設定を適用すれば、望むログストリーム名でパースされたログがFluent BitによってCloudwatchに転送されます。

あとは、FluentDのDaemonSetを消しましょう。


関連記事

https://zenn.dev/k5trismegistus/articles/5f9d2efec997cf

Discussion