Logstash cheat sheet
ELK (Elasticsearch + Logstash + Kibana)
splunk のデモをみて、自分の環境に logstash を入れてみた。 :)
- (ELKの更新が速いので、随時記事をアップデートします。Elasticsearch 2.0.0, Logstash 2.0.0, Logstash Forwarder 0.4.0 (Filebeat 1.0.0-rc1), Kibana 4.2.0)
- splunk のデモを見て、構造化ロギング・高速検索・可視化の素晴らしさが解ったので、それをオープンソースの ELK stack で実現する。
- ELK でログ管理をしはじめて、いままで気付かなかった事がいろいろ見えて、かなり改善しました(実感!)
logstash の書籍
- 突っ込んだ内容ですの大変参考になります。
The Logstash Book
logstash
構成
Deploying with Message Queueing で構成してみた。(The Logstash Book に同様な構成の構築手順あり)
- この構成を取ることで、ログ収集と、ログの解析・構造化の処理が分離でき、スケールの余地と、ログを落とす可能性を低減する。
- logstash architecture イメージ検索
logstash-forwader/Filebeat(送る) ↘︎ logstash-forwader/Filebeat(送る) → logstash-shipper(受け取りredisに送る) → redis(ブローカー) → logstash-indexer(パース・構造化) → Elasticsearch(蓄積・検索エンジン) → Kibana(可視化) logstash-forwader/Filebeat(送る) ↗︎ ↗︎ logstash-shipper(redisに送る)ーーーーーーーーーーーーーーーーーーーーーー↗︎ beaver(redisに送る)ーーーーーーーーーーーーーーーーーーーーーーーーーー↗︎
- 私は各端末には Java 環境は入れたくないので logstash-forwarder (もうすぐ Filebeatに代わる) を使ってます。
logstash-forwarder (Filebeat):
端末(logstash-forwarder / Filebeat) ----> 解析サーバ(logstash-shipper)
logstash-shipper:
logstash-forwarder / Filebeat の待ち受け(input lumberjack / input beats)、ブローカーへそのまま吐き出す(output redis)
logstash-indexer:
ブローカーから逐次取り出し(input redis)、ログのパース・構造化(filter)、ESへ出力(output elasticsearch)
- (解析サーバを1台で処理する場合は、indexer と shipper の java プロセスは別に起動したほうがいろいろ楽。パッケージ版の起動スクリプトを名前かえて二つにする)
INPUT (PLUGINS) FILTER (PLUGINS) OUTPUT (PLUGINS)
- 簡単に言えば、なんらかの log (何かしらのデータ/IoTデバイスからも/この書式等は問わない/複数箇所からも) を input で取り込む。filter で正規表現でパターンマッチング (grok)して整形したり、さまざまな filter plugin で加工する。もちろん主キーになる時刻も定義する。その構造化した JSON を output elasticsearch で ES に送る。これだけです。(もちろん output 先は ES だけに限りません。output influxdb で influxDB に送って grafana で可視化も/複数箇所へも)
- github に自分の設定をおいています。参考にしてください。
https://github.com/nxhack/logstash
- logstash filter の geoip, ruby, kv, dns 逆引き等の典型的な使い方をしています。
- たとえば apache のサーバでは IP の逆引きするのは無駄なので、解析サーバでホスト名を引くというような使い方ができます。
- IP address から GeoIP データベースを引いたり、apache の user agent の解析をしたりして自分が見たい情報に加工しています。
logstash-forwarder (Filebeat)
SSL 証明書の件
IMPORTANT TLS/SSL CERTIFICATE NOTES Logstash-forwarder is throwing SSL errors - Server Fault
- IP address で サーバ指定している場合は、SAN (Subject Alternative Name) の証明書を作る必要がある。
- /etc/logstash/openssl-logstash.cnf:
[req]
distinguished_name = req_distinguished_name
x509_extensions = v3_req
prompt = no
[req_distinguished_name]
C = AU
ST = Some-State
L = Locality Name
O = Internet Widgits Pty Ltd
CN = *
[v3_req]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
basicConstraints = CA:TRUE
subjectAltName = @alt_names
[alt_names]
DNS.1 = *
DNS.2 = *.*
DNS.3 = *.*.*
DNS.4 = *.*.*.*
DNS.5 = *.*.*.*.*
DNS.6 = *.*.*.*.*.*
DNS.7 = *.*.*.*.*.*.*
IP.1 = 192.168.1.2
IP.2 = 127.0.0.1
[ v3_ca ]
subjectAltName = @alt_names
cd /etc/logstash
openssl req -config ./openssl-logstash.cnf -x509 -batch -nodes -days 365 -newkey rsa:2048 -sha256 -keyout ./logstash-forwarder.key -out ./logstash-forwarder.crt
Filebeat Migration
Logtash-Forwarder to Filebeat Migration
logstash-input-beats へ入れ替え
LS 1.5.x でも 2.x も可
cd /opt/logstash
./bin/plugin install logstash-input-beats
shipper.conf:
input {
beats {
port => 5000
type => "ctrllogs"
target_field_for_codec => "line"
ssl => true
ssl_certificate => "/etc/logstash/logstash-forwarder.crt"
ssl_key => "/etc/logstash/logstash-forwarder.key"
}
}
- plugin 名を 'lumberjack' から 'beats' へ変更。'ssl => true' 行を追加 (SSL はデフォルト false)
- クライアントが LSF のときは、 target_field_for_codec => "line" 行が必要。Filebeat になれば不要。
Filebeat 設定
(クライアント側はリリースされてパッケージが出たら作業する)
- 1.0.0-beta4 でちょっと動かしてみたら、LSF でよくあった証明書問題にひっかかるようだ。コードをみたら tls なんかまだおかしい気がするのでもう少し様子見したほうが良さそう。(insecure: true にしているのに InsecureSkipVerify がちゃんと設定されてない?)
- やっぱり insesure option がうごいてなかった。 TLS insecure option is ignored for logstash · Issue #238 · elastic/libbeat
- 1.0.0-rc1 まで待つ...1.0.0-rc1 出たが...動かない...configかなりかわってる...LSFマイグレーションガイドはほぼ無かったことになってる...
- shipper: セクション書くとうごいた...とりあえずテストする。
- LSF 互換性が微妙(違うものであるからこれで良いのかもしれないが、違いを押さえておきたい)
- LSF ではある host field がない。その代わり shipper field がある。また、file field が source field になってる。とりあえず issue あげといた。
- offset field の mapping が long になってる。logstash 側で対処してみた。
/usr/bin/filebeat[9999]: transport.go:129: SSL client failed to connect with: x509: certificate signed by unknown authority
log.go:126: File reading error. Stopping harvester. Error: EOF
filebeat:
prospectors:
-
paths:
- /var/log/syslog
- /var/log/mail.log
- /var/log/auth.log
input_type: log
document_type: syslog
-
paths:
- /var/log/apache2/access.log
input_type: log
document_type: apache
-
paths:
- /var/log/apache2/other_vhosts_access.log
input_type: log
document_type: apache-other-vhost
-
paths:
- /var/log/apache2/error.log
input_type: log
document_type: apache-error
-
paths:
- /var/log/dpkg.log
input_type: log
document_type: dpkg
#registry_file: /var/lib/logstash-forwarder/.logstash-forwarder
#registry_file: /var/lib/logstash-forwarder/.filebeat
registry_file: /var/lib/filebeat/registry
output:
logstash:
enabled: true
# The Logstash hosts
hosts: ["127.0.0.1:5000"]
tls:
disabled: false
# List of root certificates for HTTPS server verifications
certificate_authorities: ["/etc/logstash/logstash-forwarder.crt"]
# Certificate for TLS client authentication
#certificate: "/etc/logstash/logstash-forwarder.crt"
# Client Certificate Key
#certificate_key: "/etc/logstash/logstash-forwarder.key"
# Controls whether the client verifies server certificates and host name.
# If insecure is set to true, all server host names and certificates will be
# accepted. In this mode TLS based connections are susceptible to
# man-in-the-middle attacks. Use only for testing.
insecure: true
shipper:
# The name of the shipper that publishes the network data. It can be used to group
# all the transactions sent by a single shipper in the web interface.
# If this options is not defined, the hostname is used.
name: ShipperHostName
# The tags of the shipper are included in their own field with each
# transaction published. Tags make it easy to group servers by different
# logical properties.
#tags: ["service-X", "web-tier"]
# Uncomment the following if you want to ignore transactions created
# by the server on which the shipper is installed. This option is useful
# to remove duplicates if shippers are installed on multiple servers.
#ignore_outgoing: true
logging:
# Send all logging output to syslog. On Windows default is false, otherwise
# default is true.
#to_syslog: true
to_syslog: false
# Write all logging output to files. Beats automatically rotate files if configurable
# limit is reached.
#to_files: false
to_files: true
# Enable debug output for selected components.
#selectors: []
# Set log level
#level: error
level: INFO
files:
# The directory where the log files will written to.
path: /var/log/filebeat
# The name of the files where the logs are written to.
name: filebeat.log
# Configure log file size limit. If limit is reached, log file will be
# automatically rotated
rotateeverybytes: 10485760 # = 10MB
# Number of rotated log files to keep. Oldest files will be deleted first.
keepfiles: 7
これ忘れそうなので注意する事
The registry file stores the state and location from which Filbeat was reading last. Under Logstash-Forwarder it was called .logstash-fowarder. For Filebeat it was renamed to .filebeat or /usr/lib/filebeat/registry if you install from packages or C:\ProgramData\filebeat\registry if you run as a Windows service.
- ここが rc1 とは違う...
メンテナンス
cd /opt/logstash
./bin/plugin list
./bin/plugin list --verbose
./bin/plugin update
plugin version 指定の方法
cd /opt/logstash
./bin/plugin install --version=2.0.2 logstash-input-redis
2015/08/21 LS 1.5.4 のバグ
- Logstash 1.5.4 で配布されている logstash-input-lumberjack 1.0.4 で、
The error reported is: uninitialized constant Concurrent::Delay::Executor
1.0.5 で fix : https://github.com/ph/logstash-input-lumberjack/commit/a3499b25cb2f03587ce8598c0df70fc80ce9beeb
cd /opt/logstash
./bin/plugin update --version=1.0.5 logstash-input-lumberjack
- もちろん LS 1.5.5 や LS 2.0.0 は大丈夫
2015/11/06 LS 2.0.0 のバグ
- jruby concurrent-ruby が 0.9.2 になって
RuntimeError: Logstash expects concurrent-ruby version 0.9.1 and version 0.9.2 is installed, please verify this patch: /opt/logstash/vendor/bundle/jruby/1.9/gems/logstash-core-2.0.0-java/lib/logstash/patches/silence_concurrent_ruby_warning.rb
Since concurrent-ruby 0.9.2 this patch isnt necessary. · elastic/logstash@972e13d
- logstash-input-beats 0.9.5 で FIX
lightweight shipper
- beaver (redis に直接送る事ができる)
beaver : python daemon that munches on logs and sends their contents to logstash
- logstash-forwarder (昔の名前は lumberjack) (次の名前は Filebeat)
logstash-forwarder
- elastic.co の repository に ubuntu i386 版がなくってアセった....
- Filebeat というのに置き換わるそうだ。
Filebeat
parser / grok patterns
各種ログのパターン
- logstash-patterns-core
logstash-patterns-core
- apache
grok-patterns の COMBINEDAPACHELOG apache grok pattern
- postfix
postfix grok pattern
- sshd
sshd grok pattern
- zimbra (mailbox.log, amavis)
mailbox.log grok pattern amavis grok pattern
パターンの作成
- デバッグ
Grok Debugger
- 正規表現を思い出す ;)
正規表現の構文
geoip, user-agent
http://dev.maxmind.com/geoip/legacy/geolite/ http://download.maxmind.com/download/geoip/database/asnum/GeoIPASNum.dat.gz http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz
https://github.com/ua-parser/uap-core/blob/master/regexes.yaml https://raw.githubusercontent.com/ua-parser/uap-core/master/regexes.yaml
enable high precision timestamps
- ログ管理は時刻がキーになるので、時刻の精度を高めたい (TraditionalFileFormat を前提にしている処理も多いので変更する際は要注意)
rsyslog の timestamp を milliseconds まで取る
- /etc/rsyslog.conf の
# Use traditional timestamp format. # To enable high precision timestamps, comment out the following line. # $ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat
- の指示通り、"ActionFileDefaultTemplate" 行をコメントアウトする。
#$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat
traditional と high precision 両方対応した syslog 用の logstash filter
grok {
match => { "message" => "(?:%{SYSLOGTIMESTAMP:syslog_timestamp}|%{TIMESTAMP_ISO8601:syslog_timestamp}) %{SYSLOGHOST:syslog_hostname} %{DATA:syslog_program}(?:[%{POSINT:syslog_pid:int}\])?: %{GREEDYDATA:syslog_message}" }
add_field => {
"syslog_received_at" => "%{@timestamp}"
"syslog_received_from" => "%{host}"
}
}
syslog_pri {
}
date {
match => [ "syslog_timestamp", "MMM d HH:mm:ss", "MMM dd HH:mm:ss", "ISO8601" ]
timezone => "Asia/Tokyo"
locale => "en"
}
mutate {
replace => { "syslog_timestamp" => "%{@timestamp}" }
}
- (切り戻してもエラーがでないように mutate, replace 処理追加)
apache2.4 のログの場合(未確認)
%{%Y-%m-%dT%H:%M:%S}t.%{msec_frac}t%{%z}t
注意点
- traditional timestamp から high precision timestamp に変える場合は、mapping type が string に代入するので問題は起こらない。
- 逆に high precision timestamp から traditional timestamp に戻す場合は、mapping type が date なので dateOptionalTime という format 以外はエラーになる。
kibana
ES 2.0.0 ではいま(2015/10/29)のところ kibana 4.1.2 が動かない。kibana 4.2.0 は apache-proxy 環境でうまく動作しない。早急に hack しまする...(ということはまだ ES 2.0.0 は入れちゃダメかな)
- とりあえず ssh tunneling で
ssh -L 127.0.0.1:80:127.0.0.1:5601 USER@KIBANA_HOST
kibana 4
- apache reverse proxy で network 制限と basic 認証をかける(できたら mod_ssl も)
ProxyRequests Off
ProxyPreserveHost On
ProxyPass /kibana/ http://127.0.0.1:5601/ disablereuse=On ttl=120 timeout=3000
ProxyPassReverse /kibana/ http://127.0.0.1:5601/ timeout=3000
<Location /kibana>
Order Allow,Deny
Allow from 127.0.0.1 *ALLOW-NETWORKS*
<IfModule mod_authn_file.c>
AuthUserFile /path/htpasswd
AuthType Basic
</IfModule>
require valid-user
</Location>
kibana 3 から kibana 4
map
- map 用の geoip の field に geo_point 属性を付けてやる必要がある。elasticsearch-template.json を元に必要な設定を追加する。
you need to alter the template provided with the Elasticsearch output and configure the output to use the new template.
- logstash ES output に template 行を追加する。
output {
elasticsearch {
hosts => ["127.0.0.1"]
template => "/etc/logstash/elasticsearch-template.json"
template_overwrite => true
}
}
- もちろん各フィールドについても適切なマッピングをするべき。ES 2.x では(以前より早くなった) doc_values をうまく使うことも考慮する。
- 私は、type: string はすべて not_analyzed にして、本当に必要なフィールドのみ analyzed にするようにした。
(2015/11/02) LS 2.0.0 の logstash-output-elasticsearch (2.1.2) で配布される elasticsearch-template.json は ".raw" が生成されない。2.1.3 で元に戻しそうだが、やはり analyzed not_analyzed とか field type の mapping は自分でコントロールする癖をつけたほうが良いと思う。
- ".raw" がないから kibana でエラー出まくりだった...
filter edit
kibana 4 の "Discover" filter は kibana 3 のように柔軟な編集機能がまだ実装されていない
- いったん Save しておいて "Setting" -> "Objects" から "Edit visualization Object" や "Edit search Object" で直接編集すれば可能。
"query": {
"wildcard": {
"foo": "bar*"
}
}
dashboardの初期 Timepicker を任意に変更
- いったん Save しておいて "Setting" -> "Objects" から "Edit dashboard Object" の timeFrom で直接編集すれば可能。
Field が未定義という filter
- "Discover" で Field をクリックして "Quick Count" ででてくる数字をクリック。そして Invert すればよい。
- このあたりの改善は kibana 4.3.0 ぐらいには実装されそう。
dashboard URL
dashboard の URL の GET パラメータ
- panels
- row : 一番上は1
- col : size_x が 12より小さいときの横の開始位置
- size_x : 横幅全部は12、横幅半分は6
- size_y : パネルの高さ(縦方向の大きさ)
- type : visualization, search
kibana screen shots
- kibana 4 で kibana 3 風に
- kibana 4 で ssh の攻撃元マップ Heatmap カッコイイ
- 迷惑メール
メモ
テスト用途で Kibana index の replica を作りたく無い場合 (Standalone な ES の health status を Green にしたい場合)
- ./src/plugins/elasticsearch/lib/create_kibana_index.js:
number_of_replicas: 0
Elasticsearch
構造
http://127.0.0.1:9200/{INDEX}/{TYPE:mapping}/{ID:Document} http://127.0.0.1:9200/{INDEX}/{TYPE:mapping}/{ID:Document}/_source http://127.0.0.1:9200/{INDEX}/{TYPE:mapping}/_mapping http://127.0.0.1:9200/{INDEX}/{TYPE:mapping}/_mapping?pretty
http://127.0.0.1:9200/_search?q=tags:_grokparsefailure
http://127.0.0.1:9200/_cluster/health?pretty http://127.0.0.1:9200/_template?pretty
http://127.0.0.1:9200/kibana-int/_search?q=*:*&pretty http://127.0.0.1:9200/kibana-int/_search?q=*:*&size=100&pretty http://127.0.0.1:9200/kibana-int/_search/?size=100&pretty
http://127.0.0.1:9200/_nodes?clear&all&pretty
設定
- 実験環境(m3.large)で 7.5GB しかメモリがないので、まだ時々 "java.lang.OutOfMemoryError: Java heap space" がでてしまう。 少しずつ手なずけ中...
- elasticsearch.yml で特別に意識して設定して実験しているのは、
bootstrap.mlockall: true
- あとは tcsh の rmstar 的な "action.destructive_requires_name: true" か
- 起動スクリプトでは
ES_HEAP_SIZE=3g (主メモリーの半分以下で) MAX_LOCKED_MEMORY=unlimited
- まだまだノウハウが足りないで実験中。
- デフォルト値で無制限の indices.fielddata.cache.size を設定することで OOM は少なくなりそう。実験中...
http://www.elastic.co/guide/en/elasticsearch/guide/master/_limiting_memory_usage.html#fielddata-size
- これによると indices.fielddata.cache.size を設定するのは、あくまでもメモリ不足を緩和する為だけで、本来はもっとメモリーを増やすのが本道とのこと。
- まー OOM になるよるはましなので、無制限ではなくって ギリギリ目一杯 の設定にしておくのがいいかも。
http://evertrue.github.io/blog/2014/11/16/3-performance-tuning-tips-for-elasticsearch/
- ES_HEAP_SIZE=3g の場合 indices.fielddata.cache.size: 30% が限界かも...
- いちど頭打つとかなり処理速度が遅くなるようだ。
- 新しいハマりどころで、kibana で index pattern を再構築しようとして、
failed to execute [org.elasticsearch.action.admin.indices.mapping.get.GetFieldMappingsIndexRequest@XXXXXXXX]
- 対処はメモリー増やすか、index 削除ぐらい。(curator で定期的に削除する方法をとるかな...)
メンテナンス
elasticsearch-curator
/usr/local/bin/curator --host 127.0.0.1 delete indices --older-than 90 --time-unit days --timestring '%Y.%m.%d'
elasticsearch-head
Elastic HQ
- メモメモ (sysdig の パース実験中なので、type:sysdig をいろいろ削除したい
curl -XDELETE 'http://127.0.0.1:9200/logstash-YYYY.MM.DD/sysdig/_query?q=tags:_grokparsefailure'
curl -XDELETE 'http://127.0.0.1:9200/logstash-YYYY.MM.DD/sysdig'
memo
munin
- logstash をモニタリングする munin plugin (なんか微妙なのですが munin ファンなので私)
https://raymii.org/s/software/Munin_plugin_Logstash_Kibana_messages_per_hour.html
- elasticsearch の日付は UTC なので、マシンの時刻が JST な場合は、スクリプト内に date を date -u にしておく。
- 日付またぎ問題を大胆に処理してみた。
TOTAL_EVENTS=$(curl -s -k -XGET http://127.0.0.1:9200/logstash-`/bin/date -u --date "1 day ago" +%Y.%m.%d`,logstash-`/bin/date -u +%Y.%m.%d`/_search -d '{ "size": 0, "query": { "filtered": { "query": { "match_all": { } }, "filter": { "range": { "@timestamp": { "from": "'`/bin/date -u --date "1 hours ago" +%Y-%m-%dT%H:00:00`'", "to": "'`/bin/date -u +%Y-%m-%dT%H:00:00`'" } } } } }, "from": 0, "sort": { "@timestamp": { "order": "desc" } }}' | /bin/grep --only \"hits\"\:\{\"total\"\:[0-9]*,\" | /bin/grep -o [0-9]*)
おもいっきりメモ
stty -f /dev/tty.usbserial-XXXXXX 9600
cat /dev/tty.usbserial-XXXXXX | logstash-forwarder -config logstash-forwarder-arduino.conf
{
"network": {
"servers": [ "172.16.2.3:5000" ],
"timeout": 15,
"ssl strict verify": false,
"ssl ca": "/usr/local/etc/logstash/logstash-forwarder.crt"
},
"files": [
{
"paths": [ "-" ],
"fields": { "type": "stdin" }
}
]
}