AWS FireLensってなんだ？

# What's？

AWS FireLensについて、知っておきたかったので軽く調べてみました、と。


# AWS FireLensとは？

AWS FireLensとは、2019年9月に発表された、Amazon ECSで使用できるログルーターのことです。

[Firelens の発表 – コンテナログの新たな管理方法](https://aws.amazon.com/jp/blogs/news/announcing-firelens-a-new-way-to-manage-container-logs/)

タスク定義の中に含めてサイドカーとして配置しつつ、他のコンテナからはログドライバーとして使用します。

[カスタムログルーティング](https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/using_firelens.html)

AWS FireLensからは、Amazon CloudWatch LogsまたはAmazon Kinesis Data Streams、Amazon Kinesis Data Firehose、そして別のFluentdやFluent Bitに転送することができます。

以下のタスク定義サンプルは、[Firelens の発表 – コンテナログの新たな管理方法](https://aws.amazon.com/jp/blogs/news/announcing-firelens-a-new-way-to-manage-container-logs/)からの抜粋です。

```json
{
	"family": "firelens-example-cloudwatch",
	"taskRoleArn": "arn:aws:iam::365489000573:role/ecsInstanceRole",
	"executionRoleArn": "arn:aws:iam::365489300073:role/ecsTaskExecutionRole",
	"containerDefinitions": [
		{
			"essential": true,
			"image": "906394416424.dkr.ecr.us-east-1.amazonaws.com/aws-for-fluent-bit:latest",
			"name": "log_router",
			"firelensConfiguration": {
				"type": "fluentbit"
			},
			"logConfiguration": {
				"logDriver": "awslogs",
				"options": {
					"awslogs-group": "firelens-container",
					"awslogs-region": "us-west-2",
					"awslogs-create-group": "true",
					"awslogs-stream-prefix": "firelens"
				}
			},
			"memoryReservation": 50
		 },
		 {
			 "essential": true,
			 "image": "nginx",
			 "name": "app",
			 "portMappings": [
				{
				  "containerPort": 80,
				  "hostPort": 80
				}
			  ],
			 "logConfiguration": {
				 "logDriver":"awsfirelens",
				 "options": {
					"Name": "cloudwatch",
					"region": "us-west-2",
					"log_group_name": "firelens-fluent-bit",
					"auto_create_group": "true",
					"log_stream_prefix": "from-fluent-bit"
				}
			},
			"memoryReservation": 100
		}
	]
}
```


# AWS for Fluent Bitイメージ

AWS FireLensとここまで書いてきましたが、ドキュメントをちゃんと眺めてみます。

> Amazon ECS 対応 FireLens では、タスク定義パラメータを使用して AWS のサービスや AWS パートナーネットワーク (APN ) の宛先にログをルーティングし、ログを保存および分析できます。FireLens は Fluentd および Fluent Bitで動作します。提供されている AWS for Fluent Bit イメージを使用することも、独自の Fluentd または Fluent Bit イメージを使用することもできます。

[カスタムログルーティング](https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/using_firelens.html)

このように書かれているので、AWS FireLensそのものは、Amazon ECSのコンテナログを同タスク定義内のサイドカーとして配置されたFluentdまたはFluent Bitに転送することができる仕組みだ、と考えた方がよさそうな気がします。

また、他のコンテナには、FluentdまたはFluent Bitへの接続情報が渡されるようです。

> awsfirelens ログドライバーがタスク定義で指定されている場合、ECS エージェントは次の環境変数をコンテナに挿入します。
>
> FLUENT_HOST および FLUENT_PORT 環境変数を使用すると、コードからログ ルータに直接ログできます。

[流線型ロガーライブラリの使用](https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/using_firelens.html#firelens-fluent-logger)

よって、AWS FireLensはFluentdまたはFluent Bitのコンテナイメージが必要になります。

そしてFluent BitのコンテナイメージをAWSが提供しているものを、AWS for Fluent Bitと言います。

[AWS for Fluent Bitイメージの使用](https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/using_firelens.html#firelens-using-fluentbit)

AWS for Fluent BitはDocker Hubにも置かれていますが、上記のドキュメントにあるようにAmazon ECRが使える場合はそちらで提供されているものを使った方が良さそうです。

[Docker Hub / amazon/aws-for-fluent-bit](https://hub.docker.com/r/amazon/aws-for-fluent-bit)

Docker Hubに置かれているイメージのソースコード（GitHubリポジトリ）は、こちら。

[GitHub / AWS for Fluent Bit Docker Image](https://github.com/aws/aws-for-fluent-bit)

現時点のAWS for Fluent Bitのバージョンは、`2.6.1`のようです。

`Dockerfile`を中心に、少し中身を見てみましょう。

ビルドは、AWS CodeBuildで行っているようですね。

https://github.com/aws/aws-for-fluent-bit/blob/v2.6.1/buildspec.yml

`make release`に対応するところを見ると、2つのDockerイメージをビルドしています。

https://github.com/aws/aws-for-fluent-bit/blob/v2.6.1/Makefile#L17-L19

3種類のプラグインが入っているようで、

* amazon-kinesis-firehose-for-fluent-bit
* amazon-cloudwatch-logs-for-fluent-bit
* amazon-kinesis-streams-for-fluent-bit

それが組み込まれているのがこちら。`Dockerfile`の前に、`Dockerfile.plugins`で作るイメージがビルドされます。

https://github.com/aws/aws-for-fluent-bit/blob/v2.6.1/Dockerfile.plugins

本体の`Dockerfile`はこちら。

https://github.com/aws/aws-for-fluent-bit/blob/v2.6.1/Dockerfile

中を見ていくと、マルチステージビルド構成になっていてFluent Bitのビルドをして

https://github.com/aws/aws-for-fluent-bit/blob/v2.6.1/Dockerfile#L41-L56

ビルドしたFluent Bitやプラグインを、ここまでに作ったイメージから`COPY`してくるという構成になっています。

https://github.com/aws/aws-for-fluent-bit/blob/v2.6.1/Dockerfile#L81-L98

ベースとなっているFluent Bitのバージョンは、こちらに定義されています。

https://github.com/aws/aws-for-fluent-bit/blob/v2.6.1/Dockerfile#L4

最終的なコンテナイメージのベースイメージは、Amazon Linux 2ですね。

https://github.com/aws/aws-for-fluent-bit/blob/v2.6.1/Dockerfile#L72

`ENTRYPOINT`の定義。

https://github.com/aws/aws-for-fluent-bit/blob/v2.6.1/entrypoint.sh

```shell
exec /fluent-bit/bin/fluent-bit -e /fluent-bit/firehose.so -e /fluent-bit/cloudwatch.so -e /fluent-bit/kinesis.so -c /fluent-bit/etc/fluent-bit.conf
```

最終的に含まれる設定としては、`INPUT`として`forward`、`OUTPUT`として`cloudwatch`というシンプルなものです。

https://github.com/aws/aws-for-fluent-bit/blob/v2.6.1/fluent-bit.conf

```shell
[INPUT]
    Name        forward
    Listen      0.0.0.0
    Port        24224

[OUTPUT]
    Name cloudwatch
    Match   **
    region us-east-1
    log_group_name fluent-bit-cloudwatch
    log_stream_prefix from-fluent-bit-
    auto_create_group true
```

とはいえ、この設定は`logConfiguration`の指定で動的に変わりそうですけどね。

> Amazon ECS はログ設定を変換し、Fluentd または Fluent Bit 出力設定を生成します。出力設定は、/fluent-bit/etc/fluent-bit.conf (Fluent Bit) および /fluentd/etc/fluent.conf (Fluentd) のログルーティングコンテナにマウントされます。
> 
> logConfiguration オブジェクトのオプションとして指定されたキーと値のペアは、Fluentd または Fluent Bit 出力設定の生成に使用されます。

[FireLens構成を使用するタスク定義の作成](https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/using_firelens.html#firelens-taskdef)

ところで、ドキュメントにはAmazon ECRにあるイメージの方が可用性が高いと書いてあるのですが、

> AWS for Fluent Bit イメージは Docker Hub で利用できます。ただし、Amazon ECR では、以下のイメージを使用することをお勧めします。これらのイメージにより、可用性が向上します。

Amazon ECRにPushしているAWS CodeBuildの内容を見る限りコンテナイメージ自体に差があるわけではなさそうなので、可用性というのはDocker HubとAmazon ECRの比較をしているのでしょうね。

https://github.com/aws/aws-for-fluent-bit/blob/v2.6.1/buildspec_publish_ecr.yml


# AWS for Fluent Bitを試してみる

あとは、少しだけローカルでAWS for Fluent Bitを使ってみます。

今回の環境は、こちら。

```shell
$ uname -srvmpio
Linux 5.4.0-47-generic #51-Ubuntu SMP Fri Sep 4 19:50:52 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux


$ lsb_release -a
No LSB modules are available.
Distributor ID:	Ubuntu
Description:	Ubuntu 20.04.1 LTS
Release:	20.04
Codename:	focal


$ docker version
Client: Docker Engine - Community
 Version:           19.03.12
 API version:       1.40
 Go version:        go1.13.10
 Git commit:        48a66213fe
 Built:             Mon Jun 22 15:45:44 2020
 OS/Arch:           linux/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          19.03.12
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.13.10
  Git commit:       48a66213fe
  Built:            Mon Jun 22 15:44:15 2020
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.2.13
  GitCommit:        7ad184331fa3e55e52b890ea95e65ba581ae3429
 runc:
  Version:          1.0.0-rc10
  GitCommit:        dc9208a3303feef5b3839f4323d9beb36df0a9dd
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683
```

とりあえず、イメージを取得して起動。

```shell
$ docker image pull amazon/aws-for-fluent-bit:2.6.1
$ docker container run -it --rm --name fluent-bit amazon/aws-for-fluent-bit:2.6.1
```

起動時のログ。今回は、Fluent Bit 1.5.2で動作しています。AWS for Fluent Bitとしては、`2.6.1`ですね。

```shell
AWS for Fluent Bit Container Image Version 2.6.1
Fluent Bit v1.5.2
* Copyright (C) 2019-2020 The Fluent Bit Authors
* Copyright (C) 2015-2018 Treasure Data
* Fluent Bit is a CNCF sub-project under the umbrella of Fluentd
* https://fluentbit.io

[2020/09/10 06:49:53] [ info] [engine] started (pid=1)
[2020/09/10 06:49:53] [ info] [storage] version=1.0.4, initializing...
[2020/09/10 06:49:53] [ info] [storage] in-memory
INFO[0000] [cloudwatch 0] plugin parameter log_group = 'fluent-bit-cloudwatch' 
INFO[0000] [cloudwatch 0] plugin parameter log_stream_prefix = 'from-fluent-bit-' 
INFO[0000] [cloudwatch 0] plugin parameter log_stream = '' 
INFO[0000] [cloudwatch 0] plugin parameter region = 'us-east-1' 
INFO[0000] [cloudwatch 0] plugin parameter log_key = '' 
INFO[0000] [cloudwatch 0] plugin parameter role_arn = '' 
INFO[0000] [cloudwatch 0] plugin parameter auto_create_group = 'true' 
INFO[0000] [cloudwatch 0] plugin parameter endpoint = '' 
INFO[0000] [cloudwatch 0] plugin parameter sts_endpoint = '' 
INFO[0000] [cloudwatch 0] plugin parameter credentials_endpoint =  
INFO[0000] [cloudwatch 0] plugin parameter log_format = '' 
[2020/09/10 06:49:53] [ info] [storage] normal synchronization mode, checksum disabled, max_chunks_up=128
[2020/09/10 06:49:53] [ info] [input:forward:forward.0] listening on 0.0.0.0:24224
[2020/09/10 06:49:53] [ info] [sp] stream processor started
```

ちょっとコンテナの中に入って

```shell
$ docker container exec -it fluent-bit bash
```

確認。

```shell
# /fluent-bit/bin/fluent-bit --version
Fluent Bit v1.5.2
```

いくつか、見慣れない設定ファイルもありますね。

```shell
# ls -l /fluent-bit/etc
total 36
-rw-r--r-- 1 root root  251 Jul 30 21:32 fluent-bit.conf
-rw-r--r-- 1 root root 4664 Jul 30 21:41 parsers.conf
-rw-r--r-- 1 root root  584 Jul 30 21:41 parsers_ambassador.conf
-rw-r--r-- 1 root root  226 Jul 30 21:41 parsers_cinder.conf
-rw-r--r-- 1 root root 2798 Jul 30 21:41 parsers_extra.conf
-rw-r--r-- 1 root root  240 Jul 30 21:41 parsers_java.conf
-rw-r--r-- 1 root root  845 Jul 30 21:41 parsers_mult.conf
-rw-r--r-- 1 root root 2954 Jul 30 21:41 parsers_openstack.conf
```

`/fluent-bit/etc/fluent-bit.conf`

```shell
[INPUT]
    Name        forward
    Listen      0.0.0.0
    Port        24224

[OUTPUT]
    Name cloudwatch
    Match   **
    region us-east-1
    log_group_name fluent-bit-cloudwatch
    log_stream_prefix from-fluent-bit-
    auto_create_group true
```

## 設定まわり

実際に使う時の設定としては、こちらのドキュメントを見ると

[FireLens構成を使用するタスク定義の作成](https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/using_firelens.html#firelens-taskdef)

これが

```json
		 {
			 "essential": true,
			 "image": "httpd",
			 "name": "app",
			 "logConfiguration": {
				 "logDriver":"awsfirelens",
				 "options": {
					"Name": "firehose",
					"region": "us-west-2",
					"delivery_stream": "my-stream"
				}
			},
			"memoryReservation": 100		
            }
```

こうなると言っているので

```shell
[OUTPUT]
    Name   firehose
    Match  app-firelens*
    region us-west-2
    delivery_stream my-stream
```

各コンテナの`logConfiguration / options`と`name`あたりがAWS FireLens側の`OUTPUT`の設定に反映されると思っていたらいいんでしょうかね？

AWS FireLensとして動作しているFluentd、Fluent Bit自体のログ出力は、自身の`logConfiguration`で決まるようですが…。

このあたりは、また試してみましょう。

`firelensConfiguration`については、こちら。

[FirelensConfiguration](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_FirelensConfiguration.html)

Fluentd、Fluent Bitの設定ファイルを追加で指定したり（`config-file-type / config-type-value`）、Amazon ECSのメタデータを含めたりするようにできるようです。

設定ファイルの追加のイメージは、`@INCLUDE`みたいです。

[Configuration File / Include File](https://docs.fluentbit.io/manual/administration/configuring-fluent-bit/configuration-file#config_include_file)