Monitoring Fluentd with Mackerel and Tuning Fluentd buffer config
h2oのログをbigqueryに送り始めました。
今のところ特に問題は無いのですが、正直バッファの各設定値やリトライ回数のチューニングについてはどうすれば良いのかよくわからないのでなんとかしたいところです。
そこで、mackerel-agent-pluginsを導入してみます。メトリクスを取ることでチューニングしやすくなるだろうと言う目論見です。
バッファについては、下記のサイトが分かりやすかったです。
td-agent側の準備
まずtd-agent.confでmonitor_agentプラグインを有効化します。下記設定を追加してtd-agentを再起動。
<source>
@type monitor_agent
bind 0.0.0.0
port 24220
</source>
monitor_agentプラグインを有効にするとapiを通じて各プラグインの状態をjson形式やltsv形式で取得できるようになります。
実際に手動で取得してみます。inputプラグイン、outputプラグインで取得する値が異なります。outputプラグインにはプロバイダにログを送るにあたってのバッファの設定などが含まれています。
curlでapiを叩きます。
curl http://127.0.0.1:24220/api/plugins.json | jq .
inputプラグインとoutputプラグインでは以下のようなデータが取れます。
input
{
"plugin_id": "object:3f9ac13277ec",
"plugin_category": "input",
"type": "tail",
"config": {
設定内容(デフォルト値も含む)
},
"output_plugin": false,
"retry_count": null
}
output
{
"plugin_id": "object:3f9ac2a4855c",
"plugin_category": "output",
"type": "bigquery",
"config": {
設定内容(デフォルト値も含む)
},
"output_plugin": true,
"buffer_queue_length": 0,
"buffer_total_queued_size": 0,
"retry_count": 0
}
"output_plugin": true
のプラグインで取れる値について。
- buffer_queue_length = キューに蓄積されたchunkの数
- buffer_total_queued_size = キューに蓄積された全chunkのサイズ合計
- retry_count = 再送を試みた回数
mackerel側の準備
mackerel-agent-plugins
パッケージをインストールしておきます。/usr/bin/mackerel-plugin-fluentd
を実行するconfを書いて/etc/mackerel-agent/conf.d
以下に置きます。
[plugin.metrics.fluentd]
command = "/usr/bin/mackerel-plugin-fluentd"
apiで取得できる、
- retry_count
- buffer_queue_length
- buffer_total_queued_size
をメトリクスとしてmackerel送っているようです。
グラフはこんな感じ。平和。
それぞれのobject_idの内訳はこんな感じでした。
{
"plugin_id": "object:3f9ac29c1a34",
"plugin_category": "output",
"type": "stdout",
"output_plugin": true
},
{
"plugin_id": "object:3f9ac3adf154",
"plugin_category": "output",
"type": "tdlog",
"output_plugin": true
},
{
"plugin_id": "object:3f9ac2a4855c",
"plugin_category": "output",
"type": "bigquery",
"output_plugin": true
}
プラグインの引数でtypeやidを指定できるので、必要なプラグインの値のみ選択することも出来ます。
チューニング
グラフから現状問題無し!なことがわかったので、サーバのリソースから適切な値を考えてみます。bigqueryプラグインのバッファ周りの設定値は以下(デフォルト値)。
"buffer_chunk_limit": 1048576,
"buffer_queue_limit": 1024,
"buffer_chunk_records_limit": 500
"buffer_type": "lightening",
1チャンク当たりの最大サイズが1M、キューイングするチャンクの最大数が1024個、1チャンクあたりの最大レコード数が500行。
ちなみにbigqueryで受け付けられる1リクエストあたりのサイズは1M (fluentdはチャンク毎にデータを送信していくので数字だけ見るとギリギリですね)。
buffer_typeのlighteningはチャンクをメモリ上に置く設定っぽい。
ということは、もし何か問題があって(bq管理画面で間違えて鍵消しちゃったりとか)bqにログを送れなかった場合、最大1Gまでメモリを消費できるという計算になります。今使ってるサーバがメモリ512Mなので1G使おうとされたら死ぬ!
ただ、1チャンクあたりのレコード数上限が500行なので、1チャンクで1Mまで達し無さそう。
実際に送信しているh2oのaccess.logを見ると、10760行で1.7Mでした。単純計算で1行あたり159Bくらいなので、500行でだいたい80Kくらいでしょうか。1チャンクの実測値80K。少なッ!!仮にキューを使い切ったとしても80Mくらい。
free -h
でavailableなメモリ容量を確認したところ247M
だったので、とりあえず最大100Mに収まる感じで設定すれば良さそう。
- bigquery側の制限を考えてbuffer_chunk_limitを800Kにする
- 1レコード200Bとして、buffer_chunk_records_limitは800K / 200B = 4000にする
- 100Mに収まるようにしたいので、buffer_queue_limitは100M / 800K = 125とする
チャンクが大きいと送信失敗した時キューが溜まる速度が遅かったりとか、求めるもの(絶対欠損したくないとか欠損してもいいからたくさん送りたいとか)に応じてチューニングする点はもっと考える余地がありそうですがいったんこれでやってみます。
リトライ数やフラッシュ周りの設定は今回いじってないので別の機会に設定してみようと思ふ。