tech.guitarrapc.cóm

Technical updates

Datadog Log Management で Kubernetes の external-dns やkube2iam のログレベルを適切に扱いたい

Kubernetes のログを見るといえば、Datadog Log Mangement が楽なのですが時々ログメッセージが適切なレベルで扱われません。

そんなときによくやる「ログメッセージからレベルになるフィールドを取り出して Log Status として認識させる」ことを見てみましょう。

Before

After

目次

TL;DR

  • Custom Pipeline を使って、ログメッセージを構造化とLog Status の変更を行えばok
  • ログメッセージがkey=value で構造化されているとさくさく構築できるので神

問題

Kubernetes に限らず、Log Management でログを取り込んだ時に意図と違ったログレベルとして認識されることがあります。

たとえば Kubernetes で external-dns を使っているとき、実行するものがないときは All records are already up to date というメッセージ出力されるのですが、Datadog Log Management では Status が Error となっています。

level=info msg="All records are already up to date"

しかしこのログは、Message に level=info とある通りエラーログではありません。 これをInfoとして扱いたいのでさくっと対処しましょう。

ログを見てみる

まずはログがどう認識されているのか見てみましょう。

何も実行するものがないときのログ

対象のログを見てみると、Log Status が Error となっていることがわかります。

Log Status が Error

また、ログも構造化されていません。

ログが構造化されていない

対処方針

external-dns のログは、level key でログレベルを表現しています。 こういったログへの追加対応は、Log Management のPipeline に追加のカスタムパイプラインを追加することでできます。 パイプラインには様々な処理(Processor)を設定できます。 今回はデフォルトのパイプラインで設定されたログレベルを書き換えたいので、Log Status Remapper を用いることでログに含まれる level キーの値を Log Status として認識させることができます。

Use this Processor if you want to assign some attributes as the official status. For example, it can transform this log:

before

after

docs.datadoghq.com

対応方針は次の通りです。

  • 新規パイプランを作る
  • ログメッセージがただの文字列として扱われているのでJSON として認識されるように構造化
  • 構造化したデータから対象の level key を拾ってLog Status を書き換える

パイプライン対応

Custom Pipeline を追加して、2つProcessorを追加していきます。

Custom Pipeline の追加

Datadog Agent のPipeline の後ろに新規Pipeline を追加します。

パイプラインを作成するときに、対象となるログを絞り込みます。 今回は All records are already up to date となっているログを絞りたいので、Source とメッセージで指定してみましょう。

source:external-dns message:"*All records are already up to date"

Processor の追加: Grok Parserで構造化する

パイプラインができたら、具体的な処理単位であるProcessor を追加します。 まずは、ただの文字列になっているログを構造化 (JSON) 変換するため、Grok Parserを用います。

https://docs.datadoghq.com/logs/processing/processors/?tab=ui#grok-parser

変換方法を考えるため、対象にしたいログメッセージを見てみましょう。

time="2020-01-07T09:49:07Z" level=info msg="All records are already up to date"

今回のログは 「key=value がスペースで羅列されている構造」とわかります。 こういった、文字列が key{何かの文字}value で構成されている場合、%{data::keyvalue} を使うだけでサクッと構造化できます。

external_dns_rule %{data::keyvalue}

docs.datadoghq.com

これでいい感じのJSON に変換されてました。

{
  "time": "2020-01-07T09:49:07Z",
  "level": "info",
  "msg": "All records are already up to date"
}

Grok Parser で構造化

Processor の追加: Log Status Remapperでログステータスとする

構造化したデータからステータスをとります。 もう一度Processor を追加して、今度は Log Status Remapper を使ってログステータスの差し替えを行います。

https://docs.datadoghq.com/logs/processing/processors/?tab=ui#log-status-remapper

level キーの値を使うので、対象キーに level を指定します。

Log Status Remapper で level キーを用いる

これでおしまいます。

Pipelineの結果を確認

Log Explorer でログの結果を見てみると、いい感じに Status が変わったことが確認できます。

先ほどなにもデータがなかった ATTRIBUTES にも、変換した構造化データがのっていることがわかります。

このパターンはちょくちょく使うので、さくっとできると捗るでしょう。

REF

github.com