JP7FKFの備忘録

ヒトは,忘れる生き物だから.

Ubuntu18.04にELK Stackを構成する

概要

  • Ubuntu18.04に
  • Elasticsearch(7.7)まわりのdebパッケージを
  • aptレポジトリから引っ張ってきて
  • インストールして
  • Logstash(log insert) -> Elasticsearch(processiog) <-> Kibana(visualize)ができる ところまでを実施します.

基本的に下記を参照します

Elastic Stack Install Battle

Install PGP key

$ wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -
OK

add repository to apt source list

$ echo "deb https://artifacts.elastic.co/packages/7.x/apt stable main" | sudo tee -a /etc/apt/sources.list.d/elastic-7.x.list
deb https://artifacts.elastic.co/packages/7.x/apt stable main

Install Elasticsearch

$ sudo apt update
$ sudo apt install elasticsearch
$ sudo apt install elasticsearch
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following NEW packages will be installed:
  elasticsearch
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 314 MB of archives.
After this operation, 527 MB of additional disk space will be used.
Get:1 https://artifacts.elastic.co/packages/7.x/apt stable/main amd64 elasticsearch amd64 7.7.0 [314 MB]
Fetched 314 MB in 5min 57s (881 kB/s)
Selecting previously unselected package elasticsearch.
(Reading database ... 116882 files and directories currently installed.)
Preparing to unpack .../elasticsearch_7.7.0_amd64.deb ...
Creating elasticsearch group... OK
Creating elasticsearch user... OK
Unpacking elasticsearch (7.7.0) ...
Setting up elasticsearch (7.7.0) ...
Created elasticsearch keystore in /etc/elasticsearch/elasticsearch.keystore
Processing triggers for ureadahead (0.100.0-21) ...
Processing triggers for systemd (237-3ubuntu10.40) ...

ここまででelasticsearch自体のインストール自体は完了.

  • ヒープサイズのconfig
    JVMで使わせるヒープサイズをチューンする.一般には物理メモリの約半分を割り当てればいいそう. ただし32GBらへんに圧縮オブジェクトポインタのしきい値があるらしく,だいたい26GB以下にしておけば安全そう.
  • ref: Setting the heap size | Elasticsearch Reference [7.7] | Elastic
    今回は物理メモリとして16GB割り当てているので8GBにしておく.
$ sudo cat /etc/elasticsearch/jvm.options | head -30
## JVM configuration

################################################################
## IMPORTANT: JVM heap size
################################################################
##
## You should always set the min and max JVM heap
## size to the same value. For example, to set
## the heap to 4 GB, set:
##
## -Xms4g
## -Xmx4g
##
## See https://www.elastic.co/guide/en/elasticsearch/reference/current/heap-size.html
## for more information
##
################################################################

# Xms represents the initial size of total heap space
# Xmx represents the maximum size of total heap space

-Xms8g
-Xmx8g

################################################################
## Expert settings
################################################################
##
## All settings below this section are considered
## expert settings. Don't tamper with them unless
$ sudo vim /etc/elasticsearch/elasticsearch.yml
# ---------------------------------- Network -----------------------------------
#
# Set the bind address to a specific IP (IPv4 or IPv6):
#
network.host: <bind_ip>
#
# Set a custom port for HTTP:
#
http.port: 9200
#
# For more information, consult the network module documentation.

脳死したければ network.host: "0.0.0.0"とか入れておけばいいと思う.v6なら network.host: "::0"とか?

  • 起動してみる.
    構築したホスト上でcurl "http://localhost:9200/" を打つと実際にelasticsearchにアクセスすることができる.
$ sudo systemctl start elasticsearch.service
$ sudo systemctl enable elasticsearch.service
$ sudo systemctl status elasticsearch.service
● elasticsearch.service - Elasticsearch
   Loaded: loaded (/usr/lib/systemd/system/elasticsearch.service; disabled; vendor preset: enabled)
   Active: active (running) since Sat 2020-05-16 14:33:17 UTC; 1 day 13h ago
     Docs: https://www.elastic.co
 Main PID: 3301 (java)
    Tasks: 83 (limit: 4915)
   CGroup: /system.slice/elasticsearch.service
           ├─3301 /usr/share/elasticsearch/jdk/bin/java -Xshare:auto -Des.networkaddress.cache.ttl=60 -Des.networkadd
           └─3505 /usr/share/elasticsearch/modules/x-pack-ml/platform/linux-x86_64/bin/controller

May 16 14:33:01 elk01 systemd[1]: Starting Elasticsearch...
May 16 14:33:17 elk01 systemd[1]: Started Elasticsearch.

$ curl "http://localhost:9200/"
{
  "name" : "ela01",
  "cluster_name" : "elc01",
  "cluster_uuid" : "xxxxxxxxxxxxxxxxxxxxxx",
  "version" : {
    "number" : "7.7.0",
    "build_flavor" : "default",
    "build_type" : "deb",
    "build_hash" : "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "build_date" : "2020-05-12T02:01:37.602180Z",
    "build_snapshot" : false,
    "lucene_version" : "8.5.1",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}
  • [つぶやき]: javaをinstallしてないのに動いたなーと思ったらelasticsearchのパッケージを入れるとjavaも一緒に入ってくるっぽい
$ /usr/share/elasticsearch/jdk/bin/java --version
openjdk 13.0.2 2020-01-14
OpenJDK Runtime Environment AdoptOpenJDK (build 13.0.2+8)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 13.0.2+8, mixed mode, sharing)

debパッケージをdpkgでいれたりtarballで引っ張ってきて展開したjavaまでついてくるかは知らない. 前はaptでも別にjdk入れないといけなかった気がしたけど,もう忘れてしまった.少なくとも最近のaptからのinstallでは一緒についてくるらしい.
- Elastic Support Matrix | Elasticsearch
と思ったらこれのサポートはあくまでelasticsearchを動かすだけにすぎなかった.elasticsearch本体だけなら動くけどlogstashとかはこのjdk verでは動かない. javaまでのpathが通ってない(and JAVA_HOMEが適切に環境変数に設定されていないと)こんな感じでapt installでerrorを吐く.

$ sudo apt install logstash
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following NEW packages will be installed:
  logstash
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 167 MB of archives.
After this operation, 295 MB of additional disk space will be used.
Get:1 https://artifacts.elastic.co/packages/7.x/apt stable/main amd64 logstash all 1:7.7.0-1 [167 MB]
Fetched 167 MB in 4min 54s (569 kB/s)
Selecting previously unselected package logstash.
(Reading database ... 103575 files and directories currently installed.)
Preparing to unpack .../logstash_1%3a7.7.0-1_all.deb ...
Unpacking logstash (1:7.7.0-1) ...
Setting up logstash (1:7.7.0-1) ...
could not find java; set JAVA_HOME or ensure java is in PATH
chmod: cannot access '/etc/default/logstash': No such file or directory
dpkg: error processing package logstash (--configure):
 installed logstash package post-installation script subprocess returned error exit status 1

なのでやっぱりELK stackを構築するなら
$ sudo apt install openjdk-8-jre
するのが正解.最近のELKコンポーネントだとopenjdk-11でもいいっぽいけどまぁ好きなの使えばいい気がする.ただjdk9以降はaptとかでさくっと入らないっぽく見えるからめんどそう.

Install logstash and Kibana

$ java -version
openjdk version "1.8.0_252"
OpenJDK Runtime Environment (build 1.8.0_252-8u252-b09-1~18.04-b09)
OpenJDK 64-Bit Server VM (build 25.252-b09, mixed mode)

javaが入ってる(PATHが通る)ことを確認して

sudo apt install logstash
sudo apt install kibana

でさくっとはいる.javaへのPATHが通ってないと失敗するので注意.

  • kibanaのconfig
$ sudo vim /etc/kibana/kibana.yml
server.port: 5601
server.host: "<bind_ip>"
elasticsearch.hosts: ["http://localhost:9200"]

<bind_ip>には前述のとおりlistenするipを入れる.

  • logstashのconfig
$ sudo vim /etc/logstash/jvm.options
-Xms8g
-Xmx8g
  • 起動
$ sudo systemctl start logstash
$ sudo systemctl start kibana
$ sudo systemctl enable logstash
$ sudo systemctl enable kibana

$ sudo systemctl status logstash
● logstash.service - logstash
   Loaded: loaded (/etc/systemd/system/logstash.service; disabled; vendor preset: enabled)
   Active: active (running) since Sat 2020-05-16 15:33:30 UTC; 1 day 11h ago
 Main PID: 7282 (java)
    Tasks: 43 (limit: 4915)
   CGroup: /system.slice/logstash.service
           └─7282 /usr/bin/java -Xms4g -Xmx4g -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseC
...(snip)...

$ sudo systemctl status kibana
● kibana.service - Kibana
   Loaded: loaded (/etc/systemd/system/kibana.service; enabled; vendor preset: enabled)
   Active: active (running) since Sat 2020-05-16 14:40:41 UTC; 1 day 12h ago
 Main PID: 4569 (node)
    Tasks: 11 (limit: 4915)
   CGroup: /system.slice/kibana.service
           └─4569 /usr/share/kibana/bin/../node/bin/node /usr/share/kibana/bin/../src/cli -c /etc/kibana/kibana.yml
...(snip)...

ex. syslog insert to elasticsearch via logstash

syslogをlogstash経由でelasticsearchにいれてkibanaでみるところまでをやってみる. まずはsyslog pluginをlogstash-pluginを使って入れる.

$ /usr/share/logstash/bin/logstash-plugin list syslog
logstash-filter-syslog_pri
logstash-input-syslog
$ /usr/share/logstash/bin/logstash-plugin install logstash-input-syslog
ERROR: File /usr/share/logstash/Gemfile does not exist or is not writable, aborting
$ sudo /usr/share/logstash/bin/logstash-plugin install logstash-input-syslog
Validating logstash-input-syslog
Installing logstash-input-syslog
Installation successful

次にlogstashのconfigを作っていく. 適当にsyslogを受ける例を書くとこんな感じ.

$ cat /etc/logstash/conf.d/01-syslog.conf
input {
  syslog {
      port => 10514
      type => "syslog"
  }
}

filter {
} # filter

output {
  if "syslog" in [type] {
    elasticsearch {
      hosts => ["localhost:9200"]
      index => "logstash-syslog"
   }
    # stdout { codec => rubydebug }
  }
}

ポート番号1024以下はpriviledgedなのでroot権限等がないとpermission deniedで弾かれる.
rootで実行するのも一つの手ではあるが,下記などではport forward(redirect)する例が挙げられている.
今回は10514としてそのまま利用する.

configを書いたらlogstash をrestartする.logstashの嫌なところはこのconfigを変えたらrestartする必要があるところ. 前段にkafkaなどのqueueをいれたりするのがこのrestartによるデータ欠損回避手段のうちの一つかもしれない.

$ sudo systemctl restart logstash

さて,ここまででlogstash -> elasticsearch ->kibanaのパイプラインが完成した.
実際にlogを突っ込んで見る.

logger -n localhost -P 10514 -t mytest -p user.notice --rfc3164 "TEST LOG"

これで送られた"はず"である.

ここからはkibanaでみていこう.
kibanaへはconfigした通り,デフォルトでは5601ポートでアクセスする.
kibanaでデータを取り扱う上でまずindex-patternを作る必要がある. Management -> Index Managementでelasticsearch側に先程のsyslogのindexが作成されていることを確認.
これがないとindex patternを作っても見れない.これがない場合elasticsearchに正常にinsertされていない可能性が高いのでまずはそのdebugをしよう.
この画面ではlogstashのconfigでindexとして指定したlogstash-syslogが見えている. f:id:jp7fkf:20200518215937p:plain elasticsearchにindexがあることが確認できたら,今度はkibana側のindex patternsを見る デフォルトだと何も登録されていないので,Create Index Patternを押す f:id:jp7fkf:20200518220014p:plain するとelasticsearchのindexが候補で見えてくる. f:id:jp7fkf:20200518220020p:plain index patternの定義をするので,textboxにindex patternの名前(ワイルドカード可)を入れて1つに絞る.
ここではlogstash-syslogそのまま入れると一つに絞ることができるのでNext Stepが押せるようになる. f:id:jp7fkf:20200518220026p:plain 次にtime filter firldを指定する.ここではlogstashでつける@timestampをそのまま使う. これでCreate Index Patternを押す. f:id:jp7fkf:20200518220046p:plain するとIndexがつくられて f:id:jp7fkf:20200518220031p:plain Index Patternのできあがり. f:id:jp7fkf:20200518220035p:plain discover画面に行って確認すると,無事先ほどのloggerコマンドで転送したログが見える. f:id:jp7fkf:20200518220040p:plain

ここまでで一通りELKスタックを用いてsyslogをkibanaで見えるようになった.

 まとめ

  • Ubuntu18.04にElastic Stack (ELK, Logstash, Elasticsearch, Kibana)をaptパッケージを用いて構築した
  • Logstash(log insert) -> Elasticsearch(processiog) <-> Kibana(visualize)のパイプラインにsyslogを投入しkibanaで観測した.

logstashにはこの他にも色々なpluginがあり,様々なデータをELKスタックを用いてデータ分析/可視化することができる . また,logstash以外にもelasticsearchへの出力機能を持ったコンポーネント(ex. fluentd)などが数多くあるので,それらとうまく組み合わせて柔軟な分析基盤の構成ができそうである.

個人的にはDHCPサーバのリースログからクライアントのMACアドレスのベンダコード(OUI)をもとにベンダをを可視化したり,xflow(sflow/netflow)を食わせてgeo-ipの緯度経度データとIPアドレスを突き合わせてどの国/regionとの通信が多いのかを可視化したりすることもやってみたが,なかなかおもしろい. flowデータをもとにすれば通信をポート番号ベースで可視化したりすることができ,特定ポート宛などのDDoSの検知や内部から外部への不正な大量トラフィック(マルウェア感染端末からのDNS Amp.など)の検出もできそうである.可視化で得られた異常なデータをクリックすることでそのデータの詳細なレコードもkibanaならすぐに見ることができてユーザ体験はとてもよい.
可視化することは人間に直感的にあらゆる物事を短時間で理解させることを手助けする大きな価値のある手法であると思うので,是非このような可視化/分析ツール活用していきたいものである.