ktranslateのS3 sinkを試してみた ー SyslogもSNMP Trapも送れないと気づくまでの調査記録
はじめに
New Relicの機能として提供されているktranslateを使うと、ネットワーク機器の状態をまとめて監視できます。ICMPやSNMP Pollingで取得したメトリクス情報に加え、ネットワーク機器から送られてくるSyslogやSNMP Trapといった形式のログも収集できます。
こうしたSyslogやSNMP TrapをNew Relic以外の場所にも転送したいという話があり、実際にできるのかどうか調査しました。ktranslateはkentik社が開発するオープンソースのネットワークテレメトリ収集エージェントで、New Relicへのメトリクス転送以外にも、複数の送信先(sink)にデータを並行して転送できる設計になっています。今回はその機能を使って、SyslogとSNMP TrapをNew RelicとAmazon S3の両方に送れるかどうかを検証しました。
ktranslateのドキュメントを見ると-sinksフラグにカンマ区切りで複数の送信先を指定できると書いてあり、最初は簡単に実現できそうに思えました。ところが実際に動かしてみると、S3に届いているのはSNMPメトリクスだけで、SyslogもSNMP Trapも届いていませんでした。この記事では、その原因を調査した過程と、コードを読んで判明したktranslateのアーキテクチャ上の制約を整理します。
S3 sinkの基本設定とnr1.syslogの関係
複数sinkへの並行送信の仕組み
ktranslateは-sinksフラグにカンマ区切りで複数の送信先を指定するだけで、データを並行転送できます。New RelicとS3に同時に送る場合は次のように指定します。
-sinks=new_relic,s3
S3への送信に最低限必要なフラグは-s3_bucketのみで、リージョンやプレフィックスはデフォルト値が用意されています。
| フラグ | デフォルト値 | 説明 |
|---|---|---|
-s3_bucket |
なし(必須) | 送信先バケット名 |
-s3_region |
us-east-1 |
バケットのリージョン |
-s3_prefix |
/kentik |
オブジェクトのプレフィックス |
-s3_flush_sec |
60 |
ファイルを作成する間隔(秒) |
※詳細なパラメータリストは ktranslateのリポジトリをご参照ください
一見すると非常にシンプルな設定です。ただし、Syslog受信用の構成ではnr1.syslogというモードを使うのが一般的で、ここに問題がありました。
nr1.syslogとは何か
nr1.syslogはNew Relic × Syslog構成向けのプリセットで、次の6つの設定を一括で適用するショートカットです。
Sinks = ["new_relic"] Format = "new_relic_metric" Compression = "gzip" SNMPInput.FlowOnly = true SyslogInput.ListenAddr = "0.0.0.0:5143" SyslogInput.Enable = true
New Relicだけに送るシンプルな構成では設定が簡潔になる便利なモードですが、送信先がNew Relicのみに固定される設計になっています。
-sinks=new_relic,s3が無効になる理由
-sinks=new_relic,s3を指定していても、nr1.syslogを同時に使うとS3への送信が機能しません。原因はcmd/ktranslate/main.goの処理順序にあります。
※ https://github.com/kentik/ktranslate/blob/main/cmd/ktranslate/main.go の122行目~147行目
cfg := ktranslate.DefaultConfig() applyFlags(cfg) // ① -sinks=new_relic,s3 が適用される mergo.Merge(ktCfg, cfg) // ② configファイルがあればマージ applyMode(cfg, ...) // ③ nr1.syslogがcfg.Sinksを上書き ← ここが問題
applyMode()は常に最後に実行されるため、nr1.syslogの内部処理でcfg.Sinks = []string{"new_relic"}が実行されると、それ以前に指定したフラグの内容が上書きされてしまいます。コード上にこれを回避する手段はありません。
解決策:個別フラグで設定を再現する
nr1.syslogが内部で行っている6項目を個別フラグで明示的に指定することで、S3への並行送信と共存できます。
command: - "-snmp=/syslog-base.yaml" # -- New Relic と S3 を有効にする -- - "-sinks=new_relic,s3" # -- New Relicのnr1.syslog 代替設定-- - "-format=new_relic_metric" - "-compression=gzip" - "-syslog.source=0.0.0.0:5143" - "-flow_only=true" # -- sinksのS3設定-- - "-s3_bucket=your-bucket-name" - "-s3_region=ap-northeast-1" # -- New Relic 標準設定 -- - "-nr_account_id=${NR_ACCOUNT_ID}" - "-metrics=jchf", \ - "-tee_logs=true", \ - "-dns=local", \ # "nr1.syslog" は削除
この変更によりs3 sinkが認識されるようになりました。ところが、S3バケットに書き込まれるのはSNMPメトリクスだけで、SyslogもSNMP Trapも届いていませんでした。
S3に届いたのはメトリクスだけだった ー コードで読み解く根本原因
nr1.syslogの問題を解消してもSyslogとSNMP TrapがS3に届かない理由を調べるため、ktranslateのデータフローをコードレベルで追いかけました。
S3 sinkが受け取れるデータの範囲
ktranslateのデータ転送には大きく2つの経路があります。
ひとつはJCHF(Kentik Compressed Header Format)パイプラインで、SNMPメトリクスなどはこの経路を通って各sinkのSend()メソッドに届きます。もうひとつはそれ以外の専用チャネルで、SyslogとSNMP Trapはこちらを使います。
S3 sinkの実装(pkg/sinks/s3/s3.go)はSend()メソッドのみを持っており、JCHFパイプライン経由のデータしか受け取れません。
Syslogが届かない理由
Syslogの処理はpkg/inputs/syslog/syslog.goで行われており、受信したメッセージは文字列チャネル(logchan)に書き込まれます。
// syslogメッセージは文字列チャネルに直接書き込まれる case ks.logchan <- string(msg):
このlogchanを受信しているのはNR sinkのwatchLogs()だけです。S3 sinkにはこれに相当するメソッドが実装されていないため、Syslogメッセージはそもそも届きません。
SNMP Trapが届かない理由
SNMP Trapは一度JCHFパイプラインに乗りますが、-format=new_relic_metricを使う場合に問題が起きます。pkg/formats/nrm/nrm.goでトラップを処理する際、データはJCHFとしてではなくEventChan(イベント専用チャネル)に送られます。
case kt.KENTIK_EVENT_SNMP_TRAP: err := events.SendEvent(in, f.doGz, f.EventChan) ... return nil // JCHFとしてはnilを返すためS3に渡るデータがない
EventChanを受信しているのもNR sinkのcheckForEvents()だけで、S3 sinkには対応するメソッドがありません。
データ種別ごとの送信先まとめ
| データ種別 | New Relic | S3 |
|---|---|---|
| Syslog | ✅(watchLogs()経由) |
❌ 未実装 |
| SNMP Trap | ✅(checkForEvents()経由) |
❌ 未実装 |
| SNMPメトリクス | ✅ | ✅(JCHFパイプライン経由) |
SNMPメトリクスのS3送信は正常に動作することを確認しました。SyslogとSNMP Trapについては、現時点のktranslateのコード上、S3への送信はサポートされていません。
まとめ
今回の調査で明らかになったことを整理します。
まずnr1.syslogモードはNew Relicへの単体送信に特化したプリセットで、S3を含む複数sinkとの共存を想定した設計ではありません。S3に並行送信したい場合はnr1.syslogを使わず、内部で行われている設定を個別フラグで再現するのがベストプラクティスです。
次に、ktranslateのS3 sinkはJCHFパイプライン経由のデータ(主にSNMPメトリクス)しか受け取れない実装になっています。SyslogとSNMP Trapは専用のチャネル経由でNR sinkにのみ届く設計のため、S3への送信はコードレベルで未対応です。
SyslogやSNMP TrapをS3に保存したい場合は、ktranslateのS3 sinkに頼るのではなく、New Relicに届いたデータをData Exportなどの機能でS3に転送する別アプローチを検討するのが現実的です。
ktranslateはネットワークテレメトリを幅広い形式で収集できる強力なツールですが、各sinkがどのデータ経路に対応しているかはドキュメントだけでは判断しにくい部分もあります。設定前にコードレベルで動作を確認する習慣が役立つと実感した検証でした。
この記事がどなたかのお役に立てれば幸いです。
◆ 塩野 正人
◆ マネージドサービス部 所属
◆ X(Twitter):@shioccii
◆ 過去記事はこちら
前職ではオンプレミスで仮想化基盤の構築や運用に従事。現在は運用部隊でNew Relicを使ってサービス改善に奮闘中。New Relic User Group運営。