Open10

Vagrant環境にElasticStackをインストールしてみる

環境:
vagrant:2.2.9
vagrant box: bento/CentOS7.8
virtualbox6.1

任意のディレクトリ内でvagrant環境作成

vagrant init

vagrantfileに下記追加
自分はデフォルトのIPを使っていたので、下記のように変更
メモリは、初め1024mbに設定していたが、ElasticSearchがめちゃめちゃリソースを食い、タイムアウトして起動できなかった。そのため現在は2048mbで設定している。

Vagrantfile
  config.vm.provider "virtualbox" do |vb|
    vb.memory = "2048"
  end

# ~省略~

  config.vm.network "private_network", ip: "192.168.1.11"

実行

vagrant up

修了したら、リモートログイン

vagrant ssh

無事CentOS内に入れたら、yum updateして、vimを入れておく

# yum update
# yum -y install vim

version7からは、OpenJDKバンドルしているらしい。

https://www.elastic.co/guide/en/elasticsearch/reference/7.5/rpm.html

しかし、Logstashでなんだかんだ必要みたいなので、Open JDKをインストール

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

elasticsearch.repoというファイルを作成

# vim /etc/yum.repos.d/elasticsearch.repo
elasticsearch.repo
[elasticsearch]
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=0
autorefresh=1
type=rpm-md

インストール

# yum install -y --enablerepo=elasticsearch elasticsearch kibana logstash

Elasticsearchが利用するIPアドレス変更、シングルノードで動くように変更

vi /etc/elasticsearch/elasticsearch.yml

kibanaが利用するIPアドレス設定

vim /etc/kibana/kibana.yml
kibana.yml
network.host: 0.0.0.0

discovery.type: single-node

必要であれば、ファイアウォールで下記ポート開放(今回はVagrant環境のため割愛)
Kibana:5601
Elasticsearch: 9200
logstash: 9600

起動

systemctl start elasticsearch kibana logstash
systemctl enable elasticsearch kibana logstash

アクセス確認

# curl http://localhost:9200
{
  "name" : "localhost.localdomain",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "KhyKAv6UTK21hfu_l2Ka1Q",
  "version" : {
    "number" : "7.10.2",
    "build_flavor" : "default",
    "build_type" : "rpm",
    "build_hash" : "747e1cc71def077253878a59143c1f785afa92b9",
    "build_date" : "2021-01-13T00:42:12.435326Z",
    "build_snapshot" : false,
    "lucene_version" : "8.7.0",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}

kibanaにブラウザからアクセス
起動したてブラウザに表示させてもKibana server is not ready yetと表示されるだけなので、その場合は少し時間を置く

http://192.168.1.11:5601

とりあえず「Explore on my own」選択
そうすると、Home画面に移動する

#systemctl start elasticsearchでタイムアウトになってしまう場合

参考:https://mebee.info/2020/07/15/post-13503/

##手段1: タイムアウトまでの時間を延ばす

# mkdir /etc/systemd/system/elasticsearch.service.d
# echo -e "[Service] \nTimeoutStartSec = 180" | sudo tee /etc/systemd/system/elasticsearch.service.d/startup-timeout.conf
# systemctl daemon-reload

##手段2: Vagrantfileでメモリ容量を大きくする

Vagrantfile
  config.vm.provider "virtualbox" do |vb|
    vb.memory = "2048"
  end

この場合、Javaで利用するメモリも増やす

# vi /etc/elasticsearch/jvm.options
jvm.options
# Xms represents the initial size of total heap space
# Xmx represents the maximum size of total heap space

# -Xms1g
# -Xmx1g
-Xms2g
-Xmx2g

#nginxのログを集計してみる

Nginxのログをfilebeats→Logstash→Elasticksearch→kibanaという流れで最終的にkibana上で表示させてみます。

上記を参考に新しくVagrant環境をもう一個立ち上げる
今回はIPに192.168.1.12を指定。
ログイン後、例のごとくyum updateとお好みでvimをインストール(なくてもviで問題なし!)

nginxインストール
参考:https://weblabo.oscasierra.net/nginx-centos7-install/
nginxのために、yumリポジトリを初めに追加する。

# vim /etc/yum.repos.d/nginx.repo
nginx.repo
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/7/$basearch/
gpgcheck=0
enabled=1

nginx.repoが追加されているかチェック。

# ls -l /etc/yum.repos.d/
total 48
-rw-r--r--. 1 root root 1664 Nov 24 00:08 CentOS-Base.repo
-rw-r--r--. 1 root root 1309 Nov 24 00:08 CentOS-CR.repo
-rw-r--r--. 1 root root  649 Nov 24 00:08 CentOS-Debuginfo.repo
-rw-r--r--. 1 root root  314 Nov 24 00:08 CentOS-fasttrack.repo
-rw-r--r--. 1 root root  630 Nov 24 00:08 CentOS-Media.repo
-rw-r--r--. 1 root root 1331 Nov 24 00:08 CentOS-Sources.repo
-rw-r--r--. 1 root root 8515 Nov 24 00:08 CentOS-Vault.repo
-rw-r--r--. 1 root root  616 Nov 24 00:08 CentOS-x86_64-kernel.repo
-rw-r--r--. 1 root root  222 Feb  3 17:04 elasticsearch.repo
-rw-r--r--. 1 root root   99 Feb  5 17:31 nginx.repo
# yum info nginx
~省略~
Available Packages
Name        : nginx
Arch        : x86_64
Epoch       : 1
Version     : 1.18.0
Release     : 2.el7.ngx
Size        : 769 k
Repo        : nginx/x86_64
Summary     : High performance web server
URL         : http://nginx.org/
License     : 2-clause BSD-like license
Description : nginx [engine x] is an HTTP and reverse proxy server, as well as
            : a mail proxy server.

無事確認できたら、インストール、自動起動設定、起動

# yum install nginx
# systemctl  enable nginx
# systemctl start nginx

インストール出来たら、以下にアクセス

http://192.168.1.12
ウェルカムページが表示されればOK。firewalldが起動している場合は、ポートあけてあげたりなんなりする必要あり。

#filebeatインストール
前回同様、elasticsearch.repoを作成。内容は同じなので割愛。

vim /etc/yum.repos.d/elasticsearch.repo
# yum install -y --enablerepo=elasticsearch filebeat

始めに作ったマシン(192.168.1.11)のLogstashに出力を指定する。

# vim /etc/filebeat/filebeat.yml

~ 省略 ~

filebeat.inputs:
    # ↓追記
    - /var/log/nginx/*.log
~省略~

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

~省略~

# ------------------------------ Logstash Output -------------------------------
# ↓コメントアウト外す
output.logstash:
  # The Logstash hosts
  # ↓ホスト指定
  hosts: ["192.168.1.11:5044"]

Nginxモジュールを有効化

# filebeat modules enable nginx

取得するログファイルを指定する

# vim /etc/modules.d/nginx.yml
/etc/filebeat/modules.d/nginx.yml
- module: nginx
  # Access logs
  access:
    enabled: true

    # Set custom paths for the log files. If left empty,
    # Filebeat will choose the paths depending on your OS.
    #var.paths:
    # ↓追記
    var.paths: ["/var/log/nginx/access.log*"]

  # Error logs
  error:
    enabled: true

    # Set custom paths for the log files. If left empty,
    # Filebeat will choose the paths depending on your OS.
    #var.paths:
    # ↓追記
    var.paths: ["/var/log/nginx/error.log*"]

~省略~

filebeat内でElasticsearchのモジュールを有効化させる

# filebeat modules enable elasticsearch
# filebeat setup -e

設定を反映させつつ、自動起動も追加

# systemctl restart filebeat
# systemctl enable filebeat

https://www.elastic.co/guide/en/logstash/current/advanced-pipeline.html

一時退避メモ
logstashコマンドが使えない
/usr/share/logstash/bin/logstashにあることを確認

logstashがこのエラーで突っかかってる
warning: Option UseConcMarkSweepGC was deprecated in version 9.0 and will likely be removed in a future release.

filebeatが飛ばしているのをチェックするコマンド
filebeat -e -c /etc/filebeat/filebeat.yml -d "publish"

filebeat setupコマンド

Sets up the initial environment, including the index template, ILM policy and write alias, Kibana dashboards (when available), and machine learning jobs (when available)
https://www.elastic.co/guide/en/beats/filebeat/current/command-line-options.html

filebeat setup --pipelines

logstash コンフィグテスト

bin/logstash -f config/first-pipeline.conf --config.test_and_exit

--config.test_and_exitオプションを使用すると構文チェックが行われます。
--config.reload.automaticオプションを使用すると、設定の自動読み込みが行われ、

Address already in useとなった場合

https://github.com/elastic/logstash/issues/6279
systemctl stopしてしまおういっそ
systemdとパス直指定のlogstashが競合してしまって困る。
filebeatでconnection reset by peerといわれてしまう。
https://discuss.elastic.co/t/filebeat-logstash-connection-reset-by-peer/211739
Elasticsearch側への出力にもんだいがあった場合、LogstashがBeatへの接続を遮断することがある。

Harvester started for file: /var/log/nginx/error.log

https://discuss.elastic.co/t/nginx-harvester-finds-and-loads-log-files-but-no-publish-output/130657

https://qiita.com/nihei9/items/1ebc7934eb1e1ce66162
自分もヘルスチェックで失敗しているみたいなので、下記をlogstash.ymlに追加
/etc/logstash/logstash.yml
xpack.monitoring.enabled: false

LogStash起動時のError: Address already in useについて

状況

logstash.ymlやconfファイル編集後、起動起動させようとした際に発生。

/usr/share/logstash/bin/logstash -f /etc/logstash/conf.d/syslog.conf

原因: すでにインスタンスが起動している

systemctl start logstashなどで起動した後、logstash ...コマンドで起動しようとしたため起きた
psコマンドで5044ポートの状況を確認し、何か出力されれば、使用されていることになる。

ps ax | grep 5044
4655 pts/1    S+     0:00 grep --color=auto 5044

解決策: systemctl 起動しているサービスを消す or 再起動

今回自分の場合、すでにLogstashが起動しているにもかかわらず、さらに起動させようとしたことが問題であったため、再起動することでファイルを反映させた。

LogStashのパイプラインの書き方について

##基本形
inputとoutputは必須。filterは任意。

input {
 
}
filter {

}
output {

}

標準出力を設定することで、設定のデバッグが楽になる

input {

}
filter {

}
output {
  stdout {
    codec => rubydebug
  }
}

##ファイルの起動・反映
/etc/logstash/conf.d/syslog.confのところは、任意のconfファイルのパスで
-rは、ファイルを自動反映してくれる
-fは、confファイルを直接指定できるため、デバッグ時に便利

/usr/share/logstash/bin/logstash -r -f /etc/logstash/conf.d/syslog.conf

エラー: runner - Logstash could not be started because there is already another instance using the configured data directory.

# /usr/share/logstash/bin/logstash -r -f /etc/logstash/conf.d/test.conf
~省略~
[FATAL] 2021-02-17 01:53:47.117 [LogStash::Runner] runner - Logstash could not be started because there is already another instance using the configured data directory.  If you wish to run multiple instances, you must change the "path.data" setting.

/usr/share/logstash/bin/logstash -r -f /etc/logstash/conf.d/test.confを実行したところ、エラー
別インスタンスが起動しているよ~的なこと言われたので、停止してから改めてコマンドを実行

# systemctl stop logstash
#  /usr/share/logstash/bin/logstash -r -f /etc/logstash/conf.d/test.conf
~省略~
[INFO ] 2021-02-17 02:06:24.310 [[main]<beats] Server - Starting server on port: 5044
[INFO ] 2021-02-17 02:06:25.112 [Api Webserver] agent - Successfully started Logstash API endpoint {:port=>9600}

無事成功。Nginxのaccessログを監視している別ホストfilebeatから受信できるか確認

{
       "fileset" => {
        "name" => "access"
    },
       "service" => {
        "type" => "nginx"
    },
         "agent" => {
            "hostname" => "localhost.localdomain",
                "name" => "localhost.localdomain",
                "type" => "filebeat",
                  "id" => "aa222f46-f798-482e-98e5-0a2a945ebfb6",
             "version" => "7.10.2",
        "ephemeral_id" => "134970e0-853f-4fb1-823d-d4976cf0b854"
    },
          "type" => "beats",
       "message" => "192.168.1.1 - - [16/Feb/2021:17:07:52 +0000] \"GET / HTTP/1.1\" 304 0 \"-\" \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36\" \"-\"",
          "tags" => [
        [0] "beats_input_codec_plain_applied"
    ],
      "@version" => "1",
    "@timestamp" => 2021-02-16T17:08:01.181Z,
           "log" => {
          "file" => {
            "path" => "/var/log/nginx/access.log"
        },
        "offset" => 36673
    },
           "ecs" => {
        "version" => "1.5.0"
    },
         "event" => {
          "module" => "nginx",
        "timezone" => "+09:00",
         "dataset" => "nginx.access"
    },
         "input" => {
        "type" => "log"
    },
          "host" => {
         "architecture" => "x86_64",
                   "ip" => [
            [0] "10.0.2.15",
            [1] "fe80::eb4b:6d81:e129:ecfe",
            [2] "192.168.1.12",
            [3] "fe80::a00:27ff:fe28:2f54"
        ],
             "hostname" => "localhost.localdomain",
                 "name" => "localhost.localdomain",
                   "id" => "6b55c49d03fd3144918fc6166f4f350d",
        "containerized" => false,
                   "os" => {
            "codename" => "Core",
                "name" => "CentOS Linux",
              "kernel" => "3.10.0-1160.15.2.el7.x86_64",
              "family" => "redhat",
            "platform" => "centos",
             "version" => "7 (Core)"
        },
                  "mac" => [
            [0] "08:00:27:96:ec:15",
            [1] "08:00:27:28:2f:54"
        ]
    }
}

こちらも受け取れていることを確認

Nginxのgrokパターンを作成する

概要

Nginxのログを収集するElasticStackの環境が構築できたので、Logstashのパイプラインについて理解を深める。
今回はgrokを使ってNginxのaccess.log用のパターンを作成する

デバックには、Test grok patternsというサイトを使用した。

http://grokconstructor.appspot.com/do/match#result

今回は以下のログをパターン化することが目標

192.168.1.1 - - [16/Feb/2021:17:07:52 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36" "-"

以下が正解のパターンっぽいので、こちらを読み解くことで理解することを試みた。

https://gist.github.com/mariotacke/88053be5be5ef87b7544ece220f41af4
Nginxのaccess.logのフォーマット
log_format combined '$remote_addr - $remote_user [$time_local] '
                    '"$request" $status $body_bytes_sent '
                    '"$http_referer" "$http_user_agent"';
NGINX_ACCESS %{IPORHOST:remote_addr} - %{USERNAME:remote_user} \[%{HTTPDATE:time_local}\] \"%{DATA:request}\" %{INT:status} %{NUMBER:bytes_sent} \"%{DATA:http_referer}\" \"%{DATA:http_user_agent}\"

IPGREEDYDATAは標準パターンとして用意されているらしい。

https://www.elastic.co/jp/blog/a-practical-introduction-to-logstash

grokの設定を作成する際、一般的に使用される標準パターンが多数あります。

WORD-単一のワードにマッチするパターン
NUMBER-正または負の整数あるいは浮動小数点数にマッチするパターン。
POSINT-正の整数にマッチするパターン
IP-IPv4またはIPv6のIPアドレスにマッチするパターン
NOTSPACE-スペース以外のものすべてにマッチするパターン
SPACE-連続しているスペースの任意の数にマッチするパターン
DATA-制限された量のあらゆる種類のデータにマッチ(最短マッチ)するパターン
GREEDYDATA-すべての残りのデータにマッチするパターン

%{IPORHOST:remote_addr}
IPORHOSTは上記に乗っていないが、名前からしてホスト名かIPアドレスを取得できるパターンであることがわかる
そしてそちらの値をremote_addrとしてLogstashのConfigから後で指定できるようにしている。
%{INT:status}
INTなので、整数用の標準パターンです。

作成したパターンを実装してみる

作成したGrokパターンを、configファイルのfilterに追加
remove_field => ["message"]で不要になった大元のmessageフィールドを取り除く。

input {
  beats {
    port => "5044"
    type => "beats"
    client_inactivity_timeout => 120
  }
}
filter {
  grok {
    match => {
      "message" => "%{IP:ip} - %{USER:remote_addr} \[%{HTTPDATE:time_local}\] \"%{DATA:request}\" %{INT:status} %{NUMBER:bytes_sent} \"%{DATA:http_reffer}\" \"%{DATA:http_user_agent}\""
    }
    remove_field => ["message"]
  }
}
output {
  stdout {
    codec => rubydebug
  }
  elasticsearch {
    hosts => ["localhost:9200"]
    index => "%{[@metadata][beat]}-%{[@metadata][version]}-%{+YYYY.MM.dd}"
  }
}

outputに
mtricbeat

ログインするとコメントできます