CUEBiC TEC BLOG

キュービックTECチームの技術ネタを投稿しております。

EC2上で動かしていたDatadog監視をECSクラスター上に構築してみました

概要

こんにちは、キュービックでSREをやっているYuhta28です。キュービック内のテック技術について発信します。
前回の記事で弊社のモニタリング運用をDatadogに集約したことを紹介しました。OpenSearch時代に活用していた集約サーバーのFluentdの設定ファイルをDatadogに向き先を変えて、さらにDatadogエージェントをインストールして、集約サーバーから弊社メディアへの外形監視とDBのパフォーマンスモニタリングを実施しています。

アーキテクチャ

アーキテクチャ

課題

ただ単なる集約サーバーだったものにDatadogエージェントを導入して、外形監視も担うとなるとサーバー運用が必要となり、負荷が生じてきました。
そこでEC2ではなく、ECSに移行してDatadogモニタリングクラスターを構築してみることにしました。

アーキテクチャ

アーキテクチャ

FargateのアーキテクチャはFluentdのECSサービスとDatadogのECSサービスを組み合わせたクラスタ構成になります。

Fluentdコンテナ構築

図では省略していますが、FluentdのECSに転送する際にメディアサーバー群とFargateの間にNLBを置いています。これによってIPアドレス単位で集約先を指定したものをNLBのドメイン単位で宛先を指定することが可能になります。

# fluentd設定ファイル(メディアサーバー側)
<source>
  @type tail
  path /var/log/nginx/access.log
  format ltsv
  time_format %d/%b/%Y:%H:%M:%S %z
  types size:integer,status:integer,upstream_response_time:float,time:time,response_time:float
  tag nginx
</source>
<match nginx>
  @type forward
  <server>
#    host XXX.XXX.XXX.XXX  #IPアドレス
    host XXXXXXXXXXXXXXX.elb.ap-northeast-1.amazonaws.com
    port XXXXXXX
  </server>
</match>
# fluentd設定ファイル(fluentd ECS側)
<source>
  @type forward
  port 24224
  bind 0.0.0.0
</source>

<match nginx>
  @type copy
  <store>
    @type datadog
    @id nginx-access
    api_key "#{ENV['ddapikey']}"  #fluentd設定ファイル内の環境変数設定

    include_tag_key true
    tag_key @log_name

    dd_source 'nginx'
    service   'access-log'
  </store>
</match>

幸いなことにFluentdのDockerイメージは公式がDocker Hubに用意していました。後は先のfluentd設定ファイルをコンテナにコピーするDockerfileを書いてECSにデプロイします。

# Fluentdコンテナ
FROM fluent/fluentd:v1.15.3-debian-1.0
USER root

RUN buildDeps="sudo make gcc g++ libc-dev" \
    && apt-get update && apt-get upgrade -y \
    && apt-get install -y --no-install-recommends $buildDeps \
    && sudo gem install fluent-plugin-datadog \
    && sudo gem sources --clear-all \
    && SUDO_FORCE_REMOVE=yes \
       apt-get  purge -y --auto-remove \
               -o APT::AutoRemove::RecommendsImportant=false \
               $buildDeps \
    && rm -rf /var/lib/apt/lists/* \
    && rm -rf /tmp/* /var/tmp/* /usr/lib/ruby/gems/*/cache/*.gem

COPY  fluentd/etc/fluent.conf /fluentd/etc/

USER fluent

ちなみにFluentdの設定ファイルにDatadogのAPIキーを埋め込む場合、ECSタスク定義から環境変数を設定しますが、認証情報系は直打ちせずにSecrets Manager*1やSystems Managerのパラメータストア*2から呼び出すようにしておいたほうが安全です。

"secrets": [
    {
        "name": "ddapikey",
        "valueFrom": "arn:aws:ssm:ap-northeast-1:XXXXXXXXXXXX:parameter/datadog/apikey"
    }
]

Datadogエージェントコンテナ構築

Datadogエージェントも公式がコンテナイメージを配布しているので、必要な環境変数をセットしてECSサービスに組み込みました。

# Datadogエージェントコンテナ
FROM public.ecr.aws/datadog/agent:latest

USER dd-agent
RUN mkdir /etc/datadog-agent/secrets

# HTTPチェック設定ファイル配置
COPY etc/datadog-agent/conf.d/http_check.d/conf.yaml /etc/datadog-agent/conf.d/http_check.d/conf.yaml

# DB Application Performance Monitoring設定ファイル&DBパスワード情報配置(db_password情報は暗号化)
COPY etc/datadog-agent/conf.d/mysql.d/conf.yaml /etc/datadog-agent/conf.d/mysql.d/conf.yaml
COPY etc/datadog-agent/secrets/db_password /etc/datadog-agent/secrets/db_password

http_check.d/conf.yamlの中に監視したいメディアの情報を記載しています。

# コーポレートサイト
  - name: cuebic website
    url: https://cuebic.co.jp/
    timeout: 5
    tags:
        - "env:prd"

実は当初DatadogエージェントのコンテナはApp Runner*3を使って実装してみようと思いました。App RunnerならECRにコンテナイメージをセットして指定するだけで自動デプロイの実装までマネージドにやってくれるので、新規メディアへの外形監視作業も先述のHTTPチェックの設定ファイルを更新し、ECRにプッシュするだけで自動的に監視されて運用が楽になるからだと考えました。
ところがApp RunnerではDatadogエージェントのようなコンテナからのプッシュ型通信とは相性が悪くうまくいかないことが判明しました。このあたりの詳細はこちらのブログを御覧ください。 zenn.dev

妥協案としては自前でGitHub Actions☓ECSの自動デプロイ基盤を実装することで解決しました。ECSへデプロイしてくれるGitHub Actionsワークフローファイルは公式が用意してくれているのでそちらを活用します。*4

GitHub Actions☓ECS自動デプロイアーキテクチャ

デプロイアーキテクチャ

これでHTTPチェック設定ファイルに新規メディア情報を記載してGitHubリポジトリにプッシュすることでGitHub Actionsが起動し、リポジトリ内のDockerfileをビルド、プッシュしてECRに格納されます。その後ECRのイメージを基にFargateへデプロイすることでECSによるDatadogモニタリングクラスタ基盤が構築できます。

所感

EC2上で動かしていたDatadog監視をECSへ移行できました。ガッツリとECSクラスタをイチから構築するのは今回が初めてで、セキュリティ設定ミスやネットワーク設定の不備など不慣れから生じるミスが多かったですが、最終的に実現したいことができてよかったと思います。App Runnerを使った挑戦は残念ながらできませんでしたが、違う機会で再挑戦してみようと思います。