Logstash cheat sheet: Difference between revisions

From misc notes
Jump to navigation Jump to search
Line 506: Line 506:
== kibana screen shots ==
== kibana screen shots ==
:Arduino YUN で計測した気象データを TimeLion で
:Arduino YUN で計測した気象データを TimeLion で
[[ファイル:TimeLion.png]]
[[ファイル:timelion.png]]


:kibana 4 で kibana 3 風に
:kibana 4 で kibana 3 風に

Revision as of 14:04, 7 December 2015

ELK (Elasticsearch + Logstash + Kibana)

splunk のデモをみて、自分の環境に logstash を入れてみた。 :)

(ELKの更新が速いので、随時記事をアップデートします。Elasticsearch 2.1.0, Logstash 2.1.0, Filebeat 1.0.0, Kibana 4.3.0)
splunk のデモを見て、構造化ロギング・高速検索・可視化の素晴らしさが解ったので、それをオープンソースの ELK stack で実現する。
ELK でログ管理をしはじめて、いままで気付かなかった事がいろいろ見えて、かなり改善しました(実感!)

logstash の書籍

突っ込んだ内容ですの大変参考になります。
The Logstash Book

logstash

構成

Deploying with Message Queueing で構成してみた。(The Logstash Book に同様な構成の構築手順あり)

この構成を取ることで、ログ収集と、ログの解析・構造化の処理が分離でき、スケールの余地と、ログを落とす可能性を低減する。
logstash architecture イメージ検索
Filebeat(送る) ↘︎
Filebeat(送る) → logstash-shipper(受け取りredisに送る) → redis(ブローカー) → logstash-indexer(パース・構造化) → Elasticsearch(蓄積・検索エンジン) → Kibana(可視化)
Filebeat(送る) ↗︎                    ↗︎
logstash-shipper(redisに送る)ーーーーーーーーーーーーー↗︎
beaver(redisに送る)ーーーーーーーーーーーーーーーーー↗︎
私は各端末には Java 環境は入れたくないので Filebeat を使ってます。ちなみに Arduino YUN の OpenWrt では python beaver から redis に送ってます。

Filebeat:

端末(filebeat) ----> 解析サーバ(logstash-shipper)

logstash-shipper:

Filebeat の待ち受け(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 の解析をしたりして自分が見たい情報に加工しています。

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
今後 GA にむけてかなり書き直されるはず。

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 設定

filebeat.yml 例

############################# Filebeat ######################################
filebeat:
  # List of prospectors to fetch data.
  prospectors:
    # Each - is a prospector. Below are the prospector specific configurations
    -
      paths:
        - /var/log/syslog
        - /var/log/mail.log
        - /var/log/auth.log
      input_type: log
      document_type: syslog
      fields_under_root: true

    -
      paths:
        - /var/log/apache2/access.log
      input_type: log
      document_type: apache
      fields_under_root: true

    -
      paths:
        - /var/log/apache2/other_vhosts_access.log
      input_type: log
      document_type: apache-other-vhost
      fields_under_root: true

    -
      paths:
        - /var/log/apache2/error.log
      input_type: log
      document_type: apache-error
      fields_under_root: true

    -
      paths:
        - /var/log/dpkg.log
      input_type: log
      document_type: dpkg
      fields_under_root: true

  # General filebeat configuration options
  #
  # Event count spool threshold - forces network flush if exceeded
  #spool_size: 1024

  # Defines how often the spooler is flushed. After idle_timeout the spooler is
  # Flush even though spool_size is not reached.
  #idle_timeout: 5s

  # Name of the registry file. Per default it is put in the current working
  # directory. In case the working directory is changed after when running
  # filebeat again, indexing starts from the beginning again.
  registry_file: /var/lib/filebeat/registry

  # Full Path to directory with additional prospector configuration files. Each file must end with .yml
  # These config files must have the full filebeat config part inside, but only
  # the prospector part is processed. All global options like spool_size are ignored.
  # The config_dir MUST point to a different directory then where the main filebeat config file is in.
  #config_dir:


###############################################################################
############################# Libbeat Config ##################################
# Base config file used by all other beats for using libbeat features

############################# Output ##########################################

# Configure what outputs to use when sending the data collected by the beat.
# Multiple outputs may be used.
output:
  ### Logstash as output
  logstash:
    # The Logstash hosts
    hosts: ["localhost:5044"]

    # Number of workers per Logstash host.
    #worker: 1

    # Optional load balance the events between the Logstash hosts
    #loadbalance: true

    # Optional index name. The default index name depends on the each beat.
    # For Packetbeat, the default is set to packetbeat, for Topbeat
    # top topbeat and for Filebeat to filebeat.
    #index: filebeat

    # Optional TLS. By default is off.
    tls:
      # 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

      # Configure cipher suites to be used for TLS connections
      #cipher_suites: []

      # Configure curve types for ECDHE based cipher suites
      #curve_types: []


############################# Shipper #########################################

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:

  # 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

  # How often (in seconds) shippers are publishing their IPs to the topology map.
  # The default is 10 seconds.
  #refresh_topology_freq: 10

  # Expiration time (in seconds) of the IPs published by a shipper to the topology map.
  # All the IPs will be deleted afterwards. Note, that the value must be higher than
  # refresh_topology_freq. The default is 15 seconds.
  #topology_expire: 15

  # Configure local GeoIP database support.
  # If no paths are not configured geoip is disabled.
  #geoip:
    #paths:
    #  - "/usr/share/GeoIP/GeoLiteCity.dat"
    #  - "/usr/local/var/GeoIP/GeoLiteCity.dat"



############################# Logging #########################################

# There are three options for the log ouput: syslog, file, stderr.
# Under Windos systems, the log files are per default sent to the file output,
# under all other system per default to syslog.
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 rotateeverybytes
  # limit is reached.
  #to_files: false
  to_files: true

  # To enable logging to files, to_files option has to be set to true
  files:
    # The directory where the log files will written to.
    #path: /var/log/mybeat
    path: /var/log/filebeat

    # The name of the files where the logs are written to.
    #name: mybeat
    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
    keepfiles: 7

  # Enable debug output for selected components. To enable all selectors use ["*"]
  # Other available selectors are beat, publish, service
  # Multiple selectors can be chained.
  #selectors: [ ]

  # Sets log level. The default log level is error.
  # Available log levels are: critical, error, warning, info, debug
  #level: error
  level: info

メンテナンス

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

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 以外はエラーになる。

rsyslog limit 解除

/etc/rsyslog.conf:

$SystemLogRateLimitInterval 0
$RepeatedMsgReduction off

kibana

kibana 4.3.0 で apache-proxy 環境で動作した。

timelion を評価してるので ssh tunneling をつかう運用に変えつつある...
ssh -n -N -o BatchMode=yes -L 127.0.0.1:80:127.0.0.1:5601 USER@KIBANA_HOST

4.2.2 で対応できそう。

https://github.com/elastic/kibana/pull/5337
Merge pull request #5337 from spalger/fix/relativePathsInKibana
# If you are running kibana behind a proxy, and want to mount it at a path,
# specify that path here. The basePath can't end in a slash.
# server.basePath: ""

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

Arduino YUN で計測した気象データを TimeLion で

ファイル:timelion.png

kibana 4 で kibana 3 風に

ファイル:Kibana4-apache.png

kibana 4 で ssh の攻撃元マップ Heatmap カッコイイ

ファイル:Kibana4-sshd-heatmap.png

迷惑メール

ファイル:Kibana4-amavis.png

メモ

テスト用途で 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" }
    }
  ]
}