ELK實時日誌分析平臺環境部署

一、概念介紹

日誌主要包括系統日誌、應用程序日誌和安全日誌。系統運維和開發人員可以通過日誌瞭解服務器軟硬件信息、檢查配置過程中的錯誤及錯誤發生的原因。經常分析日誌可以瞭解服務器的負荷,性能安全性,從而及時採取措施糾正錯誤。

通常,日誌被分散的儲存不同的設備上。如果你管理數十上百臺服務器,你還在使用依次登錄每臺機器的傳統方法查閱日誌。這樣是不是感覺很繁瑣和效率低下。當務之急我們使用集中化的日誌管理,例如:開源的syslog,將所有服務器上的日誌採集彙總。

集中化管理日誌後,日誌的統計和檢索又成爲一件比較麻煩的事情,一般我們使用grep、awk和wc等Linux命令能實現檢索和統計,但是對於要求更高的查詢、排序和統計等要求和龐大的機器數量依然使用這樣的方法難免有點力不從心。

通過我們需要對日誌進行集中化管理,將所有機器上的日誌信息採集、彙總到一起。完整的日誌數據具有非常重要的作用:

  • 信息查找。通過檢索日誌信息,定位相應的bug,找出解決方案。
  • 服務診斷。通過對日誌信息進行統計、分析,瞭解服務器的負荷和服務運行狀態,找出耗時請求進行優化等等。
  • 數據分析。如果是格式化的log,可以做進一步的數據分析,統計、聚合出有意義的信息,比如根據請求中的商品id,找出TOP10用戶感興趣商品。

那麼,有沒有一種方法能解決日誌採集、統計和檢索?開源實時日誌分析ELK平臺就能夠完美的解決我們上述的問題。

簡單地來說,ELK 就是 Elasticsearch、Logstash 和 Kibana 三個開源工具的首字母簡寫。

1、Elasticsearch

Elasticsearch是一個開源的基於Lucene的開源實時的分佈式搜索分析引擎工具。它能讓你以一個之前從未有過的速度和規模,去探索你的數據。它的特點有:分佈式,零配置,自動發現,索引自動分片,集羣配置方便等。索引副本機制,restful風格接口,多數據源,自動搜索負載等。它提供了一個分佈式多用戶能力的全文搜索引擎,基於RESTful web接口。Elasticsearch是用Java開發的,並作爲Apache許可條款下的開放源碼發佈,是第二流行的企業搜索引擎。設計用於雲計算中,能夠達到實時搜索,穩定,可靠,快速,安裝使用方便。在Elasticsearch中,所有節點的數據是均等的。

(1)關於集羣配置

  • discovery.zen.ping.unicast.hosts,Elasticsearch默認使用Zen Discovery來做節點發現機制,推薦使用unicast來做通信方式,在該配置項中列舉出Master節點。
  • discovery.zen.minimum_master_nodes,該參數表示集羣中可工作的具有Master節點資格的最小數量,默認值是1。爲了提高集羣的可用性,官方推薦設置爲(N/2)+1,其中N是具有Master資格的節點的數量。
  • discovery.zen.ping_timeout,表示節點在發現過程中的等待時間,默認值是3秒,可以根據自身網絡環境進行調整,一定程度上提供可用性。
    discovery.zen.ping.unicast.hosts: ["host1", "host2"]
    discovery.zen.minimum_master_nodes: 2
    discovery.zen.ping_timeout: 10

(2)關於集羣節點

  • 節點類型包括:候選Master節點、數據節點和Client節點。通過設置兩個配置項node.master和node.data爲true或false,來決定將一個節點分配爲什麼類型的節點。
  • 儘量將候選Master節點和Data節點分離開,通常Data節點負載較重,需要考慮單獨部署。

(3)關於內存
Elasticsearch默認設置的內存是1GB,對於任何一個業務部署來說,這個都太小了。通過指定ES_HEAP_SIZE環境變量,可以修改其堆內存大小,服務進程在啓動時候會讀取這個變量,並相應的設置堆的大小。建議設置系統內存的一半給Elasticsearch,但是不要超過32GB。

(4)關於硬盤空間
Elasticsearch將數據存儲在自定義的路徑下,隨着數據的增長,一定會出現硬盤空間不夠用的情形,此時就需要給機器掛載新的硬盤,並將Elasticsearch的路徑配置到新硬盤的路徑下。通過“path.data”配置項來進行設置,比如“path.data: /elk/elasticsearch/data”。需要注意的是,同一分片下的數據只能寫入到一個路徑下,因此還是需要合理的規劃。

(5)關於Index的劃分和分片的個數
這個需要根據數據量來做權衡了,Index可以按時間劃分,比如每月一個或者每天一個,在Logstash輸出時進行配置,shard的數量也需要做好控制。

(6)關於監控
這裏我使用head和kopf兩個監控插件。

2、Logstash

Logstash是一個開源的日誌採集工具,是一個數據管道。主要用來採集、解析和分析大量結構化和非結構化的數據以及各種系統產生的事件。它可以對你的日誌進行採集、過濾、分析,並將其存儲供以後使用(如,搜索),我們可以使用它。說到搜索,logstash帶有一個web界面,搜索和展示所有日誌。

Logstash工作原理展示圖:
ELK實時日誌分析平臺環境部署

(1)常用的輸入input

  • file:文件輸入插件用於將事件和日誌文件輸入給logstash。它會自動檢測日誌文件輪轉,並從上次讀取的位點讀取數據。
  • syslog:在514端口上監聽系統日誌消息,並根據RFC3164標準進行解析
  • redis:從redis service中讀取
  • beats:從filebeat中讀取
  • Filters:數據中間處理,對數據進行操作。

(2)常用的過濾器filter

  • grok:解析任意文本數據,Grok 是 Logstash 最重要的插件。它的主要作用就是將文本格式的字符串,轉換成爲具體的結構化的數據,配合正則表達式使用。內置120多個解析語法。
  • mutate:對字段進行轉換。例如對字段進行刪除、替換、修改、重命名等。
  • drop:丟棄一部分events不進行處理。
  • clone:拷貝 event,這個過程中也可以添加或移除字段。
  • geoip:添加地理信息(爲前臺kibana圖形化展示使用)。
  • Outputs:outputs是logstash處理管道的最末端組件。一個event可以在處理過程中經過多重輸出,但是一旦所有的outputs都執行結束,這個event也就完成生命週期。

(3)常見的輸出output

  • elasticsearch:elasticsearch插件是ELK技術棧中用到的最重要的插件,它用於將輸出的結果存儲到elasticsearch搜索引擎中供Kibana分析。
  • file:將event數據保存到文件中。
  • graphite:將event數據發送到圖形化組件中,一個很流行的開源存儲圖形化展示的組件。
  • codecs:codecs 是基於數據流的過濾器,它可以作爲input,output的一部分配置。Codecs可以幫助你輕鬆的分割發送過來已經被序列化的數據。

(4)常見的編解碼codecs

  • json:使用json格式對數據進行編碼/解碼。
  • line:用於將每行輸入日誌作爲一個事件,將每個事件解碼成一行。
  • multiline:將匯多個事件中數據彙總爲一個單一的行。比如:java異常信息和堆棧信息。
  • plain:插件用於指示輸入或輸出事件時,不需要額外的編解碼操作,對應的輸入輸出插件會自己處理編解碼。對很多插件如redis、mongondb等而言,plain是默認的編解碼類型。
  • rubydebug:只在輸出事件時使用,它使用Ruby Awesome打印庫打印輸出事件。

(5)採集日誌信息

pattern => "^\["             # 採集以"["開頭的日誌信息
pattern => "^2018"           # 採集以"2018"開頭的日誌信息
pattern => "^[a-zA-Z0-9]"      # 採集以字母(大小寫)或數字開頭的日誌信息
pattern => "^[a-zA-Z0-9]|[^ ]+"  # 採集以字母(大小寫)或數字或空格的日誌信息

3、Kibana

Kibana是一個開源的基於瀏覽器頁面的Elasticsearch前端展示工具。它Kibana可以爲 Logstash 和 ElasticSearch 提供的日誌分析友好的 Web 界面,可以幫助我們彙總、分析和搜索重要數據日誌,也可以通過直方圖、地圖、餅圖、其它圖形和表格等方式來表達數據。只需要點擊鼠標,就可以完成搜索、聚合功能,生成炫麗的儀表板。
Kibana提供的是數據查詢和顯示的Web服務,有豐富的圖表樣板,能滿足大部分的數據可視化需求,這也是很多人選擇ELK的主要原因之一。

而在5.0版本以後,Elastic公司將原來的 ELK Stack 稱之爲 Elastic Stack,原因是引入了 Beats 套件。

官網:https://www.elastic.co/products

ELK工作原理展示圖:
ELK實時日誌分析平臺環境部署

如上圖所示:多個應用服務器上的日誌通過Logstash採集器傳輸到一個集中化的索引器中,索引器將處理後的數據結果輸出到ElasticSearch集羣,然後Kibana通過下查詢ElasticSearch集羣中的日誌數據創建儀表盤,做可視化展現。

二、ELK整體方案

ELK中的三個系統分別扮演着不同的角色,組成了一個整體的解決方案。Logstash是一個ETL工具,負責從每臺機器抓取日誌數據,對數據進行格式轉換和處理後,輸出到Elasticsearch中存儲。Elasticsearch是一個分佈式搜索引擎和分析引擎,用於數據存儲,可提供實時的數據查詢。Kibana是一個數據可視化服務,根據用戶的操作從Elasticsearch中查詢數據,形成相應的分析結果,以圖表的形式展現給用戶。
ELK的安裝很簡單,可以按照“下載->修改配置文件->啓動”方法分別部署三個系統,也可以使用Docker來快速部署。下面來看一個常見的部署方案,如下圖所示:
ELK實時日誌分析平臺環境部署

  1. 在每臺生成日誌文件的機器上,部署Logstash,作爲Shipper的角色,負責從日誌文件中提取數據,但是不做任何處理,直接將數據輸出到Redis隊列(list)中;
  2. 需要一臺機器部署Logstash,作爲Indexer的角色,負責從Redis中取出數據,對數據進行格式化和相關處理後,輸出到Elasticsearch中存儲;
  3. 部署Elasticsearch集羣,當然取決於你的數據量了,數據量小的話可以使用單臺服務,如果做集羣的話,最好是有3個以上節點,同時還需要部署相關的監控插件;
  4. 部署Kibana服務,提供Web可視化展現服務。

在前期部署階段,主要工作是Logstash節點和Elasticsearch集羣的部署,而在後期使用階段,主要工作就是Elasticsearch集羣的監控和使用Kibana來檢索、分析日誌數據了,當然也可以直接編寫程序來消費Elasticsearch中的數據。

在上面的部署方案中,我們將Logstash分爲Shipper和Indexer兩種角色來完成不同的工作,中間通過Redis做數據管道,爲什麼要這樣做?爲什麼不是直接在每臺機器上使用Logstash提取數據、處理、存入Elasticsearch?

首先,採用這樣的架構部署,有三點優勢:

  1. 降低對日誌所在機器的影響,這些機器上一般都部署着反向代理或應用服務,本身負載就很重了,所以儘可能的在這些機器上少做事。
  2. 如果有很多臺機器需要做日誌採集,那麼讓每臺機器都向Elasticsearch持續寫入數據,必然會對Elasticsearch造成壓力,因此需要對數據進行緩衝,同時,這樣的緩衝也可以一定程度的保護數據不丟失。
  3. 將日誌數據的格式化與處理放到Indexer中統一做,可以在一處修改代碼、部署,避免需要到多臺機器上去修改配置。

其次,我們需要做的是將數據放入一個消息隊列中進行緩衝,所以Redis只是其中一個選擇,也可以是RabbitMQ、Kafka等等,在實際生產中,Redis與Kafka用的比較多。由於Redis集羣一般都是通過key來做分片,無法對list類型做集羣,在數據量大的時候必然不合適了,而Kafka天生就是分佈式的消息隊列系統。
ELK實時日誌分析平臺環境部署

三、ELK環境部署

1、基礎環境介紹

# 系統: Centos7.3
[root@elk-01 ~]# cat /etc/redhat-release 
CentOS Linux release 7.3.1611 (Core)

# 防火牆: 關閉
[root@elk-01 ~]# systemctl stop firewalld && systemctl disable firewalld
Removed symlink /etc/systemd/system/multi-user.target.wants/firewalld.service.
Removed symlink /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.

# Sellinux: 關閉
[root@elk-01 ~]# setenforce 0
[root@elk-01 ~]# sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config

# 機器環境: 兩臺
elk-01: 192.168.8.55       # master機器
elk-02: 192.168.8.66       # slave機器

說明:
master-slave模式:master採集到日誌後,會把一部分數據碎片到salve上(隨機的一部分數據);同時,master和slave又都會各自做副本,並把副本放到對方機器上,這樣就保證了數據不會丟失。
如果master宕機了,那麼客戶端在日誌採集配置中將Elasticsearch主機指向改爲slave,就可以保證ELK日誌的正常採集和web展示

2、Elasticsearch安裝配置

Elasticsearch是java程序,而且要跑在jdk1.8版本以上
elk-01和elk-02同時操作

(1)寫hosts文件

[root@elk-01 ~]# echo "192.168.8.55 elk-01" >> /etc/hosts
[root@elk-02 ~]# echo "192.168.8.66 elk-02" >> /etc/hosts

(2)安裝jdk1.8版本

[root@elk-01 ~]# yum -y install java-1.8.0
[root@elk-01 ~]# java -version
openjdk version "1.8.0_102"
OpenJDK Runtime Environment (build 1.8.0_102-b14)
OpenJDK 64-Bit Server VM (build 25.102-b14, mixed mode)

(3)安裝Elasticsearch

[root@elk-01 ~]# wget https://download.elastic.co/elasticsearch/release/org/elasticsearch/distribution/tar/elasticsearch/2.4.6/elasticsearch-2.4.6.tar.gz
[root@elk-01 ~]# mkdir /elk
[root@elk-01 ~]# tar zxvf elasticsearch-2.4.6.tar.gz -C /elk
[root@elk-01 ~]# cd /elk/
[root@elk-01 elk]# ls
elasticsearch-2.4.6
[root@elk-01 elk]# mv ./elasticsearch-2.4.6 ./elasticsearch

(4)修改Elasticsearch配置文件

[root@elk-01 ~]# vim /elk/elasticsearch/config/elasticsearch.yml     #將配置文件內容修改如下,打開註釋
17 cluster.name: test-ELK     # 配置集羣名,兩臺服務器名保持一致
23 node.name: elk-01   # 配置單一節點名稱,每個節點唯一標識
33 path.data: /elk/elasticsearch/data   # data存儲路徑
37 path.logs: /elk/elasticsearch/logs   #log存儲路徑
43 bootstrap.memory_lock: true      # 鎖住內存,不被使用到交換分區去
54 network.host: 0.0.0.0    # 監聽地址
58 http.port: 9200          # 監聽端口
68 discovery.zen.ping.unicast.hosts: ["192.168.8.66"]   # 集羣節點發現列表,寫另外一臺的ip
72 discovery.zen.minimum_master_nodes: 2   # 集羣可做master的最小節點數

[root@elk-01 ~]# mkdir -p /elk/elasticsearch/{data,logs}

(5)修改系統參數

[root@elk-01 ~]# vim /etc/security/limits.conf     --文件最後添加系統參數,讓系統用戶打開文件無限制
# 添加配置
*        soft    nofile  65536
*        hard    nofile  131072
*        soft    nproc   2048
*        hard    nproc   4096
*        soft    memlock unlimited
*        hard    memlock unlimited

[root@elk-01 ~]# vim /etc/sysctl.conf   --在此文件里加入以下參數
# 添加配置
vm.max_map_count= 262144

[root@elk-01 ~]# sysctl -p  --刷新
vm.max_map_count = 262144

(6)開戶啓動Elasticsearch服務

當使用root賬戶啓動Elasticsearch會出現錯誤信息,這是因爲處於系統安裝考慮的設置,由於Elasticsearch可以接收用戶輸入的腳本並且執行,爲了系統安全考慮,不允許root賬號啓動,所以建議給Elasticsearch單獨創建一個用戶來運行Elasticsearch。

# 創建elk用戶組及elk用戶
[root@elk-01 ~]# groupadd elk
[root@elk-01 ~]# useradd elk -g elk -p 123
[root@elk-01 ~]# chown -R elk.elk /elk/elasticsearch
[root@elk-01 ~]# su - elk
上一次登錄:六 5月  5 11:08:30 CST 2018pts/5 上
[elk@elk-01 ~]$ cd /elk/elasticsearch/
[elk@elk-01 elasticsearch]$ nohup ./bin/elasticsearch &
[1] 3503
[elk@elk-01 elasticsearch]$ nohup: 忽略輸入並把輸出追加到"nohup.out"

[root@elk-01 ~]# netstat -antlp |egrep "9200|9300"
tcp6       0      0 :::9200                 :::*                    LISTEN      1608/java
tcp6       0      0 :::9300                 :::*                    LISTEN      1608/java
tcp6       0      1 192.168.8.66:47992      192.168.8.55:9300       SYN_SENT    1608/java
tcp6       0      0 192.168.8.66:9200       192.168.8.1:2015        ESTABLISHED 1608/java

如果啓動失敗,在系統日誌(我們的示例中爲/ var/log/messages)中將會遇到與以下類似的錯誤:

Apr  9 15:39:09 elk-02 kernel: [ 3727]  1000  3727   784748   214244     617    70749             0 java
Apr  9 15:39:09 elk-02 kernel: Out of memory: Kill process 3727 (java) score 368 or sacrifice child
Apr  9 15:39:09 elk-02 kernel: Killed process 3727 (java) total-vm:3138992kB, anon-rss:849016kB, file-rss:7960kB, shmem-rss:0kB

這個錯誤的原因是low memory耗盡。“內核使用low memory來跟蹤所有的內存分配,一旦low memory耗盡,就會查殺進程,以保持系統的正常運轉。說白了 OOM Killer 就是一層保護機制,用於避免 Linux 在內存不足的時候不至於出太嚴重的問題,把無關緊要的進程殺掉。
最簡單的解決方法就是增加內存空間。

(7)訪問Elasticsearch

http://192.168.8.55:9200/
http://192.168.8.66:9200/

瀏覽器訪問結果(訪問時建議使用chrome、firefox瀏覽器)
ELK實時日誌分析平臺環境部署
ELK實時日誌分析平臺環境部署

3、安裝Elasticsearch-head插件

elasticsearch-head是用於瀏覽Elasticsearch集羣並與其進行交互的Web前端。也就是用於顯示集羣節點和數據信息。

Elasticsearch 5及以上版本(可自行研究)中的head插件已經不通過elasticsearch-plugin 來進行安裝,已經成爲了一個獨立的服務,需要單獨進行安裝,安裝方法可參考GitHub網站

在Elasticsearch 5之前的版本,安裝起來比較簡單,在安裝成功後可以在瀏覽器中通過http://ip:9200/_plugin/head 就可以訪問了,這裏的IP地址即爲你的Elasticsearch服務器地址。查看官方文檔 。具體安裝如下:

[root@elk-01 ~]# /elk/elasticsearch/bin/plugin install mobz/elasticsearch-head
-> Installing mobz/elasticsearch-head...
Trying https://github.com/mobz/elasticsearch-head/archive/master.zip ...
Downloading .............................................................................................................................DONE
Verifying https://github.com/mobz/elasticsearch-head/archive/master.zip checksums if available ...
NOTE: Unable to verify checksum for downloaded plugin (unable to find .sha1 or .md5 file to verify)
Installed head into /elk/elasticsearch/plugins/head

插件安裝的目錄:/elk/elasticsearch/plugins
在線安裝完成之後,進行授予權限

[root@elk-01 ~]# chown -R elk:elk /elk/elasticsearch/plugins
[root@elk-01 ~]# ll /elk/elasticsearch/plugins/head/

ELK實時日誌分析平臺環境部署

插件訪問(最好提前將elk-02節點的配置和插件都安裝後,再來進行訪問和數據插入測試)

http://192.168.8.55:9200/_plugin/head/
http://192.168.8.66:9200/_plugin/head/

ELK實時日誌分析平臺環境部署
ELK實時日誌分析平臺環境部署

注:ES集羣健康度分爲:紅、黃、綠三種顏色
紅色:個別分片 副本不可用
×××:個別副本不可用
綠色:爲健康

兩臺機器看到的內容完全一致,test-ELK是集羣名稱,集羣健康值爲綠色。

測試一
插入數據實例,看界面能不能正常顯示
如下:點擊“複合查詢”,在POST選項下,任意輸入如/2018/test然後在下面輸入數據(注意內容之間換行的逗號不要漏掉);
數據輸入好之後(如下輸入"user":"xiaozuo","mess":"test Elasticsearch"內容),下面點擊“驗證JSON”->“提交請求”,提交成功後,觀察右欄內出現的信息:有index、type、version等信息,failed:0(成功消息)
ELK實時日誌分析平臺環境部署

測試二
如下:點擊“複合查詢”,選擇GET選項,在/2018/test/後面輸入上面POST結果中的id號,不輸入內容,即{}括號裏爲空!
然後點擊“驗證JSON”->“提交請求”,觀察右欄內就有了上面插入的數據了(即xiaozuo,test Elasticsearch)
ELK實時日誌分析平臺環境部署

點擊“基本查詢”,查看數據,如下圖所示,即可查詢到上面插入的數據:
ELK實時日誌分析平臺環境部署

點擊“數據瀏覽”,也能查看到插入的數據:
ELK實時日誌分析平臺環境部署

點擊“概覽”,主界面也會更新,顯示剛纔創建類型,也會顯示數據碎片存取的位置:
ELK實時日誌分析平臺環境部署

每個索引都有5個分片,粗線寬的分片是主節點分片,細線寬的是副本。這樣kibana在搜索的時候就可以從多個Easticsearch服務器上讀取,壓力也按比例分佈在各個集羣節點中。

說明:
一定要提前在elk-02節點上也完成配置(配置內容同上)。如果你還沒有建立集羣,那麼只能看到一個節點,而且上面插入數據後,Elasticsearch集羣狀態會呈現×××yellow狀態,elk-02完成配置加入到集羣裏後就會恢復到正常的綠色狀態。
當數據不多的時候通過一臺Elasticsearch服務器也能完成任務。但是數據隨着時間的推移而增多,尤其需要查詢6個月、一年甚至更長時間跨度的數據時,你會發現集羣有多麼重要。

4、安裝kopf監控插件

Kopf展示了ElasticSearch的節點分片、文檔、所佔用空間、大小等信息,並且可以查詢文檔的索引。

[root@elk-01 ~]# /elk/elasticsearch/bin/plugin install lmenezes/elasticsearch-kopf
-> Installing lmenezes/elasticsearch-kopf...
Trying https://github.com/lmenezes/elasticsearch-kopf/archive/master.zip ...
Downloading .............................................................................................................................DONE
Verifying https://github.com/lmenezes/elasticsearch-kopf/archive/master.zip checksums if available ...
NOTE: Unable to verify checksum for downloaded plugin (unable to find .sha1 or .md5 file to verify)
Installed kopf into /elk/elasticsearch/plugins/kopf

# 授予權限
[root@elk-01 ~]# chown -R elk:elk /elk/elasticsearch/plugins
[root@elk-01 ~]# ll /elk/elasticsearch/plugins/kopf/

ELK實時日誌分析平臺環境部署

訪問插件:(如下,同樣要提前安裝好elk-02節點上的插件,否則訪問時會出現集羣節點爲×××的yellow告警狀態)

http://192.168.8.55:9200/_plugin/kopf/#!/cluster
http://192.168.8.66:9200/_plugin/kopf/#!/cluster

ELK實時日誌分析平臺環境部署

到此Elasticsearch軟件包安裝完成。

5、Logstash安裝配置

elk-01和elk-02都要安裝。同時,Logstash部署在每臺生成日誌文件的機器上,採集到的數據寫入到Elasticsearch裏,就可以登陸Logstash界面查看到了)

(1)安裝Logstash

[root@elk-01 ~]# wget https://download.elastic.co/logstash/logstash/logstash-2.4.1.tar.gz
[root@elk-01 ~]# tar zxvf logstash-2.4.1.tar.gz -C /elk/
[root@elk-01 ~]# mv /elk/logstash-2.4.1/ /elk/logstash/
[root@elk-01 ~]# useradd logstash -s /sbin/nologin 
[root@elk-01 ~]# chown -R logstash.logstash /elk/logstash/

(2)數據的測試

測試一
基本的輸入輸出,驗證logstash能否接收到數據。

[root@elk-01 ~]# /elk/logstash/bin/logstash -e "input { stdin{ } } output { stdout{} }"
Settings: Default pipeline workers: 1
Pipeline main started
xiaozuo      # 輸入的內容
2018-05-06T07:15:50.140Z elk-01.com xiaozuo   # 輸出的內容
hello        # 輸入的內容
2018-05-06T07:16:09.850Z elk-01.com hello     # 輸出的內容

ELK實時日誌分析平臺環境部署

在這個例子中,我們通過輸入插件stdin和輸出插件stdout來運行Logstash,所以不管你輸入什麼,都會輸出同樣的信息。使用-e參數可以在命令行中快速地測試配置是否正確。

測試二
使用rubydebug詳細輸出

[root@elk-01 ~]# /elk/logstash/bin/logstash -e "input { stdin{} } output { stdout{ codec => rubydebug} }"
Settings: Default pipeline workers: 1
Pipeline main started
hello    # 輸入的內容
{       # 輸出下面信息
       "message" => "hello",
      "@version" => "1",
    "@timestamp" => "2018-05-06T07:23:16.933Z",
          "host" => "elk-01.com"
}
xiaozuoxiansen   # 輸入的內容
{       # 輸出下面信息
       "message" => "xiaozuoxiansen",
      "@version" => "1",
    "@timestamp" => "2018-05-06T07:23:48.631Z",
          "host" => "elk-01.com"
}

ELK實時日誌分析平臺環境部署

測試三
把內容寫到Elasticsearch中

[root@elk-01 ~]# /elk/logstash/bin/logstash -e "input { stdin{} } output { elasticsearch { hosts => ['192.168.8.55:9200']} }"
Settings: Default pipeline workers: 1
Pipeline main started
123456     # 隨意輸入內容
xiaozuo
hello

ELK實時日誌分析平臺環境部署

說明:
使用rubydebug和寫到elasticsearch中的區別:其實就在於後面標準輸出的區別,前者使用codec;後者使用elasticsearch。

寫到Elasticsearch中在Logstash中查看,如下圖所示:
ELK實時日誌分析平臺環境部署

注意:
master採集到日誌後,會把一部分數據碎片到salve上(隨機的一部分數據),master和slave又都會各自做副本,並把副本放到對方機器上,這樣就保證了數據不會丟失。
如下,master採集到的數據放到了自己的第0、2、4分片上,其他的放到了slave的第1、3分片上。

再點擊“數據瀏覽”,可以看到剛纔輸入的內容:
ELK實時日誌分析平臺環境部署ELK實時日誌分析平臺環境部署

(3) Logstash的配置和文件的編寫

1)Logstash的配置
簡單的配置方式:

[root@elk-01 ~]# mkdir /elk/logstash/conf.d/
[root@elk-01 ~]# vim /elk/logstash/conf.d/01-logstash.conf
input { stdin { } }
output {
        elasticsearch { hosts => ["192.168.8.55:9200"]}
        stdout { codec => rubydebug }
}

執行結果:

[root@elk-01 ~]# /elk/logstash/bin/logstash -f /elk/logstash/conf.d/01-logstash.conf 
Settings: Default pipeline workers: 1
Pipeline main started
ShenZhen       # 隨意輸入內容
{       # 輸出下面的信息
       "message" => "ShenZhen",
      "@version" => "1",
    "@timestamp" => "2018-05-06T07:59:40.650Z",
          "host" => "elk-01.com"
}

ELK實時日誌分析平臺環境部署

再擊“數據瀏覽”,可以看到剛纔輸入的內容:
ELK實時日誌分析平臺環境部署

參考官方文檔:
https://www.elastic.co/guide/en/logstash/current/configuration.html
https://www.elastic.co/guide/en/logstash/current/configuration-file-structure.html

2)採集系統日誌

[root@elk-01 ~]# vim /elk/logstash/conf.d/file.conf
input {            # 指定輸出
    file {         # 輸出的內容爲文件
      path => "/var/log/messages"   # 文件路徑
      type => "system"            # 給該類日誌內容定一個名稱,可自定義
      start_position => "beginning"  # 表示從哪裏開始讀取日誌,beginning是所有都讀
    }
}

output {               # 指定輸出到哪裏
    elasticsearch {      # 指定輸出到elasticaearch服務裏
       hosts => ["192.168.8.55:9200"]     # 指定連接elasticaearch服務的IP和端口
       index => "system-%{+YYYY.MM.dd}"   # 把日誌按日期進行分類
    }
}

執行上面日誌信息的採集,如下圖所示,這個命令會一直在執行中,表示日誌在監控採集中;如果中斷,就表示日誌不在採集!所以需要放在後臺執行&

[root@elk-01 ~]# /elk/logstash/bin/logstash -f /elk/logstash/conf.d/file.conf &

登陸Elasticsearch界面,查看本機系統日誌的信息:
ELK實時日誌分析平臺環境部署
ELK實時日誌分析平臺環境部署
ELK實時日誌分析平臺環境部署

參考官方文檔:
https://www.elastic.co/guide/en/logstash/current/plugins-outputs-elasticsearch.html
https://www.elastic.co/guide/en/logstash/current/event-dependent-configuration.html

從上面採集系統日誌的“數據瀏覽”中可以看出,每個日誌都給採集成一行了,不是按照一個日誌,一個事件模塊採集的。

(4)將行換成事件的方式展示

[root@elk-01 ~]# vim /elk/logstash/conf.d/multiline.conf
input {
    stdin {
       codec => multiline {
          pattern => "^\["
          negate => true
          what => "previous"
        }
    }
}
output {
    stdout {
      codec => "rubydebug"
     }
}

執行命令:

[root@elk-01 ~]# /elk/logstash/bin/logstash -f /elk/logstash/conf.d/multiline.conf

ELK實時日誌分析平臺環境部署

說明:
在沒有遇“[”的時候,系統不會採集,只有遇見“[”的時候,纔算是一個事件,才採集起來。

參考官方文檔:
https://www.elastic.co/guide/en/logstash/current/plugins-codecs-multiline.html

6、Kibana安裝配置

(1)安裝Kibana

[root@elk-01 ~]# wget https://download.elastic.co/kibana/kibana/kibana-4.6.6-linux-x86_64.tar.gz
[root@elk-01 ~]# tar zxvf kibana-4.6.6-linux-x86_64.tar.gz -C /elk/
[root@elk-01 ~]# mv /elk/kibana-4.6.6-linux-x86_64/ /elk/kibana/

(2)修改配置文件

[root@elk-01 ~]# cd /elk/kibana/config/
[root@elk-01 config]# pwd
/elk/kibana/config
[root@elk-01 config]# ls
kibana.yml
[root@elk-01 config]# mv kibana.yml kibana.yml.bak
[root@elk-01 config]# vim kibana.yml
server.port: 5601
server.host: "0.0.0.0"
elasticsearch.url: "http://192.168.8.55:9200"
kibana.index: ".kibana"  # 注意這個.Kibana的index索引配置一定要有,它是將ES數據通過kibana進行web展示的關鍵。這個配置後,在ES的web界面裏就會看到這個.kibana索引。

(3)啓動Kibana

因爲Kibana一直運行在前臺,所以可以放在後臺執行&

[root@elk-01 ~]# cd /elk/kibana/
[root@elk-01 kibana]# nohup ./bin/kibana &
[1] 10314
[root@elk-01 kibana]# nohup: 忽略輸入並把輸出追加到"nohup.out"
[root@elk-01 kibana]# lsof -i:5601
COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
node    10314 root   11u  IPv4 107473      0t0  TCP *:esmagent (LISTEN)

ELK實時日誌分析平臺環境部署

(4)訪問Kibana

http://192.168.8.55:5601

ELK實時日誌分析平臺環境部署

(5)創建日誌採集項

創建一個日誌採集項,該名稱要和前面寫的file.conf配置文件裏的type字段一致。比如添加system系統日誌。注意後面的*不要忘了。
ELK實時日誌分析平臺環境部署

創建完成後,再點擊“Discover”,在Discover中查看:
ELK實時日誌分析平臺環境部署

查看日誌登陸,需要點擊“Discover”-->“message”,點擊它後面的“add”
說明:
需要右邊查看日誌內容時帶什麼屬性,就在左邊點擊相應屬性後面的“add”
如下圖,添加了message和path的屬性:
ELK實時日誌分析平臺環境部署
ELK實時日誌分析平臺環境部署

這樣,右邊顯示的日誌內容的屬性就帶了message和path。
ELK實時日誌分析平臺環境部署

點擊右邊日誌內容屬性後面隱藏的<<,就可將內容向前縮進:
ELK實時日誌分析平臺環境部署
ELK實時日誌分析平臺環境部署

添加新的日誌採集項,點擊“Settings”->“ +Add New”,比如添加logstash-日誌。注意後面的*不要忘了。
ELK實時日誌分析平臺環境部署
ELK實時日誌分析平臺環境部署
ELK實時日誌分析平臺環境部署
ELK實時日誌分析平臺環境部署

刪除Kibana裏的日誌採集項,點擊刪除圖標即可,如下圖所示:
ELK實時日誌分析平臺環境部署

如果打開Kibana查看日誌,發現沒有日誌內容,出現“No results found”,如下圖所示,這說明要查看的日誌在當前時間沒有日誌信息輸出,可以點擊右上角的時間鍾來調試日誌信息的查看。
ELK實時日誌分析平臺環境部署
ELK實時日誌分析平臺環境部署

(6)採集nginx的訪問日誌

[root@elk-01 ~]# wget https://nginx.org/download/nginx-1.14.0.tar.gz
[root@elk-01 ~]# tar zxf nginx-1.14.0.tar.gz -C /usr/src/
[root@elk-01 ~]# cd /usr/src/nginx-1.14.0/
[root@elk-01 ~]# ./configure --prefix=/usr/local/nginx
[root@elk-01 ~]# make && make install
[root@elk-01 ~]# useradd nginx -s /sbin/nologin  --創建nginx用戶,-s制定shell,nginx用戶不需要登錄系統
[root@elk-01 ~]# id nginx
uid=1002(nginx) gid=1002(nginx) 組=1002(nginx)
[root@elk-01 ~]# chown -R nginx.nginx /usr/local/nginx/
[root@elk-01 ~]# vim /usr/local/nginx/conf/nginx.conf  --打開以下注釋(根據需求)
  2 user nginx nginx;  # 運行的用戶和組,打開註釋,使用nginx身份
  7 error_log  logs/error.log  info;  # 錯誤日誌以及日誌等級,打開等級爲info級別的日誌
  9 pid        logs/nginx.pid;  # pid文件
33     gzip  on;  # 在服務器壓縮數據,進行傳輸
37         server_name  192.168.8.55;  # 主機名或者IP
39         charset utf8;  # 字符集,改成utf8
48         error_page  404              /404.html;  # 錯誤頁面

Nginx安裝配置完成後,先查看一下80端口是否被佔用,佔用的話先停掉Apache(因Apache默認是80端口,如果是其它程序佔用,則停掉佔用80端口的程序)

[root@elk-01 ~]# lsof -i:80   --80端口沒有佔用
[root@elk-01 ~]# /usr/local/nginx/sbin/nginx 
[root@elk-01 ~]# lsof -i:80   --Nginx啓動成功
COMMAND   PID   USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
nginx   13375   root    6u  IPv4 166972      0t0  TCP *:http (LISTEN)
nginx   13376 nobody    6u  IPv4 166972      0t0  TCP *:http (LISTEN)

瀏覽器訪問Nginx

http://192.168.8.55/

ELK實時日誌分析平臺環境部署

Nginx安裝成功之後,修改Nginx的配置文件,分別在nginx.conf的http和server配置區域添加下面內容:

# http 標籤中
    log_format json '{"@timestamp":"$time_iso8601",'
                      '"@version":"1",'
                      '"client":"$remote_addr",'
                      '"url":"$uri",'
                      '"status":"$status",'
                      '"domain":"$host",'
                      '"host":"$server_addr",'
                      '"size":$body_bytes_sent,'
                      '"responsetime":$request_time,'
                      '"referer": "$http_referer",'
                      '"ua": "$http_user_agent"'
                      '}';

# server標籤中
        access_log /var/log/nginx/access_json.log json;

截圖如下:
ELK實時日誌分析平臺環境部署
ELK實時日誌分析平臺環境部署

啓動Nginx服務:

[root@elk-01 ~]# mkdir /var/log/nginx/
[root@elk-01 ~]# touch /var/log/nginx/access_json.log
[root@elk-01 ~]# /usr/local/nginx/sbin/nginx -s stop
[root@elk-01 ~]# /usr/local/nginx/sbin/nginx

編寫日誌採集文件:
使用的是json的方式採集:

[root@elk-01 ~]# vim json.conf
input {
   file {
      path => "/var/log/nginx/access_json.log"
      codec => "json"
   }
}

output {
   stdout {
      codec => "rubydebug"
   }
}

啓動日誌採集程序:

[root@elk-01 ~]# /elk/logstash/bin/logstash -f /root/json.conf &   --加個&放在後臺執行

訪問nginx頁面(在elk-01的主機上執行訪問頁面的命令:curl http://192.168.8.55)就會出現以下圖所示
ELK實時日誌分析平臺環境部署

注意:
上面的json.conf配置只是將nginx日誌輸出,還沒有輸入到Elasticsearch裏,所以這個時候在Elasticsearch界面裏是採集不到nginx日誌的。
需要配置一下,將Nginx日誌輸入到Elasticsearch中,將其彙總到總文件file.conf裏,如下也將nginx-log日誌輸入到Elasticserach裏:(後續就可以只用這個彙總文件,把要追加的日誌彙總到這個總文件裏即可)

[root@elk-01 ~]# cat file.conf 
input {
    file {
      path => "/var/log/messages"
      type => "system"
      start_position => "beginning"
    }

    file {
       path => "/var/log/nginx/access_json.log"
       codec => json
       start_position => "beginning"
       type => "nginx-log"
    }
}

output {

    if [type] == "system"{
        elasticsearch {
           hosts => ["192.168.8.55:9200"]
           index => "system-%{+YYYY.MM.dd}"
        }
    }

    if [type] == "nginx-log"{
        elasticsearch {
           hosts => ["192.168.8.55:9200"]
           index => "nignx-log-%{+YYYY.MM.dd}"
        }
    }
}

在執行日誌採集命令時,可以加上--configtest參數,測試下配置文件是否有語法錯誤或配置不當的地方,這個很重要!!

[root@elk-01 ~]# /elk/logstash/bin/logstash -f file.conf --configtest
Configuration OK

然後接着執行Logstash命令(由於上面已經將這個執行命令放到了後臺,所以這裏其實不用執行,也可以先kill之前的,再放後臺執行),然後可以再訪問Nginx界面測試下

[root@elk-01 ~]# /elk/logstash/bin/logstash -f /root/file.conf &

登陸Elasticsearch主界面查看:
ELK實時日誌分析平臺環境部署

登陸Kibana主界面查看:
ELK實時日誌分析平臺環境部署
ELK實時日誌分析平臺環境部署

(7)採集系統日誌

編寫日誌採集文件:

[root@elk-01 ~]# cat syslog.conf 
input {
    syslog {
        type => "system-syslog"
        host => "192.168.8.55"
        port => "514"
    }
}

output {
    stdout {
        codec => "rubydebug"
    }
}

對上面的採集文件進行執行:

[root@elk-01 ~]# /elk/logstash/bin/logstash -f syslog.conf

重新開啓一個窗口,查看服務是否啓動:

[root@elk-01 ~]# netstat -antlp | grep 514
tcp6       0      0 192.168.8.55:514        :::*                    LISTEN      14101/java          
[root@elk-01 ~]# vim /etc/rsyslog.conf
[root@elk-01 ~]# systemctl restart rsyslog

回到原來的窗口(即上面採集文件的執行終端),就會出現數據:

[root@elk-01 ~]# /elk/logstash/bin/logstash -f syslog.conf
Settings: Default pipeline workers: 1
Pipeline main started
{
           "message" => "[origin software=\"rsyslogd\" swVersion=\"7.4.7\" x-pid=\"14155\" x-info=\"http://www.rsyslog.com\"] start\n",
          "@version" => "1",
        "@timestamp" => "2018-05-07T08:30:05.000Z",
              "type" => "system-syslog",
              "host" => "192.168.8.55",
          "priority" => 46,
         "timestamp" => "May  7 16:30:05",
         "logsource" => "elk-01",
           "program" => "rsyslogd",
          "severity" => 6,
          "facility" => 5,
    "facility_label" => "syslogd",
    "severity_label" => "Informational"
}
........
........

再次把syslog.conf文件的內容添加到總文件file.conf中:

[root@elk-01 ~]# cat file.conf 
input {
    file {
      path => "/var/log/messages"
      type => "system"
      start_position => "beginning"
    }

    file {
       path => "/var/log/nginx/access_json.log"
       codec => json
       start_position => "beginning"
       type => "nginx-log"
    }
    syslog {
        type => "system-syslog"
        host => "192.168.8.55"
        port => "514"
    }
}

output {
    if [type] == "system"{
        elasticsearch {
           hosts => ["192.168.8.55:9200"]
           index => "system-%{+YYYY.MM.dd}"
        }
    }

    if [type] == "nginx-log"{
        elasticsearch {
           hosts => ["192.168.8.55:9200"]
           index => "nignx-log-%{+YYYY.MM.dd}"
        }
    }
        ``
    if [type] == "system-syslog"{
        elasticsearch {
           hosts => ["192.168.8.55:9200"]
           index => "system-syslog-%{+YYYY.MM.dd}"
        }
    }
}

執行總文件(先測試下總文件file.conf配置是否有誤,然後先kill之前在後臺啓動的file.conf文件,再次執行):

[root@elk-01 ~]# /elk/logstash/bin/logstash -f /root/file.conf --configtest
Configuration OK
[root@elk-01 ~]# jobs -l
[1]  13511 運行中               nohup ./bin/kibana &(工作目錄:/elk/kibana)
[2]- 13645 運行中               /elk/logstash/bin/logstash -f /root/json.conf &
[3]+ 13815 運行中               /elk/logstash/bin/logstash -f /root/file.conf &
[root@elk-01 ~]# kill -9 13815
[root@elk-01 ~]# 
[3]+  已殺死               /elk/logstash/bin/logstash -f /root/file.conf
[root@elk-01 ~]# /elk/logstash/bin/logstash -f /root/file.conf &

測試:
向日志中添加數據,查看Elasticsearch和Kibana的變化:

[root@elk-01 ~]# logger "Hello World_01"
[root@elk-01 ~]# logger "Hello World_02"
[root@elk-01 ~]# logger "Hello World_03"
[root@elk-01 ~]# logger "Hello World_04"
[root@elk-01 ~]# logger "Hello World_05"

ELK實時日誌分析平臺環境部署
ELK實時日誌分析平臺環境部署
ELK實時日誌分析平臺環境部署

(8)TCP日誌的採集

編寫日誌採集文件,並執行:(有需要的話,可以將下面採集文件的配置彙總到上面的總文件file.conf裏,進而輸入到Elasticsearch界面裏和Kibana裏查看)

[root@elk-01 ~]# cat tcp.conf 
input {
    tcp {
        host => "192.168.8.55"
        port => "6666"
    }
}

output {
    stdout {
        codec => "rubydebug"
    }
}
# 執行
[root@elk-01 ~]# /elk/logstash/bin/logstash -f /root/tcp.conf

重新開啓一個窗口,執行如下命令:
測試一(安裝nc命令):

[root@elk-01 ~]# yum install -y nc
[root@elk-01 ~]# nc 192.168.8.55 6666 < /etc/resolv.conf

回到原來的窗口(即上面採集文件的執行終端),就會出現數據:

[root@elk-01 ~]# /elk/logstash/bin/logstash -f /root/tcp.conf 
Settings: Default pipeline workers: 1
Pipeline main started
{                  
       "message" => "# Generated by NetworkManager",
      "@version" => "1",
    "@timestamp" => "2018-05-07T08:59:11.599Z",
          "host" => "192.168.8.55",
          "port" => 58622
}
{
       "message" => "search elk-01.com",
      "@version" => "1",
    "@timestamp" => "2018-05-07T08:59:11.601Z",
          "host" => "192.168.8.55",
          "port" => 58622
}
{
       "message" => "nameserver 192.168.8.1",
      "@version" => "1",
    "@timestamp" => "2018-05-07T08:59:11.614Z",
          "host" => "192.168.8.55",
          "port" => 58622
}

測試二

[root@elk-01 ~]# echo "hello" | nc 192.168.8.55 6666
[root@elk-01 ~]# echo "hello" > /dev/tcp/192.168.8.55/6666

回到之前的執行端口,再去查看,就會顯示出數據:

[root@elk-01 ~]# /elk/logstash/bin/logstash -f /root/tcp.conf 
Settings: Default pipeline workers: 1
Pipeline main started
{
       "message" => "hello",
      "@version" => "1",
    "@timestamp" => "2018-05-07T09:00:51.130Z",
          "host" => "192.168.8.55",
          "port" => 58970
}
{
       "message" => "hello",
      "@version" => "1",
    "@timestamp" => "2018-05-07T09:01:13.536Z",
          "host" => "192.168.8.55",
          "port" => 59048
}

(9)使用filter

編寫日誌採集文件:

[root@elk-01 ~]# cat grok.conf 
input {
    stdin { }
}
filter {
    grok {
        match => { "message" => "%{IP:client} %{WORD:method} %{URIPATHPARAM:request} %{NUMBER:bytes} %{NUMBER:duration}" }
    }
}

output {
    stdout{
        codec => "rubydebug"
    }
}

對上面的採集文件進行執行:

[root@elk-01 ~]# /elk/logstash/bin/logstash -f grok.conf 
Settings: Default pipeline workers: 1
Pipeline main started
55.3.244.1 GET /index.html 15824 0.043   # 輸入左邊內容,下面就會自動生成字典的形式
{
       "message" => "55.3.244.1 GET /index.html 15824 0.043",
      "@version" => "1",
    "@timestamp" => "2018-05-07T09:14:56.201Z",
          "host" => "elk-01.com",
        "client" => "55.3.244.1",
        "method" => "GET",
       "request" => "/index.html",
         "bytes" => "15824",
      "duration" => "0.043"
}

ELK實時日誌分析平臺環境部署

其實上面使用的那些正則在程序中都有定義:

[root@elk-01 patterns]# cd /elk/logstash/vendor/bundle/jruby/1.9/gems/logstash-patterns-core-2.0.5/patterns
[root@elk-01 patterns]# ls
aws     bro   firewalls      haproxy  junos         mcollective           mongodb  postgresql  redis
bacula  exim  grok-patterns  java     linux-syslog  mcollective-patterns  nagios   rails       ruby
[root@elk-01 patterns]# cat grok-patterns

ELK實時日誌分析平臺環境部署

(10)mysql慢查詢

編寫日誌採集文件:

[root@elk-01 ~]# cat mysql-slow.conf 
input {
    file {
        path => "/var/lib/mysql/elk-01-slow.log"
        type => "mysql-slowlog"
        codec => multiline {
            pattern => "^# User@Host"
            negate => true
            what => "previous"
        }
    }
}

filter {
    # drop sleep events
    grok {
        match => { "message" =>"SELECT SLEEP" }
        add_tag => [ "sleep_drop" ]
        tag_on_failure => [] # prevent default _grokparsefailure tag on real records
    }
    if "sleep_drop" in [tags] {
        drop {}
    }
    grok {
        match => [ "message", "(?m)^# User@Host: %{USER:user}\[[^\]]+\] @ (?:(?<clienthost>\S*) )?\[(?:%{IP:clientip})?\]\s+Id: %{NUMBER:row_id:int}\s*# Query_time: %{NUMBER:query_time:float}\s+Lock_time: %{NUMBER:lock_time:float}\s+Rows_sent: %{NUMBER:rows_sent:int}\s+Rows_examined: %{NUMBER:rows_examined:int}\s*(?:use %{DATA:database};\s*)?SET timestamp=%{NUMBER:timestamp};\s*(?<query>(?<action>\w+)\s+.*)\n#\s*" ]
    }
    date {
        match => [ "timestamp", "UNIX" ]
        remove_field => [ "timestamp" ]
    }
}

output {
    stdout {
       codec =>"rubydebug"
    }
}

安裝好mysql數據庫之後,在配置文件my.cnf

[root@elk-01 ~]# vim /etc/my.cnf   --在[mysqld]組裏面添加以下內容
slow_query_log      # 打開慢查詢日誌
slow_query_log_file=/var/lib/mysql/elk-01-slow.log   # 指定慢查詢日誌所在文件
long_query_time=2               # 設一個閾值,要大於這個值纔會記錄,等於該值時不記錄。
log_queries_not_using_indexes   # 如果運行的SQL語句沒有使用索引,則MySQl數據庫同樣會將這條SQL語句記錄到慢查詢日誌文件

對上面的採集文件進行執行:

[root@elk-01 ~]# /elk/logstash/bin/logstash -f /root/mysql-slow.conf
Settings: Default pipeline workers: 1
Pipeline main started
{
    "@timestamp" => "2018-05-08T04:19:49.871Z",
       "message" => "/usr/libexec/mysqld, Version: 5.5.52-MariaDB (MariaDB Server). started with:\nTcp port: 0  Unix socket: /var/lib/mysql/mysql.sock\nTime                 Id Command    Argument\n# Time: 180508 12:19:47",
      "@version" => "1",
          "tags" => [
        [0] "multiline",
        [1] "_grokparsefailure"
    ],
          "path" => "/var/lib/mysql/elk-01-slow.log",
          "host" => "elk-01.com",
          "type" => "mysql-slowlog"
}

ELK實時日誌分析平臺環境部署

再次把mysql-slow.conf文件的內容添加到總文件file.conf中,或者修改mysql-slow.conf文件,讓數據展示在ES和Kibana中:

[root@elk-01 ~]# cat mysql-slow.conf 
input {
    file {
        path => "/var/lib/mysql/elk-01-slow.log"
        type => "mysql-slowlog"
        start_position => "beginning"
        codec => multiline {
            pattern => "^# User@Host"
            negate => true
            what => "previous"
        }
    }
}

filter {
    # drop sleep events
    grok {
        match => { "message" =>"SELECT SLEEP" }
        add_tag => [ "sleep_drop" ]
        tag_on_failure => [] # prevent default _grokparsefailure tag on real records
    }
    if "sleep_drop" in [tags] {
        drop {}
    }
    grok {
        match => [ "message", "(?m)^# User@Host: %{USER:user}\[[^\]]+\] @ (?:(?<clienthost>\S*) )?\[(?:%{IP:clientip})?\]\s+Id: %{NUMBER:row_id:int}\s*# Query_time: %{NUMBER:query_time:float}\s+Lock_time: %{NUMBER:lock_time:float}\s+Rows_sent: %{NUMBER:rows_sent:int}\s+Rows_examined: %{NUMBER:rows_examined:int}\s*(?:use %{DATA:database};\s*)?SET timestamp=%{NUMBER:timestamp};\s*(?<query>(?<action>\w+)\s+.*)\n#\s*" ]
    }
    date {
        match => [ "timestamp", "UNIX" ]
        remove_field => [ "timestamp" ]
    }
}

output {
    if [type] == " mysql-slowlog"{
        elasticsearch {
            hosts => ["192.168.8.55:9200"]
            index => "mysql-slowlog-%{+YYYY.MM.dd}"
        }
    }
}

對上面的採集文件進行執行:

[root@elk-01 ~]# /elk/logstash/bin/logstash -f /root/mysql-slow.conf --configtest
Configuration OK
[root@elk-01 ~]# /elk/logstash/bin/logstash -f /root/mysql-slow.conf &

登陸Elasticsearch主界面查看:
ELK實時日誌分析平臺環境部署

登陸Kibana主界面查看:
ELK實時日誌分析平臺環境部署
ELK實時日誌分析平臺環境部署

接下來,我們試想一個問題:
如果我們的Elasticsearch出現了問題,那就不能進行日誌採集處理了!
這種情況下該怎麼辦呢?
解決方案:
可以在Client和Elasticsearch之間添加一箇中間件作爲緩存,先將採集到的日誌內容寫到中間件上,然後再從中間件輸入到Elasticsearch中。
這樣,就完美的解決了上述的問題了。

7、ELK中使用redis作爲中間件,緩存日誌採集數據

(1)redis的配置和啓動

# 下載解壓
[root@elk-01 ~]# wget http://download.redis.io/releases/redis-4.0.8.tar.gz
[root@elk-01 ~]# tar zxvf redis-4.0.8.tar.gz -C /usr/src/
[root@elk-01 ~]# cd /usr/src/redis-4.0.8/
# 進入解壓後的文件目錄,之後直接編譯即可(redis安裝相對簡單)
[root@elk-01 redis-4.0.8]# make
[root@elk-01 redis-4.0.8]# make install
[root@elk-01 redis-4.0.8]# cd utils
[root@elk-01 utils]# ./install_server.sh
Selected config:
Port           : 6379
Config file    : /etc/redis/6379.conf
Log file       : /var/log/redis_6379.log
Data dir       : /var/lib/redis/6379
Executable     : /usr/local/bin/redis-server
Cli Executable : /usr/local/bin/redis-cli

# 修改配置文件和啓動
[root@elk-01 ~]# vim /etc/redis/6379.conf   --修改下面內容
# bind 127.0.0.1   # 註釋掉
protected-mode no  # 保護模式爲no
daemonize yes  # 守護進程模式爲yes

# 啓動
[root@elk-01 ~]# redis-server /etc/redis/6379.conf
[root@elk-01 ~]# lsof -i:6379
COMMAND     PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
redis-ser 27502 root    6u  IPv6 380301      0t0  TCP *:6379 (LISTEN)
redis-ser 27502 root    7u  IPv4 380302      0t0  TCP *:6379 (LISTEN)
# 登陸
[root@elk-01 ~]# redis-cli -h 192.168.8.55 
192.168.8.55:6379> info
# Server
redis_version:4.0.8
……

(2)編寫從Client端採集數據的文件

編寫日誌採集文件:

[root@elk-01 ~]# cat redis-out.conf
input {
   stdin {}
}

output {
   redis {
      host => "192.168.8.55"
      port => "6379"
      db => "6"
      data_type => "list"
      key => "demo"
   }
}

(3)執行採集數據的文件,並輸入數據hello redis

[root@elk-01 ~]# /elk/logstash/bin/logstash -f redis-out.conf
Settings: Default pipeline workers: 1
Pipeline main started    # 下面輸入數據hello redis
hello redis

(4)在redis中查看數據

重新開啓一個窗口,在redis中查看數據:

[root@elk-01 ~]# redis-cli -h 192.168.8.55
192.168.8.55:6379> info  # 輸入內容
# Server
redis_version:4.0.8
……
……
# Keyspace   # 在最下面一行,顯示是db6
db6:keys=1,expires=0,avg_ttl=0
192.168.8.55:6379> select 6  # 輸入內容
OK
192.168.8.55:6379[6]> keys *  # 輸入內容
1) "demo"
192.168.8.55:6379[6]> LINDEX demo -1  # 輸入內容
"{\"message\":\"hello redis\",\"@version\":\"1\",\"@timestamp\":\"2018-05-08T08:53:16.806Z\",\"host\":\"elk-01.com\"}"

ELK實時日誌分析平臺環境部署

(5)繼續自定義輸入數據

[root@elk-01 ~]# /elk/logstash/bin/logstash -f redis-out.conf 
Settings: Default pipeline workers: 1
Pipeline main started
hello redis
123456
xiaozuo
51cto
test
haha

(6)在redis中查看

在redis中查看長度:

[root@elk-01 ~]# redis-cli -h 192.168.8.55
192.168.8.55:6379> info  # 輸入內容
# Server
redis_version:4.0.8
……
……
# Keyspace
db6:keys=1,expires=0,avg_ttl=0  # 顯示是db6
192.168.8.55:6379> select 6  # 輸入內容
OK
192.168.8.55:6379[6]> keys *  # 輸入內容
1) "demo"
192.168.8.55:6379[6]> LLEN demo  # 輸入內容
(integer) 6  # 剛纔自定義輸入了6個字符串

(7)將redis中的內容寫到ES中

編寫日誌採集文件:

[root@elk-01 ~]# cat redis-in.conf 
input {
    redis {
        host => "192.168.8.55"
        port => "6379"
        db => "6"
        data_type => "list"
        key => "demo"
    }
}

output {
    elasticsearch {
        hosts => ["192.168.8.55:9200"]
        index => "redis-in-%{+YYYY.MM.dd}"
    }
}

對上面的採集文件進行執行:

[root@elk-01 ~]# /elk/logstash/bin/logstash -f /root/redis-in.conf --configtest
Configuration OK
[root@elk-01 ~]# /elk/logstash/bin/logstash -f /root/redis-in.conf &

在redis中查看,發現數據已被讀出:

[root@elk-01 ~]# redis-cli -h 192.168.8.55
192.168.8.55:6379> LLEN demo
(integer) 0

登陸Elasticsearch主界面查看:
ELK實時日誌分析平臺環境部署
ELK實時日誌分析平臺環境部署

(8)將採集到的所有日誌寫入到redis中

我這裏重新定義一個添加redis緩存後的總文件shipper.conf。(可以將之前執行的總文件file.conf停掉)
編寫總採集shipper.conf文件:

[root@elk-01 ~]# cat shipper.conf 
input {
    file {
        path => "/var/log/messages"
        type => "system"
        start_position => "beginning"
    }
    file {
        path => "/var/log/nginx/access_json.log"
        codec => json
        start_position => "beginning"
        type => "nginx-log"
    }
    syslog {
        type => "system-syslog"
        host => "192.168.8.55"
        port => "514"
    }
}

output {
    if [type] == "system"{
        redis {
            host => "192.168.8.55"
            port => "6379"
            db => "6"
            data_type => "list"
            key => "system"
        }
    }
    if [type] == "nginx-log"{   
        redis {
            host => "192.168.8.55"
            port => "6379"
            db => "6"
            data_type => "list"
            key => "nginx-log"
        }
    }
    if [type] == "system-syslog"{
        redis {
            host => "192.168.8.55"
            port => "6379"
            db => "6"
            data_type => "list"
            key => "system-syslog"
        }   
    }
}

對上面的採集文件進行執行(提前將上面之前啓動的file.conf文件的執行給結束掉!)

[root@elk-01 ~]# /elk/logstash/bin/logstash -f /root/shipper.conf --configtest
Configuration OK
[root@elk-01 ~]# /elk/logstash/bin/logstash -f /root/shipper.conf &

在redis中查看:

[root@elk-01 ~]# redis-cli -h 192.168.8.55
192.168.8.55:6379> info  # 輸入內容
# Server
redis_version:4.0.8
……
……
# Keyspace
db6:keys=1,expires=0,avg_ttl=0  # 顯示是db6
192.168.8.55:6379> select 6   # 輸入內容
OK
192.168.8.55:6379[6]> keys *  # 輸入內容
1) "system"
192.168.8.55:6379[6]> keys *  # 輸入內容
1) "nginx-log"
2) "system"

重新開啓一個窗口,自定義添加日誌數據:

[root@elk-01 ~]# logger "Hello World"
[root@elk-01 ~]# logger "123456"
[root@elk-01 ~]# logger "test"
[root@elk-01 ~]# logger "hello"
[root@elk-01 ~]# logger "hello"
[root@elk-01 ~]# logger "hello"

回到原來的窗口(即上面執行redis命令的終端),查看內容:

192.168.8.55:6379[6]> keys *  # 輸入內容
1) "system-syslog"   # 新增的日誌
2) "nginx-log"
3) "system"

其實可以在任意的一臺ES中,將數據從redis讀取到ES中。
下面我們在elk-02節點上,將數據從redis讀取到ES中:
編寫日誌採集文件:

[root@elk-02 ~]# cat file.conf 
input {
    redis {
        type => "system"
        host => "192.168.8.55"
        port => "6379"
        db => "6"
        data_type => "list"
        key => "system"
    }
    redis {
        type => "nginx-log"
        host => "192.168.8.55"
        port => "6379"
        db => "6"
        data_type => "list"
        key => "nginx-log"
    }
    redis {
        type => "system-syslog"
        host => "192.168.8.55"
        port => "6379"
        db => "6"
        data_type => "list"
        key => "system-syslog"
    }   
}

output { 
    if [type] == "system"{
        elasticsearch {
            hosts => ["192.168.8.55:9200"]
            index => "system-%{+YYYY.MM.dd}"
        }
    }
    if [type] == "nginx-log"{
        elasticsearch {
            hosts => ["192.168.8.55:9200"]
            index => "nignx-log-%{+YYYY.MM.dd}"
        }
    }
    if [type] == "system-syslog"{
        elasticsearch {
            hosts => ["192.168.8.55:9200"]
            index => "system-syslog-%{+YYYY.MM.dd}"
        }
    }
}

對上面的日誌採集文件進行執行:

[root@elk-02 ~]# /elk/logstash/bin/logstash -f /root/file.conf --configtest
Configuration OK
[root@elk-02 ~]# /elk/logstash/bin/logstash -f /root/file.conf &

在redis中查看,發現數據已經被讀出到Elasticsearch中了。

[root@elk-01 ~]# redis-cli -h 192.168.8.55
192.168.8.55:6379> keys *
(empty list or set)

同時登陸Logstash和Kibana看,發現可以正常採集到日誌了。
ELK實時日誌分析平臺環境部署

也可以啓動多個redis寫到ES中,具體根據自己的實際情況而定。

當客戶機的日誌信息收集後,經過redis剛讀到ES數據庫裏後,如果沒有新數據寫入,則默認在ES的訪問界面裏是看不到數據的。只有當日志文件裏有新的日誌寫入後纔會觸發數據展示的動作,即ES的訪問界面(http://192.168.8.55:9200/_plugin/head/) 裏才能看到日誌數據的展示效果。

四、配置示例

# 192.168.8.55爲ELK的master節點,同時也是redis節點
# 編寫日誌採集文件
[root@elk-01 ~]# cat /conf/tomacat-log.conf 
input {
    file {
        path => "/usr/local/tomcat/logs/catalina.out"
        type => "tomcat-logs"
        start_position => "beginning"
        codec => multiline {
            pattern => "^\["           # 表示採集以“[”開頭的日誌信息
            negate => true
            what => "previous"
        }
    }
}

output {
    if [type] == "tomcat-logs"{
        redis {
            host => "192.168.8.55"
            port => "6379"
            db => "1"
            data_type => "list"
            key => "tomcat-logs"
        }
    }
}

[root@elk-01 ~]# cat /conf/system-log.conf 
input {
    file {
        path => "/var/log/messages"
        type => "systemlog"
        start_position => "beginning"
        stat_interval => "2"
    }
}

output {
    if [type] == "systemlog" {
        redis {
            data_type => "list"
            host => "192.168.10.44"
            db => "2"
            port => "6379"
            key => "systemlog"
        }
    }
}

[root@elk-01 ~]# cat /conf/file.conf 
input {
    redis {
        type => "tomcat8-logs"
        host => "192.168.10.44"
        port => "6379"
        db => "1"
        data_type => "list"
        key => "tomcat8-logs"
    }

    redis {
        type => "systemlog"
        host => "192.168.10.44"
        port => "6379"
        db => "2"
        data_type => "list"
        key => "systemlog"
    }
}

output {
    if [type] == "tomcat8-logs"{
        elasticsearch {
            hosts => ["192.168.10.44:9200"]
            index => "elk-node2-tomcat8-logs-%{+YYYY.MM.dd}"
        }
    }

    if [type] == "systemlog"{
        elasticsearch {
            hosts => ["192.168.10.44:9200"]
            index => "elk-node2-systemlog-%{+YYYY.MM.dd}"
        }
    }
}

# 驗證
[root@elk-01 ~]# /elk/logstash/bin/logstash -f /conf/tomacat-log.conf --configtest
Configuration OK
[root@elk-01 ~]# /elk/logstash/bin/logstash -f /conf/system-log.conf --configtest
Configuration OK
[root@elk-01 ~]# /elk/logstash/bin/logstash -f /conf/file.conf --configtest
Configuration OK

# 執行
[root@elk-01 ~]# /elk/logstash/bin/logstash -f /conf/tomacat-log.conf &
[root@elk-01 ~]# /elk/logstash/bin/logstash -f /conf/system-log.conf &
[root@elk-01 ~]# /elk/logstash/bin/logstash -f /conf/file.conf &

當/usr/local/tomcat/logs/catalina.out和/var/log/messages文件裏有新日誌信息寫入時,就會觸發動作,在redis裏就能查看到相關信息,並查看寫入到ES裏。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章