🐶

DatadogでKubernetes JobのDeadlineExceededエラーを検知する方法とその限界

2024/09/09に公開

はじめに

株式会社カナリーでは現在「Canary」というお部屋探しのアプリを作っています。
https://corp.canary-app.jp/about/about_canary.html
https://prtimes.jp/main/html/rd/p/000000018.000046040.html

我々のシステムでは、定期的に実行されるジョブがDeadlineExceededエラーによって失敗することがあり、その影響が広範囲に及ぶ可能性があります。このため、特定のエラー条件に基づいたアラートを設定し、迅速に対応することが求められています。私たちは既にモニタリングにDatadogを利用しているため、このプラットフォームでのエラー検知手段を調査しました。

Datadog: Kubernetes State Coreの概要

Datadog は、Kubernetes 環境の状態をリアルタイムで監視するための強力なツールを提供しています。中でも Kubernetes State Metrics Core は、クラスタ内の各種リソースの状態を詳細にモニタリングするために利用されます。

DeadlineExceededの検知に有用なメトリクスの選定

kubernetes_state.container.status_report.count.terminatedは下記の説明にある通り、ある時点でTerminated状態にあるコンテナのreasonを持ちます。

Describes the reason the container is currently in terminated state. Tags:kube_namespace pod_name kube_container_name reason (env service version from standard labels).

https://docs.datadoghq.com/ja/integrations/kubernetes_state_core/?tab=helm

実験: DeadlineExceededを検知してみる

以下のK8sマニフェストは、意図的にDeadlineExceededエラーを発生させるためのジョブ設定です。この実験により、Datadogがどのようにメトリクスを収集するかを検証しました。

apiVersion: batch/v1
kind: Job
metadata:
  name: deadline-exceeded-test-job
spec:
  activeDeadlineSeconds: 10
  template:
    spec:
      containers:
        - name: busybox
          image: busybox
          command: ["sleep", "infinity"]
      restartPolicy: Never

結果として、失敗理由が「error」としか検出されないため、DeadlineExceededを特定することは困難でした。また、メトリクス自体が収集できないこともありました。収集できなかった原因としては、kubernetes_state.container.status_report.count.terminatedがある時点でのTerminatedなコンテナを対象としているため、メトリクスの収集間隔による問題と予想しています。

なぜDeadlineExceededが区別できなかったか

上記の実験の結果reasonがerrorとしか表示されませんでした。
Datadogのkube-state-metricsの実装を斜め読みした限りだと、区別できそうな雰囲気なのですが、原因がよくわかりません。
https://github.com/DataDog/kube-state-metrics/blob/main/internal/store/job.go

Datadogのサポートに問い合わせたところ、以下のPull Requestを作成していただきました。
https://github.com/DataDog/datadog-agent/pull/25103

内容としては kubernetes_state.job.failed に reason タグを追加するものです。
Pull Requestの中で言及されている通り、Datadogのkube-state-metricsは本家のフォークとなっており、2024/7/12時点ではreasonを本家と同じ様に区別することはできないようです。

代替案: 本家 kube-state-metrics をデプロイする

以上から、2024/7/12時点ではDatadogが提供するメトリクスだけではJobのDeadlineExceededを区別することは難しいことがわかりました。
そこで、代替案として本家のkube-state-metricsを時前でデプロイして、Datadogにメトリクスをエクスポートすることにしました。
今回は kube_job_status_failed だけが必要なので、以下のようにhelmのvalues.yamlを設定しました。

metricAllowlist:
  # JobがDeadlineExceededになったことを検知するためにJobの失敗理由を取りたい
  - "kube_job_status_failed"

podAnnotations:
  ad.datadoghq.com/kube-state-metrics.checks: |
    {
      "openmetrics": {
        "init_config": {},
        "instances": [
          {
            "openmetrics_endpoint": "http://%%host%%:%%port%%/metrics",
            "namespace": "kube-state-metrics",
            "metrics": [{"kube_job_status_failed":"kube_job_status_failed"}]
          }
        ]
      }
    }

まとめ

Kubernetes JobのDeadlineExceededを検知するアラートを設定するために、Datadogでの実現手段を調査しました。2024/7/12時点ではkubernetes/kube-state-metricsと同様にJobの失敗理由を区別することは難しいことがわかりました。そこで、kubernetes/kube-state-metricsを時前でデプロイしてJobのDeadlineExceededを検知することにしました。

Canary Tech Blog

Discussion