在業內常見的部署組合就是ELK系統了,ELK是elasticsearch、logstash、kibana三個系統的首字母組合。接下來的幾篇博客會從整體和三個系統細分角度看ELK如何使用。
使用場景
說道日志,一般有這么幾類:異常日志、請求日志、操作日志。
異常日志是大家寫代碼時經常看到的日志堆棧,這類日志有很多行,詳細列出了異常信息、異常名稱、出錯的代碼調用棧、內部異常原因(Caused by),是一類多行日志。
請求日志是接口的調用日志,常見的是nginx、tomcat、weblogic等負載均衡和web容器的日志,一行里面包含了訪問時間、訪問路徑、狀態碼、結果大小、響應時間等信息。也有一些自定義的信息,比如SLA統計系統或者一些性能監控系統所需的日志信息,一般來說會包含請求編號、訪問路徑、步驟編號、響應時間等自定義的信息。
操作日志一般是用來審計或者結果追蹤的信息,這類信息一般會專門的做統一存儲,這類日志也比較重要,一般用數據庫專門存儲。
在ELK使用的場景中,多見的是對異常日志和請求日志的統一處理。
然而,由於請求日志一般來說生成的速度比較快。是至少相當於系統訪問量,通常大於訪問量,因為日志記錄大多還會記錄系統下游接口的訪問日志,緩存訪問日志等。因此,對於請求日志放到ELK的可能也不是特別多見,而是通過腳本針對特定的需求進行收集和查詢。
部署方式
ELK部署最簡單的方式就是L-E-K方式,不添加任何其他輔助系統,部署簡單快速,容易上手。
第二種方式是在L-E之間添加一層redis輔助,這樣能夠減少日志在服務端的積壓,把壓力轉移到ELK系統服務器上。這種方式添加redis之后,由於redis是內存系統所以響應速度很快,而且可以在redis后添加多個消費系統(Logstash),來擴展消費能力,增強處理速度。
接下來簡單說一下E-L-K的三個組成部分。
Logstash
Logstash的獨立性很強,它的用途就是一個內容的轉存系統,通過靈活的插件可以做到很多種類數據的讀取和很多種類數據的寫入。
支持的輸入類型很多,當前包括以下這些:
輸出類型包括這些:
logstash在ELK組合里面擔當的是數據收集和解析的功能。
elasticsearch
es的獨立性也很強,它本身是一個分布式的搜索引擎,通過倒排序索引對存儲的數據進行索引。
當輸入查詢關鍵字之后,es依據命中結果的匹配度有序返回結果,效果就像大家百度或者google搜索一樣。
在ELK組合中,擔當的是數據存儲、索引和提供查詢接口的功能。
kibana
kibana是一個數據展示的客戶端,提供對es中數據的可視化搜索和展示功能,主要提供了時間維度和數據中字段值的檢索。以及功能豐富的看板,能夠添加曲線圖、餅圖、地址分布圖等多種樣式的展示圖形。
在開始之前先說一下Logstash的使用和熟悉路線圖。接觸ELK的時候不能圖快,可以嘗試着一部分一部分的安裝起來熟悉,之后再逐個組裝到一起,看效果。
Logstash的獨立性很高,熟悉路線可以按照這樣來:
1.最基本的就是接收控制台輸入,然后解析輸出到控制台。
2.從文件讀入,解析輸出到控制台。
3.從文件讀入,解析輸出到elasticsearch。
4.實際應用中需要打通的關節。
接下來一起看一下Logstash,這個系列使用的版本(Logstash5.3.0)下載地址是:https://www.elastic.co/cn/downloads
安裝
1.安裝JDK 1.8.0_65
2.下載logstash5.3.0
3.解壓logstash
控制台—》控制台
1.在…/logstash-5.3.0/bin/目錄中新建一個文件std_std.conf文件
2.錄入如下內容:
input {
stdin{
}
}
output {
stdout{
}
}
3.在bin目錄執行命令:./logstash -f std_std.conf
4.稍等片刻,看到如下信息,說明啟動完成了:
5.輸入hello logstash!!!!,logash會在控制台回寫出來這條信息:
文件—-》控制台
這里使用的文件是tomcat輸出的access日志文件,很常見,內容如下:
111.206.36.140 - - [10/Aug/2016:23:16:29 +0800] "GET /nggirl-web/web/admin/work/special/listSelectedWork/v1.4.0?workIds=780 HTTP/1.1" 200 78 "http://www.baidu.com/s?wd=www" "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)" 111.206.36.140 - - [10/Aug/2016:23:16:29 +0800] "GET /nggirl-web/web/admin/work/special/listSelectedWork/v1.4.0?workIds=780 HTTP/1.1" 200 78 "http://www.baidu.com/s?wd=www" "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)"
1.在bin目錄新建file_std.conf文件;
2.內容如下:
input{ file{ path =>"/Develop/Tools/apache-tomcat-8.0.30/webapps/nggirllog/access.log" start_position=>"beginning" } } filter{ grok{ match=>{ "message"=>"%{DATA:clientIp} - - \[%{HTTPDATE:accessTime}\] \"%{DATA:method} %{DATA:requestPath} %{DATA:httpversion}\" %{DATA:retcode} %{DATA:size} \"%{DATA:fromHtml}\" \"%{DATA:useragent}\"" } remove_field=>"message" } date{ match=>["accessTime","dd/MMM/yyyy:HH:mm:ss Z"] } } output{ stdout{ codec=>rubydebug }
3.然后運行./logstash -f file_std.conf,就會看到文件中原有的內容被逐條的顯示在命令行了。
這個配置文件相對比較復雜,而且我們一般在使用elk的時候logstash的配置文件基本也是和這個類似,大同小異了,這里對關鍵部分詳細解說一下。更深入的內容和使用方式,大家可以到elastic官網或者到logstash的最佳實戰頁面去看,網址是:http://udn.yyuap.com/doc/logstash-best-practice-cn/index.html。
input/file/path:這里指定了要對哪個日志文件進行掃描。如果希望掃描多個文件,可以使用*這個路徑通配符;或者使用多個日志路徑以數組形式提供(path=>[“outer-access.log”,”access.log”]);或者直接給定一個目錄,logstash會掃描所有的文件,並監聽是否有新文件。
filter/grok/match/message:里面的DATA和HTTPDATE都是grok語法內置的正則表達式,DATA匹配任意字符,HTTPDATE匹配joda類型的日期格式字符。上例中”\[“是匹配“[”。
filter/grok/match/date: 是對HTTPDATE日期格式的解釋,joda可以支持很多復雜的日期格式,需要在這里指明才能正確匹配。
remove_field=>”message”:用處是去掉原有的整個日志字符串,僅保留filter解析后的信息。你可以試着去掉這一句就明白他的用處了。
解析成功后會看到控制台中類似如下的內容:
文件到elasticsearch
1.在bin目錄新建file_es.conf文件
2.錄入如下內容,和上一個例子的區別僅在於out部分:
input{ file{ path =>"/Develop/Tools/apache-tomcat-8.0.30/webapps/nggirllog/access*.log" start_position=>"beginning" } } filter{ grok{ match=>{ "message"=>"%{DATA:clientIp} - - \[%{HTTPDATE:accessTime}\] \"%{DATA:method} %{DATA:requestPath} %{DATA:httpversion}\" %{DATA:retcode} %{DATA:size} \"%{DATA:fromHtml}\" \"%{DATA:useragent}\"" } remove_field=>["message"] } date{ match=>["accessTime","dd/MMM/yyyy:HH:mm:ss Z"] } } output { elasticsearch { hosts => "127.0.0.1" } stdout { codec => rubydebug} }
3.執行./logstash -f file_es.conf
由於我們還沒有開始部署elasticsearch,暫時不貼出效果,效果圖將在下一個博客里面看到。
多行日志的處理
通過上面3步的熟悉,我們大概清楚了logstash的工作過程:
1.input讀取指定文件里面的文本行,這里是一行一行讀取的;
2.然后filter對讀入的每一行進行解析,拆分成一組一組的key-value值;
3.out將解析后的結果輸出寫入到指定的系統。
但是,我們知道異常日志是一個多行文本,我們需要把多行信息輸出到一行里面去處理,那么怎么辦呢?
如果仍然按照單行文本的類似處理方式的話,我們需要在input部分添加配置項,如下:
input { stdin { codec => multiline { pattern => "^\[" negate => true what => "previous" } } }
這個配置是對每一個以”[“開頭的行認作一個數據行的開始,后續不是以”[“開頭的行都會認為是同一個數據的內容,當再次遇到”[“時結束這一個數據內容的讀取,開始下一行。
這里有一個問題是,最后一個異常日志不能輸出,因為logstash一直在等待下一個”[“的出現,但是一直沒有出現,那么就不會輸出了。
我們采用的處理多行文本的方式是自己實現了一個LogAppender,直接由程序日志類庫以json串的形式輸出到redis中,然后再由logstash讀取。架構方式上屬於第一篇中寫的第二種架構方式。
以下是一些關鍵部分的代碼片段:
緊接上一篇,這一篇我們開始安裝es,這里使用的是es5.3.0版本,可以在官網下載:https://www.elastic.co/cn/downloads。
5.0以后的版本和之前的版本在安裝head插件上有一些區別,之前的版本安裝head插件很容易,只需要運行
elasticsearch/bin/plugin -install mobz/elasticsearch-head
就可以了,但是5.0之后,head插件換成了采用grunt服務方式啟動,需要用npm方式打包安裝,稍微復雜一些。
接下來,一塊看下es和head的安裝。
安裝elasticsearch
1.下載elasticsearch;
2.解壓縮;
3.修改/elasticsearch-5.3.0/config/elasticsearch.yml
打開:
network.host: 127.0.0.1 http.port: 9200
增加:
http.cors.allow-origin: "/.*/" http.cors.enabled: true
這兩個配置是支持跨域訪問用的,這樣的話后續安裝的head插件和kibana才能夠正常的訪問es的查詢接口。
現在網上的教程大多是老版本的安裝說明,所以有可能你會遇到有些配置項不能使用的情況,如果遇到了只需要按照es啟動時的提示信息或去掉或修改即可。
4.啟動es服務
/elasticsearch-5.3.0/bin/elasticsearch -d #表示以daemon的方式啟動,命令行輸入輸出不被占用
5.可以通過es的http接口進行es的測試,也可以等下一步的head插件安裝完成之后在head里進行測試。
1.安裝nodejs
2.安裝grunt-cli
3.下載安裝head插件
這里只是給出了簡單的步驟,具體的安裝過程請參見以下博客:http://www.cnblogs.com/xiaofei1205/p/6704239.html作者講的比較詳細,這里不進行重復。
其中有一點不同的地方是,在安裝的過程中遇到了和以上作者不同的異常,是“”license”: “Apache2””的異常,提示需要修改成BSD授權。
修改方法參見這一篇博客:http://blog.csdn.net/u010504064/article/details/53312093
這里給出一個head的截圖:
這是這個小系列的最后一篇了,我們將看到如何安裝kibana,以及對ELK中的日志信息進行快速查詢。
kibana安裝
1.到官網下載kibana;
2.解壓縮;
3.修改配置文件kibana-5.3.0-darwin-x86_64/config/kibana.yml
打開:
elasticsearch.url: "http://localhost:9200"
這是鏈接es的http地址,kibana自身服務器默認的端口是5601.
4.控制台中運行./kibana,運行成功會看到如下信息:
查看日志內容
首次訪問的時候,需要添加一個index pattern,用來告訴kibana我們需要從es里面搜索哪些類型的索引。
里面的index name or pattern不用改,因為logstash默認在es里創建的索引就是logstash-*格式命名的。
Time-field name選擇 @timestamp,然后點擊創建。然后就會看到kibana把es里面對應索引的所有字段信息都獲取過來了:
時間過濾器使用
要檢索數據,我們需要進入到Discover標簽頁面,先來熟悉時間過濾器,在頁面的右上角,點擊一下就可以展開選擇區了。用來選擇一個時間范圍內的數據。
這里提供了三種設置方式:
1.快速的:可以快速的選擇一個到當前時間為止N天,N月,N年的時間段;
2.相對於現在的時間:可以更加細致的設置第一種方式中的N值;
3.時間范圍:可以明確指定開始時間和結束時間。
選中一個時間段后,可以看到搜索的結果分布和前500個結果的結果列表,以及左側的字段列表、字段值top5.
添加快速顯示字段
在左側的字段列表中,鼠標滑動到某一個字段,字段右側會出現一個add按鈕,就是用來添加快速顯示字段的。
快速顯示字段是哪里呢,就是頁面右側的日志信息列表,因為日志信息包含的字段很多,默認只顯示了time和_source兩個字段,如果我們想快速顯示path字段怎么辦?就需要用到添加快速顯示字段的功能了。
關鍵字包含匹配
有時候我們會看到日志中有很多接口的訪問日志,如果我想看某一個特定接口的訪問日志怎么辦呢?
仍然需要在左側的字段列表里操作,首先點擊某個字段,比如來源於哪個日志文件(path),會看到列出的top5接口,而且每個接口旁邊有一個放大鏡和放小鏡。放大鏡就是用來增加包含匹配的,點擊之后僅顯示該字段值的日志。
關鍵字不包含匹配
字段列表處的放小鏡就是用來設定不包含某個值了,比如我們只能看到top5,但是前幾項我不關心,那么我們就可以把他排除掉,讓更多的日志在top5能被看到,就需要這個功能了。
備注:大家可能很多接觸es的人或者mongodb的讓你都記得前段時間的比特幣勒索,很多es和mongodb由於沒有設置密碼,庫中的數據都被刪除了。遺憾的是我們外網的一個es也被清洗了。所以如果自己的ELK是公網可以訪問的那么最好給es設定一個用戶名密碼,讓數據更安全一些。
一般來說日志信息我們只需要一段時間以內的,為了節省空間和服務器,可能會定期的刪除一部分比較老的日志文件,比如一個月之前的。我們自己這邊設定的是刪除兩周之前的。
這里給出一個示例,不是我們用的,公司用的是運維搭建的環境。這里示例來源是:http://www.iyunv.com/thread-259586-1-1.html
清理日志腳本
新建文件es-index-clear.sh,寫入如下腳本內容
#/bin/bash #es-index-clear #獲取上個月份日期 LAST_DATA=`date -d "last month"+%Y-%m` #刪除上個月份所有的索引 curl -XDELETE'http://127.0.0.1:9200/logstash-'${LAST_DATA}'-*'
添加定時任務
執行crontab -e增加如下定時任務:
0 1 5 * * /script/es-index-clear.sh
意思是每月5日1點清理一個月前的日志數據。