ELK是Elasticsearch、Logstash、Kibana的簡稱,這三者是核心套件,但並非全部。
Elasticsearch是實時全文搜索和分析引擎,提供蒐集、分析、存儲數據三大功能;是一套開放REST和JAVA API等結構提供高效搜索功能,可擴展的分佈式系統。它構建於Apache Lucene搜索引擎庫之上。
Logstash是一個用來蒐集、分析、過濾日誌的工具。它支持幾乎任何類型的日誌,包括系統日誌、錯誤日誌和自定義應用程序日誌。它可以從許多來源接收日誌,這些來源包括 syslog、消息傳遞(例如 RabbitMQ)和JMX,它能夠以多種方式輸出數據,包括電子郵件、websockets和Elasticsearch。
Kibana是一個基於Web的圖形界面,用於搜索、分析和可視化存儲在 Elasticsearch指標中的日誌數據。它利用Elasticsearch的REST接口來檢索數據,不僅允許用戶創建他們自己的數據的定製儀表板視圖,還允許他們以特殊的方式查詢和過濾數據。
ELK架構
通常來說,只使用這三個組件就可以進行日誌收集了,不過在企業實際生產中,需要用到ELK做集中日誌收集的話,日誌的產生量都是驚人的,所以通常情況下會需要緩存層來防止elasticsearch被壓垮。架構如下圖所示。(也可以通過filebeat來收集日誌。)
ELK的部署
需要注意的是,ELK的這三個組件版本要一致,否則可能會出現一些不必要的問題。我們這裏選用最新版本7.5.1爲例,演示主機均爲ubuntu1804。
Elasticsearch
我們這裏用兩臺主機來搭建一個elasticsearch集羣,一般來說因爲他的選舉機制,elasticsearch集羣都是3、5、7奇數個,不過2臺主機也可以使用,我們這裏節約主機使用兩臺主機做演示,IP分別爲192.168.32.41
、192.168.32.42
。
官網下載鏈接爲https://www.elastic.co/cn/downloads/elasticsearch。
我們這裏選擇deb安裝包安裝,也可以選用源碼tar包自己解壓安裝。
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.5.1-amd64.deb
這個版本的deb包是自帶java環境(openjdk11)的,如果主機已經預製java環境,可以去官網下載no-java的版本,使用jdk8的時候有warning,說未來版本將不支持jdk8,建議使用jdk11及以上。
dpkg -i elasticsearch-7.5.1-amd64.deb
elasticsearch的配置文件路徑爲/etc/elasticsearch/elasticsearch.yml
,需要修改的不多,將集羣主機IP設置好就可以了,如下所示
root@elasticsearch1:~# grep "^[a-Z]" /etc/elasticsearch/elasticsearch.yml
cluster.name: ELK-CLuster #集羣名稱,名稱相同即屬於是同一個集羣
node.name: node-1 #本機在集羣內的節點名稱
path.data: /elasticsearch/data
path.logs: /elasticsearch/logs
bootstrap.memory_lock: true #服務啓動的時候鎖定足夠的內存, 防止數據寫入swap
network.host: 0.0.0.0
http.port: 9200
discovery.seed_hosts: ["192.168.32.41","192.168.32.42"]
cluster.initial_master_nodes: ["node-1","node-2"]
我這裏是單獨創建了一個日誌路徑和數據路徑,方便管理,並修改屬主賦予權限。
mkdir -p /elasticsearch/{data,logs}
chown -R elasticsearch:elasticsearch /elasticsearch
除了在配置文件中設置bootstrap.memory_lock: true
以外,還需要在啓動配置文件中設置允許無限制使用內存,否則啓動檢查就會報錯,導致服務起不來。
vim /usr/lib/systemd/system/elasticsearch.service
LimitMEMLOCK=infinity
而且根據官方文檔https://www.elastic.co/guide/en/elasticsearch/reference/current/heap-size.html,最大30G 以內的內存。
在一般使用中,使用最大內存和最小內存都設置爲2G就可以了。
vim /etc/elasticsearch/jvm.options
-Xms2g
-Xmx2g
另一臺主機也同樣配置,記得修改node.name
,之後就可以啓動elasticsearch了。
systemctl enable --now elasticsearch
在任意主機使用curl命令可以檢查集羣的健康狀態。
curl -sXGET http://192.168.32.41:9200/_cluster/health?pretty=true
獲取到的是一個 json 格式的返回值,那就可以通過 python 對其中的信息進行分析,例如對 status 進行分析,如果等於 green(綠色)就是運行在正常,等於yellow(黃色)表示副本分片丟失, red(紅色)表示主分片丟失。
至此,elasticsearch服務的部署就算是完成了。
Logstash
logstash也是一個基於java的插件式服務,很多功能都是依靠於插件來實現的,我們安裝官方的安裝包,大部分常用插件都是已經預置了,如果還有其他的功能需求,就需要去官網或者github下載插件了。這些之後再說,我們先去官網上將Logstash7.5.1安裝包下載下來並部署上。
wget https://artifacts.elastic.co/downloads/logstash/logstash-7.5.1.deb
logstash也同樣需要java環境
apt update
apt install openjdk-8-jdk
或者安裝oracle的jdk,生產環境還是推薦使用oracle公司的jdk,更加穩定。然後安裝logstash
dpkg -i logstash-7.5.1.deb
對於logstash的配置也很少,不做修改也可以使用,不過我們這裏同樣還是修改一下數據目錄和日誌目錄
root@logstash1:~# grep "^[a-Z]" /etc/logstash/logstash.yml
path.data: /logstash/data
path.logs: /logstash/logs
修改屬主
mkdir -p /logstash/{data,logs}
chown -R /logstash
logstash的默認執行程序路徑爲/usr/share/logstash/bin/logstash
,這其實也是一個shell腳本文件,腳本中調用java的類庫。
root@logstash1:~# /usr/share/logstash/bin/logstash --help
Thread.exclusive is deprecated, use Thread::Mutex
WARNING: Could not find logstash.yml which is typically located in
$LS_HOME/config or /etc/logstash. You can specify the path using --path.settings.
Continuing using the defaults
Usage:
bin/logstash [OPTIONS]
Options:
-n, --node.name NAME Specify the name of this logstash instance,
if no value is given
it will default to the current hostname.
(default: "logstash1")
-f, --path.config CONFIG_PATH Load the logstash config from a specific file
or directory. If a directory is given, all
files in that directory will be concatenated
in lexicographical order and then parsed as a
single config file. You can also specify
wildcards (globs) and any matched files will
be loaded in the order described above.
-e, --config.string CONFIG_STRING Use the given string as the configuration
data. Same syntax as the config file. If no
input is specified, then the following is
used as the default input:
"input { stdin { type => stdin } }"
and if no output is specified, then the
following is used as the default output:
"output { stdout { codec => rubydebug } }"
If you wish to use both defaults, please use
the empty string for the '-e' flag.
(default: nil)
不過常用的選項也就-e
和-f
,分別是通過命令行指定參數或者通過文件來指定配置參數。我們可以使用命令來測試
/usr/share/logstash/bin/logstash -e 'input { stdin{} } output { stdout{ codec => rubydebug }}'
通過標準輸入輸入信息,並通過標準輸出返回日誌信息。同樣,我們也可以調用input的file插件和output的file插件實現從文件中讀取數據,或者寫入文件。這樣就可以實現對日誌文件的抓取了。我們可以先嚐試抓取系統日誌如syslog
。
/usr/share/logstash/bin/logstash -e 'input { file { path => "/var/log/syslog"} } output { stdout{ codec => rubydebug }}'
哈,系統日誌如果太多,估計會刷屏的。
不過剛纔那些都只是一些基本用法而已,而實際生產中,我們肯定不能使用命令行來手動獲取數據,我們需要的是一個可靠的服務,來幫我們自動抓取日誌並篩選過濾,這就需要我們使用配置文件來設置了。
例如我們要做的抓取本機的nginx的訪問日誌、錯誤日誌還有系統日誌,並傳遞至之前配好的elasticsearch中。
那就在路徑/etc/logstash/conf.d/
目錄下,創建一個新的配置文件,使用systemd啓動時會自動讀取conf.d下的配置文件。
vim /etc/logstash/conf.d/nginx.conf
input {
file {
path => "/var/log/syslog"
stat_interval => 3
start_position => "beginning"
type => "syslog"
}
file {
path => "/apps/nginx/logs/access_json.log"
stat_interval => 3
start_position => "beginning"
codec => "json"
type => "nginx_accesslog"
}
file {
path => "/apps/nginx/logs/error.log"
stat_interval => 3
start_position => "beginning"
type => "nginx_errorlog"
}
}
output {
if [type] == "syslog" {
elasticsearch {
hosts => ["192.168.32.41:9200"]
index => "syslog-%{+YYYY.MM.dd}"
}}
if [type] == "nginx_accesslog" {
elasticsearch {
hosts => ["192.168.32.41:9200"]
index => "nginx_accesslog-%{+YYYY.MM.dd}
}}
if [type] == "nginx_errorlog" {
elasticsearch {
hosts => ["192.168.32.41:9200"]
index => "nginx_accesslog-%{+YYYY.MM.dd}
}}
}
logstash支持條件判斷,多輸入以及多輸出,設定type規則,來將每一類日誌分類在不同的索引,且支持java的時間變量,可以實現根據日期歸檔每一天的日誌,方便查看和統計。
我們可以使用命令來測試腳本的語法是否正確,如果不加-t
可以直接以前臺進程的方式啓動logstash,不過會佔據終端,但測試的時候還是蠻方便的。
/usr/share/logstash/bin/logstash -f /etc/log/logstash/conf,d/nginx.conf -t
不過僅僅是這樣,是無法統計具體訪問時間、訪問ip及訪問路徑的詳細信息的,我們需要將nginx的日誌序列化,或者說是儲存爲json格式。
所以修改nginx的配置文件,將日誌格式修改一下。
http {
include mime.types;
default_type application/octet-stream;
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
log_format access_json '{"@timestamp":"$time_iso8601",'
'"host":"$server_addr",'
'"clientip":"$remote_addr",'
'"size":$body_bytes_sent,'
'"responsetime":$request_time,'
'"upstreamtime":"$upstream_response_time",'
'"upstreamhost":"$upstream_addr",'
'"http_host":"$host",'
'"uri":"$uri",'
'"domain":"$host",'
'"xff":"$http_x_forwarded_for",'
'"referer":"$http_referer",'
'"tcp_xff":"$proxy_protocol_addr",'
'"http_user_agent":"$http_user_agent",'
'"status":"$status"}';
access_log /apps/nginx/logs/access_json.log access_json;
PS:加入的屬性名稱不要有type
,否則會影響到logstash做type判斷。然後記得在配置文件中註明輸入信息爲json格式。看到如下信息,則說明日誌被成功拆解。
{
"http_user_agent" => "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:69.0) Gecko/20100101 Firefox/69.0",
"path" => "/apps/nginx/logs/access_json.log",
"@timestamp" => 2020-01-03T08:17:47.000Z,
"upstreamhost" => "-",
"xff" => "-",
"responsetime" => 0.0,
"size" => 0,
"status" => "304",
"http_host" => "192.168.32.51",
"clientip" => "192.168.32.1",
"domain" => "192.168.32.51",
"tcp_xff" => "",
"host" => "192.168.32.51",
"@version" => "1",
"uri" => "/index.html",
"referer" => "-",
"upstreamtime" => "-"
}
使用systemctl enable --now logstash
啓動logstash服務,過一會,日誌就寫入elasticsearch服務器中了,最好將/etc/systemd/system/logstash.service
文件的中啓動用戶組都改爲root
,避免因爲權限問題,導致無法讀取數據。
我記得之前遇到過一次,命令行可以正常使用logstash,不過使用systemd啓動就一直報錯,logstash: could not find java; set JAVA_HOME or ensure java is in PATH
,明明環境變量都是正常的,後來在/usr/share/logstash/bin/logstash
腳本文件中加了一個JAVA_HOME=/usr/local/jdk
環境變量就好了,而之後配的時候就沒有遇到這個問題了,這就很奇怪了。
Kibana
日誌信息都已經寫到elasticsearch服務器中了,不過我們怎麼纔可以看到具體的日誌信息呢?這就需要藉助日誌展示工具Kibana了。
雖然elasticsearch可視化工具也有不少,例如head、kopf、cerebro等等,不過他們都是監控elasticsearch集羣狀態的,對日誌做展示分析的還是首推開源的官方組件Kibana。
同樣下載kibana7.5.1版本
https://artifacts.elastic.co/downloads/kibana/kibana-7.5.1-amd64.deb
配置上也很簡單,設置監聽IP及端口,設置elasticsearch主機地址,最後再將語言環境改爲中文就可以啓動kibana服務了。
root@kibana1:~# grep "^[a-Z]" /etc/kibana/kibana.yml
server.port: 5601
server.host: "0.0.0.0"
elasticsearch.hosts: ["http://192.168.32.41:9200"]
i18n.locale: "zh-CN"
瀏覽器訪問kibana主機的5601端口。
創建索引模式,依次添加索引。
然後點左邊第一個(最上面)的那個discover圖標,就可以看到數據了。點擊更改,選擇對應的索引,還可以創建各種視圖等一系列功能這裏就不再詳細講解了。都比較簡單。
至此ELK的初步部署就算完成了。