【Datadog】APM導入とコストの最適化
株式会社オープンエイト インフラ基盤グループの水谷です。
当記事では、先日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月に弊社神山が記事を執筆しているため、
ぜひそちらもご一読ください。
基本方針
Datadog AgentのDockerイメージが公開されていたので、AWS環境ではこのイメージを使用してコンテナを起動することにしました。
また、OCI環境はkubernetesを利用しているため、helmを用いて導入することにしました。
Datadogの料金体系はホスト(サーバー)単位での課金のため、全サーバーをエージェントで監視するのではなく、必要なサーバーを選定し導入を行うことにしました。
よって、監視したいECSクラスター・k8sクラスターにDatadog Agentのコンテナを1台のみ配置することにしました。
AWS環境への導入
弊社AWS環境はCloudFormationによるIaCで構築されているため、
指定したECSクラスターにサービスを追加するCloudFormationを作成し、
監視対象のECSクラスターに、Datadog Agentのコンテナをレプリカモードで1台ずつ配置しました。
※見やすいように要約しております。
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
を活用することにしました。
nodeAffinity
は特定のノードに対してpodを割り当てることができるため、
あらかじめノードにラベルを付けておき、特定のラベルが付いたノードのみにDatadog Agentが起動するように設定を追加しました。
※見やすいように要約しております。
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を導入する際は全サーバーを対象にすることが多いかと思います。
今回の内容は少しカスタマイズした利用方法ですが、コストを抑えつつ、
社内エンジニアのニーズに応えることができました。
当記事の一部だけでも、どなたかの参考になれば幸いです。
株式会社オープンエイトのテックブログです!カジュアル面談大歓迎ですー!エンジニア積極採用中 👉 open.talentio.com/r/1/c/open8/homes/3396
Discussion