はじめに
こんにちは!コンテナ基盤グループの楠本です。
今回はマルチテナント運用におけるKubernetesクラスタ内のコスト把握方法についてご紹介します。
見どころは
- EKSでKubecostを使ってみたがうまくいかなかったこと
- OpenCostを導入して解消したこと
- Datadogを使ってマルチクラウドのKubernetesを把握できるようにしたこと
の3点です。
- はじめに
- 結果:OpenCost・Datadogを使って出来たもの
- EKSにKubecostを試験導入してみた
- Kubecostに躓いた
- OpenCostでリトライ
- 可視化をして得られたこと
- 注意しておくこと
- まとめ
結果:OpenCost・Datadogを使って出来たもの

EKSにKubecostを試験導入してみた
スプレッドシートで頑張っていた頃
前回の記事で、EKS on FargateからKarpenterを使ったEKS on EC2について紹介しました。
tech-blog.monotaro.com
KubecostはFargateをサポートしていないため、EC2である必要がありました。
この条件があったため、Fargateで運用していた頃は把握したかったのですが把握ができず…
とはいえプロダクトとして「いくらかかるの?」を知っておくのは当たり前のこと
なので、スプレッドシートで簡易的な試算を出し、スケールアウトによって発生するプラスの部分はある程度実績値から補うという運用を行っていました。

EC2にかわって出番が回ってきた
Fargateは管理が不要な分、言い換えると「管理ができない」ということでもあると思います。
どういうインスタンスを使っているのか、そのインスタンスの利用金額はいくらなのか
自分たちで管理を行うようにした分、そういった把握ができるようになります。
EC2にしたことでようやく出番が回ってきたというところで
まずは開発環境にKubecostを導入してみました。Freeプランを利用しました。
以下にいくつか考えておくポイントについてご紹介します。
過去分は取得できない
Kubecostを導入してから収集を開始するので、もちろん過去分については取得することはできません。
EBSボリュームの管理
Kubecostは、Persistent Volumeを利用します。これはPrometheusが収集したメトリクスデータが保管されます。
デフォルトのData Retentionは15 Daysとなっているため、そのままで運用する場合は、少なくとも15日分は保管できるだけの容量にしておくほうがよいでしょう。
ただ15日のため、月額コストを把握したいといった場合には期間が足りません。
Helmのvaluesの設定になりますが、Persistent Volumeに必要な期間分残すようにするにはprometheus.server.retention を上書きするようにすれば期間を伸ばすことが可能です。
そのかわりData Retentionが長くなるのでボリュームのサイズも調整が必要です。
デフォルトは32Giです。
valuesの各パラメータについてはこちらを参照ください。
また、デフォルトのメトリクスを使ってボリュームの使用量を把握することもできます。
kubernetes.kubelet.volume.stats.used_bytes kubernetes.kubelet.volume.stats.capacity_bytes kubernetes.kubelet.volume.stats.inodes ...
後述しますが、私達はボリュームに残しておくパターンではなく、メトリクスをDatadogに送るようにしたためData Retentionも短くかつKubecost専用のGUIもオフにしました。
EBSボリュームタイプ
デフォルトでは gp2 が設定されます。
できれば費用対効果を考え、gp3にしたいのですがいくつか設定が必要でした。
1.Prometheus側のannotationsに以下を設定する
helmで上書きするvalues
persistentVolume:
enabled: true
# storageClass: "-" # https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/ebs-csi-migration-faq.html
annotations: {
"ebs.csi.aws.com/volumeType": "gp3"
}
...
2.EBS CSI ドライバーに以下を設定する(参考)
aws-ebs-csi-driverの高度な設定に以下を追加します。 Amazon EBSが推奨するデフォルトのストレージクラスが使えるようにdefaultStorageClassもtrueにしています。
{"controller":{"volumeModificationFeature":{"enabled":true}}, "defaultStorageClass":{"enabled":true}}
terraformのコード
aws_ebs_csi_driver_addon_config = jsonencode({
controller = {
volumeModificationFeature = {
enabled = true
}
},
defaultStorageClass = {
enabled = true
}
})
レポート出力
Kubecostでは、csv/pdf出力やSlackへコストアラートを送信することができます。 ただ、Datadogで参照することにしたため、こちらの機能は使いませんでした。
インスタンスの割引率
なるべく厳密にコスト把握できるようにするにはawsのキー、シークレットアクセスキーなどが必要になります。
ここは特に指定せずに進めました。指定しない場合はオンデマンドでの計算となります。
Kubecostに躓いた
dev環境・stg環境や他のクラスタと増やしていく中で、突然KubecostのPodが立ち上がらない状況が発生しました。
調査してみると
$ curl localhost:9004/healthz Current core count of 327 is greater than maximum of 250 for non-enterprise license. Contact us at team@kubecost.com to learn more.
FreeプランのCore数の上限250をこえてしまったことが原因でした…
コストに対するモチベーション
細かいコストが把握できるのが望ましいのですが、AWSアカウントでもEKSの利用料金、EC2の利用料金はわかります。
クラスタ内の細かいコスト把握は、マルチテナントで運用しているがゆえというところもあり、コスト把握のためにEnterpriseプランでとなると、実現したいことに対しての負担が大きいと感じました。(予算やツールを使うための社内調整という意味でも)
感触としてはすごく良かったのですが、Kubecostについての本格導入は中断し、見送ることにしました。
OpenCostでリトライ
Kubecost社はKubecostだけでなくOSSのOpenCostも開発してくださっています。 AWSのドキュメントからKubecostを導入してみたのですが、OpenCostでリトライすることにしました。
必要なものはOpenCostとPrometheus
OpenCostだけではメトリクスを収集することはできず、別途Prometheusが必要となります。
KubecostはPrometheusも同梱されているため特に意識することはなかったのですが、OpenCostで実施する場合はそれぞれインストールしていく必要があります。
導入詳細は公式ドキュメントを参照ください。
OpencostもPrometheusどちらもHelmでインストールが可能なので、それぞれのChartを指定し、導入することにしました。
Prometheus
prometheus-node-exporterがDaemonsetとして各ノードに配置されます。
prometheus-serverが各node-exporterからメトリクスを収集してくれます。

Karpenterを利用している場合は、ベストプラクティスとしてKarpenterはFargateノードで運用するのを推奨しています。
そのため、FargateノードとEC2ノードの両方が混在したクラスタとなっているためaffinityを使って、Fargateノードには入らないようにしました。
prometheus-node-exporter:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: eks.amazonaws.com/compute-type
operator: NotIn
values:
- fargate
またDatadogを利用していたため、既にKube_のメトリクスは取得できていたのでkube-state-metricsについてはオフにし、EBSボリュームのretentionも1dでなくなるようにしました。
kube-state-metrics:
enabled: false
server:
persistentVolume:
annotations:
ebs.csi.aws.com/volumeType: gp3
size: 32Gi
retention: "1d"
OpenCost
Opencostはシンプルなリソース類しかありません。
Cost Allocationは公開されているjsonを取得し、コスト分析を行ってくれます。(公式ドキュメント)

入れ替えてみて
Kubecostのようにレポート出力などのリッチ機能はありませんが、各環境・各クラスタに整備しDatadog上で各Namespace毎に視覚化することができました。
可視化をして得られたこと
基盤への問い合わせに対してスムーズに回答できるようになったことが非常に大きいです。
またアプリケーション開発者自身で確認できるようにしたことで問い合わせも減ったようです。
こういったところはエンジニアにとってあまり生産的でもなく、無駄にコミュニケーションが発生しやすいポイントだと思います。
とはいえ事業運営上は必要なことですし、なるべく省力化していきたいところでした。
「その金額にどの程度の精度が求められるか」を考え、概算がわかればよい という落とし所が見つけられていた点もよかったと感じています。
コストは様々な要素で揺れ動くものなので、概算がわかるだけで十分役にたちます。(もちろん的外れすぎてはNGですが)
GCPプロジェクトやAWSアカウントのコスト管理 と Kubernetes内のコスト管理 の立ち位置から、あまり厳密さにこだわらずコスト可視化を試みても良いと思います。
また、コストの増加を検知し、担当者へ連絡したところ、即日対応&効果もお互いに共有できたという嬉しいことがありました。
コストに対してお互い向き合う先(ダッシュボード)があったことで、「どの程度」「何をすれば」「実施してどうなった」がスムーズにコミュニケーションが取れました。

私達の場合、マルチクラウド利用のため、外部でまとめて参照できるのが手間や認知負荷が少ないという点からも、Datadogを活用することで1箇所で確認できるようになったことも良かったところです。
注意しておくこと
他にもいくつか注意点があります。
GCPは公開jsonがないのでAPIキーが必要
AWSでは公開されたCost Allocationがありますが、GCPではないため、Cloud Billing APIが参照できるAPIキーを発行することでOpenCostのPodが正常に起動します。(公式ドキュメント)
送信するメトリクスは必要なものだけにする
特に指定しないまま設定するとかなりのカスタムメトリクスが送信されてしまうため、Datadog側のコスト増につながってしまいます。
ダッシュボードに必要なメトリクスだけに絞って送信するのが望ましいです。
Datadogが1インスタンスで送信できるメトリクス数は2000メトリクスの制限があります。(公式ドキュメント)
最初にお見せした画像イメージは、6つのメトリクスで十分です。
podAnnotations:
prometheus.io/port: "9003"
prometheus.io/scrape: "true"
ad.datadoghq.com/opencost.checks: |
{
"openmetrics": {
"instances": [
{
"openmetrics_endpoint": "http://%%host%%:9003/metrics",
"namespace": "opencost",
"metrics": [
{"node_cpu_hourly_cost": "node.cpu.hourly.cost"},
{"node_gpu_hourly_cost": "node.gpu.hourly.cost"},
{"node_ram_hourly_cost": "node.ram.hourly.cost"},
{"pv_hourly_cost": "pv.hourly.cost"},
{"container_cpu_allocation": "container.cpu.allocation"},
{"container_memory_allocation_bytes": "container.memory.allocation.bytes"}
]
}
]
}
}
まとめ
今回はコストの可視化の取組みについてご紹介しました。 マルチテナント運用だったり、マルチクラウド&マルチテナントの運用を行っている方の参考になれば幸いです。
プラットフォームエンジニアリング部門の1グループとして社内のアプリケーション開発者へより会社の価値提供に早く・効率的につなげるような基盤整備に取り組んでいます。
当記事を通じてMonotaROに興味を持っていただいた方は、カジュアル面談もやっていますのでぜひご連絡ください。 チームの採用募集も合わせてご覧ください。