IDCF テックブログ

IDCF テックブログ

クラウド・データセンターを提供するIDCフロンティアの公式テックブログ

Fluentd + Elasticsearch + Kibanaでログを可視化

こんにちは、インフラ開発部の鳥垣です。

今回のブログではアクセスログの解析作業の効率化を図るため、ログの可視化のお話をさせていただければと思います。 導入の背景は、仕組みとしてサーバーからsyslogサーバーへのログの集積はすでに実装されていました。 しかし、syslogへの送信元のサーバー数の肥大化に伴い多量のログが保存されるようになり、ログ調査に時間がかかるようになってきました。 もっとサックリとログの調査を行う基盤が欲しいということで、今回Fluentd + Elasticsearch + Kibanaを導入しました。 FluentdでsyslogサーバーからElasticsearchにログを送り、Elasticserchでログ検索、Kibanaでグラフ化しました。 Fluentd + Elasticsearch + Kibanaを導入する際の設定や、構成などを紹介します。

f:id:syamada21:20170914103914p:plain

システム構成

f:id:ttorigaki:20170823135135p:plain

  • サーバー情報(10台)
OS CPUコア数 メモリ HDD
CentOS 7.3 24 64GB 500GB

※全台スペック共通の物理サーバーです。

  • バージョン情報
ミドルウェア バージョン
Elasticsearch 5.5.0
kibana 5.5.0
Fluentd 2.3.5

※Elasticsearchは10台でクラスタ構築しています。

※Kibanaで使用するサーバーがリソースに余裕があったのでFluentdと兼用しています。

インストール

Elasticsearch

最初にjdkをインストールします。

sudo yum install java-1.8.0-openjdk

以下手順でElasticsearchをインストールします。

sudo rpm --import https://artifacts.elastic.co/GPG-KEY-elasticsearch
 
sudo vim /etc/yum.repos.d/elasticsearch.repo にて以下内容のファイルを作成します。
[elasticsearch-5.x]
name=Elasticsearch repository for 5.x packages
baseurl=https://artifacts.elastic.co/packages/5.x/yum
gpgcheck=1
gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
enabled=1
autorefresh=1
type=rpm-md
 
sudo yum install elasticsearch
kibana

最初にjdkをインストールします。

sudo yum install java-1.8.0-openjdk

以下手順でkibanaをインストールします。

sudo rpm --import https://artifacts.elastic.co/GPG-KEY-elasticsearch
 
sudo vim /etc/yum.repos.d/kibana.repo にて以下内容のファイルを作成します。
[kibana-5.x]
name=Kibana repository for 5.x packages
baseurl=https://artifacts.elastic.co/packages/5.x/yum
gpgcheck=1
gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
enabled=1
autorefresh=1
type=rpm-md
 
sudo yum install kibana
Fluentd

以下手順でFluentdをインストールします。

sudo curl -L https://toolbelt.treasuredata.com/sh/install-redhat-td-agent2.sh | sh
  • Fluentdのプラグインをインストール

送信側

sudo /usr/sbin/td-agent-gem install fluent-plugin-multiprocess

受信側

sudo /usr/sbin/td-agent-gem install fluent-plugin-multiprocess
sudo /usr/sbin/td-agent-gem install fluent-plugin-multi-format-parser
sudo /usr/sbin/td-agent-gem install fluent-plugin-elasticsearch
sudo /usr/sbin/td-agent-gem install fluent-plugin-file-alternative

Elasticsearchの設定

/etc/elasticsearch/elasticsearch.yml を変更します。

cluster.name: cluster_name ← 任意の名前を指定。
 
network.host: 0.0.0.0 ← リモートホストからの接続を受け付けられるように設定。
 
bootstrap.memory_lock: true ←スワップ無効化の設定。
 
node.name: hostname ← サーバーのホスト名を指定。
 
discovery.zen.ping.unicast.hosts: ["xxx.xxx.xxx.xxx", "xxx.xxx.xxx.xxx","xxx.xxx.xxx.xxx"] ←ElasticsearchをインストールしたサーバーのIPアドレスを指定。
 
discovery.zen.minimum_master_nodes: 6 ← 計算式(ノード数 / 2 + 1)に従った数値を指定。10台の場合は6。

ヒープ設定を変更するため、/etc/elasticsearch/jvm.options を変更します。

今回使用するサーバーのメモリが64GBのため半分の32GBを指定します。

-Xms32g
-Xmx32g

kibanaの設定

/etc/kibana/kibana.yml を変更します。

server.host: "0.0.0.0" ← リモートホストからの接続を受け付けられるように設定。
 
elasticsearch.url: "http://xxx.xxx.xxx.xxx:9200" ←ElasticsearchサーバーのIPを指定。

Fluentdの設定

ログデータの送信

解析対象のアクセスログはsyslogサーバーに集約されているので、syslogサーバーにFluentdをインストールし、アクセスログを読み込んで送信します。

可視化したいログファイルは4つあるので、multiprocess を使ってFluentdをマルチプロセス化して4プロセス起動し、それぞれのプロセスでログファイルを読み込ませて送信させています。

f:id:ttorigaki:20170823141928p:plain

syslogサーバーは低スペックなうえ、様々なバッチ処理が動いているのでサーバー負荷を上げないようにするため、syslogサーバーのFluentdはログファイルを読み込んで送信するだけの処理をしています。

また、送信先が障害になった場合、送信先をスタンバイ機に切り替えるようにも設定してあります。

以下はログ送信のFluentd設定になります。

※multiprocessプラグインを使用しているので、設定は親プロセスと子プロセスに分けてあります。

親プロセス(/etc/td-agent/td-agent.conf)の設定

<source>
  type multiprocess
 
  <process>
    cmdline -c /etc/td-agent/td-agent-child1.conf --log /var/log/td-agent/td-agent-child1.log ←子プロセスの設定ファイルとログの出力ファイルを指定。
    sleep_before_start 1s
    sleep_before_shutdown 5s
  </process>
  <process>
    cmdline -c /etc/td-agent/td-agent-child2.conf --log /var/log/td-agent/td-agent-child2.log
    sleep_before_start 1s
    sleep_before_shutdown 5s
  </process>
  <process>
    cmdline -c /etc/td-agent/td-agent-child3.conf --log /var/log/td-agent/td-agent-child3.log
    sleep_before_start 1s
    sleep_before_shutdown 5s
  </process>
  <process>
    cmdline -c /etc/td-agent/td-agent-child4.conf --log /var/log/td-agent/td-agent-child4.log
    sleep_before_start 1s
    sleep_before_shutdown 5s
  </process>
</source>

子プロセス(/etc/td-agent/td-agent-child1.conf)の設定

<source>
  @type tail
  path /var/log/filename01.log ← 読み込むファイルを設定。
  pos_file /var/log/td-agent/filename01.log.pos
  format none ← 生ログデータを送信するため「none」を設定。
  read_from_head true ← ファイルの先頭から読み込ませるため設定。
  tag filename01.log
</source>
 
<match filename01.log>
  @type forward
  require_ack_response true ←再送設定を有効にするため設定。
  buffer_type file ←ファイルバッファを有効にするため設定。
  buffer_path /var/log/td-agent/buffer/filename01
  buffer_chunk_limit 8m
  buffer_queue_limit 128
  <server>
    host xxx.xxx.xxx.xxx ←アクティブ機のIPアドレスを指定。
    port 24221
  </server>
  <server>
    host xxx.xxx.xxx.xxx ←スタンバイ機のIPアドレスを指定。
    port 24221
    standby
  </server>
</match>

※上記を4プロセス分設定します。

ログデータの受信と加工

syslogサーバーから送信されたログデータを受信し、fluent-plugin-file-alternative を使って一旦ファイルに書き出します。Elasticsearchに送るデータはこのファイルを読み込んで送信します。

こうすることで、もしElasticsearch側で障害発生した場合でもsyslogサーバー側のFluentdでバッファが溜まることを防ぐことができます。

書き出したファイルは日付でローテーションさせ、過去ログをJenkinsのJOBで定期削除するようにしています。

受信するFluentdプロセスもマルチプロセス化して4プロセス起動しておき、それぞれのプロセスで受信します。

ログデータは3種類のフォーマットが混ざった形で出力されているので、Elasticsearchに送る前に fluent-plugin-multi-format-parser を使ってそれぞれパースします。

Elasticsearchに送信するFluentdもマルチプロセス化して4プロセスで処理させています。

f:id:ttorigaki:20170823142646p:plain

以下は受信側のFluentd設定です。

※multiprocessプラグインを使用しているので、設定は親プロセスと子プロセスに分けてあります。

親プロセス(/etc/td-agent/td-agent.conf)の設定

<source>
  type multiprocess
 
# 受信したログデータをファイルに出力する子プロセス
  <process>
    cmdline -c /etc/td-agent/child_conf.d/file_alternative01.conf --log /var/log/td-agent/file_alternative01.log ←子プロセスの設定ファイルとログの出力ファイルを指定。
    sleep_before_start 1s
    sleep_before_shutdown 5s
  </process>
  <process>
    cmdline -c /etc/td-agent/child_conf.d/file_alternative02.conf --log /var/log/td-agent/file_alternative02.log
    sleep_before_start 1s
    sleep_before_shutdown 5s
  </process>
  <process>
    cmdline -c /etc/td-agent/child_conf.d/file_alternative03.conf --log /var/log/td-agent/file_alternative03.log
    sleep_before_start 1s
    sleep_before_shutdown 5s
  </process>
  <process>
    cmdline -c /etc/td-agent/child_conf.d/file_alternative04.conf --log /var/log/td-agent/file_alternative04.log
    sleep_before_start 1s
    sleep_before_shutdown 5s
  </process>
 
# 読み込んだデータをパースしてElastcSearchに送信する子プロセス
  <process>
    cmdline -c /etc/td-agent/child_conf.d/multi_format_tail01.conf --log /var/log/td-agent/multi_format_tail01.log
    sleep_before_start 1s
    sleep_before_shutdown 5s
  </process>
  <process>
    cmdline -c /etc/td-agent/child_conf.d/multi_format_tail02.conf --log /var/log/td-agent/multi_format_tail02.log
    sleep_before_start 1s
    sleep_before_shutdown 5s
  </process>
  <process>
    cmdline -c /etc/td-agent/child_conf.d/multi_format_tail03.conf --log /var/log/td-agent/multi_format_tail03.log
    sleep_before_start 1s
    sleep_before_shutdown 5s
  </process>
  <process>
    cmdline -c /etc/td-agent/child_conf.d/multi_format_tail04.conf --log /var/log/td-agent/multi_format_tail04.log
    sleep_before_start 1s
    sleep_before_shutdown 5s
  </process>
</source>

以下は、ログデータを受信してファイルに書き出すFluentdの設定(/etc/td-agent/child_conf.d/file_alternative01.conf)になります。

<source>
  @type forward
  port 24221
</source>
 
<match filename01.log>
  type file_alternative
  path /var/log/td-agent/file/filename01.log.%Y%m%d ←受信したデータを出力するファイルのパス(日毎でローテーションされます)。
 
  buffer_type file
  buffer_path /var/log/td-agent/buffer/filename01
  buffer_chunk_limit 8m
  buffer_queue_limit 256
 
  output_data_type attr:message
  output_include_time false
  output_include_tag  false
  add_newline         true
</match>

※上記を4プロセス分設定します。

以下は、ログデータをパースしてElastcSearchに送信する設定(/etc/td-agent/child_conf.d/multi_format_tail01.conf)になります。

<source>
  @type tail
  path /var/log/td-agent/file/filename*
  pos_file /var/log/td-agent/filename01.log.pos
 
  format multi_format
  <pattern>
    format /^xxxxxxxx$/ ←パースするフォーマットを正規表現で指定。
  </pattern>
  <pattern>
    format /^xxxxxxxx$/
  </pattern>
  <pattern>
    format /^xxxxxxxx$/
  </pattern>
  tag filename01_multi_format.log
  read_from_head true
</source>
 
<match filename01_multi_format.log>
  @type elasticsearch
  logstash_format true
  hosts xxx.xxx.xxx.xxx:9200 ←ElasitcSearchサーバーのIPを指定。
  logstash_prefix filename_log
  buffer_type file
  buffer_path /var/log/td-agent/buffer/filename01_multi_format
  flush_interval 1
</match>

※上記を4プロセス分設定します。

各プロセスの起動

設定完了後、各ミドルウェアのプロセスを起動していきます。

Elasticsearchの起動

sudo systemctl start elasticsearch

Kibanaの起動

systemctl start kibana

Fluentdの起動

systemctl start td-agent

Elasticsearchの過去Index削除

過去のIndexの削除処理にはelasticsearch-curator を使用しており、Jenkinsから定期実行するようしています。

elasticsearch-curatorをJenkinsサーバーにインストールします。インストール方法は以下になります。

sudo rpm --import https://artifacts.elastic.co/GPG-KEY-elasticsearch

sudo vim /etc/yum.repos.d/curator.repo にて以下内容のファイルを作成します。
[curator-4] 
name=CentOS/RHEL 7 repository for Elasticsearch Curator 4.x packages
baseurl=http://packages.elastic.co/curator/4/centos/7
gpgcheck=1
gpgkey=http://packages.elastic.co/GPG-KEY-elasticsearch
enabled=1

sudo yum install elasticsearch-curator

mkdir /var/lib/jenkins/.curator/ ← 設定ファイルを配置するためのディレクトリを作成します。

elasticsearch-curatorの設定は以下になります。

  • configファイル(/var/lib/jenkins/.curator/curator.yml) の設定
client:
  hosts:
    - xxx.xxx.xxx.xxx  ←ElasticsearchサーバーのIPを指定。
  port: 9200
  url_prefix:
  use_ssl: False
  certificate:
  client_cert:
  client_key:
  ssl_no_validate: False
  http_auth:
  timeout: 30
  master_only: False
 
logging:
  loglevel: INFO
  logfile:
  logformat: default
  blacklist: ['elasticsearch', 'urllib3']
  • actionファイル(/var/lib/jenkins/.curator/delete_indices.yml)の設定
actions:
  1:
    action: delete_indices
    description: "Delete filename_log indices"
    options:
      ignore_empty_list: True
      continue_if_exception: False
      disable_action: False
    filters:
    - filtertype: pattern
      kind: prefix
      value: filename_log- ←削除するIndexのprefixを指定。
      exclude:
    - filtertype: age
      source: name
      direction: older
      timestring: '%Y.%m.%d'
      unit: days
      unit_count: 20 ←何日前のIndexを削除するか指定。「20」の場合は20日前のIndexが削除されます。
      exclude:

上記設定のうえ、Jenkinsで以下を定期実行しています。

/usr/bin/curator /var/lib/jenkins/.curator/delete_indices.yml

最後に

今回はFluentd + Elasticsearch + Kibanaの構成や設定についてお話させていただきました。

これからログの可視化にチャレンジする方の参考になれば幸いです! それでは!

Copyright © IDC Frontier Inc.