Open4

EKS FargateのFluentBitの組み込みログルータでCloudwatchLogsへ出力する際の課題

よしのりよしのり

ありがたいことに、EKS FargateにはFluentBitが予め組み込まれており、ConfigMapを適用するだけでCloudwatchLogsやその他のターゲットへログ出力ができる。
https://aws.amazon.com/jp/blogs/news/fluent-bit-for-amazon-eks-on-aws-fargate-is-here-jp/

しかしながら一つ残念な点として、filterにKubernetesの指定ができない。
以下ドキュメントに記載がある。(最新の内容は英語版で見るのが吉)

Fargate validates against the following supported filters: grep, parser, record_modifier, rewrite_tag, throttle, nest, and modify.

https://docs.aws.amazon.com/eks/latest/userguide/fargate-logging.html

filterにKubernetesの指定ができないと、Podやコンテナの情報が拾えない。

これで何が困るかというと、CloudwatchLogsに出力するような場合、ログストリーム名の動的生成がやりにくくなる。

Container Insightsでは、DaemonSetとしてFluentdをデプロイして、その設定ファイル内に以下のようなフィルタを指定可能だった。

<filter **>
  @type kubernetes_metadata
  @id filter_kube_metadata_systemd
</filter>

こうすると、以下のような情報を拾うことができた。

"kubernetes": {
        "container_name": "container_name",
        "namespace_name": "namespace_name",
        "pod_name": "container_name-65ccfb4d4c-4zdlf",
        "container_image": "111111111111.dkr.ecr.ap-northeast-1.amazonaws.com/container_name-golang:tag",
        "container_image_id": "docker-pullable://111111111111.dkr.ecr.ap-northeast-1.amazonaws.com/image_name@sha256:xxxxxxxxxxxxxxxxxxx",
        "pod_id": "xxxxxxxx-496e-4864-ad51-f12b246275f4",
        "host": "ip-xx-xx-xx-xx.ap-northeast-1.compute.internal",
        "labels": {
            "app": "container_name",
            "env": "develop",
            "pod-template-hash": "xxxxxxxxxxx"
        },
        "master_url": "https://172.20.0.1:443/api",
        "namespace_id": "xxxxxxxxxx-4311-4263-91a8-76765fd44b32",
        "namespace_labels": {
            "env": "develop"
        }
    },

これらの情報から、ストリーム名を動的に作成可能であったのだが、これと同様のことがFargateに組み込まれているFluentBitではできないということになる。(2021/08/23現在)

ストリーム名は、なるべく簡潔でわかりやすく、かつ同じworkload(deploymentなど)のPodは同じストリームへ出力したいなど、結構柔軟に整備したいところ。

現状でこれをやろうとすると、アプリケーション側でアプリ名や環境名などを出力する必要がある。

新規構築なら問題ないけど、既存で沢山のworkloadを抱えている状態なので、もう少し何かスマートな解決策がないものか。

悩み中。

よしのりよしのり

FluentBitのConfigMapを更新した場合、既存のPodに対して適用するためにはPodを再起動する必要がある。
反映されないなーって時は、rollout restartするべし。

Important
Amazon EKS Fargate logging doesn't support dynamic configuration of ConfigMaps. Any changes to ConfigMaps are applied to new pods only. Changes aren't applied to existing pods.
よしのりよしのり

ストリーム名は、なるべく簡潔でわかりやすく、かつ同じworkload(deploymentなど)のPodは同じストリームへ出力したいなど、結構柔軟に整備したいところ。

もしかすると、この要件に固着しすぎているのかもしれないと思い始めた。

ConfigMapのOutputにて、log_stream_prefixをすると、以下のような形式のストリームが作成される。

<log_stream_prefix>kube.var.log.containers.<pod_name>_<namespace>_<container_name>-<container_id>.log

直近のログ閲覧時は最新のストリームを選択して、検索時にはログストリーム名で絞り込む、ということにもできる。
検索はContainerInsightsだと以下のようにしてできそうではある。

fields @timestamp, @message
| filter @logStream LIKE /<log_stream_prefix>kube.var.log.containers.<workload_name>*/
| sort @timestamp desc
| limit 20

とはいえ、検索時にコストがかかるのが気になるし、扱い方もやや直感的じゃないので、あまりAWSやCloudwatch Logsに明るくないアプリケーションエンジニアに扱ってもらう際のハードルもあるなあ。