rabbit-slide-kou-hatohol-log-archive-and-search-2014-12 2014.12.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.rabbit +1 -0
- data/README.rd +48 -0
- data/Rakefile +17 -0
- data/config.yaml +22 -0
- data/images/fluentd-icon.png +0 -0
- data/images/fluentd-logotype.png +0 -0
- data/images/fluentd.png +0 -0
- data/images/groonga-icon-full-size.svg +97 -0
- data/images/hatohol-log-search-form.png +0 -0
- data/images/hatohol-log-search-systems-add-button.png +0 -0
- data/images/hatohol-log-search-systems-add-form.png +0 -0
- data/images/hatohol-log-search-systems-configuration-menu.png +0 -0
- data/images/log-archive-and-search-system.svg +9209 -0
- data/images/log-archive-system.svg +12499 -0
- data/images/log-search-system.svg +10410 -0
- data/overview.rab +549 -0
- data/pdf/hatohol-log-archive-and-search-2014-12-overview.pdf +0 -0
- metadata +89 -0
data/overview.rab
ADDED
@@ -0,0 +1,549 @@
|
|
1
|
+
= Hatoholの\nログ蓄積・検索機能\n2014/12版
|
2
|
+
|
3
|
+
: author
|
4
|
+
須藤功平
|
5
|
+
: institution
|
6
|
+
株式会社クリアコード
|
7
|
+
: date
|
8
|
+
2014/12/09
|
9
|
+
: allotted-time
|
10
|
+
60m
|
11
|
+
: theme
|
12
|
+
clear-code
|
13
|
+
|
14
|
+
= 内容
|
15
|
+
|
16
|
+
* ログ蓄積・検索機能の概要
|
17
|
+
* ただし2014年12月時点での情報
|
18
|
+
* 詳細はWikiを参照
|
19
|
+
* (('note:https://github.com/project-hatohol/hatohol/wiki/Log-archive'))
|
20
|
+
* (('note:https://github.com/project-hatohol/hatohol/wiki/Log-search'))
|
21
|
+
|
22
|
+
= 目的
|
23
|
+
|
24
|
+
* 現状を共有すること
|
25
|
+
|
26
|
+
= 蓄積:解決したい問題
|
27
|
+
|
28
|
+
* 大量のログを蓄積したい
|
29
|
+
* 目的:ルールを満たすため\n
|
30
|
+
(('note:例:一定期間の過去ログ蓄積が義務'))
|
31
|
+
* 目的:問題発生時期の特定\n
|
32
|
+
(('note:問題発覚時にいつから問題が起こっていたかを確認'))
|
33
|
+
|
34
|
+
= 蓄積:解決方法の問題
|
35
|
+
|
36
|
+
* ZabbixでやるならRDBMSへ蓄積
|
37
|
+
* RDBMSへ蓄積:オーバースペック
|
38
|
+
* リソース消費が割にあわない\n
|
39
|
+
* めったに参照しない
|
40
|
+
* 処理量が多い
|
41
|
+
* レプリケーション必須
|
42
|
+
* 失いたくないデータだから
|
43
|
+
|
44
|
+
= 蓄積:解決方針
|
45
|
+
|
46
|
+
* ファイルに保存
|
47
|
+
* オーバーヘッドが少ない
|
48
|
+
* 扱いやすい(コピー・圧縮)
|
49
|
+
* Fluentdと連携
|
50
|
+
* データ配送システム
|
51
|
+
|
52
|
+
= 蓄積:構成
|
53
|
+
|
54
|
+
# image
|
55
|
+
# src = images/log-archive-system.svg
|
56
|
+
# relative_width = 100
|
57
|
+
|
58
|
+
== スライドプロパティー
|
59
|
+
|
60
|
+
: enable-title-on-image
|
61
|
+
false
|
62
|
+
|
63
|
+
= 蓄積:ポイント(1)
|
64
|
+
|
65
|
+
* 監視対象は生ログを収集・転送
|
66
|
+
* 直接蓄積ノードに送らない
|
67
|
+
* ルーティングノードの導入
|
68
|
+
* 目的:構成変更耐性の強化
|
69
|
+
* 変更:蓄積ノードの増減
|
70
|
+
* 全監視対象を変更するより楽
|
71
|
+
|
72
|
+
= 蓄積:ポイント(2)
|
73
|
+
|
74
|
+
* 蓄積ノードでのソート
|
75
|
+
* 時間順にログが届くとは限らない
|
76
|
+
* 一定時間バッファリング
|
77
|
+
* バッファ内をソート後に書き込み
|
78
|
+
* ↑用プラグインは新規開発\n
|
79
|
+
(('note:(fluent-plugin-sort)'))
|
80
|
+
|
81
|
+
= 蓄積:タグ設計
|
82
|
+
|
83
|
+
* 監視対象
|
84
|
+
* (({raw.${type}.log.${host_name}}))
|
85
|
+
* 例:(({raw.messages.log.node1}))
|
86
|
+
* 蓄積ノード
|
87
|
+
* (({raw....}))→ソート→(({sorted.raw....}))
|
88
|
+
* →蓄積
|
89
|
+
|
90
|
+
= 蓄積:設定:監視対象(1)
|
91
|
+
|
92
|
+
<source>
|
93
|
+
type tail
|
94
|
+
path /var/log/messages
|
95
|
+
pos_file /var/log/td-agent/messages.pos
|
96
|
+
tag "raw.messages.log.#{Socket.gethostname}"
|
97
|
+
format none
|
98
|
+
</source>
|
99
|
+
|
100
|
+
= 蓄積:設定:監視対象(2)
|
101
|
+
|
102
|
+
<match raw.*.log.**>
|
103
|
+
type copy
|
104
|
+
<store>
|
105
|
+
type secure_forward
|
106
|
+
shared_key fluentd-secret
|
107
|
+
self_hostname "#{Socket.gethostname}"
|
108
|
+
# バッファー設定は省略
|
109
|
+
<server>
|
110
|
+
host router1.example.com
|
111
|
+
</server> # ←ルーティングノードの数だけ書く
|
112
|
+
</store>
|
113
|
+
</match>
|
114
|
+
|
115
|
+
= 蓄積:設定:ルーター(1)
|
116
|
+
|
117
|
+
# 受信
|
118
|
+
<source>
|
119
|
+
type secure_forward
|
120
|
+
shared_key fluentd-secret
|
121
|
+
self_hostname "#{Socket.gethostname}"
|
122
|
+
cert_auto_generate yes
|
123
|
+
</source>
|
124
|
+
|
125
|
+
= 蓄積:設定:ルーター(2)
|
126
|
+
|
127
|
+
<match raw.*.log.**> # 転送
|
128
|
+
type forest
|
129
|
+
subtype secure_forward
|
130
|
+
<template> # 共通設定
|
131
|
+
shared_key fluentd-secret
|
132
|
+
self_hostname "#{Socket.gethostname}"
|
133
|
+
# バッファー設定は省略
|
134
|
+
</template>
|
135
|
+
# 個別ケースは後述
|
136
|
+
<case **> # デフォルト
|
137
|
+
<server>
|
138
|
+
host archiver2.example.com
|
139
|
+
</server>
|
140
|
+
</case>
|
141
|
+
</match>
|
142
|
+
|
143
|
+
= 蓄積:設定:ルーター(3)
|
144
|
+
|
145
|
+
# 個別設定
|
146
|
+
<case raw.*.log.node1.example.com>
|
147
|
+
<server>
|
148
|
+
host archiver1.example.com
|
149
|
+
</server>
|
150
|
+
</case>
|
151
|
+
<case raw.*.log.node2.example.com>
|
152
|
+
<server>
|
153
|
+
host archiver2.example.com
|
154
|
+
</server>
|
155
|
+
</case>
|
156
|
+
|
157
|
+
= 蓄積:設定:蓄積(1)
|
158
|
+
|
159
|
+
# 受信
|
160
|
+
<source>
|
161
|
+
type secure_forward
|
162
|
+
shared_key fluentd-secret
|
163
|
+
self_hostname "#{Socket.gethostname}"
|
164
|
+
cert_auto_generate yes
|
165
|
+
</source>
|
166
|
+
|
167
|
+
= 蓄積:設定:蓄積(2)
|
168
|
+
|
169
|
+
# ソート
|
170
|
+
<match raw.**>
|
171
|
+
type sort
|
172
|
+
add_tag_prefix sorted.
|
173
|
+
buffer_type file
|
174
|
+
buffer_path /var/spool/td-agent/buffer/sort
|
175
|
+
flush_interval 60
|
176
|
+
</match>
|
177
|
+
|
178
|
+
= 蓄積:設定:蓄積(3)
|
179
|
+
|
180
|
+
# タグの並び替え(次の処理をしやすくするためだけ)
|
181
|
+
# sorted.raw.${type}.log.${host_name}
|
182
|
+
# ↓
|
183
|
+
# archive.raw.log.${host_name}.${type}
|
184
|
+
<match sorted.raw.**>
|
185
|
+
type record_reformer
|
186
|
+
enable_ruby false
|
187
|
+
|
188
|
+
tag archive.${tag_parts[1]}.${tag_parts[3]}.${tag_suffix[4]}.${tag_parts[2]}
|
189
|
+
</match>
|
190
|
+
|
191
|
+
= 蓄積:設定:蓄積(4)
|
192
|
+
|
193
|
+
<match archive.raw.log.**> # ←蓄積
|
194
|
+
type forest
|
195
|
+
remove_prefix archive.raw.log
|
196
|
+
# ↓タグの区切りでディレクトリーを掘る
|
197
|
+
escape_tag_separator /
|
198
|
+
subtype file
|
199
|
+
<template>
|
200
|
+
path /var/log/archive/${escaped_tag}
|
201
|
+
compress gz # ← 圧縮
|
202
|
+
format single_value
|
203
|
+
append true
|
204
|
+
flush_interval 60
|
205
|
+
</template>
|
206
|
+
</match>
|
207
|
+
|
208
|
+
= 蓄積:Hatohol連携
|
209
|
+
|
210
|
+
なし
|
211
|
+
|
212
|
+
= 蓄積:Hatohol連携案(1)
|
213
|
+
|
214
|
+
* 蓄積ノードへリンク
|
215
|
+
* ログは単なるファイル
|
216
|
+
* HTTPで公開することは簡単
|
217
|
+
* 課題
|
218
|
+
* アクセス権限はどうする?
|
219
|
+
* Hatoholが認可サーバーになる?
|
220
|
+
* HatoholをLDAP対応させる?
|
221
|
+
|
222
|
+
= 蓄積:Hatohol連携案(2)
|
223
|
+
|
224
|
+
* ログ検索システムへのロードUI
|
225
|
+
* 検索→ログ検索システム(('note:(後述)'))へ\n
|
226
|
+
ロードが必要
|
227
|
+
* ロードは(({fluent-cat}))で可能
|
228
|
+
* 課題
|
229
|
+
* 蓄積ノードでのコマンド実行が必要
|
230
|
+
* ホスト管理機能との連携で可能?
|
231
|
+
|
232
|
+
= 検索:解決したい問題
|
233
|
+
|
234
|
+
* ログの確認が面倒
|
235
|
+
* 対象ホスト数が多い\n
|
236
|
+
(('note:(Hatoholは大規模システム用のソフトウェア)'))
|
237
|
+
* 個別にログインするのが面倒
|
238
|
+
* 対象ログ数が多い
|
239
|
+
* 該当ログを探すのが面倒
|
240
|
+
|
241
|
+
= 検索:解決方法
|
242
|
+
|
243
|
+
* 全文検索システムの利用
|
244
|
+
* 要件
|
245
|
+
* 最新のログをすぐに検索できる
|
246
|
+
* 十分高速
|
247
|
+
* 検索対象は最新数週間から数ヶ月
|
248
|
+
|
249
|
+
= 検索:全文検索システム
|
250
|
+
|
251
|
+
* Groongaを採用
|
252
|
+
* 即時検索可能・十分高速
|
253
|
+
* 追加中も検索性能が落ちない\n
|
254
|
+
(('note:(ログは常に追加される)'))
|
255
|
+
* nginxのモジュールとしても使える
|
256
|
+
* nginxの機能・ノウハウを使える\n
|
257
|
+
(('note:(HTTPSや認証周りなど)'))
|
258
|
+
* 運用が容易
|
259
|
+
|
260
|
+
= 検索:構成
|
261
|
+
|
262
|
+
# image
|
263
|
+
# src = images/log-search-system.svg
|
264
|
+
# relative_width = 100
|
265
|
+
|
266
|
+
== スライドプロパティー
|
267
|
+
|
268
|
+
: enable-title-on-image
|
269
|
+
false
|
270
|
+
|
271
|
+
= 検索:ポイント
|
272
|
+
|
273
|
+
* 監視対象は生ログを収集・転送
|
274
|
+
* パースしない
|
275
|
+
* ログ蓄積と同じ設定→共通化可能
|
276
|
+
* ログパースノードの導入
|
277
|
+
* 監視対象の負荷を下げる
|
278
|
+
|
279
|
+
= 検索:構成:共通化
|
280
|
+
|
281
|
+
# image
|
282
|
+
# src = images/log-archive-and-search-system.svg
|
283
|
+
# relative_width = 100
|
284
|
+
|
285
|
+
== スライドプロパティー
|
286
|
+
|
287
|
+
: enable-title-on-image
|
288
|
+
false
|
289
|
+
|
290
|
+
= 検索:タグ設計(1)
|
291
|
+
|
292
|
+
* 監視対象
|
293
|
+
* (({raw.${type}.log.${host_name}}))
|
294
|
+
* 例:(({raw.messages.log.node1}))
|
295
|
+
* ログパースノード
|
296
|
+
* (({raw.${type}....}))→パース→
|
297
|
+
* (({${type}....}))→フォーマット→(({log}))
|
298
|
+
|
299
|
+
= 検索:タグ設計(2)
|
300
|
+
|
301
|
+
* 検索ノード
|
302
|
+
* (({log}))→Groonga
|
303
|
+
|
304
|
+
= 検索:設定:監視対象(1)
|
305
|
+
|
306
|
+
<source>
|
307
|
+
type tail
|
308
|
+
path /var/log/messages
|
309
|
+
pos_file /var/log/td-agent/messages.pos
|
310
|
+
tag "raw.messages.log.#{Socket.gethostname}"
|
311
|
+
format none
|
312
|
+
</source>
|
313
|
+
|
314
|
+
= 検索:設定:監視対象(2)
|
315
|
+
|
316
|
+
<match raw.*.log.**>
|
317
|
+
type copy
|
318
|
+
<store>
|
319
|
+
# 蓄積用設定
|
320
|
+
</store>
|
321
|
+
<store>
|
322
|
+
type secure_forward
|
323
|
+
# 蓄積用と同じなので設定は省略
|
324
|
+
<server>
|
325
|
+
host parser1.example.com
|
326
|
+
</server> # ←ログパースノードの数だけ書く
|
327
|
+
</store>
|
328
|
+
</match>
|
329
|
+
|
330
|
+
= 検索:設定:パース(1)
|
331
|
+
|
332
|
+
# 受信
|
333
|
+
<source>
|
334
|
+
type secure_forward
|
335
|
+
shared_key fluentd-secret
|
336
|
+
self_hostname "#{Socket.gethostname}"
|
337
|
+
cert_auto_generate yes
|
338
|
+
</source>
|
339
|
+
|
340
|
+
= 検索:設定:パース(2)
|
341
|
+
|
342
|
+
# パース
|
343
|
+
<match raw.*.log.**>
|
344
|
+
type forest
|
345
|
+
subtype parser
|
346
|
+
<template>
|
347
|
+
key_name message
|
348
|
+
</template>
|
349
|
+
<case raw.messages.log.**>
|
350
|
+
remove_prefix raw
|
351
|
+
format syslog # ← messages型はsyslogとしてパース
|
352
|
+
</case>
|
353
|
+
</match>
|
354
|
+
|
355
|
+
= 検索:設定:パース(3)
|
356
|
+
|
357
|
+
# フォーマット
|
358
|
+
<match *.log.*.**>
|
359
|
+
type record_reformer
|
360
|
+
enable_ruby false
|
361
|
+
tag ${tag_parts[1]} # ←tagをlogだけにする
|
362
|
+
<record> # メタデータをデータにする
|
363
|
+
host ${tag_suffix[2]}
|
364
|
+
type ${tag_parts[0]}
|
365
|
+
timestamp ${time}
|
366
|
+
</record>
|
367
|
+
</match>
|
368
|
+
|
369
|
+
= 検索:設定:パース(4)
|
370
|
+
|
371
|
+
# 転送
|
372
|
+
<match log>
|
373
|
+
type secure_forward
|
374
|
+
shared_key fluentd-secret
|
375
|
+
self_hostname "#{Socket.gethostname}"
|
376
|
+
# バッファー設定は省略
|
377
|
+
<server>
|
378
|
+
host search.example.com
|
379
|
+
</server>
|
380
|
+
</match>
|
381
|
+
|
382
|
+
= 検索:設定:検索(1)
|
383
|
+
|
384
|
+
# 受信
|
385
|
+
<source>
|
386
|
+
type secure_forward
|
387
|
+
shared_key fluentd-secret
|
388
|
+
self_hostname "#{Socket.gethostname}"
|
389
|
+
cert_auto_generate yes
|
390
|
+
</source>
|
391
|
+
|
392
|
+
= 検索:設定:検索(2)
|
393
|
+
|
394
|
+
# 保存
|
395
|
+
<match log>
|
396
|
+
type groonga
|
397
|
+
store_table Logs
|
398
|
+
# バッファー設定は省略
|
399
|
+
protocol http
|
400
|
+
host 127.0.0.1
|
401
|
+
# スキーマ定義
|
402
|
+
</match>
|
403
|
+
|
404
|
+
= 検索:設定:検索(3)
|
405
|
+
|
406
|
+
# スキーマ定義
|
407
|
+
<match log>
|
408
|
+
<table> # 全文検索用語彙表
|
409
|
+
name Terms
|
410
|
+
flags TABLE_PAT_KEY
|
411
|
+
key_type ShortText
|
412
|
+
default_tokenizer TokenBigram
|
413
|
+
normalizer NormalizerAuto
|
414
|
+
</table>
|
415
|
+
</match>
|
416
|
+
|
417
|
+
= 検索:設定:検索(4)
|
418
|
+
|
419
|
+
# スキーマ定義
|
420
|
+
<match log>
|
421
|
+
<table> # ホスト名データを共有
|
422
|
+
name Hosts
|
423
|
+
flags TABLE_PAT_KEY
|
424
|
+
key_type ShortText
|
425
|
+
# normalizer NormalizerAuto
|
426
|
+
</table>
|
427
|
+
</match>
|
428
|
+
|
429
|
+
= 検索:設定:検索(5)
|
430
|
+
|
431
|
+
# スキーマ定義
|
432
|
+
<match log>
|
433
|
+
<table> # タイムスタンプ用語彙表
|
434
|
+
name Timestamps
|
435
|
+
flags TABLE_PAT_KEY
|
436
|
+
key_type Time
|
437
|
+
</table>
|
438
|
+
</match>
|
439
|
+
|
440
|
+
= 検索:設定:検索(6)
|
441
|
+
|
442
|
+
# スキーマ定義
|
443
|
+
<match log>
|
444
|
+
<mapping> # ホスト名データを共有
|
445
|
+
name host
|
446
|
+
type Hosts
|
447
|
+
<index> # 高速検索のための索引定義
|
448
|
+
table Hosts
|
449
|
+
name logs_index
|
450
|
+
</index>
|
451
|
+
</mapping>
|
452
|
+
</match>
|
453
|
+
|
454
|
+
= 検索:設定:検索(7)
|
455
|
+
|
456
|
+
# スキーマ定義
|
457
|
+
<match log>
|
458
|
+
<mapping>
|
459
|
+
name timestamp
|
460
|
+
type Time
|
461
|
+
<index> # 高速検索のための索引定義
|
462
|
+
table Timestamps
|
463
|
+
name logs_index
|
464
|
+
</index>
|
465
|
+
</mapping>
|
466
|
+
</mapping>
|
467
|
+
|
468
|
+
= 検索:設定:検索(7)
|
469
|
+
|
470
|
+
# スキーマ定義
|
471
|
+
<match log>
|
472
|
+
<mapping>
|
473
|
+
name message
|
474
|
+
type Text
|
475
|
+
<index> # 全文検索用索引定義
|
476
|
+
table Terms
|
477
|
+
name logs_message_index
|
478
|
+
</index>
|
479
|
+
</mapping>
|
480
|
+
</match>
|
481
|
+
|
482
|
+
= 検索:設定:Hatohol(1)
|
483
|
+
|
484
|
+
# image
|
485
|
+
# src = images/hatohol-log-search-systems-configuration-menu.png
|
486
|
+
# relative_height = 60
|
487
|
+
|
488
|
+
(('tag:center'))検索UI管理画面に移動
|
489
|
+
|
490
|
+
= 検索:設定:Hatohol(2)
|
491
|
+
|
492
|
+
# image
|
493
|
+
# src = images/hatohol-log-search-systems-add-button.png
|
494
|
+
# relative_height = 60
|
495
|
+
|
496
|
+
(('tag:center'))検索UIの追加フォームを出す
|
497
|
+
|
498
|
+
= 検索:設定:Hatohol(3)
|
499
|
+
|
500
|
+
# image
|
501
|
+
# src = images/hatohol-log-search-systems-add-form.png
|
502
|
+
# relative_height = 60
|
503
|
+
|
504
|
+
(('tag:center'))検索UIの追加フォームを入力
|
505
|
+
|
506
|
+
= 検索:Hatohol連携
|
507
|
+
|
508
|
+
# image
|
509
|
+
# src = images/hatohol-log-search-form.png
|
510
|
+
# relative_width = 100
|
511
|
+
|
512
|
+
(('tag:center'))ダッシュボードに検索フォーム
|
513
|
+
|
514
|
+
= 検索:Hatohol連携案(1)
|
515
|
+
|
516
|
+
* イベントページにリンク
|
517
|
+
* 障害情報から検索できる
|
518
|
+
* 時間情報から検索できる
|
519
|
+
* 課題
|
520
|
+
* ログ以外の情報が多い
|
521
|
+
* ↑検索可能ではない情報が多い
|
522
|
+
|
523
|
+
= 検索:Hatohol連携案(2)
|
524
|
+
|
525
|
+
* ログ以外も検索可能にする
|
526
|
+
* 例:イベントの説明
|
527
|
+
* 例:Redmineのコメント
|
528
|
+
* 課題
|
529
|
+
* 検索結果の見せ方はどうなる?
|
530
|
+
* 見つかった後の動線は?
|
531
|
+
* Hatoholに戻る?Redmineに行く?
|
532
|
+
|
533
|
+
= 検索:Hatohol連携案(3)
|
534
|
+
|
535
|
+
* 検索キーワードを事前登録
|
536
|
+
* クリックで検索できて楽
|
537
|
+
* 課題
|
538
|
+
* 誰が登録するのか
|
539
|
+
* 既存ログから拾ってこれると\n
|
540
|
+
よさそう?
|
541
|
+
|
542
|
+
= 検索:課題
|
543
|
+
|
544
|
+
* ユーザー毎に権限設定できない
|
545
|
+
* ログ検索UIのURLをサーバーではなく\n
|
546
|
+
UIに保存しているため
|
547
|
+
* 検索UIからHatoholに戻って\n
|
548
|
+
これない
|
549
|
+
* Redmine連携も同じ?
|