📝

【Datadog】APM導入とコストの最適化

2023/10/30に公開

株式会社オープンエイト インフラ基盤グループの水谷です。
当記事では、先日Datadogを試験導入した際の内容についてお話しいたします。

前提と背景

一口にAPMといっても、現代では様々なツールが存在します。
以前はNew Relicを使用していましたが、下記のような課題感がありました。

  • アカウント(利用ユーザー)単位での課金のため、気軽にアカウントを増やせない。
  • ユーザーを追加すると、1人あたり年間費用が50万円程増える
  • コストの観点で、全エンジニアがAPMを利用できるようにするのは難しい。
  • 取り込みデータ量が年間での契約のため、超過した際の制約が重たい。

よって、利用人数に縛られないDatadogが候補として上がりました。

New RelicとDatadogの大まかな料金体系は、下記のようになります。
※2023/10現在のものです。

サービス 料金体系
New Relic ・基本的には年間契約。
・アカウント単位での固定課金。
・契約時に年間の取り込みデータ量を指定して契約。
・契約分のデータ量を超過した場合、データ取り込みを停止するか
 年間契約を更新する必要がある。
Datadog ・Datadog Agentが起動しているホスト(サーバー)単位での課金。
・ホスト単位で毎月一定量(GB単位)までのデータ取り込みが基本料金に含まれる。
 超過分は追加料金。
・利用機能に応じた追加課金。

アプリケーションチームからの要望としては、下記の内容があがりました。

  • Datadog APMを利用したい
  • 全エンジニアがAPMを利用できるようにしたい
  • できるだけコストを抑えたい
  • 全てのサーバー(コンテナ)を監視する必要はない

上記内容を踏まえて調査を行い、導入を進めることにしました。

インフラ環境について

弊社サービスは、Amazon Web Services(以下:AWS)・Oracle Cloud Infrastructure(以下:OCI)を活用したコンテナ環境で構築されています。
AWS環境はECS on EC2構成、OCI環境はkubernetesを利用しています。
インフラ環境の詳細については、2023年9月に弊社神山が記事を執筆しているため、
ぜひそちらもご一読ください。
https://zenn.dev/open8/articles/84e4bb88a343fa

基本方針

Datadog AgentのDockerイメージが公開されていたので、AWS環境ではこのイメージを使用してコンテナを起動することにしました。
また、OCI環境はkubernetesを利用しているため、helmを用いて導入することにしました。

Datadogの料金体系はホスト(サーバー)単位での課金のため、全サーバーをエージェントで監視するのではなく、必要なサーバーを選定し導入を行うことにしました。
よって、監視したいECSクラスター・k8sクラスターにDatadog Agentのコンテナを1台のみ配置することにしました。

AWS環境への導入

弊社AWS環境はCloudFormationによるIaCで構築されているため、
指定したECSクラスターにサービスを追加するCloudFormationを作成し、
監視対象のECSクラスターに、Datadog Agentのコンテナをレプリカモードで1台ずつ配置しました。
※見やすいように要約しております。

datadog-replica-ecs-service.yaml
Parameters:
  Env:
    Type: "String"
    Default: "dev"
  ImageURI:
    Type: "String"
    Default: "public.ecr.aws/datadog/agent:latest"
  ContainerName:
    Type: "String"
    Default: "container-datadog"
  ContainerCPU:
    Type: "Number"
    Default: "0"
  ContainerMem:
    Type: "Number"
    Default: "256"
  ServiceName:
    Type: "String"
    Default: "datadog"
  EcsCluster:
    Type: "String"
    Default: "arn:aws:ecs:ap-northeast-1:xxxxxxxxxx:cluster/xxx-xxx-cluster"
  DatadogApiKey:
    Type: "String"
    Default: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    NoEcho: true
  DatadogSite:
    Type: "String"
    Default: "ap1.datadoghq.com"

Resources:
  TaskDefinition:
    Type: "AWS::ECS::TaskDefinition"
    Properties:
      ContainerDefinitions:
        - Name: !Sub "${Env}-${ContainerName}"
          Image: !Ref "ImageURI"
          Cpu: !Ref "ContainerCPU"
          memoryReservation: !Ref "ContainerMem"
          PortMappings:
            - ContainerPort: "8125"
              HostPort: "8125"
            - ContainerPort: "8126"
              HostPort: "8126"
          Essential: "true"
          Environment:
            - Name: "DD_API_KEY"
              Value: !Ref "DatadogApiKey"
            - Name: "DD_SITE"
              Value: !Ref "DatadogSite"
      Volumes:
        - Host:
            SourcePath: "/var/run/docker.sock"
          Name: "docker_sock"

  EcsService:
    Type: "AWS::ECS::Service"
    Properties:
      ServiceName: !Sub "${Env}-${ServiceName}-service"
      Cluster: !Ref "EcsCluster"
      TaskDefinition: !Ref "TaskDefinition"
      LaunchType: "EC2"
      SchedulingStrategy: "REPLICA"
      DesiredCount: "1"
      PlacementConstraints:
        - Type: "distinctInstance"
      DeploymentController:
        Type: "ECS"

OCI環境への導入

前述した通り、OCI環境への導入はhelmを利用することにしました。
helmコマンドを用いてDatadog Agentのpodを起動したところ、
k8sクラスターの全ノードに1台ずつpodが起動しました。

OCI環境には多くのリソースを必要とするシステムが構築されており、サーバーの台数も多いです。
このままでは全ノード(サーバー)分の料金がかかってしまい、コストが上がってしまいます。

そこで、Datadog Agentのpodを1台にするために、
k8sの機能であるnodeAffinityを活用することにしました。
https://kubernetes.io/ja/docs/tasks/configure-pod-container/assign-pods-nodes-using-node-affinity/

nodeAffinityは特定のノードに対してpodを割り当てることができるため、
あらかじめノードにラベルを付けておき、特定のラベルが付いたノードのみにDatadog Agentが起動するように設定を追加しました。
※見やすいように要約しております。

datadog-values.yaml
datadog:
  apiKeyExistingSecret: datadog-secret
  appKeyExistingSecret: datadog-secret
  site: ap1.datadoghq.com
agents:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
          - matchExpressions:
              - key: label-name
                operator: In
                values:
                  - label-value

おわりに

DatadogにはAPMの他にもログ管理・トラフィック監視・アラート通知など様々な機能があります。
弊社では現状APMのみの利用のため全サーバーを監視対象にはしていませんが、
一般的にDatadogを導入する際は全サーバーを対象にすることが多いかと思います。

今回の内容は少しカスタマイズした利用方法ですが、コストを抑えつつ、
社内エンジニアのニーズに応えることができました。

当記事の一部だけでも、どなたかの参考になれば幸いです。

OPEN8 テックブログ

Discussion