Azure IoT Edgeでモジュールログのローテーション設定

# 概要

Azure IoT Edgeでモジュールをデプロイして運用するとモジュールから発生したログをどのように管理すべきなのが悩むことがあります。もし、デフォルト設定して運用するとログファイルがドンドン巨大なファイルとなってディスク容量を圧迫することになるでしょう。
そこで、運用モードだとログファイルをローテーションすることについて整理します。

# ログドライバー確認

Dockerホストの設定や状態のうち、ログに関連する項目をフィルタリングして表示します。
デフォルトのログドライバが`json-file`となっていてログイベントをJSONオブジェクトとしてファイルに書き込むことになります。

```bash
$ docker info | grep Log
 Logging Driver: json-file
  Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
```

# モジュール確認

Azur IoT Edgeのモジュールリストを確認し、対象モジュールを変数化します。

```bash
$ iotedge list
NAME             STATUS           DESCRIPTION      Config
DevPy            running          Up 17 hours      motojin-cr.azurecr.io/devpy:latest
edgeAgent        running          Up 17 hours      mcr.microsoft.com/azureiotedge-agent:1.4
edgeHub          running          Up 17 hours      mcr.microsoft.com/azureiotedge-hub:1.4

$ MODULE_NAME="DevPy"
```

# モジュールのログ設定確認

Dockerコンテナの設定を確認するためには`docker inspect`コマンドを使用します。
ログ設定は`LogConfig`セクションに格納されています。
デフォルトで`/var/lib/docker/containers/<container-id>/`ディレクトリに各コンテナのログファイルが保存されることが分かります。
ログパスも変数化します。
ちなみに、`<container-id>`は数値になっていて64文字の長さを持つハッシュ値となります。

```bash
$ docker inspect $MODULE_NAME | grep 'LogPath'
        "LogPath": "/var/lib/docker/containers/35bc8414742252882f6893dfe3e11abcccd24e16b14162d6c254a06b0f389333/35bc8414742172882f6893dfe3e11abcccd21116b14162d6c254a33b0f3898ed-json.log",

$ LOG_PATH=$(docker inspect --format='{{.LogPath}}' ${MODULE_NAME})
```

ファイルを確認してみると現在容量がどのぐらい確保しているか確認できます。
もし、`/var/lib/docker`ディレクトリが`root`権限の領域なら`sudo`をつけて確認します。

```bash
$ ls -l /var/lib | grep docker
drwx--x--- 13 root root 4096 Jun 23 09:23 docker

$ sudo ls -l $LOG_PATH
-rw-r----- 1 root root 1135527 Jun 24 03:39 /var/lib/docker/containers/35bc8414742252882f6893dfe3e11abcccd24e16b14162d6c254a06b0f389333/35bc8414742172882f6893dfe3e11abcccd21116b14162d6c254a33b0f3898ed-json.log
```

# `Deployment Manifest`でログローテーション設定

`Deployment Manifest`ファイルはIoT Edgeデバイス上でどのモジュールを実行するか、それらのモジュールがどのように定義するJSON形式のファイルです。
Azure IoT Edgeの各モジュールはDockerコンテナとして実行されるのでログローテーションの設定はDockerの設定を用いて行います。

Dockerでは`log-opt`オプションで`max-size`と`max-file`を設定することでログのローテーションを実現できます。`max-size`は各ログファイルの最大サイズを指定し、`max-file`は保持するログファイルの数を指定します。

Azure IoT Edgeの`Deployment Manifest`ファイルに適用するには、該当モジュールの`createOptions`項目にこれらの設定を追加します。

以下に、`Deployment Manifest`ファイル`DevPy`モジュールのログを10MBごとにローテートし、5世代まで保存する設定例を示します。

```json
{
  "modulesContent": {
    "$edgeAgent": {
      "properties.desired": {
        "modules": {
          "DevPy": {
            "settings": {
              //...
              "createOptions": {
                //...
                "HostConfig": {
                  "LogConfig": {
                    "Type": "json-file",
                    "Config": {
                      "max-size": "10m",
                      "max-file": "5"
                    }
                  }
                }
            }
          },
          //...
        },
        //...
      }
    }
  }
}
```

`Deployment Manifest`ファイルからIoT Edgeデバイスにデプロイする手順については割愛します。

# ログローテーションの設定確認

`モジュールのログ設定確認`セッションで触れたようにDockerコンテナの設定を確認するためには`docker inspect`コマンドを使用します。

DockerのinspectコマンドはJSON形式で出力されますので、jqというコマンドラインJSONパーサーを使って LogConfigセクションだけを抽出することができます。

```bash
$ sudo apt install -y jq
$ docker inspect $MODULE_NAME | jq '.[] | .HostConfig.LogConfig'
{
  "Type": "json-file",
  "Config": {
    "max-file": "5",
    "max-size": "10m"
  }
}
```

もし、jqコマンドを使えない環境なら、`docker inspect`コマンドでも抽出できます。

```bash
$ docker inspect --format='{{.HostConfig.LogConfig}}' $MODULE_NAME
{json-file map[max-file:5 max-size:10m]}
```

# ログローテーションファイル確認

モジュールから頻繁にログ出力しておかないと10MB容量を超えるまで時間かかると思いますが、
しばらく時間がたつと下記のようなログファイルの世代を確認することができます。

そして64文字の長さを持つハッシュ値のコンテナーIDも変わることもあるので、再度取得して確認します。

```bash
$ LOG_PATH=$(docker inspect --format='{{.LogPath}}' $MODULE_NAME)
$ CONTAINER_ID=${LOG_PATH#/var/lib/docker/containers/}
$ CONTAINER_ID=${CONTAINER_ID%%/*}
$ sudo ls -l /var/lib/docker/containers/${CONTAINER_ID} | grep log
-rw-r----- 1 root root  7027461 Jun 24 04:54 35bc8414742252882f6893dfe3e11abcccd24e16b14162d6c254a06b0f389333-json.log
-rw-r----- 1 root root 10000086 Jun 24 03:36 35bc8414742252882f6893dfe3e11abcccd24e16b14162d6c254a06b0f389333-json.log.1
```

まだ5世代分のファイルを確認するにはできなかったですが、10MBごとにファイルがローテーションされていることが確認できました。