Container InsightsでFluentdをFluent Bitに変更

はじめに

EKS 1.24へのアップグレードに伴い、コンテナのログをFluent BitでCloudWatch Logsに送るように変更しました。

Amazon EKS Kubernetes versions - Amazon EKS

If you already have Fluentd configured for Container Insights, then you must migrate Fluentd to Fluent Bit before updating your cluster. The Fluentd parsers are configured to only parse log messages in JSON format. Unlike dockerd, the containerd container runtime has log messages that aren't in JSON format. If you don't migrate to Fluent Bit, some of the configured Fluentd's parsers will generate a massive amount of errors inside the Fluentd container.

FluentdとFluent Bitの差異

こちらを参照します。

docs.aws.amazon.com

設定はFluent Bit optimized configurationFluentd-compatible configurationが提供されていますが、Fluentd-compatible configurationは containerd に対応していなさそう(#139)ですし、Fluent Bit optimized configurationを使用します。

主な違いは以下の通りです。

  • ログストリーム名
  • kube-proxyaws-node のログを格納するロググループ
  • メタデータ
    • 変更: docker.container_id -> kubernetes.docker_id
    • 削除: kubernetescontainer_image_idmaster_urlnamespace_idnamespace_labels

Fluentdの削除

まずは既存のリソースを削除します。
メトリクスを収集するCloudWatchエージェントについては、必要であれば除外するか、こちらの手順で再インストールしてください。

docs.aws.amazon.com

curl https://raw.githubusercontent.com/aws-samples/amazon-cloudwatch-container-insights/latest/k8s-deployment-manifest-templates/deployment-mode/daemonset/container-insights-monitoring/quickstart/cwagent-fluentd-quickstart.yaml | sed "s/{{cluster_name}}/Cluster_Name/;s/{{region_name}}/Region/" | kubectl delete -f -
namespace "amazon-cloudwatch" deleted
serviceaccount "cloudwatch-agent" deleted
clusterrole.rbac.authorization.k8s.io "cloudwatch-agent-role" deleted
clusterrolebinding.rbac.authorization.k8s.io "cloudwatch-agent-role-binding" deleted
configmap "cwagentconfig" deleted
daemonset.apps "cloudwatch-agent" deleted
configmap "cluster-info" deleted
serviceaccount "fluentd" deleted
clusterrole.rbac.authorization.k8s.io "fluentd-role" deleted
clusterrolebinding.rbac.authorization.k8s.io "fluentd-role-binding" deleted
configmap "fluentd-config" deleted
daemonset.apps "fluentd-cloudwatch" deleted

Fluent Bitのインストール

こちらの手順を行います。

docs.aws.amazon.com

YAMLリポジトリで管理・カスタマイズしたいので、手元に取得します。 各リソースの説明についてはリンク先を参照してください。

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

# fluent-bit-cluster-info.yaml
ClusterName=cluster-name
RegionName=cluster-region
FluentBitHttpPort='2020'
FluentBitReadFromHead='Off'
[[ ${FluentBitReadFromHead} = 'On' ]] && FluentBitReadFromTail='Off'|| FluentBitReadFromTail='On'
[[ -z ${FluentBitHttpPort} ]] && FluentBitHttpServer='Off' || FluentBitHttpServer='On'
kubectl create configmap fluent-bit-cluster-info \
--from-literal=cluster.name=${ClusterName} \
--from-literal=http.server=${FluentBitHttpServer} \
--from-literal=http.port=${FluentBitHttpPort} \
--from-literal=read.head=${FluentBitReadFromHead} \
--from-literal=read.tail=${FluentBitReadFromTail} \
--from-literal=logs.region=${RegionName} -n amazon-cloudwatch -o yaml --dry-run > fluent-bit-cluster-info.yaml

# fluent-bit.yaml
wget 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

マニフェストを適用します。

namespace/amazon-cloudwatch created
serviceaccount/fluent-bit created
clusterrole.rbac.authorization.k8s.io/fluent-bit-role created
clusterrolebinding.rbac.authorization.k8s.io/fluent-bit-role-binding created
configmap/fluent-bit-cluster-info created
configmap/fluent-bit-config created
daemonset.apps/fluent-bit created

CloudWatch Logsでログストリームの作成を確認します。 先頭にノード名がついてますね。

ログのフォーマットは以下です。

{
    "log": "...",
    "stream": "...",
    "time": "...",
    "kubernetes": {
        "pod_name": "...",
        "namespace_name": "...",
        "pod_id": "...",
        "host": "....",
        "container_name": "...",
        "docker_id": "...",
        "container_hash": "...",
        "container_image": "..."
    }
}

ログストリーム名の変更

アプリケーション( /aws/containerinsights/<Cluster_Name>/application )のログストリームについては、従来の単位(Pod、Namespace、コンテナ、コンテナID)で構成したいので、log_stream_templateで名前を変更します(区切り文字には制限があります)。

apiVersion: v1
kind: ConfigMap
metadata:
  name: fluent-bit-config
  namespace: amazon-cloudwatch
  labels:
    k8s-app: fluent-bit
data:
...
  application-log.conf: |
...
    [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['pod_name'].$kubernetes['namespace_name'].$kubernetes['container_name'].$kubernetes['docker_id']
        auto_create_group   true
        extra_user_agent    container-insights