kurosame’s diary

フロントエンドが得意です

レガシーな CoffeeScript で書かれた hubot に Datadog 監視を導入する

CoffeeScript で書かれた hubot が ECS + Fargate 上で稼働中なのですが、これに Datadog の監視を入れてみます

ChatWork 経由で hubot に命令しているのですが、ChatWork のメンテナンス等があるとメンテナンス後も hubot がエラーで落ちたままになったことがあったので、hubot を監視して異常があれば、Slack に通知する機能作ります

コンテナーのメトリクスを取得

Datadog Agent をインストール

まずは、Datadog 管理画面の Integrations から Amazon Fargate をインストール

次はホストに Datadog Agent をインストールします
ECS + Fargate の場合は、Datadog Agent のコンテナーを作成し、ECS のタスク定義内で設定します

今回は AWS コンソール上から作業します

タスク定義の新しいリビジョンを作成します

コンテナーの追加をクリックして、以下の内容を設定します

項目名 設定値
コンテナー名 datadog-agent
イメージ datadog/agent:latest
環境変数 Key=DD_API_KEY, Value=Datadog の API Key
環境変数 Key=ECS_FARGATE, Value=true

Datadog のドキュメントでは、メモリ制限 (MiB)や CPU ユニット数も細かく指定しています

ただし、AWS の開発ガイドを見てみると、コンテナーのメモリはオプションで、 「ほとんどのユースケースでは、タスクレベルでこれらのリソースを指定するだけで十分です。」 って書いてあるので、今回は設定しませんでした
https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/AWS_Fargate.html

CPU ユニット数も 1vCPU なら 1024CPU ユニット以内の数値であれば、設定できますが、Fargate の場合は、こちらもオプションだったので、設定しませんでした

この辺は使いながら、調整しようと思います

タスク定義更新後は、ECS のサービスをタスク定義の新しいリビジョンを使うように更新します

IAM ポリシーの設定

Datadog の Amazon Web Services Integration に設定しているロールのポリシーに以下の権限を追加します

  • ecs:ListClusters
  • ecs:ListContainerInstances
  • ecs:DescribeContainerInstances

確認

Datadog の管理画面からInfrastructure -> Containersに移動し、アプリケーションの CPU やメモリ等のメトリクス情報が取得できていたら成功です

hubot のプロセス監視

先ほど作成したdatadog-agentコンテナーの環境変数に以下を追加すれば、プロセス情報の収集ができるようになります

Key Value
DD_PROCESS_AGENT_ENABLED true

Datadog の管理画面からInfrastructure -> Processesに移動し、プロセス情報が取れていたら成功です

ただ、今回は有用な情報は取れませんでした

hubot コンテナーのログ監視

色々調べたのですが、hubot が CoffeeScript というレガシーな言語を使っているという縛りもあり、アプリ側から何か仕込むことが難しかったので、結局コンテナー内のログを全部 Datadog へ飛ばすことにしました

ログドライバーを FireLens に変更

FireLens は ECS で使えるログルーターであり、ログの出力先をルーティングできます
ここでは FireLens から Fluent Bit にログを転送し、Fluent Bit が Datadog をサポートしているので、Fluent Bit から Datadog にログを転送します

hubot が動いている方のコンテナーのログドライバーをawsfirelensに設定し、以下の Key/Value を設定します

Key Value
Name datadog
Host http-intake.logs.datadoghq.com
TLS on
apikey Datadog の API Key
dd_service 対象のサービス名
dd_source 対象のミドルウェア
provider ecs

上記で保存すると、log_routerというコンテナー名でaws-for-fluent-bitイメージのコンテナーがタスク定義内に追加されます
これを独自の Fluentd や Fluent Bit イメージを使うように書き換えることもできます

この Fluent Bit を使って Datadog にログを転送します

他のやり方として、awslogsログドライバーでも Lambda を使って、Datadog にログを転送するやり方もありますが、Datadog では FireLens を使ったやり方を推奨しているみたいです

確認

Datadog の管理画面からLogsに移動し、ログが出力されていたら成功です

Slack 通知

Datadog の Integrations から Slack を追加し、Webhook URL と通知先の Channel 名を設定しておきます

Datadog 管理画面のMonitors -> New Monitor -> Logsに移動します

hubot から ChatWork に対してポーリングしているので、hubot と ChatWork 間でエラーが発生しているとエラーログを出力し続けます
ポーリングの回数は環境変数の HUBOT_CHATWORK_API_RATE の設定値によって変動しますが、とりあえず以下のように直近 15 分で 20 件より多くのログが出力されたら、Slack へ通知するようにしました

logs("service:hubot").index("*").rollup("count").last("15m") > 20

これで上手くいかなかったら、また考えます

追記 - 2020/11/13
ログの Facet を追加して、以下のように 500 系のエラーが出た場合に通知するように変更した

logs("service:stg-hubot @log:(*ERROR* *Chatwork* *50*)").index("*").rollup("count").last("15m") > 0

参考

https://docs.datadoghq.com/integrations/ecs_fargate/?tab=fluentbitandfirelens