こんにちは。SREのid:do-su-0805です。普段はid:do_su_0805として生活しています。
この記事では、Amazon ECS(以下、ECS)でコンテナを動かすとき、ログドライバーとしてawslogs
を利用してAmazon CloudWatch Logs(以下、CloudWatch Logs)にログを出力する際に、awslogs-stream-prefix
というパラメータには何を設定するとよいかについて考察します。
結論から言うと、このパラメータに「コンテナのイメージタグ」を入れるようにしたところ、出力されるログストリームの/
区切りの階層が見やすくなり、ログが世代別に扱いやすくなったよ、というお話です。
- ECS+CloudWatch Logs構成時のロググループとログストリームについて
- どのようなログストリームが構成されがちかを事例から考えてみる
- awslogs-stream-prefixにイメージタグを入れるとログストリームが整理できる
- この記事のまとめ
ECS+CloudWatch Logs構成時のロググループとログストリームについて
ECSのドキュメント「awslogs ログドライバーを使用する」に詳しく記載されていますが、awslogs
ログドライバーを利用してCloudWatch Logsにログを出力する際に、ロググループおよびログストリームの形式は以下のようになります。
- ロググループ: 指定したロググループ
- ログストリーム:
${prefix-name}/${container-name}/${ecs-task-id}
ログストリームのそれぞれは次の通りです。
prefix-name
:awslogs-stream-prefix
オプションで指定*1container-name
: タスク定義内で定義しているコンテナ名ecs-task-id
: ECS側で決定されたタスクのID
以上がつながって1つのログストリームを指し示すということは、可視性の高いログストリームを設計するには「ロググループの名前」「awslogs-stream-prefix
」「コンテナ名」を決める際に、この事実を意識しておく必要があります。
なぜなら、awslogs-stream-prefix
以外の2つは、ログ出力をする設定以外の場所で命名が行われるからです。
どのようなログストリームが構成されがちかを事例から考えてみる
ここで事例として、以下のような状況を想定してみます。
- 1つのAWSアカウントで、各コンポーネントをprefixで区別することで、production環境とstaging環境を用意する
- ただし、ECSタスクの中で動くコンテナについては、既にサービスレベルで分離されていることからprefixは付けない
- ECSサービスでは、1種類のタスクが動作し、2タスク起動する
- サービス単位でロググループを共有する
- ECSタスク内では、次の2つのコンテナが動作する
- アプリケーション
- サイドカーとして監視用のAgent
この場合、前提として「prefixで区別する」ことを意識しながら作成していくと、以下のような構成になるかなと思います(細かい差はあると思いますが概念としてお読みください)。
項目 | 設定 |
---|---|
ECSサービス | Hoge-production |
ロググループ | Hoge-production-logs |
コンテナ名 | app もしくはmonitor |
awslogs-stream-prefix |
Hoge-production |
特にawslogs-stream-prefix
は「結局どこに入るのか?」を意識しないと、上記のようにECSサービスの名前や、利用するコンテナの名前、あるいはecs
などと入れがちかなぁと思います。
この構成でapp
コンテナおよびmonitor
コンテナからCloudWatch Logsに送られるログストリームは、以下のようになります。
app
コンテナのとき:Hoge-production-logs:Hoge-production/app/${ecs-task-id}
monitor
コンテナのとき:Hoge-production-logs:Hoge-production/monitor/${ecs-task-id}
いかがでしょうか? Hoge-production
が即座に2回登場し、目が滑り、かつ冗長であることがわかります。
言い換えると、awslogs-strema-prefix
が情報の区切りとして機能していないことが分かります。今回は、この観点から整理を進めてみます。
awslogs-stream-prefixにイメージタグを入れるとログストリームが整理できる
先ほど想定した事例では、ログストリームが次のようになりました。
Hoge-production-logs:Hoge-production/(app|monitor)/${ecs-task-id}
この全体を、それぞれの項目から得られる情報を指し示す日本語で書き換えると、次のようになります。
ロググループ名(サービス名を含む):サービス名/コンテナ名/タスクID
このように「サービス名」をawslogs-stream-prefix
に入れてしまったため、情報が全く増えていません。何かもったいない気がします。それでは「何が入ると嬉しいかなぁ?」と考えてみたところ、アプリケーションの世代が分かると、情報の区分がさらに増せるなと気づきました。
そこで、当該タスクが利用するコンテナイメージのイメージタグを入れてみました(ただし、イメージ利用時にmaster
stable
latest
などと書いている場合は特に意味がない状況が続きます。固有のビルドタグなどが入ったユニークなものを指すタグを利用する場合のみ効果を発揮します)。
変更の前後で、先ほどの「得られる情報を指し示す日本語」を比較してみます。
- before:
ロググループ名(サービス名を含む):サービス名/コンテナ名/タスクID
- after:
ロググループ名(サービス名を含む):イメージタグ/コンテナ名/タスクID
いかがでしょうか? 「サービス」「イメージ」「コンテナ」「タスク」と情報の要素が階層的に整理されたように見えます。
ECSのタスクIDはタスク自体に紐づくため、今回の場合はapp
とmonitor
それぞれ同じタスクIDが発番されるわけですが、それでも
- このタスクのログを調べたい
- このイメージで起動した
app
もしくはmonitor
のログを調べたい
という2つのケースには対応できるようになり、ログの利用や解析がしやすくなったのではないでしょうか。
このようにawslogs-stream-prefix
にイメージタグを入れることで、世代別のログを見ることができるようになり、たいへん便利になったと思っています。
この記事のまとめ
この記事では次の内容を紹介しました。
awslogs
ログドライバーを利用したECS+CloudWatch Logs構成時は「ログ出力をする設定以外の場所で命名が行われる」コンポーネント名が、ログストリームに影響するawslogs-stream-prefix
(prefix-name
)にコンテナのイメージタグを入れると、情報の整理が進む
はてなでは、情報の整理を進める仲間を募集しています。
*1:EC2起動タイプの場合はオプションで、指定しないとDockerデーモンが割り振ったコンテナIDになる。Fargate起動タイプでは指定が必須
id:do-su-0805
Akira Sudo。2018年9月入社。システムプラットフォーム部でSREを務める。普段使いのはてなIDは id:do_su_0805。はてなで働くエンジニアにアンケートの「頑張らなくていいチームだからこそ自分の強みを増やしていきたい」も参照。
Twitter: @do_su_0805
GitHub: do-su-0805
blog: do_su_0805’s blog