AWS ECS FargateのFireLensでConfigurationファイルを読み込む

# 概要
AWS Firelensを利用する際に、カスタマイズした [Fluentbit Configurationファイル](https://fluentbit.io/documentation/0.12/configuration/file.html) （以下、confファイル）をロードしたい時がある。
このconfファイルロードの方法がやや分かりづらかったので、備忘録的にまとめた。
なお、本記事はFluentbit想定で記述しているが、Fluentdを利用する場合も同様のはずである。

# ロード方法
いくつかの項目の設定が必要なので、項目ごとに説明する。

## 1. Fluentbit コンテナの `firelensConfiguration` を設定
ECS Fargateを用いる場合、S3からconfファイルをロードする方法は利用できない（2020/1 現在。）
このため、Fluentbit コンテナ内に配置した conf ファイルを直接ロードする方法をとる。
このためには、 `containerDefinitions` に下記の記述を追加すれば良い。

```json
            "firelensConfiguration": {
                "type": "fluentbit",
                "options": {
                    "config-file-type": "file",
                    "config-file-value": "/fluent_conf/custom.conf"
                }
            },
```

なお、 `/fluent_conf/custom.conf` には後の手順でファイルを配置する設定をする。
また、この設定は現状マネジメントコンソールのGUIで設定することはできないため、 `タスク定義` 画面の`JSONで設定` から設定すること。

この設定をすることで、 Fluentbit が実際に利用するconfファイルは、下記のようになる。
`@INCLUDE` で指定したファイルが注入されていることがわかる。

```
[INPUT]
    Name forward
    unix_path /var/run/fluent.sock

[INPUT]
    Name forward
    Listen 127.0.0.1
    Port 24224

[INPUT]
    Name tcp
    Tag firelens-healthcheck
    Listen 127.0.0.1
    Port 8877

[FILTER]
    Name record_modifier
    Match *
    Record ec2_instance_id i-0073fe00
    Record ecs_cluster ec2-sandbox
    Record ecs_task_arn arn:aws:ecs:ap-northeast-1:
    Record ecs_task_definition api-on-ec2:8

# ここより上の部分はFireLensのデフォルト設定

# ここでcustom configurationが注入されている
@INCLUDE /fluent_conf/custom.conf

[OUTPUT]
    Name null
    Match firelens-healthcheck

[OUTPUT]
    # ここはメインコンテナのFireLens設定に記述した通りになる
    Name null
```

なお、ECS on EC2を利用する場合は、素直にS3からファイルをロードするのが楽だと思われる。

## 2. メインコンテナとの共有ボリュームを作成する
confファイルはFluentbitコンテナ内に配置する必要があるが、これをメインコンテナ側から注入する形にしたい。
この方法には、下記のメリットがある:

* Fluentbitコンテナを修正することなく、公式イメージのまま利用できる
* メインコンテナ側アプリケーションコードと同一のリポジトリでconfファイルもバージョン管理できる

これは、メインコンテナのconfファイルを配置したフォルダを共有ボリュームとしてFluentbitコンテナから参照させることで実現できる。

`タスク定義` コンソールで下記の設定をすれば良い:

1.  共有ボリュームの作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127392/57e608c4-f24e-7c8a-c041-8a56c56975c8.png)
2. メインコンテナ側で共有ボリュームにフォルダをマウント
  * メインコンテナの `/app/fluent_conf/custom.conf` に利用するconfファイルが配置されている想定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127392/8b395caf-01f2-b136-ed2d-50ea59fc9cc6.png)
3. Fluentbitコンテナ側で共有ボリュームを読み取り専用でマウント
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127392/6d681dbc-2c22-c3d4-82eb-5fa05a2aa4a6.png)

上記の設定をすることで、 Fluentbitコンテナでは `/fluent_conf/custom.conf` にconfファイルが配置された状態になる。

## 3. コンテナ初期化の順序関係を定義する
Fluentbitコンテナは、共有ボリュームにマウントが完了した状態で起動する必要がある。
（マウントが完了していない場合、 Fluentbitの初期化時に `custom.conf` が見つからないためエラーが発生する。）
このため、Fluentbitコンテナの `スタートアップ依存順序` 設定で、メインコンテナがSTART状態である依存を追加する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127392/ecb49cfa-7ae2-1ae8-7736-384995243efe.png)

これで必要な設定は完了した。


(2020/09追記)
Fargate 1.4.0ではFirelensコンテナは全ての他のコンテナが起動する前に起動するよう、暗黙の依存関係が追加されている。
このため、この依存関係を設定すると、永遠にコンテナが起動しなくなる。 [参考](https://github.com/aws/containers-roadmap/issues/1070
)
このため、Custom configurationファイルは、独自のFluentbit Dockerイメージを定義して、その中に埋め込む方法が推奨される。



# 参考情報
* https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/using_firelens.html#firelens-taskdef