ラック
Home > ブログ > 記事 > 2016年12月 > ELKスタック構築の記録

ELKスタック構築の記録

カテゴリ: Linux, サーバ

途中嵌まったり沼に落ちたりした作業メモから、成功した部分のみを抽出して手順書とします。

目次

目標

ELKスタックのインストール・構築。最終的には、Kibanaでログを解析した結果のグラフの表示を行う。

事前情報

  1. Beats:エージェントとしてログサーバにログを投げる
  2. Logstash:Beatsが投げてきたログをキャッチして、Elasticsearchに蓄積しやすい形にデータを整形・加工してElasticsearchに渡す
  3. Elasticsearch:ログ蓄積サーバ&全文検索エンジン
  4. Kibana:Elasticsearchに蓄積されたログデータを条件によって抽出・結果を可視化する

ざっくり調べた感じでは、こんなイメージです。なお、各ツールの開発環境は多彩で

  • Beats:Go言語
  • Logstash:JRuby
  • Elasticsearch:Java
  • Kibana:node.js

という環境になっているようです(インストールの際には気にしなくても良いですが)。

テスト環境・方針

サーバA
Apacheのログと、オリジナルアプリの独自フォーマットのログの2種をBeatsを使ってサーバBに蓄積させる
サーバB
ELKスタック(Elasticsearch, Logstash, Kibana)を構築するサーバ

サーバAにテキスト形式で2つのログがダンプされるので、FilebeatでサーバBに投げる、という方針。

なお、サーバA、BともにCentOSとします。

また、製品ページでの最新版のバージョンは5.0.2のようです(216/12/9現在)。各インストール手順のコマンドは6.0.0-alpha1になっていてずれているのですが、コマンド内のバージョンを5.0.2に合わせて実行します。

Elasticsearch

基本は上記ページに沿ってコマンドを入力します。

ダウンロード&インストール


#curl -L -O https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5.0.2.rpm
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 31.3M  100 31.3M    0     0  3813k      0  0:00:08  0:00:08 --:--:-- 5824k

#sudo rpm -i elasticsearch-5.0.2.rpm
警告: elasticsearch-5.0.2.rpm: ヘッダ V4 RSA/SHA512 Signature, key ID d88e42b4: NOKEY
Creating elasticsearch group... OK
Creating elasticsearch user... OK
### NOT starting on installation, please execute the following statements to configure elasticsearch service to start automatically using chkconfig
 sudo chkconfig --add elasticsearch
### You can start elasticsearch service by executing
 sudo service elasticsearch start

#sudo service elasticsearch start
elasticsearch を起動中:                                    [  OK  ]

ダウンロード時に暗号化キーの設定しなかったのですが、とりあえず起動までOK。

動作テスト


# curl http://127.0.0.1:9200
{
  "name" : "541jXlG",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "yIYeR4yRQxGAtDPMZh4osA",
  "version" : {
    "number" : "5.0.2",
    "build_hash" : "f6b4951",
    "build_date" : "2016-11-24T10:07:18.101Z",
    "build_snapshot" : false,
    "lucene_version" : "6.2.1"
  },
  "tagline" : "You Know, for Search"
}

curlで9200ポートにアクセスし、json形式のデータが戻ってくればOKです。※Elasticsearchは結構スペックを要求されるので、環境によっては起動に時間がかかる場合があります。curl: (7) couldn’t connect to hostとなっても焦らないこと。

一旦停止し、設定変更

Elasticsearch 5.0.2はデフォルトではローカルホストからのアクセスしか受け付けません。

しかし、Logstashを使う場合、Filebeatの設定の際にElasticsearchのテンプレートをFilebeat側に読み込ませる必要があります。FilebeatはELKスタックを構築するサーバ(サーバB)の外(サーバA)にあるため、Elasticsearchに外部からアクセスできるように設定します。設定するパラメータはnetwork.hostです。


# sudo service elasticsearch stop
elasticsearch を停止中:                                    [  OK  ]

# vi /etc/elasticsearch/elasticsearch.yml
# ---------------------------------- Network -----------------------------------
#
# Set the bind address to a specific IP (IPv4 or IPv6):
#
#network.host: 192.168.0.1
network.host: 0.0.0.0 #追加

kuromojiのインストール

ついでに、kuromojiも入れます。Elasticsearchはデフォルトでは日本語の検索に対応しておらず、それを対応させるためのプラグインがkuromojiになります。


# /usr/share/elasticsearch/bin/elasticsearch-plugin install analysis-kuromoji
-> Downloading analysis-kuromoji from elastic
[=================================================] 100%??
-> Installed analysis-kuromoji

OKです。

ファイルディスクリプタの上限を設定

Java系のアプリケーションの場合、ファイルディスクリプタ(実行可能なスレッド数)の上限に達してアプリケーションが起動直後に落ちることがしばしばあるようです。Elasticsearchも消費量が多く、テスト途中に起動しないことがあったので、この上限値を引き上げる設定を行います。

今回は


sudo service elasticsearch start

でサービスを起動しているので、rootの上限数を引き上げます。


# ulimit -n 2048
# ulimit -n
2048

OKです。

Elasticsearchを再起動


# sudo service elasticsearch start
elasticsearch を起動中:                                    [  OK  ]

ログ確認

Elasticsearchの動作ログは/var/log/elasticsearch/elasticsearch.logを見れば確認できます。

例えば、先のファイルディスクリプタの上限を引き上げなかった場合、ログにmax number of threads [1024] for user [elasticsearch] is too low, increase to at least [2048]というログが記録されます。

Logstash

ダウンロード&インストール

こちらも上記ページに従います。


#curl -L -O https://artifacts.elastic.co/downloads/logstash/logstash-5.0.2.rpm
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  100M  100  100M    0     0  1563k      0  0:01:06  0:01:06 --:--:--  921k

#sudo rpm -i logstash-5.0.2.rpm
警告: logstash-5.0.2.rpm: ヘッダ V4 RSA/SHA512 Signature, key ID d88e42b4: NOKEY
Using provided startup.options file: /etc/logstash/startup.options
Successfully created system startup script for Logstash

入りました。

ドキュメントでは「ver1.5.4ちょうどの場合はBeats用プラグインを入れて」とありますが、今回は5.0.2なのでその部分はスルーします(ただしアップデートは行う)。まずは設定を行います。


# cd /etc/logstash/conf.d/
 
# vi logstash.conf
input {
  beats {
    port => 5044
  }
}

output {
  elasticsearch {
    hosts => "localhost:9200"
    manage_template => false
    index => "%{[@metadata][beat]}-%{+YYYY.MM.dd}"
    document_type => "%{[@metadata][type]}"
  }
}

とりあえずサンプルをそのまま貼り付けて名前もそのままでテストします。この設定は最後の方で変更・調整します。

Beats用プラグインのアップデート

先述の通り、Beats用プラグインのアップデートを行います。


# whereis logstash
logstash: /etc/logstash /usr/share/logstash

whereisコマンドでlogstash本体の所在を確認し、ディレクトリに移動。


# cd /usr/share/logstash/
# ./bin/logstash-plugin update logstash-input-beats
Updating logstash-input-beats
Updated logstash-input-beats 3.1.8 to 3.1.12

アップデート完了です。

Logstashの起動

サービス化しておらず、service logstash startでは起動できなかったのでコマンドで起動させます。


# pwd
/usr/share/logstash

# ./bin/logstash -f /etc/logstash/conf.d/logstash.conf &
[1] 1734

最後の&(バックグラウンドで実行)を抜かすとlogstashのログが標準出力にダンプされて作業できなくなるので注意。

Logstashの停止

service logstash stopが使えないので、Logstashを停止するには


# ps aux | grep logstash

でプロセスIDを見付けて


# kill

で停止させます。なお、テスト環境ではkillした直後にすぐ起動を始めたので注意。logstash.confの調整で難度もkillする場合は、

  1. Logstashが動いていても構わないので、logstash.confを編集
  2. kill -1 Logstashのpid

と-1オプションを付けてkillすればOK。設定の読み込みが成功しているか否かは/var/log/logstash/logstash-plain.logを見れば確認できます。

Kibana

こちらも公式ドキュメント通りに。

ダウンロード&インストール


#curl -L -O https://artifacts.elastic.co/downloads/kibana/kibana-5.0.2-linux-x86_64.tar.gz
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 38.3M  100 38.3M    0     0  1273k      0  0:00:30  0:00:30 --:--:--  520k

# tar xzvf kibana-5.0.2-linux-x86_64.tar.gz

##大量に展開

Kibanaは今までと違って展開があります。大量に展開されるので待ちます。

設定変更

KibanaはPCから画面を開いてログを見る部分なので、当然外部からアクセスすることになります。しかし、Elasticsearchと同様にデフォルトではローカルホストからのアクセスしか許可されていないので、外部からのアクセスも受け付けるように設定します。設定するパラメータはserver.hostです。network.hostではありません。


# vi config/kibana.yml

# Specifies the address to which the Kibana server will bind. IP addresses and host names are both valid values.
# The default is 'localhost', which usually means remote machines will not be able to connect.
# To allow connections from remote users, set this parameter to a non-loopback address.
#server.host: "localhost"
server.host: 0.0.0.0 #追加

起動


# cd kibana-5.0.2-linux-x86_64/

# ./bin/kibana &
[1] 8170
#   log   [08:40:00.403] [info][status][plugin:kibana@5.0.2] Status changed from uninitialized to green - Ready
  log   [08:40:00.505] [info][status][plugin:elasticsearch@5.0.2] Status changed from uninitialized to yellow - Waiting for Elasticsearch
  log   [08:40:00.563] [info][status][plugin:console@5.0.2] Status changed from uninitialized to green - Ready
  log   [08:40:00.590] [info][status][plugin:elasticsearch@5.0.2] Status changed from yellow to green - Kibana index ready
  log   [08:40:00.877] [info][status][plugin:timelion@5.0.2] Status changed from uninitialized to green - Ready
  log   [08:40:00.884] [info][listening] Server running at http://0.0.0.0:5601
  log   [08:40:00.886] [info][status][ui settings] Status changed from uninitialized to green - Ready

これでブラウザでアクセスし、下記のような画面が表示されればOkです。

動作確認・停止方法

Kibanaはnode.jsで動いているため、プロセスIDでkillする場合は

メモ


# ps aux | grep node

とnodeでgrepすると見付かります(他にnode.jsを使用しているものがなければ)。あとはkillすればOkです。

Beats(Filebeat)

ダウンロード&インストール

ドキュメントの通りに進めるのは今までと同じです。ここでは、Filebeatをインストールします。

なお、Filebeatの作業はログをダンプするサーバ(冒頭の説明でいうと、サーバA)で作業します。


# curl -L -O https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-5.0.2-x86_64.rpm
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 8447k  100 8447k    0     0  1712k      0  0:00:04  0:00:04 --:--:-- 2234k

# sudo rpm -vi filebeat-5.0.2-x86_64.rpm
警告: filebeat-5.0.2-x86_64.rpm: ヘッダ V4 RSA/SHA512 Signature, key ID d88e42b4: NOKEY
パッケージインストールの準備中...
filebeat-5.0.2-1

# whereis filebeat
filebeat: /usr/bin/filebeat.sh /etc/filebeat /usr/share/filebeat

インストール完了。

設定変更


# vi /etc/filebeat/filebeat.yml

- input_type: log

  # Paths that should be crawled and fetched. Glob based paths.
  paths:
    - /var/log/httpd/*_log #追加
  document_type: apache #追加
- input_type: log
  paths:
    - /MY/APP/log/*.log #追加
  document_type: originapp #追加

#-------------------------- Elasticsearch output ------------------------------
#output.elasticsearch: #コメントアウト
  # Array of hosts to connect to.
  #hosts: ["localhost:9200"] #コメントアウト

#----------------------------- Logstash output --------------------------------
output.logstash: #コメント外す
  # The Logstash hosts
  #hosts: ["localhost:5044"]
  hosts: ["XXX.XXX.XXX.XXX:5044"] #サーバBのIPを指定

Filebeatの設定ですが、今回は

  • Webサーバ
  • オリジナルアプリのログ

の2つが見たかったのでそれをinputに指定します。Logstashを経由させるのでElasticsearchの設定はコメントアウトして、逆にLogstashの設定のコメントを外します(サーバのIPを指定)。

設定テスト


# cd /usr/share/filebeat/bin/

# ./filebeat -configtest -e -path.config /etc/filebeat/
beat.go:264: INFO Home path: [/usr/share/filebeat/bin] Config path: [/etc/filebeat/] Data path: [/usr/share/filebeat/bin/data] Logs path: [/usr/share/filebeat/bin/logs]
beat.go:174: INFO Setup Beat: filebeat; Version: 5.0.2
logp.go:219: INFO Metrics logging every 30s
logstash.go:90: INFO Max Retries set to: 3
outputs.go:106: INFO Activated logstash as output plugin.
publish.go:291: INFO Publisher name: bbs.acs-net.co.jp
async.go:63: INFO Flush Interval set to: 1s
async.go:64: INFO Max Bulk Size set to: 2048
Config OK

設定テスト。OKです。

Logstash・Elasticserachとの連携部分の設定

Loading the Template Manually – required for Logstash output

Step 4: Loading the Index Template in Elasticsearch | Filebeat Reference [master] | Elastic

とのことで、Logstashを使う場合は手動でElasticsearchからFilebeatのテンプレートを読み込ませないといけないので、その設定を行います。

先にElasticsearchの外部からのアクセスを許可する設定をしておいたので、読み込めるはずです。


# curl -XPUT 'http://XXX.XXX.XXX.XXX:9200/_template/filebeat' -d@/etc/filebeat/filebeat.template.json

テンプレートのインポートができました。


# sudo /etc/init.d/filebeat start
Starting filebeat:
beat.go:264: INFO Home path: [/usr/share/filebeat] Config path: [/etc/filebeat] Data path: [/var/lib/filebeat] Logs path: [/var/log/filebeat]
beat.go:174: INFO Setup Beat: filebeat; Version: 5.0.2
logp.go:219: INFO Metrics logging every 30s
logstash.go:90: INFO Max Retries set to: 3
outputs.go:106: INFO Activated logstash as output plugin.
publish.go:291: INFO Publisher name: bbs.acs-net.co.jp
async.go:63: INFO Flush Interval set to: 1s
async.go:64: INFO Max Bulk Size set to: 2048
Config OK
                                                           [  OK  ]

Filebeatの起動完了。

Kibanaで全体の動作確認

再びKibanaの画面を開いて、ログが取得されていればOKです。

Logstashのフィルタの調整

最後に、Logstashのフィルタの調整をします。やりたいことは

  • Apacheとオリジナルアプリの独自フォーマットの2つのログを取り込む
  • それぞれに対して適切にログの各パラメータをフィールド(DB的にいうとカラム(列))に落とし込む

といったところです。Apacheのログは専用テンプレートが存在するのでそれを指定すれば済むのですが、独自フォーマットのログはそうも行かないため、パターンを記述する必要があります。今回の独自フォーマットは


YYYY-MM-DDThh:mm:ss+09:00, TO=<fuga@example.com>, FROM=<piyo@example.com>, CC=<>, SUBJECT:HOGERA

といった感じの、メールフォームのログです。注意としてはCCの部分で、CC未入力の場合は上記のようにCC=<>となりますが、最大2つまで入力可能で、その場合は


YYYY-MM-DDThh:mm:ss+09:00, TO=<fuga@example.com>, FROM=<piyo@example.com>, CC=<hogehoge@example.com>, CC2=<fugafuga@example.com>, SUBJECT:HOGERA

といったようにCC2が増えるなど可変な点です。これを踏まえてlogstash.confを変更します。


input {
  beats {
    port => 5044
  }
}

filter {
  if [type] == "apache" {
    grok {
      match => { "message" => "%{COMBINEDAPACHELOG}" }
    }
    date {
      match => [ "timestamp" , "dd/MMM/yyyy:HH:mm:ss Z" ]
      locale => en
    }
  } else if [type] == "originapp" {
    grok {
      match => { "message" => "%{TIMESTAMP_ISO8601:timestamp}, TO=\<%{NOTSPACE:to}?\>, FROM=\<%{NOTSPACE:from}\>, CC=\<%{NOTSPACE:cc}*>(, CC2=\<%{NOTSPACE:cc2}?\>)?, SUBJECT:%{GREEDYDATA:subject}" }
    }
  }
}

output {
  if [type] == "apache" {
    elasticsearch {
      hosts => "localhost:9200"
      index => "apache-log_%{+YYYYMMdd}"
    }
  } else if [type] == "originapp" {
    elasticsearch {
      hosts => "localhost:9200"
      index => "originapp-log_%{+YYYYMMdd}"
    }
  }
}

こんな感じに。

  • if [type]はfilebeat.ymlのdocument_typeに対応しているので、そこで処理を振り分けています。
  • Apacheのログは“%{COMBINEDAPACHELOG}”でテンプレートを指定できるのでそれを利用
  • %{PATTERN_NAME:variable_name}という%と{}でくくった形でパターンを記述します。{}内左側がgrokで指定できるパターン、右側は変数名になります。また、マッチした場合は変数名で自動的にフィールド(カラム)に落ちるので、変数名がそのままKibanaで指定するTermの名前になります
  • originappの場合はログのパターンを地道に記述。基本的には正規表現のルールです
    • <, >はエスケープが必要
    • 複数のパターンにマッチさせるには、
      
          grok {
            match => { "message" => [
                "PATTERN1",
                "PATTERN2"
            ] }
          }
              

      のようにパターンを配列に収めてしまうのも手ですが、今回は?(直前に指定したパターンが0または1回あるか)や*(直前に指定したパターンが0回以上あるか)を使うことでCC=\<%{NOTSPACE:cc}*(メールアドレスがあってもなくてもマッチ)>(, CC2=\<%{NOTSPACE:cc2}?(CC2にメールアドレスがある)\>)?(括弧でくくったパターンが0または1回ある)というように、1行で記述することができました

    • NOTSPACEはスペース以外、なのでメールアドレスかどうかは判定していません(あくまで文字列があるかどうか)
  • outputの中のindexがKibanaで抽出する際のIndex Pettern(DB的にはテーブル)になるので、分かりやすい名前にします

以上で、やりたかった動作は実現できました。

参考

事前情報

手順など

Logstashのフィルタ調整

Logstashの設定の参考

Filebeatの設定

詰まったときの調査など

タグ: データベース, サーバ環境・構築, 手順

 



関連する記事一覧