はじめに
仕事でElastic Stack のクラスターを構築する可能性が出てきたので,プライベートの検証環境で勉強がてら構築して検証してみた.
構築した環境は以下の通り.断続的にログが転送されてくる環境にしたかったので,Web サーバーにアクセスするスクリプトを作成してそのログをSyslog サーバーに転送させ,そのログファイルをscp でElastic Stack に取り込む形にした.
Elasticsearch はElasticsearch の機能に集中させたいため,Kibana とLogstash とは分離させ,障害が発生しても機能するようにクラスター構成とした.
各ノードの構成は以下のとおりである.
ノード名 | OS | ミドルウェア/アプリケーション |
---|---|---|
Webサーバー | Cent OS 8 | apache,rsyslog,jq (1.5) |
Syslogサーバー | Cent OS 8 | rsyslog,jq (1.5) |
ログ処理サーバー | Cent OS 8 | logstash (7.4.0),kibana (7.4.0),openjdk (1.8.0),jq (1.5) |
Elasticsearch #1 | Cent OS 8 | elasticsearch (7.4.0),openjdk (1.8.0),jq (1.5) |
Elasticsearch #2 | Cent OS 8 | elasticsearch (7.4.0),openjdk (1.8.0),jq (1.5) |
Elasticsearch #3 | Cent OS 8 | elasticsearch (7.4.0),openjdk (1.8.0),jq (1.5) |
Web サーバーの構築
最初に,Web サーバーを用意し,そのアクセスログをsyslog にてSyslog サーバーに転送するインスタンスを構築する.
apache の構築
apache をインストールする.
# dnf -y install httpd
Cent OS 8 から?IPアドレス指定だけでアクセスしようとすると403がレスポンスされる.それだと正常にアクセスできたかどうかわからなかったので,ドキュメントルート直下に以下のhtml ファイルを作成して配置した.curl でアクセスするとtest とだけレスポンスされる.
test
最後に,ログ転送関連の設定を行う.
アクセススクリプトの作成
以下のスクリプトを作成し,アクセスログを定期的に発生させるようにした.
最初はsleep コマンドはなかったが,ないとログが多すぎるのでログ量を調整することにした.
#!/bin/bash
while [ true ]
do
curl http://192.168.226.135/test.html
sleep 60
done
rsyslog の設定
rsyslog により,apache のアクセスログをSyslog サーバーに転送するため,apache の設定ファイルに以下を追記する.ユーザー定義のlocal0 を利用する.
CustomLog "|/usr/bin/logger -p local0.info -t httpd_access" combined
次に,rsyslog でSyslog サーバーに転送の設定を記述する.今回は,UDP でログ転送をする.
local0.* @192.168.226.136:514
ファイアウォールの許可設定をしておく.
# firewall-cmd --add-port=80/tcp --permanent
# firewall-cmd --reload
最後にapache とrsyslogの自動実行をON にし,起動させる.
# systemctl enable httpd
# systemctl start httpd
# systemctl enable rsyslog
# systemctl start rsyslog
Syslog サーバーの構築
Syslog サーバーでは,rsyslog に受信の設定を記述する.
送信側がlocal0 でログ転送するので,そのファシリティで受信したログの保存先を指定する.
$ModLoad imudp
$UDPServerRun 514
local0.* -/var/log/test/access.log
ファイアウォールの許可設定をしておく.
# firewall-cmd --add-port=514/udp --permanent
# firewall-cmd --reload
最後にrsyslogの自動実行をON にし,起動させる.
# systemctl enable rsyslog
# systemctl start rsyslog
ログ処理サーバーの構築
Elastic Stack の役割は,Syslog サーバーに保存されているログファイルを取得してLogstash でパースおよびElasticsearch に取り込み,Kibana で可視化することである.
ログファイルを取得するスクリプトの作成
Syslog サーバーに保存されているapache のアクセスログファイルを取得するため,以下のスクリプトを作成する.このスクリプトをcrontab により定期的に自動実行させる.
logstash サービスが,logstash ユーザーで実行されるため,取得したログファイルのオーナーをlogstash ユーザーに変更し,実行権限も付与しておく.
#!/bin/bash
scp -i /root/.ssh/id_rsa root@192.168.226.136:/var/log/test/access.log /var/log/test
chown logstash /var/log/test/access.log
chmod +x /var/log/test/access.log
スクリプトを作成したら,実行権限を付与しておく.
# chmod +x /home/elastic/log_copy.sh
crontab の設定
定期的にログファイルをSyslog サーバーから取得するため,crontab の設定を行う.以下のファイルを作成する.
#分 時 月 日 曜日 ユーザ名 コマンド
*/5 * * * * root /home/elastic/log_copy.sh
このファイルにより,5分おきにlog_copy.sh が実行され,Syslog サーバーからapache のアクセスログファイルがログ処理サーバーのローカルにコピーされる.
ssh の設定
scp によりファイルを取得するため,まずはssh に使用する公開鍵と秘密鍵のペアを作成する.
以下のコマンドは,ログ取り込みサーバー上で実行する.
# ssh-keygen -t rsa
# chmod 600 /root/.ssh/id_rsa
パスフレーズなどは設定せず,すべての質問はEnter を入力して進む.
次に,公開鍵をSyslog サーバーに登録する.以下からは,Syslog サーバー上で実行する.
# scp root@192.168.226.140:/root/.ssh/id_rsa.pub /root/.ssh/authorized_keys
# chmod 600 /root/.ssh/id_rsa.pub
これで公開鍵が登録できたので,次は設定ファイルより公開鍵認証でログインできるようにする.
PubkeyAuthentication yes
今回は設定実施しなかったが,インターネット公開系のシステムであったりすると,root ログインやパスワード認証を無効にする.
PermitRootLogin no #root ログインを無効
PasswordAuthentication no #パスワード認証を無効
ssh の設定が完了したら,ssh を再起動しておく.
# systemctl restart sshd
java のインストール
Logstash やElasticsearch のインストールに必要なjava をインストールする.
# dnf -y install java-1.8.0-openjdk
Logstash のインストール
Logstash をインストールする.インストールするためのファイルは,以下のページからダウンロードする.
https://www.elastic.co/jp/downloads/
今回は,「logstash-7.4.0.rpm」をインストールする.
# rpm -ivh logstash-7.4.0.rpm
Logstash の設定
取り込むログファイルに関しての設定を行う.Logstash はinput,filter,output のパイプラインで取り込んだデータを処理する.
inputは,取り込むデータの指定,filter はデータのパース,output は,出力先を指定する形式である.
input {
file {
mode => "tail"
path => ["/var/log/test/access.log"]
sincedb_path => "/var/log/test/test_pointer"
start_position => "beginning"
type => "access"
}
}
filter {
if[type] == "access" {
grok {
match => {
"message" => "%{SYSLOGTIMESTAMP:syslog_timestamp} %{HOSTNAME:source} %{USERNAME}\[%{INT}\]: %{IPV4:destination} - - \[%{HTTPDATE:access_time}\] %{GREEDYDATA:message}"
remove_filed => ["message"]
}
}
}
}
output {
if[type] == "access" {
#debug
#stdout {
#codec => rubydebug
#}
file {
path => ["/var/log/test/result_access.log"]
}
elasticsearch {
hosts => ["192.168.226.137:9200", "192.168.226.138:9200", "192.168.226.139:9200"]
index => "test"
}
}
}
上記設定ファイルで,syslog 経由で送信されてくるapache のログファイルをパースできる.
設定が正しくできているかはlogstash を設定ファイルを指定して実行させることで確認できる.その前に,以下の文を追記しておき,パスを通しておく.
export PATH="$PATH:/usr/share/logstash/bin"
以下のコマンドを実行し,結果を確認する.
# logstash -f "/etc/logstash/conf.d/access.conf"
以下のような形で,json 形式でログが取り込まれていればOK.
{
"message": [
"Jan 3 01:36:13 localhost httpd_access[8378]: 【WebサーバーのIPアドレス】 - - [03/Jan/2020:01:36:13 -0500] \"GET /test.html HTTP/1.1\" 200 5 \"-\" \"curl/7.61.1\"",
"\"GET /test.html HTTP/1.1\" 200 5 \"-\" \"curl/7.61.1\""
],
"syslog_timestamp": "Jan 3 01:36:13",
"destination": "【WebサーバーのIPアドレス】",
"path": "/var/log/test/access.log",
"access_time": "03/Jan/2020:01:36:13 -0500",
"@timestamp": "2020-01-03T13:38:53.721Z",
"host": "elastic1",
"@version": "1",
"source": "localhost"
}
Kibana のインストール
今回は,「kibana-7.4.0-x86_64.rpm」をインストールする.ファイルはLogstash と同じページからダウンロードした.
# rpm -ivh kibana-7.4.0-x86_64.rpm
Kibana の設定
Kibana を使ってElasticsearch に蓄積されたデータを可視化する.
設定ファイルを以下のように記述する.追記した部分のみ抜粋する.
server.host: "0.0.0.0"
elasticsearch.hosts: ["http://192.168.226.137:9200", "http://192.168.226.138:9200", "http://192.168.226.139:9200"]
ファイアウォールの許可設定をしておく.
# firewall-cmd --add-port=5601/tcp --permanent
# firewall-cmd --reload
最後にLogstash とKibana の自動実行をON にし,起動させる.
# systemctl enable logstash
# systemctl start logstash
# systemctl enable kibana
# systemctl start kibana
Elasticsearch の構築
Elasticsearch のインストール
今回は,「elasticsearch-7.4.0-x86_64.rpm」をインストールする.ファイルはLogstash と同じページからダウンロードした.
# rpm -ivh elasticsearch-7.4.0-x86_64.rpm
Elasticsearch の設定
Elasticsearch は,3台でクラスターを構築し,それぞれデータノードおよびマスター候補ノードとして扱うよう設定する.以下の設定ファイルの記述は,node-1において構築に必要なため追記/修正したものを抜粋した.
cluster.name: exam-cluster
node.name: node-1 #node-2,node-3とnode ごとに名前を変える
network.host: 0.0.0.0
http.port: 9200
transport.host: 192.168.226.137 #node-2,node-3とnode ごとに値を変える
transport.tcp.port: 9300
discovery.zen.ping.unicast.hosts: ["192.168.226.137", "192.168.226.138", "192.168.226.139"]
cluster.initial_master_nodes: ["node-1", "node-2", "node-3"]
ファイアウォールの許可設定をしておく.
# firewall-cmd --add-port=9200/tcp --permanent
# firewall-cmd --add-port=9300/tcp --permanent
# firewall-cmd --reload
最後にElasticsearch の自動実行をON にし,起動させる.
# systemctl enable elasticsearch
# systemctl start elasticsearch
クラスターのノードを確認するには以下のコマンドを実行する.
# curl http://192.168.226.137:9200/_cat/nodes
ノードが3台表示され,3台でクラスターが構築されていることが分かる.
192.168.226.138 12 87 1 0.00 0.00 0.00 dilm * node-2
192.168.226.137 10 91 1 0.00 0.00 0.00 dilm - node-1
192.168.226.139 13 87 1 0.00 0.01 0.00 dilm - node-3
クラスターの状態確認は以下のコマンドを実施する.
# curl http://192.168.226.137:9200/_cluster/health?pretty
実行すると,ステータスがgreen となっており,number_of_nodes の値も3となっており,3台で正常にクラスターが組まれていることが分かる.
{
"cluster_name" : "exam-cluster",
"status" : "green",
"timed_out" : false,
"number_of_nodes" : 3,
"number_of_data_nodes" : 3,
"active_primary_shards" : 4,
"active_shards" : 8,
"relocating_shards" : 0,
"initializing_shards" : 0,
"unassigned_shards" : 0,
"delayed_unassigned_shards" : 0,
"number_of_pending_tasks" : 0,
"number_of_in_flight_fetch" : 0,
"task_max_waiting_in_queue_millis" : 0,
"active_shards_percent_as_number" : 100.0
}
データノードやマスター候補ノードの設定は明示的に設定しなかったが,デフォルトでデータノードおよびマスター候補ノードになることが分かった.
今後の予定
以下,取り組みたい内容は以下のとおりである.
複数の種類のログファイルの安全な取り込み
最新データの更新 (未実装)
他インデックスの情報の結合処理 (未実装)
csvファイルの出力 (未実装)
課題一覧
- logstash サービスから自動でログが取り込まれない【解決済み】 → logstash サービスがlogstash ユーザーで実行されるため,取り込むログファイルがroot ユーザーなど実行ユーザーのおいて権限がない場合だと,Permission denied となり失敗する.ただし,root ユーザーでlogstash の実行ファイルを実行させると,root ユーザーで実行されるため,その問題が解消される.そのため,前回は実行ファイルの実行だと問題なかったが,サービス起動だとログが取り込まれなかった.ログを取り込むスクリプトでオーナーを変更することで解決した.
本事象は,/var/log/logstash/logstash-plain.log からエラーメッセージを確認することで解決できた.(/var/log/test にあるファイルに権限がないというエラーメッセージが出力されていた.)
- Elasticsearch でクラスターが組まれない【解決済み】 → /etc/elasticsearch/elasticsearch.yml に以下の記述が必要だった. cluster.initial_master_nodes: ["node-1", "node-2", "node-3"]
本事象は,/var/log/elasticsearch/exam-cluster.log からエラーメッセージを確認することで解決できた.(上記の記述がないというエラーメッセージが出力されていた.)
- 複数の種類のログファイルの安全な取り込み【未解決】 Logstash で複数のログファイルを複数の.conf で取り込もうとすると,ログの保存先インデックスが混ざる.(Aというインデックスにだけ保存したいログデータがBというインデックスにも保存されてしまう) → おそらくlogstash の設定ファイルにtype でif の条件式をfilter やoutput に追記する必要があると思われる.