EKSのコンテナログをFluent Bitで収集しCloudWatch Logsに集約する


はじめに

EKS上のログを収集してそれをCloudWatch Logsに集約するにはfluentd-cloudwatchをデプロイするのが定番のパターンです。
これをFluent Bitでも行えるようにAWSが公式でaws-for-fluent-bitを公開しているので試してみました。

環境

macOS Mojave 10.14.6
EKS 1.16
Helm 2.14.3
Helmfile 0.122.0

導入手順

EKSやHelm Tillerは既にデプロイ済みであるとします。
Fluent BitはデフォルトでCloudWatch LogsにアクセスするためのIAM Roleが付与されないので自分で設定していく必要があります。

IAM Roleの用意

Fluent BitがCloudWatch Logsにログを転送させるためのIAM Roleを作成していきます。
kube2iamを利用するためAssume Roleを設定する必要があります。

Node用のIAM Role

作成したWorker Node用のIAM RoleにPolicyをアタッチします。
<NODE_INSTANCE_ROLE>にはWorker Nodeのインスタンスロールが入ります。

assume-role-policy.json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "sts:AssumeRole",
      "Resource": "*"
    }
  ]
}
$ aws iam create-policy \
  --policy-name assume-role-policy \
  --policy-document assume-role-policy.json
$ aws iam attach-role-policy \
  --role-name <NODE_INSTANCE_ROLE> \
  --policy-arn arn:aws:iam::XXXXXXXXXX:policy/assume-role-policy

Pod用のIAM Role

公式のCloudWatchLogsFullAccessのPolicyを付与したIAM Roleを作成します。

cloud-watch-logs-full-access-policy.json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "ec2.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    },
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::XXXXXXXXXX:role/<NODE_INSTANCE_ROLE>"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
$ aws iam create-role \
  --role-name cloud-watch-logs-full-access-role \
  --assume-role-policy-document cloud-watch-logs-full-access-policy.json
$ aws iam attach-role-policy \
  --role-name cloud-watch-logs-full-access-role \
  --policy-arn arn:aws:iam::aws:policy/CloudWatchFullAccess

kube2iamとFluent Bitのデプロイ

Helmでkube2iamとFluent Bitをデプロイしていきます。
Fluent Bitに関してはtemplateを修正する必要があるのでローカルにHelm Chartをダウンロードします。

$ helm repo add aws https://aws.github.io/eks-charts
$ helm fetch aws/aws-for-fluent-bit --version 0.1.2
$ tar xvzf aws-for-fluent-bit-0.1.2.tgz

下記のようにPodのannotationsにIAM Roleを定義します。

aws-for-fluent-bit/templates/daemonset.yaml
spec:
  template:
    metadata:
+     annotations:
+       iam.amazonaws.com/role: cloud-watch-logs-full-access-role

Helmfileにkube2iamとFluent Bitに関する情報を記述します。
cloudwatchの設定でリージョン名を入れます。firehoseとkinesisは今回使いません。

helmfile.yaml
repositories:
  - name: stable
    url: https://kubernetes-charts.storage.googleapis.com

releases:
  - name: kube2iam
    namespace: kube-system
    chart: stable/kube2iam
    version: 2.5.0
    values:
      - host:
          iptables: true
          interface: eni+
        extraArgs:
          auto-discover-base-arn: ""
        rbac:
          create: true
  - name: aws-for-fluent-bit
    namespace: kube-system
    chart: ./aws-for-fluent-bit
    values:
      - cloudWatch:
          region: "ap-northeast-1"
        firehose:
          enabled: false
        kinesis:
          enabled: false

次のコマンドでデプロイします。

$ helmfile -f ./helmfile.yaml apply

確認

AWSコンソールで実際にログが集約されていることが確認できます。
デフォルトではロググループ名は/aws/eks/fluentbit-cloudwatch/logsとなっています。

まとめ

FluentdではなくFluent Bitでコンテナログを収集してCloudWatch Logsに集約できることを確認しました。

本来はFluent Bitを使うことでリソースの節約をしたいところですが、Helm Chartのデフォルト値はresources.requests.cpu=500mresources.requests.memory=500Miとなっており、Fluentd-CloudWatchがそれぞれ100m200Miであることを考えると厳しそうです。
あくまで参考値なので、実際のリソース消費は調査しないといけないです。

導入に関してはHelm Chartが存在するのでとても簡単でした。