ホーム » 技術 » Fluentd/Elasticsearch7/Kibana7でsyslogを管理してみる

Fluentd/Elasticsearch7/Kibana7でsyslogを管理してみる

Elasticsearchの最新版は7.xであることに、どういうわけか前回の記事公開してから気づいたので、大慌てで書き直しをした。やっぱり本家のインストールガイドをきちんと読まないといけないよな、ということで改めてFlutentdでsyslogを集めてKibana7で閲覧する環境を整えてみる。

全体の構成はこんな感じだ。

構成イメージ

受信サーバのインストール

受信サーバはCPU2コア、4GBメモリ、20GBディスクのサーバを用意した。どれぐらいのスペックが適切なのかよくわからなかったので、適当に準備してみたというのが正直なところだ。これにCentOS7.xを新規に入れて、最新状態にupdateしたところから始める。

Elasticsearch7のインストール

最初にyumのrepoファイルを作成する。手動で作成することになるので、コピペ用にバッチ風のテキストを用意しておこう。

cat <<EOL >/etc/yum.repos.d/elasticsearch.repo
[elasticsearch-7.x]
name=Elasticsearch repository for 7.x packages
baseurl=https://artifacts.elastic.co/packages/7.x/yum
gpgcheck=1
gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
enabled=1
autorefresh=1
type=rpm-md
EOL

こうしておいて、PGP Keyをインポートし、yum installする。

rpm --import https://artifacts.elastic.co/GPG-KEY-elasticsearch
yum install java-1.8.0-openjdk elasticsearch

続いて設定ファイルを書く。まず /etc/elasticsearch/elasticsearch.yml だ。

cluster.name: クラスタ名
node.name: ノード名
network.host: 0.0.0.0
transport.host: localhost
transport.tcp.port: 9300
xpack.security.enabled: true
discovery.type: single-node

Elasticsearch7ではx-packは標準装備なので、xpack.security.enabled を true にするだけで認証機能を利用できる。それから本稿ではマルチノードにしていないので discovery.type を single-node に設定している。この行がないと、xpackをONにしたときにElasticsearchが起動しなくなってしまうので必ず追記する。

もうひとつ設定ファイル /etc/elasticsearch/jvm.options を確認する。サーバのメモリ容量に応じて、下記の部分を調整する。

-Xms2g
-Xmx2g
# メモリの半分を指定

設定ファイルができたら、Elasticsearchを起動する。

systemctl enable elasticsearch
systemctl start elasticsearch

次にElasticsearchの予約ユーザのパスワードを設定する。Elasticsearch7には6つの予約ユーザがあって、それぞれ任意のパスワードが設定できるが、一つずつ設定するのは面倒なので、autoモードでランダムパスワードを割り当て、利用するものだけ自分の都合のよいパスワードに付け替えるか、Kibanaログイン用のスーパーユーザーを自分の名前で新規作成することをオススメする。まずはランダムパスワードをつけてみよう。

[root@syslog ~]# /usr/share/elasticsearch/bin/elasticsearch-setup-passwords auto
Initiating the setup of passwords for reserved users elastic,apm_system,kibana,logstash_system,beats_system,remote_monitoring_user.
The passwords will be randomly generated and printed to the console.
Please confirm that you would like to continue [y/N]y


Changed password for user apm_system
PASSWORD apm_system = 9TZRzFnyN2QB4DdQgh9T

Changed password for user kibana
PASSWORD kibana = hwgZNrnNNgeBiwgN7NMh

Changed password for user logstash_system
PASSWORD logstash_system = GPw6PmAaaZWUhAF3gsTT

Changed password for user beats_system
PASSWORD beats_system = iYAQeHHhR6mvEvpTrPxe

Changed password for user remote_monitoring_user
PASSWORD remote_monitoring_user = mpPNvGxUxENw5mGQPUNM

Changed password for user elastic
PASSWORD elastic = 5hmeFXwZ3w8N4TxVusVe

表示されたパスワードは忘れないようにメモしておく。

Kibana7のインストール

続いてKibana7をインストールする。こちらもyumで簡単にインストールできる。

yum install kibana

Kibana7の設定ファイルは /etc/kibana/kibana.yml だ。インストール直後は、デフォルト値を示すコメントばかりなので、ファイルの末尾に以下のように記述するとよい。

server.host: "0.0.0.0"
elasticsearch.username: "elastic"
elasticsearch.password: "xxxxxxxxxxxxxxxxxxxx"
logging.quiet: true

3行目のパスワードは、先ほど割り当てたelasticのパスワードを指定しておく。4行目のオプションは、エラー以外の余計なログを抑制するもので、ぜひとも指定しておくことをオススメする。

次にファイアウォールを設定する。Kibanaにアクセスするだけなら、5601ポートを開ければよい。

firewall-cmd --permanent --add-port=5601/tcp
firewall-cmd --reload

最後にKibanaを起動する。

systemctl enable kibana
systemctl start kibana

これでKibanaにアクセス可能になった。http://受信サーバのIPアドレス:5601 にアクセスして確かめてみよう。次のように表示されれば成功だ。

ログイン画面

ユーザ名にelastic、パスワードに割り当て済みのパスワードを指定してログインすると、このような画面になる。

Kibanaの初期画面

無事にログインできたら、最初にやるべきはログイン用のユーザを作ることだ。下図の通り、左のサイドメニューのManagement(ギアアイコン)から始めて、Security/Users を選択し、Create new user ボタンを押す。

ユーザの追加手順

するとユーザ作成のダイアログが表示されるので、諸情報を入力してボタンを押せばよい。ログインしやすい名前とパスワードを設定し、ロールはSuperuserにしておく。Kibanaの普段使いにはそちらを利用すればよい。

Fluentdのインストール(受信サーバ)

さて、続いてFluentdのインストールだ。Fluentdのインストールは次のone linerで行う。

curl -L https://toolbelt.treasuredata.com/sh/install-redhat-td-agent3.sh | sh

次にElasticsearch用のプラグインを追加する。

td-agent-gem install fluent-plugin-elasticsearch

Fluentdは24224ポートを使ってアクセスするので、これを開けておく。単純にアクセスを開放してしまうと色々心配なので、監視対象にするサーバのIPアドレスを指定して開けるようにする。

firewall-cmd --permanent --new-zone=fluentd
firewall-cmd --permanent --zone=fluentd --set-target=ACCEPT
firewall-cmd --permanent --zone=fluentd --add-port=24224/tcp
firewall-cmd --permanent --zone=fluentd --add-source=送信サーバIP1
firewall-cmd --permanent --zone=fluentd --add-source=送信サーバIP2
firewall-cmd --reload

次にFluentdの設定ファイルを用意する。/etc/td-agent/td-agent.conf だが、インストールするとデフォルトのファイルがすでにあるので、以下のように追記する。途中にelasticのパスワードがあるので、上記で設定したものをコピペする。

<source>
  @type syslog
  port 5140
  tag fluentd.syslog
  format syslog
</source>

<match fluentd.**>
  @type copy
  <store>
    @type elasticsearch
    logstash_format true
    include_timestamp true
    port 9200
    user elastic
    password elasticのパスワード
    buffer_type file
    buffer_path /var/log/td-agent/buffer/fluentd.back
  </store>
</match>

この設定ファイルは2つのディレクティブから成る。sourceはポート5140からsyslogメッセージを受信して解析することを指示する部分、matchは内外から受信するFluentdのメッセージをElasticsearchへ突っ込む設定だ。できたらFluentdを起動する。

systemctl enable td-agent
systemctl start td-agent

さてsyslogメッセージだが、 Fluentdがログを送信する方法はいくつかある。たとえばログファイルを直接パースして送信することもできる(実際は/var/log/messagesのファイル権限の都合でうまくいかない)。だがsyslogを扱うなら本家のドキュメントが示す手段を使うのがよさそうだ。概要はこんな感じだ。

  1. rsyslogに設定を加えて、local port 5140にsyslogを送るようにする
  2. Fluentdでそれを捕まえて受信サーバへ送る

2のFluentdで捕まえるほうは、すでにtd-agent.confに記述済みなので、1のrsyslogの設定を行う。/etc/rsyslog.conf の末尾に、次の1行を追加する。

*.*  @127.0.0.1:5140

設定はお好みに合わせて変えていただきたい。もし /var/log/messages と同程度でよいと思うなら、次のようにするとよい。

*.info;mail.none;authpriv.none;cron.none                @127.0.0.1:5140

設定できたら、rsyslogを再起動する。

systemctl restart rsyslog

これで、まずは受信サーバ自身のログが溜まりはじめるはずだ。

送信サーバの設定

送信サーバでは、既存の設定にFluentdを追加する形になる。つまりrsyslogにログを出力する設定を施し、Fluentdで送信するわけだ。

まずFluentdをインストールする。受信サーバと同じone linerで行う。

curl -L https://toolbelt.treasuredata.com/sh/install-redhat-td-agent3.sh | sh

次にFluentdの設定ファイルを書く。送信サーバの /etc/td-agent/td-agent.conf はこのようにする。

<source>
  @type syslog
  port 5140
  tag fluentd.syslog
  format syslog
</source>

<match fluentd.**>
  @type forward
  <server>
    host 受信サーバのホスト名またはIPアドレス
    port 24224
  </server>
</match>

hostのところに、先ほど作成した受信サーバのホスト名またはIPアドレスを指定する。設定ファイルができたら起動する。

systemctl enable td-agent
systemctl start td-agent

最後にrsyslogを設定する。/etc/rsyslog.conf は

*.*  @127.0.0.1:5140

または

*.info;mail.none;authpriv.none;cron.none                @127.0.0.1:5140

としておき、再起動して設定を有効化する。

systemctl restart rsyslog

Kibanaのセットアップ

設定が完了したら、改めてKibanaにアクセスしてみよう。サイドメニューのManagementを選択し、Kibana/Index Patternsをクリックする。するとCreate index pattern という画面になる。

インデックスパターンの作成(1)

ここで、Elasticsearchに溜まったデータから、インデックスを頼りにどのデータを閲覧するかを選択できる。本稿の通りに設定していれば、Fluentdで収集したログには「logstash-日付」というインデックスが付与されていて、すでにログが集まってきていると思う。もしインデックスが見つからないというメッセージが表示されていたら、対象サーバがsyslogを出力していないか、設定のどこかに間違いがあるかのいずれかだ。syslogに明示的にログを出力したいなら次のようにする。

logger 'fluentd test'

数分待っても変化がなければ、/var/log/elasticsearch 以下のログを確認するとか、/var/log/td-agent/td-agent.log をチェックして、エラーがないかを見てほしい。

順調にログが収集できていれば、上記のようにlogstash-なんとか、というインデックスが見えているので、全部にマッチするパターンすなわち「logstash-*」を入力し、Next stepボタンを押す。

インデックスパターンの作成(2)

次の画面では時刻を示すフィールドを指定する。Kibana7ではユーザが指定する必要があるので、ドロップボックスから @timestamp を選び、Create index pattern ボタンを押す。これで完了だ。

フィールド設定画面

この画面になれば準備完了だ。いよいよデータを閲覧できる。今度はサイドメニューの一番上にあるDiscover(コンパスアイコン)を選択する。

Discover画面

これで準備完了だ。

Kibanaの使い方

Discover画面では、時系列にイベントの数をカウントしたグラフとその内容の一覧を表示する。スケールは右上部の「Last 15 minutes」などと表示されているところで調整できるし、グラフをクリックすることで拡大することもできる。下記の画面は、8台のサーバからsyslogを集めたデータの例だ。

12時間分のsyslog

ざっと見ると、10分あたり平均して50イベント前後記録されているのが分かる。ピーク時には200に到達している時間帯もある。このように多数のデータを、ただ時系列に眺めていては埒が明かない。そこで種別ごとに分類したり、特に多いメッセージを抽出したりして、調べていく手順を示そう。

syslogの場合、頼りになるのはidentというフィールドだ。これは単刀直入に言えばメッセージを出力したデーモンの名前に相当する。左側のサブメニューをクリックするとidentの部分が詳細化され、トップ5リストがヒストグラム化される。

フィールドを詳細化する

ここでルーペアイコンをクリックすることで、特定フィールドを抽出したり、除外することができる。 たとえばsshdの+アイコンをクリックしてみよう。するとsshdの出力だけが抽出され、こんなグラフになる。

sshdの抽出

これは実は、12時間に渡って記録された22番ポートへスキャンしにきた不埒者のログだ。8台分のサーバの合計なのと、セッションのすべての記録なので単純に人数を示しているわけではないことに留意してもらいたいが、結構な頻度であることが分かる。これらのスキャンは fail2ban でブラックリスト送りにしているので実害はないが、対策が必要なのはわかっていただけると思う。

KibanaをHTTPS化する

さてKibanaにアクセスすると、HTTPなので「保護されていない通信」と出る。実にうざったいのでLet’s Encryptを利用してHTTPS化したい。もしサーバにホスト名を割り当てられる方なら、次のような手順で実施できる。

まずサーバにcertbotをインストールする。

yum install certbot

firewall-cmdでHTTPをあけておく。

firewall-cmd --permanent --add-service=http
firewall-cmd --reload

次にstandaloneモードでLet’s Encryptから証明書をもらう。

certbot --standalone certonly

certbotの使い方は説明しないが、メールアドレスや登録したいFQDNを聞かれるのできちんと答える。最後までうまくいけば、正しく証明書ファイルが作成される。/etc/letsencrypt/archive/登録したFQDN、というディレクトリにファイルが格納されているはずだ。

次がトリックなのだが、Kibanaはこのディレクトリを直接読めない。root権限で保護されてしまっているからだ。仕方がないのでこれをコピーする。適切な場所を選んで、次のようなバッチを設置する。たとえば /usr/local/bin/kibana-letsencrypt などとしておこう。

#!/bin/sh

FQDN=登録したFQDN

LETSENCRYPT_DIR=/etc/letsencrypt/archive
KIBANA_DIR=/etc/kibana/ssl

mkdir -p $KIBANA_DIR
cp -rp $LETSENCRYPT_DIR/$FQDN $KIBANA_DIR
chmod 750 $KIBANA_DIR/$FQDN
chmod 640 $KIBANA_DIR/$FQDN/*
chown -R root:kibana $KIBANA_DIR

このバッチを実行して、ファイルが適切な場所に適切なパーミッションでコピーされていることを確認する。

[root@syslog3 ~]# ll /etc/kibana/ssl/xxxxxxxxxxxxxxxxxxx/
total 16
-rw-r----- 1 root kibana 1948 Jun 18 16:38 cert1.pem
-rw-r----- 1 root kibana 1647 Jun 18 16:38 chain1.pem
-rw-r----- 1 root kibana 3595 Jun 18 16:38 fullchain1.pem
-rw-r----- 1 root kibana 1704 Jun 18 16:38 privkey1.pem

次に /etc/kibana/kibana.yml を編集する。次の3行を追加する。

server.ssl.enabled: true
server.ssl.certificate: /etc/kibana/ssl/登録したFQDN/fullchain1.pem
server.ssl.key: /etc/kibana/ssl/登録したFQDN/privkey1.pem

最後にKibanaをリスタートする。

systemctl restart kibana

これで、https://サーバ名:5601 という名前でアクセスすることができるようになった。

なお Let’s Encrypt の証明書は3ヶ月ごとに更新が必要なので、cronを設定しておく。たとえば /etc/cron.d/cert-renew のようなバッチを用意する。これは毎週月曜日の9時30分に期限をチェックして、更新があればファイルのコピーも行ってくれる。

MAILTO=
30 9 * * mon root /usr/bin/certbot renew --standalone --post-hook "/usr/loal/bin/kibana-letsencrypt && systemctl restart kibana" | logger -t certbot-renew -p local0.info

ただ、このバッチはまだ期限を迎えていないのでテストできていない。3ヵ月後に本当に更新できたか確認しなければならない。 [6/27追記: kibanaのリスタートを追加した]

参考リンク