ELK實時日誌分析平臺環境部署--完整記錄

散盡浮華發表於2016-09-29

 

在日常運維工作中,對於系統和業務日誌的處理尤為重要。今天,在這裡分享一下自己部署的ELK(+Redis)-開源實時日誌分析平臺的記錄過程(僅依據本人的實際操作為例說明,如有誤述,敬請指出)~

================概念介紹================
日誌主要包括系統日誌、應用程式日誌和安全日誌。系統運維和開發人員可以通過日誌瞭解伺服器軟硬體資訊、檢查配置過程中的錯誤及錯誤發生的原因。經常分析日誌可以瞭解伺服器的負荷,效能安全性,從而及時採取措施糾正錯誤。

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

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

通過我們需要對日誌進行集中化管理,將所有機器上的日誌資訊收集、彙總到一起。完整的日誌資料具有非常重要的作用:
1)資訊查詢。通過檢索日誌資訊,定位相應的bug,找出解決方案。
2)服務診斷。通過對日誌資訊進行統計、分析,瞭解伺服器的負荷和服務執行狀態,找出耗時請求進行優化等等。
3)資料分析。如果是格式化的log,可以做進一步的資料分析,統計、聚合出有意義的資訊,比如根據請求中的商品id,找出TOP10使用者感興趣商品。

開源實時日誌分析ELK平臺能夠完美的解決我們上述的問題,ELK由ElasticSearch、Logstash和Kiabana三個開源工具組成:
1)ElasticSearch是一個基於Lucene的開源分散式搜尋伺服器。它的特點有:分散式,零配置,自動發現,索引自動分片,索引副本機制,restful風格介面,多資料來源,自動搜尋負載等。它提供了一個分散式多使用者能力的全文搜尋引擎,基於RESTful web介面。Elasticsearch是用Java開發的,並作為Apache許可條款下的開放原始碼釋出,是第二流行的企業搜尋引擎。設計用於雲端計算中,能夠達到實時搜尋,穩定,可靠,快速,安裝使用方便。
在elasticsearch中,所有節點的資料是均等的。
2)Logstash是一個完全開源的工具,它可以對你的日誌進行收集、過濾、分析,支援大量的資料獲取方法,並將其儲存供以後使用(如搜尋)。說到搜尋,logstash帶有一個web介面,搜尋和展示所有日誌。一般工作方式為c/s架構,client端安裝在需要收集日誌的主機上,server端負責將收到的各節點日誌進行過濾、修改等操作在一併發往elasticsearch上去。
3)Kibana 是一個基於瀏覽器頁面的Elasticsearch前端展示工具,也是一個開源和免費的工具,Kibana可以為 Logstash 和 ElasticSearch 提供的日誌分析友好的 Web 介面,可以幫助您彙總、分析和搜尋重要資料日誌。

為什麼要用到ELK?
一般我們需要進行日誌分析場景是:直接在日誌檔案中 grep、awk 就可以獲得自己想要的資訊。但在規模較大的場景中,此方法效率低下,面臨問題包括日誌量太大如何歸檔、文字搜尋太慢怎麼辦、如何多維度查詢。需要集中化的日誌管理,所有伺服器上的日誌收集彙總。常見解決思路是建立集中式日誌收集系統,將所有節點上的日誌統一收集,管理,訪問。
一般大型系統是一個分散式部署的架構,不同的服務模組部署在不同的伺服器上,問題出現時,大部分情況需要根據問題暴露的關鍵資訊,定位到具體的伺服器和服務模組,構建一套集中式日誌系統,可以提高定位問題的效率。

一般大型系統是一個分散式部署的架構,不同的服務模組部署在不同的伺服器上,問題出現時,大部分情況需要根據問題暴露的關鍵資訊,定位到具體的伺服器和服務模組,構建一套集中式日誌系統,可以提高定位問題的效率。
一個完整的集中式日誌系統,需要包含以下幾個主要特點:
1)收集-能夠採集多種來源的日誌資料
2)傳輸-能夠穩定的把日誌資料傳輸到中央系統
3)儲存-如何儲存日誌資料
4)分析-可以支援 UI 分析
5)警告-能夠提供錯誤報告,監控機制

ELK提供了一整套解決方案,並且都是開源軟體,之間互相配合使用,完美銜接,高效的滿足了很多場合的應用。目前主流的一種日誌系統。

ELK工作原理展示圖:

如上圖:Logstash收集AppServer產生的Log,並存放到ElasticSearch叢集中,而Kibana則從ES叢集中查詢資料生成圖表,再返回給Browser。

Logstash工作原理:
Logstash事件處理有三個階段:inputs → filters → outputs。是一個接收,處理,轉發日誌的工具。支援系統日誌,webserver日誌,錯誤日誌,應用日誌,總之包括所有可以丟擲來的日誌型別。

Input:輸入資料到logstash。

一些常用的輸入為:
file:從檔案系統的檔案中讀取,類似於tial -f命令
syslog:在514埠上監聽系統日誌訊息,並根據RFC3164標準進行解析
redis:從redis service中讀取
beats:從filebeat中讀取
Filters:資料中間處理,對資料進行操作。

一些常用的過濾器為:
grok:解析任意文字資料,Grok 是 Logstash 最重要的外掛。它的主要作用就是將文字格式的字串,轉換成為具體的結構化的資料,配合正規表示式使用。內建120多個解析語法。
mutate:對欄位進行轉換。例如對欄位進行刪除、替換、修改、重新命名等。
drop:丟棄一部分events不進行處理。
clone:拷貝 event,這個過程中也可以新增或移除欄位。
geoip:新增地理資訊(為前臺kibana圖形化展示使用)
Outputs:outputs是logstash處理管道的最末端元件。一個event可以在處理過程中經過多重輸出,但是一旦所有的outputs都執行結束,這個event也就完成生命週期。

一些常見的outputs為:
elasticsearch:可以高效的儲存資料,並且能夠方便和簡單的進行查詢。
file:將event資料儲存到檔案中。
graphite:將event資料傳送到圖形化元件中,一個很流行的開源儲存圖形化展示的元件。
Codecs:codecs 是基於資料流的過濾器,它可以作為input,output的一部分配置。Codecs可以幫助你輕鬆的分割傳送過來已經被序列化的資料。

一些常見的codecs:
json:使用json格式對資料進行編碼/解碼。
multiline:將匯多個事件中資料彙總為一個單一的行。比如:java異常資訊和堆疊資訊。

======================ELK整體方案=======================
ELK中的三個系統分別扮演不同的角色,組成了一個整體的解決方案。Logstash是一個ETL工具,負責從每臺機器抓取日誌資料,對資料進行格式轉換和處理後,輸出到Elasticsearch中儲存。Elasticsearch是一個分散式搜尋引擎和分析引擎,用於資料儲存,可提供實時的資料查詢。Kibana是一個資料視覺化服務,根據使用者的操作從Elasticsearch中查詢資料,形成相應的分析結果,以圖表的形式展現給使用者。
ELK的安裝很簡單,可以按照"下載->修改配置檔案->啟動"方法分別部署三個系統,也可以使用docker來快速部署。具體的安裝方法這裡不詳細介紹,下面來看一個常見的部署方案,如下圖所示,部署思路是:
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?

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

其次,我們需要做的是將資料放入一個訊息佇列中進行緩衝,所以Redis只是其中一個選擇,也可以是RabbitMQ、Kafka等等,在實際生產中,Redis與Kafka用的比較多。由於Redis叢集一般都是通過key來做分片,無法對list型別做叢集,在資料量大的時候必然不合適了,而Kafka天生就是分散式的訊息佇列系統。

1)配置nginx日誌格式
首先需要將nginx日誌格式規範化,便於做解析處理。在nginx.conf檔案中設定:

log_format main '$remote_addr "$time_iso8601" "$request" $status $body_bytes_sent "$http_user_agent" "$http_referer" "$http_x_forwarded_for" "$request_time" "$upstream_response_time" "$http_cookie" "$http_Authorization" "$http_token"';
access_log  /var/log/nginx/example.access.log  main;

2)nginx日誌–>>Logstash–>>訊息佇列
這部分是Logstash Shipper的工作,涉及input和output兩種外掛。input部分,由於需要提取的是日誌檔案,一般使用file外掛,該外掛常用的幾個引數是:
path:指定日誌檔案路徑。
type:指定一個名稱,設定type後,可以在後面的filter和output中對不同的type做不同的處理,適用於需要消費多個日誌檔案的場景。
start_position:指定起始讀取位置,“beginning”表示從檔案頭開始,“end”表示從檔案尾開始(類似tail -f)。
sincedb_path:與Logstash的一個坑有關。通常Logstash會記錄每個檔案已經被讀取到的位置,儲存在sincedb中,如果Logstash重啟,那麼對於同一個檔案,會繼續從上次記錄的位置開始讀取。如果想重新從頭讀取檔案,需要刪除sincedb檔案,sincedb_path則是指定了該檔案的路徑。為了方便,我們可以根據需要將其設定為“/dev/null”,即不儲存位置資訊。

input {
    file {
        type => "example_nginx_access"
        path => ["/var/log/nginx/example.access.log"]

        start_position => "beginning"
        sincedb_path => "/dev/null"
    }
}

output部分,將資料輸出到訊息佇列,以redis為例,需要指定redis server和list key名稱。另外,在測試階段,可以使用stdout來檢視輸出資訊。

# 輸出到redis
output {
    if [type] == "example_nginx_access" {
        redis {
            host => "127.0.0.1"
            port => "6379"
            data_type => "list"
            key => "logstash:example_nginx_access"
        }
      #  stdout {codec => rubydebug}
    }
}

3)訊息佇列–>>Logstash–>>Elasticsearch
這部分是Logstash Indexer的工作,涉及input、filter和output三種外掛。在input部分,我們通過redis外掛將資料從訊息佇列中取出來。在output部分,我們通過elasticsearch外掛將資料寫入Elasticsearch。

# 從redis輸入資料
input {
    redis {
            host => "127.0.0.1"
            port => "6379"
            data_type => "list"
            key => "logstash:example_nginx_access"
    }
}

output {
    elasticsearch {
        index => "logstash-example-nginx-%{+YYYY.MM}"
        hosts => ["127.0.0.1:9200"]
    }
}

這裡,需要重點關注filter部分,下面列舉幾個常用的外掛,實際使用中根據自身需求從官方文件中查詢適合自己業務的外掛並使用即可,當然也可以編寫自己的外掛。
grok:是Logstash最重要的一個外掛,用於將非結構化的文字資料轉化為結構化的資料。grok內部使用正則語法對文字資料進行匹配,為了降低使用複雜度,其提供了一組pattern,我們可以直接呼叫pattern而不需要自己寫正規表示式,參考原始碼grok-patterns。grok解析文字的語法格式是%{SYNTAX:SEMANTIC},SYNTAX是pattern名稱,SEMANTIC是需要生成的欄位名稱,使用工具Grok Debugger可以對解析語法進行除錯。例如,在下面的配置中,我們先使用grok對輸入的原始nginx日誌資訊(預設以message作為欄位名)進行解析,並新增新的欄位request_path_with_verb(該欄位的值是verb和request_path的組合),然後對request_path欄位做進一步解析。
kv:用於將某個欄位的值進行分解,類似於程式語言中的字串Split。在下面的配置中,我們將request_args欄位值按照“&”進行分解,分解後的欄位名稱以“request_args_”作為字首,並且丟棄重複的欄位。
geoip:用於根據IP資訊生成地理位置資訊,預設使用自帶的一份GeoLiteCity database,也可以自己更換為最新的資料庫,但是需要資料格式需要遵循Maxmind的格式(參考GeoLite),似乎目前只能支援legacy database,資料型別必須是.dat。下載GeoLiteCity.dat.gz後解壓, 並將檔案路徑配置到source中即可。
translate:用於檢測某欄位的值是否符合條件,如果符合條件則將其翻譯成新的值,寫入一個新的欄位,匹配pattern可以通過YAML檔案來配置。例如,在下面的配置中,我們對request_api欄位翻譯成更加易懂的文字描述。

filter {
    grok {
        match => {"message" => "%{IPORHOST:client_ip} \"%{TIMESTAMP_ISO8601:timestamp}\" \"%{WORD:verb} %{NOTSPACE:request_path} HTTP/%{NUMBER:httpversion}\" %{NUMBER:response_status:int} %{NUMBER:response_body_bytes:int} \"%{DATA:user_agent}\" \"%{DATA:http_referer}\" \"%{NOTSPACE:http_x_forwarder_for}\" \"%{NUMBER:request_time:float}\" \"%{DATA:upstream_resopnse_time}\" \"%{DATA:http_cookie}\" \"%{DATA:http_authorization}\" \"%{DATA:http_token}\""}
        add_field => {"request_path_with_verb" => "%{verb} %{request_path}"}
    }

    grok {
        match => {"request_path" => "%{URIPATH:request_api}(?:\?%{NOTSPACE:request_args}|)"}
        add_field => {"request_annotation" => "%{request_api}"}
    }

    kv {
        prefix => "request_args_"
        field_split => "&"
        source => "request_args"
        allow_duplicate_values => false
    }

    geoip {
        source => "client_ip"
        database => "/home/elktest/geoip_data/GeoLiteCity.dat"
    }

   translate {
        field => request_path
        destination => request_annotation
        regex => true
        exact => true
        dictionary_path => "/home/elktest/api_annotation.yaml"
        override => true
    }
}

Elasticsearch
Elasticsearch承載了資料儲存和查詢的功能,其基礎概念和使用方法可以參考另一篇博文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: ["master1", "master2", "master3"] 
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預設將資料儲存在/var/lib/elasticsearch路徑下,隨著資料的增長,一定會出現硬碟空間不夠用的情形,此時就需要給機器掛載新的硬碟,並將Elasticsearch的路徑配置到新硬碟的路徑下。通過“path.data”配置項來進行設定,比如“path.data: /data1,/var/lib/elasticsearch,/data”。需要注意的是,同一分片下的資料只能寫入到一個路徑下,因此還是需要合理的規劃和監控硬碟的使用。
5)關於Index的劃分和分片的個數,這個需要根據資料量來做權衡了,Index可以按時間劃分,比如每月一個或者每天一個,在Logstash輸出時進行配置,shard的數量也需要做好控制。
6)關於監控,筆者使用過head和marvel兩個監控外掛,head免費,功能相對有限,marvel現在需要收費了。另外,不要在資料節點開啟監控外掛。

Kibana
Kibana提供的是資料查詢和顯示的Web服務,有豐富的圖表樣板,能滿足大部分的資料視覺化需求,這也是很多人選擇ELK的主要原因之一。UI的操作沒有什麼特別需要介紹的,經常使用就會熟練,這裡主要介紹經常遇到的三個問題。
a)查詢語法
在Kibana的Discover頁面中,可以輸入一個查詢條件來查詢所需的資料。查詢條件的寫法使用的是Elasticsearch的Query String語法,而不是Query DSL,參考官方文件query-string-syntax,這裡列舉其中部分常用的:
.單欄位的全文檢索,比如搜尋args欄位中包含first的文件,寫作 args:first;
.單欄位的精確檢索,比如搜尋args欄位值為first的文件,寫作 args: “first”;
.多個檢索條件的組合,使用 NOT, AND 和 OR 來組合,注意必須是大寫,比如 args:(“first” OR “second”) AND NOT agent: “third”;
.欄位是否存在,_exists_:agent表示要求agent欄位存在,_missing_:agent表示要求agent欄位不存在;
.萬用字元:用 ? 表示單字母,* 表示任意個字母。
b)錯誤“Discover: Request Timeout after 30000ms”
這個錯誤經常發生在要查詢的資料量比較大的情況下,此時Elasticsearch需要較長時間才能返回,導致Kibana發生Timeout報錯。解決這個問題的方法,就是在Kibana的配置檔案中修改elasticsearch.requestTimeout一項的值,然後重啟Kibana服務即可,注意單位是ms。
c)疑惑“字串被分解了
經常碰到這樣一個問題:為什麼查詢結果的欄位值是正確的,可是做圖表時卻發現欄位值被分解了,不是想要的結果?如下圖所示的client_agent_info欄位。

得到這樣一個不正確結果的原因是使用了Analyzed欄位來做圖表分析,預設情況下Elasticsearch會對字串資料進行分析,建立倒排索引,所以如果對這麼一個欄位進行terms聚合,必然會得到上面所示的錯誤結果了。那麼應該怎麼做才對?預設情況下,Elasticsearch還會建立一個相對應的沒有被Analyzed的欄位,即帶“.raw”字尾的欄位,在這樣的欄位上做聚合分析即可。
又會有很多人問這樣的問題:為什麼我的Elasticsearch沒有自動建立帶“.raw”字尾的欄位?然而在Logstash中輸出資料時,設定index名稱字首為“logstash-”就有了這個欄位。這個問題的根源是Elasticsearch的dynamic template在搗鬼,dynamic temlate用於指導Elasticsearch如何為插入的資料自動建立Schema對映關係,預設情況下,Logstash會在Elasticsearch中建立一個名為“logstash”的模板,所有字首為“logstash-”的index都會參照這個模板來建立對映關係,在該模板中申明瞭要為每個字串資料建立一個額外的帶“.raw”字尾的欄位。可以向Elasticsearch來查詢你的模板,使用API:GET http://localhost:9200/_template。

以上便是對ELK日誌系統的總結介紹,還有一個重要的功能沒有提到,就是如何將日誌資料與自身產品業務的資料融合起來。舉個例子,在nginx日誌中,通常會包含API請求訪問時攜帶的使用者Token資訊,由於Token是有時效性的,我們需要及時將這些Token轉換成真實的使用者資訊儲存下來。這樣的需求通常有兩種實現方式,一種是自己寫一個Logstash filter,然後在Logstash處理資料時呼叫;另一種是將Logstash Indexer產生的資料再次輸出到訊息佇列中,由我們自己的指令碼程式從訊息佇列中取出資料,做相應的業務處理後,輸出到Elasticsearch中。

==================ELK環境部署==================

(0)基礎環境介紹

系統: Centos7.1
防火牆: 關閉
Sellinux: 關閉

機器環境: 兩臺
elk-node1: 192.168.1.160       #master機器
elk-node2:192.168.1.161      #slave機器

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

==========================================================================
由於elk-node1和elk-node2兩臺是虛擬機器,沒有外網ip,所以訪問需要通過宿主機進行代理轉發實現。

有以下兩種轉發設定:(任選其一)

通過訪問宿主機的19200,19201埠分別轉發到elk-node1,elk-node2的9200埠
通過訪問宿主機的15601埠轉發到elk-node1的5601埠

宿主機:112.110.115.10(內網ip為192.168.1.7)  (為了不讓線上的真實ip暴露,這裡任意給了一個ip做記錄)

a)通過宿主機的haproxy服務進行代理轉發,如下是宿主機上的代理配置:

[root@kvm-server conf]# pwd
/usr/local/haproxy/conf
[root@kvm-server conf]# cat haproxy.cfg
..........
..........
listen node1-9200 0.0.0.0:19200
mode tcp
option tcplog
balance roundrobin
server 192.168.1.160 192.168.1.160:9200 weight 1 check inter 1s rise 2 fall 2

listen node2-9200 0.0.0.0:19201
mode tcp
option tcplog
balance roundrobin
server 192.168.1.161 192.168.1.161:9200 weight 1 check inter 1s rise 2 fall 2

listen node1-5601 0.0.0.0:15601
mode tcp
option tcplog
balance roundrobin
server 192.168.1.160 192.168.1.160:5601 weight 1 check inter 1s rise 2 fall 2

重啟haproxy服務
[root@kvm-server conf]# /etc/init.d/haproxy restart

設定宿主機防火牆
[root@kvm-server conf]# cat /etc/sysconfig/iptables
.........
-A INPUT -p tcp -m state --state NEW -m tcp --dport 19200 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 19201 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 15601 -j ACCEPT

[root@kvm-server conf]# /etc/init.d/iptables restart

b)通過宿主機的NAT埠轉發實現

[root@kvm-server conf]# iptables -t nat -A PREROUTING -p tcp -m tcp --dport 19200 -j DNAT --to-destination 192.168.1.160:9200
[root@kvm-server conf]# iptables -t nat -A POSTROUTING -d 192.168.1.160/32 -p tcp -m tcp --sport 9200 -j SNAT --to-source 192.168.1.7
[root@kvm-server conf]# iptables -t filter -A INPUT -p tcp -m state --state NEW -m tcp --dport 19200 -j ACCEPT

[root@kvm-server conf]# iptables -t nat -A PREROUTING -p tcp -m tcp --dport 19201 -j DNAT --to-destination 192.168.1.161:9200
[root@kvm-server conf]# iptables -t nat -A POSTROUTING -d 192.168.1.161/32 -p tcp -m tcp --sport 9200 -j SNAT --to-source 192.168.1.7
[root@kvm-server conf]# iptables -t filter -A INPUT -p tcp -m state --state NEW -m tcp --dport 19201 -j ACCEPT

[root@kvm-server conf]# iptables -t nat -A PREROUTING -p tcp -m tcp --dport 15601 -j DNAT --to-destination 192.168.1.160:5601
[root@kvm-server conf]# iptables -t nat -A POSTROUTING -d 192.168.1.160/32 -p tcp -m tcp --sport 5601 -j SNAT --to-source 192.168.1.7
[root@kvm-server conf]# iptables -t filter -A INPUT -p tcp -m state --state NEW -m tcp --dport 15601 -j ACCEPT

[root@kvm-server conf]# service iptables save
[root@kvm-server conf]# service iptables restart

提醒一點:
nat埠轉發設定成功後,/etc/sysconfig/iptables檔案裡要註釋掉下面兩行!不然nat轉發會有問題!一般如上面在nat轉發規則設定好並save和restart防火牆之後就會自動在/etc/sysconfig/iptables檔案裡刪除掉下面兩行內容了。
[root@kvm-server conf]# vim /etc/sysconfig/iptables
..........
#-A INPUT -j REJECT --reject-with icmp-host-prohibited
#-A FORWARD -j REJECT --reject-with icmp-host-prohibited
[root@linux-node1 ~]# service iptables restart

=============================================================

(1)Elasticsearch安裝配置

基礎環境安裝(elk-node1和elk-node2同時操作)

1)下載並安裝GPG Key
[root@elk-node1 ~]# rpm --import https://packages.elastic.co/GPG-KEY-elasticsearch

2)新增yum倉庫
[root@elk-node1 ~]# vim /etc/yum.repos.d/elasticsearch.repo
[elasticsearch-2.x]
name=Elasticsearch repository for 2.x packages
baseurl=http://packages.elastic.co/elasticsearch/2.x/centos
gpgcheck=1
gpgkey=http://packages.elastic.co/GPG-KEY-elasticsearch
enabled=1

3)安裝elasticsearch
[root@elk-node1 ~]# yum install -y elasticsearch

4)安裝相關測試軟體
#提前先下載安裝epel源:epel-release-latest-7.noarch.rpm,否則yum會報錯:No Package.....
[root@elk-node1 ~]# wget http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
[root@elk-node1 ~]# rpm -ivh epel-release-latest-7.noarch.rpm
#安裝Redis
[root@elk-node1 ~]# yum install -y redis
#安裝Nginx
[root@elk-node1 ~]# yum install -y nginx
#安裝java
[root@elk-node1 ~]# yum install -y java

安裝完java後,檢測
[root@elk-node1 ~]# 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)

配置部署(下面先進行elk-node1的配置)

1)配置修改配置檔案
[root@elk-node1 ~]# mkdir -p /data/es-data
[root@elk-node1 ~]# vim /etc/elasticsearch/elasticsearch.yml                               【將裡面內容情況,配置下面內容】
cluster.name: huanqiu                            # 組名(同一個組,組名必須一致)
node.name: elk-node1                            # 節點名稱,建議和主機名一致
path.data: /data/es-data                         # 資料存放的路徑
path.logs: /var/log/elasticsearch/             # 日誌存放的路徑
bootstrap.mlockall: true                         # 鎖住記憶體,不被使用到交換分割槽去
network.host: 0.0.0.0                            # 網路設定
http.port: 9200                                    # 埠

2)啟動並檢視
[root@elk-node1 ~]# chown -R elasticsearch.elasticsearch /data/
[root@elk-node1 ~]# systemctl start elasticsearch
[root@elk-node1 ~]# systemctl status elasticsearch
CGroup: /system.slice/elasticsearch.service
└─3005 /bin/java -Xms256m -Xmx1g -Djava.awt.headless=true -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSI...

注意:上面可以看出elasticsearch設定的記憶體最小256m,最大1g

=====================溫馨提示:  Elasticsearch啟動出現"could not find java"===================

yum方法安裝elasticsearch, 使用"systemctl start elasticsearch"啟動服務失敗.
"systemctl status elasticsearch"檢視, 發現報錯說could not find java
但是"java -version" 檢視發現java已經安裝了

這是因為elasticsearch在啟動過程中, 引用的java路徑找不到

解決辦法: 在elasticsearch配置檔案中定義java全路徑

[root@elk-node01 ~]# java -version
java version "1.8.0_131"
Java(TM) SE Runtime Environment (build 1.8.0_131-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.131-b11, mixed mode

[root@elk-node01 ~]# find / -name java
/var/lib/alternatives/java
/usr/share/swig/2.0.10/java
/usr/java
/usr/java/jdk1.8.0_131/bin/java
/usr/java/jdk1.8.0_131/jre/bin/java
/usr/bin/java
/etc/pki/java
/etc/pki/ca-trust/extracted/java
/etc/alternatives/java

[root@elk-node01 ~]# vim /etc/sysconfig/elasticsearch
新增JAVA_HOME環境變數的配置
JAVA_HOME=/usr/java/jdk1.8.0_131

[root@linux-node1 src]# netstat -antlp |egrep "9200|9300"
tcp6 0 0 :::9200 :::* LISTEN 3005/java
tcp6 0 0 :::9300 :::* LISTEN 3005/java

然後通過web訪問(訪問的瀏覽器最好用google瀏覽器)

http://112.110.115.10:19200/

3)通過命令的方式檢視資料(在112.110.115.10宿主機或其他外網伺服器上檢視,如下)
[root@kvm-server src]# curl -i -XGET 'http://192.168.1.160:9200/_count?pretty' -d '{"query":{"match_all":{}}}'
HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8
Content-Length: 95

{
"count" : 0,
"_shards" : {
"total" : 0,
"successful" : 0,
"failed" : 0
}
}

這樣感覺用命令來檢視,特別的不爽。

4)接下來安裝外掛,使用外掛進行檢視~  (下面兩個外掛要在elk-node1和elk-node2上都要安裝)
4.1)安裝head外掛
==================================================================
a)外掛安裝方法一
[root@elk-node1 src]# /usr/share/elasticsearch/bin/plugin install mobz/elasticsearch-head

b)外掛安裝方法二
首先下載head外掛,下載到/usr/loca/src目錄下
下載地址:https://github.com/mobz/elasticsearch-head

======================================================
head外掛包百度雲盤下載:https://pan.baidu.com/s/1boBE0qj
提取密碼:ifj7
======================================================

[root@elk-node1 src]# unzip elasticsearch-head-master.zip
[root@elk-node1 src]# ls
elasticsearch-head-master elasticsearch-head-master.zip

在/usr/share/elasticsearch/plugins目錄下建立head目錄
然後將上面下載的elasticsearch-head-master.zip解壓後的檔案都移到/usr/share/elasticsearch/plugins/head下
接著重啟elasticsearch服務即可!
[root@elk-node1 src]# cd /usr/share/elasticsearch/plugins/
[root@elk-node1 plugins]# mkdir head
[root@elk-node1 plugins]# ls
head
[root@elk-node1 plugins]# cd head
[root@elk-node1 head]# cp -r /usr/local/src/elasticsearch-head-master/* ./
[root@elk-node1 head]# pwd
/usr/share/elasticsearch/plugins/head

[root@elk-node1 head]# chown -R elasticsearch:elasticsearch /usr/share/elasticsearch/plugins
[root@elk-node1 head]# ll
total 40
-rw-r--r--. 1 elasticsearch elasticsearch 104 Sep 28 01:57 elasticsearch-head.sublime-project
-rw-r--r--. 1 elasticsearch elasticsearch 2171 Sep 28 01:57 Gruntfile.js
-rw-r--r--. 1 elasticsearch elasticsearch 3482 Sep 28 01:57 grunt_fileSets.js
-rw-r--r--. 1 elasticsearch elasticsearch 1085 Sep 28 01:57 index.html
-rw-r--r--. 1 elasticsearch elasticsearch 559 Sep 28 01:57 LICENCE
-rw-r--r--. 1 elasticsearch elasticsearch 795 Sep 28 01:57 package.json
-rw-r--r--. 1 elasticsearch elasticsearch 100 Sep 28 01:57 plugin-descriptor.properties
-rw-r--r--. 1 elasticsearch elasticsearch 5211 Sep 28 01:57 README.textile
drwxr-xr-x. 5 elasticsearch elasticsearch 4096 Sep 28 01:57 _site
drwxr-xr-x. 4 elasticsearch elasticsearch 29 Sep 28 01:57 src
drwxr-xr-x. 4 elasticsearch elasticsearch 66 Sep 28 01:57 test

[root@elk-node1 _site]# systemctl restart elasticsearch
=========================================================================

外掛訪問(最好提前將elk-node2節點的配置和外掛都安裝後,再來進行訪問和資料插入測試)
http://112.110.115.10:19200/_plugin/head/

先插入資料例項,測試下
如下:開啟”複合查詢“,在POST選項下,任意輸入如/index-demo/test,然後在下面輸入資料(注意內容之間換行的逗號不要漏掉)
資料輸入好之後(如下輸入wangshibo;hello world內容),下面點選”驗證JSON“->”提交請求“,提交成功後,觀察右欄裡出現的資訊:有index,type,version等資訊,failed:0(成功訊息)

再檢視測試例項,如下:
"複合查詢"下,選擇GET選項在/index-demo/test/後面輸入上面POST結果中的id號不輸入內容,即{}括號裡為空
然後點選”驗證JSON“->"提交請求",觀察右欄內就有了上面插入的資料了(即wangshibo,hello world)

開啟"基本查詢",檢視下資料,如下,即可查詢到上面插入的資料:

開啟“資料瀏覽”,也能檢視到插入的資料:

如下:一定要提前在elk-node2節點上也完成配置(配置內容在下面提到),否則上面插入資料後,叢集狀態會呈現黃色yellow狀態,elk-node2完成配置加入到叢集裡後就會恢復到正常的綠色狀態。

4.2)安裝kopf監控外掛
==========================================================================

a)監控外掛安裝方法一

[root@elk-node1 src]# /usr/share/elasticsearch/bin/plugin install lmenezes/elasticsearch-kopf

b)監控外掛安裝方法二

首先下載監控外掛kopf,下載到/usr/loca/src目錄下
下載地址:https://github.com/lmenezes/elasticsearch-kopf

====================================================
kopf外掛包百度雲盤下載:https://pan.baidu.com/s/1qYixSL2
提取密碼:ya4t
===================================================

[root@elk-node1 src]# unzip elasticsearch-kopf-master.zip
[root@elk-node1 src]# ls
elasticsearch-kopf-master elasticsearch-kopf-master.zip

在/usr/share/elasticsearch/plugins目錄下建立kopf目錄
然後將上面下載的elasticsearch-kopf-master.zip解壓後的檔案都移到/usr/share/elasticsearch/plugins/kopf下
接著重啟elasticsearch服務即可!
[root@elk-node1 src]# cd /usr/share/elasticsearch/plugins/
[root@elk-node1 plugins]# mkdir kopf
[root@elk-node1 plugins]# cd kopf
[root@elk-node1 kopf]# cp -r /usr/local/src/elasticsearch-kopf-master/* ./
[root@elk-node1 kopf]# pwd
/usr/share/elasticsearch/plugins/kopf

[root@elk-node1 kopf]# chown -R elasticsearch:elasticsearch /usr/share/elasticsearch/plugins
[root@elk-node1 kopf]# ll
total 40
-rw-r--r--. 1 elasticsearch elasticsearch 237 Sep 28 16:28 CHANGELOG.md
drwxr-xr-x. 2 elasticsearch elasticsearch 22 Sep 28 16:28 dataset
drwxr-xr-x. 2 elasticsearch elasticsearch 73 Sep 28 16:28 docker
-rw-r--r--. 1 elasticsearch elasticsearch 4315 Sep 28 16:28 Gruntfile.js
drwxr-xr-x. 2 elasticsearch elasticsearch 4096 Sep 28 16:28 imgs
-rw-r--r--. 1 elasticsearch elasticsearch 1083 Sep 28 16:28 LICENSE
-rw-r--r--. 1 elasticsearch elasticsearch 1276 Sep 28 16:28 package.json
-rw-r--r--. 1 elasticsearch elasticsearch 102 Sep 28 16:28 plugin-descriptor.properties
-rw-r--r--. 1 elasticsearch elasticsearch 3165 Sep 28 16:28 README.md
drwxr-xr-x. 6 elasticsearch elasticsearch 4096 Sep 28 16:28 _site
drwxr-xr-x. 4 elasticsearch elasticsearch 27 Sep 28 16:28 src
drwxr-xr-x. 4 elasticsearch elasticsearch 4096 Sep 28 16:28 tests

[root@elk-node1 _site]# systemctl restart elasticsearch

============================================================================

訪問外掛:(如下,同樣要提前安裝好elk-node2節點上的外掛,否則訪問時會出現叢集節點為黃色的yellow告警狀態)

http://112.110.115.10:19200/_plugin/kopf/#!/cluster

*************************************************************************
下面進行節點elk-node2的配置  (如上的兩個外掛也在elk-node2上同樣安裝)

註釋:其實兩個的安裝配置基本上是一樣的。

[root@elk-node2 src]# mkdir -p /data/es-data
[root@elk-node2 ~]# cat /etc/elasticsearch/elasticsearch.yml
cluster.name: huanqiu
node.name: elk-node2
path.data: /data/es-data
path.logs: /var/log/elasticsearch/
bootstrap.mlockall: true
network.host: 0.0.0.0
http.port: 9200
discovery.zen.ping.multicast.enabled: false
discovery.zen.ping.unicast.hosts: ["192.168.1.160", "192.168.1.161"]

# 修改許可權配置
[root@elk-node2 src]# chown -R elasticsearch.elasticsearch /data/

# 啟動服務
[root@elk-node2 src]# systemctl start elasticsearch
[root@elk-node2 src]# systemctl status elasticsearch
● elasticsearch.service - Elasticsearch
Loaded: loaded (/usr/lib/systemd/system/elasticsearch.service; enabled; vendor preset: disabled)
Active: active (running) since Wed 2016-09-28 16:49:41 CST; 1 weeks 3 days ago
Docs: http://www.elastic.co
Process: 17798 ExecStartPre=/usr/share/elasticsearch/bin/elasticsearch-systemd-pre-exec (code=exited, status=0/SUCCESS)
Main PID: 17800 (java)
CGroup: /system.slice/elasticsearch.service
└─17800 /bin/java -Xms256m -Xmx1g -Djava.awt.headless=true -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFra...

Oct 09 13:42:22 elk-node2 elasticsearch[17800]: [2016-10-09 13:42:22,295][WARN ][transport ] [elk-node2] Transport res...943817]
Oct 09 13:42:23 elk-node2 elasticsearch[17800]: [2016-10-09 13:42:23,111][WARN ][transport ] [elk-node2] Transport res...943846]
................
................

# 檢視埠
[root@elk-node2 src]# netstat -antlp|egrep "9200|9300"
tcp6 0 0 :::9200 :::* LISTEN 2928/java
tcp6 0 0 :::9300 :::* LISTEN 2928/java
tcp6 0 0 127.0.0.1:48200 127.0.0.1:9300 TIME_WAIT -
tcp6 0 0 ::1:41892 ::1:9300 TIME_WAIT -
*************************************************************************

通過命令的方式檢視elk-node2資料(在112.110.115.10宿主機或其他外網伺服器上檢視,如下)
[root@kvm-server ~]# curl -i -XGET 'http://192.168.1.161:9200/_count?pretty' -d '{"query":{"match_all":{}}}'
HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8
Content-Length: 95

{
"count" : 1,
"_shards" : {
"total" : 5,
"successful" : 5,
"failed" : 0
}

然後通過web訪問elk-node2
http://112.110.115.10:19201/

訪問兩個外掛:
http://112.110.115.10:19201/_plugin/head/
http://112.110.115.10:19201/_plugin/kopf/#!/cluster

 

 (2)Logstash安裝配置(這個在客戶機上是要安裝的。elk-node1和elk-node2都安裝)

基礎環境安裝(客戶端安裝logstash,收集到的資料寫入到elasticsearch裡,就可以登陸logstash介面檢視到了

1)下載並安裝GPG Key
[root@elk-node1 ~]# rpm --import https://packages.elastic.co/GPG-KEY-elasticsearch

2)新增yum倉庫
[root@hadoop-node1 ~]# vim /etc/yum.repos.d/logstash.repo
[logstash-2.1]
name=Logstash repository for 2.1.x packages
baseurl=http://packages.elastic.co/logstash/2.1/centos
gpgcheck=1
gpgkey=http://packages.elastic.co/GPG-KEY-elasticsearch
enabled=1

3)安裝logstash
[root@elk-node1 ~]# yum install -y logstash

4)logstash啟動
[root@elk-node1 ~]# systemctl start elasticsearch
[root@elk-node1 ~]# systemctl status elasticsearch
● elasticsearch.service - Elasticsearch
Loaded: loaded (/usr/lib/systemd/system/elasticsearch.service; disabled; vendor preset: disabled)
Active: active (running) since Mon 2016-11-07 18:33:28 CST; 3 days ago
Docs: http://www.elastic.co
Main PID: 8275 (java)
CGroup: /system.slice/elasticsearch.service
└─8275 /bin/java -Xms256m -Xmx1g -Djava.awt.headless=true -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFrac...
..........
..........

資料的測試

1)基本的輸入輸出
[root@elk-node1 ~]# /opt/logstash/bin/logstash -e 'input { stdin{} } output { stdout{} }'
Settings: Default filter workers: 1
Logstash startup completed
hello                                                                                     #輸入這個
2016-11-11T06:41:07.690Z elk-node1 hello                        #輸出這個
wangshibo                                                                            #輸入這個
2016-11-11T06:41:10.608Z elk-node1 wangshibo               #輸出這個

2)使用rubydebug詳細輸出
[root@elk-node1 ~]# /opt/logstash/bin/logstash -e 'input { stdin{} } output { stdout{ codec => rubydebug} }'
Settings: Default filter workers: 1
Logstash startup completed
hello                                                                                    #輸入這個
{                                                                                         #輸出下面資訊
           "message" => "hello",
           "@version" => "1",
      "@timestamp" => "2016-11-11T06:44:06.711Z",
                  "host" => "elk-node1"
}
wangshibo                                                                         #輸入這個
{                                                                                       #輸出下面資訊
         "message" => "wangshibo",
        "@version" => "1",
   "@timestamp" => "2016-11-11T06:44:11.270Z",
               "host" => "elk-node1"
}

3) 把內容寫到elasticsearch中
[root@elk-node1 ~]# /opt/logstash/bin/logstash -e 'input { stdin{} } output { elasticsearch { hosts => ["192.168.1.160:9200"]} }'
Settings: Default filter workers: 1
Logstash startup completed                       #輸入下面的測試資料
123456
wangshibo
huanqiu
hahaha

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

寫到elasticsearch中在logstash中檢視,如下圖:
注意:
master收集到日誌後,會把一部分資料碎片到salve上(隨機的一部分資料),master和slave又都會各自做副本,並把副本放到對方機器上,這樣就保證了資料不會丟失。
如下,master收集到的資料放到了自己的第1,3分片上,其他的放到了slave的第0,2,4分片上。

4)即寫到elasticsearch中又寫在檔案中一份
[root@elk-node1 ~]# /opt/logstash/bin/logstash -e 'input { stdin{} } output { elasticsearch { hosts => ["192.168.1.160:9200"]} stdout{ codec => rubydebug}}'
Settings: Default filter workers: 1
Logstash startup completed
huanqiupc
{
           "message" => "huanqiupc",
          "@version" => "1",
     "@timestamp" => "2016-11-11T07:27:42.012Z",
                 "host" => "elk-node1"
}
wangshiboqun
{
         "message" => "wangshiboqun",
        "@version" => "1",
   "@timestamp" => "2016-11-11T07:27:55.396Z",
               "host" => "elk-node1"
}

以上文字可以長期保留、操作簡單、壓縮比大。下面登陸elasticsearch介面中檢視;

 logstash的配置和檔案的編寫

1)logstash的配置
簡單的配置方式:
[root@elk-node1 ~]# vim /etc/logstash/conf.d/01-logstash.conf
input { stdin { } }
output {
        elasticsearch { hosts => ["192.168.1.160:9200"]}
        stdout { codec => rubydebug }
}

它的執行:
[root@elk-node1 ~]# /opt/logstash/bin/logstash -f /etc/logstash/conf.d/01-logstash.conf
Settings: Default filter workers: 1
Logstash startup completed
beijing                                                #輸入內容
{                                                       #輸出下面資訊
             "message" => "beijing",
            "@version" => "1",
       "@timestamp" => "2016-11-11T07:41:48.401Z",
                   "host" => "elk-node1"
}

===============================================================
參考內容:
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-node1 ~]# vim  file.conf
input {
    file {
      path => "/var/log/messages"
      type => "system"
      start_position => "beginning"
    }
}

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

執行上面日誌資訊的收集,如下,這個命令會一直在執行中,表示日誌在監控收集中;如果中斷,就表示日誌不在收集!所以需要放在後臺執行~
[root@elk-node1 ~]# /opt/logstash/bin/logstash -f file.conf &

登陸elasticsearch介面,檢視本機系統日誌的資訊:

 

 

================================================================
參考內容:
https://www.elastic.co/guide/en/logstash/current/plugins-outputs-elasticsearch.html
================================================================

3)收集java日誌,其中包含上面講到的日誌收集

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

input {
    file {
       path => "/var/log/elasticsearch/huanqiu.log"
       type => "es-error" 
       start_position => "beginning"
    }
}


output {

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

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

注意:
如果你的日誌中有type欄位 那你就不能在conf檔案中使用type

執行如下命令收集:
[root@elk-node1 ~]# /opt/logstash/bin/logstash -f file.conf &

登陸elasticsearch介面,檢視資料:

====================================================================
參考內容:
https://www.elastic.co/guide/en/logstash/current/event-dependent-configuration.html
====================================================================

有個問題:
每個報錯都給收整合一行了,不是按照一個報錯,一個事件模組收集的。

下面將行換成事件的方式展示:

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

執行命令:

[root@elk-node1 ~]# /opt/logstash/bin/logstash -f multiline.conf 
Settings: Default filter workers: 1
Logstash startup completed
123
456
[123
{
    "@timestamp" => "2016-11-11T09:28:56.824Z",
       "message" => "123\n456",
      "@version" => "1",
          "tags" => [
        [0] "multiline"
    ],
          "host" => "elk-node1"
}
123]
[456]
{
    "@timestamp" => "2016-11-11T09:29:09.043Z",
       "message" => "[123\n123]",
      "@version" => "1",
          "tags" => [
        [0] "multiline"
    ],
          "host" => "elk-node1"
}

在沒有遇到[的時候,系統不會收集,只有遇見[的時候,才算是一個事件,才收集起來。
======================================================================
參考內容
https://www.elastic.co/guide/en/logstash/current/plugins-codecs-multiline.html
======================================================================

(3)Kibana安裝配置

1)kibana的安裝:
[root@elk-node1 ~]# cd /usr/local/src
[root@elk-node1 src]# wget https://download.elastic.co/kibana/kibana/kibana-4.3.1-linux-x64.tar.gz
[root@elk-node1 src]# tar zxf kibana-4.3.1-linux-x64.tar.gz
[root@elk-node1 src]# mv kibana-4.3.1-linux-x64 /usr/local/
[root@elk-node1 src]# ln -s /usr/local/kibana-4.3.1-linux-x64/ /usr/local/kibana

2)修改配置檔案:
[root@elk-node1 config]# pwd
/usr/local/kibana/config
[root@elk-node1 config]# cp kibana.yml kibana.yml.bak
[root@elk-node1 config]# vim kibana.yml
server.port: 5601
server.host: "0.0.0.0"
elasticsearch.url: "http://192.168.1.160:9200"
kibana.index: ".kibana"        #注意這個.Kibana索引用來儲存資料,千萬不要刪除了它。它是將es資料通過kibana進行web展示的關鍵。這個配置後,在es的web介面裡就會看到這個.kibana索引。

因為他一直執行在前臺,要麼選擇開一個視窗,要麼選擇使用screen。
安裝並使用screen啟動kibana:
[root@elk-node1 ~]# yum -y install screen
[root@elk-node1 ~]# screen                          #這樣就另開啟了一個終端視窗
[root@elk-node1 ~]# /usr/local/kibana/bin/kibana
log [18:23:19.867] [info][status][plugin:kibana] Status changed from uninitialized to green - Ready
log [18:23:19.911] [info][status][plugin:elasticsearch] Status changed from uninitialized to yellow - Waiting for Elasticsearch
log [18:23:19.941] [info][status][plugin:kbn_vislib_vis_types] Status changed from uninitialized to green - Ready
log [18:23:19.953] [info][status][plugin:markdown_vis] Status changed from uninitialized to green - Ready
log [18:23:19.963] [info][status][plugin:metric_vis] Status changed from uninitialized to green - Ready
log [18:23:19.995] [info][status][plugin:spyModes] Status changed from uninitialized to green - Ready
log [18:23:20.004] [info][status][plugin:statusPage] Status changed from uninitialized to green - Ready
log [18:23:20.010] [info][status][plugin:table_vis] Status changed from uninitialized to green - Ready

然後按ctrl+a+d組合鍵,這樣在上面另啟的screen屏裡啟動的kibana服務就一直執行在前臺了....
[root@elk-node1 ~]# screen -ls
There is a screen on:
15041.pts-0.elk-node1 (Detached)
1 Socket in /var/run/screen/S-root.

(3)訪問kibana:http://112.110.115.10:15601/
如下,如果是新增上面設定的java日誌收集資訊,則在下面填寫es-error*;如果是新增上面設定的系統日誌資訊system*,以此型別(可以從logstash介面看到日誌收集項)

 然後點選上面的Discover,在Discover中檢視:

檢視日誌登陸,需要點選“Discover”-->"message",點選它後面的“add”
注意:
需要右邊檢視日誌內容時帶什麼屬性,就在左邊點選相應屬性後面的“add”
如下圖,新增了message和path的屬性:

這樣,右邊顯示的日誌內容的屬性就帶了message和path

點選右邊日誌內容屬性後面隱藏的<<,就可將內容向前縮排

新增新的日誌採集項,點選Settings->+Add New,比如新增system系統日誌。注意後面的*不要忘了。

 

 

刪除kibana裡的日誌採集項,如下,點選刪除圖示即可。

 

如果開啟kibana檢視日誌,發現沒有日誌內容,出現“No results found”,如下圖所示,這說明要檢視的日誌在當前時間沒有日誌資訊輸出,可以點選右上角的時間鍾來除錯日誌資訊的檢視。

 

4)收集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;

 

截圖如下:

啟動nginx服務:

[root@elk-node1 ~]# systemctl start nginx
[root@elk-node1 ~]# systemctl status nginx
● nginx.service - The nginx HTTP and reverse proxy server
   Loaded: loaded (/usr/lib/systemd/system/nginx.service; disabled; vendor preset: disabled)
   Active: active (running) since Fri 2016-11-11 19:06:55 CST; 3s ago
  Process: 15119 ExecStart=/usr/sbin/nginx (code=exited, status=0/SUCCESS)
  Process: 15116 ExecStartPre=/usr/sbin/nginx -t (code=exited, status=0/SUCCESS)
  Process: 15114 ExecStartPre=/usr/bin/rm -f /run/nginx.pid (code=exited, status=0/SUCCESS)
 Main PID: 15122 (nginx)
   CGroup: /system.slice/nginx.service
           ├─15122 nginx: master process /usr/sbin/nginx
           ├─15123 nginx: worker process
           └─15124 nginx: worker process

Nov 11 19:06:54 elk-node1 systemd[1]: Starting The nginx HTTP and reverse proxy server...
Nov 11 19:06:55 elk-node1 nginx[15116]: nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
Nov 11 19:06:55 elk-node1 nginx[15116]: nginx: configuration file /etc/nginx/nginx.conf test is successful
Nov 11 19:06:55 elk-node1 systemd[1]: Started The nginx HTTP and reverse proxy server.

編寫收集檔案
這次使用json的方式收集:

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

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

啟動日誌收集程式:
[root@elk-node1 ~]# /opt/logstash/bin/logstash -f json.conf        #或加個&放在後臺執行

訪問nginx頁面(在elk-node1的宿主機上執行訪問頁面的命令:curl http://192.168.1.160)就會出現以下內容:

[root@elk-node1 ~]# /opt/logstash/bin/logstash -f json.conf
Settings: Default filter workers: 1
Logstash startup completed
{
      "@timestamp" => "2016-11-11T11:10:53.000Z",
        "@version" => "1",
          "client" => "192.168.1.7",
             "url" => "/index.html",
          "status" => "200",
          "domain" => "192.168.1.160",
            "host" => "192.168.1.160",
            "size" => 3700,
    "responsetime" => 0.0,
         "referer" => "-",
              "ua" => "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.14.0.0 zlib/1.2.3 libidn/1.18 libssh2/1.4.2",
            "path" => "/var/log/nginx/access_json.log"
}

注意:
上面的json.conf配置只是將nginx日誌輸出,還沒有輸入到elasticsearch裡,所以這個時候在elasticsearch介面裡是採集不到nginx日誌的。

需要配置一下,將nginx日誌輸入到elasticsearch中,將其彙總到總檔案file.conf裡,如下也將nginx-log日誌輸入到elasticserach裡:(後續就可以只用這個彙總檔案,把要追加的日誌彙總到這個總檔案裡即可)

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

    file {
       path => "/var/log/elasticsearch/huanqiu.log"
       type => "es-error" 
       start_position => "beginning"
       codec => multiline {
           pattern => "^\["
           negate => true
           what => "previous"
       }
    }
    file {
       path => "/var/log/nginx/access_json.log"
       codec => json
       start_position => "beginning"
       type => "nginx-log"
    }
}


output {

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

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

可以加上--configtest引數,測試下配置檔案是否有語法錯誤或配置不當的地方,這個很重要!!
[root@elk-node1 ~]# /opt/logstash/bin/logstash -f file.conf --configtest
Configuration OK

然後接著執行logstash命令(由於上面已經將這個執行命令放到了後臺,所以這裡其實不用執行,也可以先kill之前的,再放後臺執行),然後可以再訪問nginx介面測試下
[root@elk-node1 ~]# /opt/logstash/bin/logstash -f file.conf &

登陸elasticsearch介面檢視:

 將nginx日誌整合到kibana介面裡,如下:

5)收集系統日誌

編寫收集檔案並執行。

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

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

對上面的採集檔案進行執行:
[root@elk-node1 ~]# /opt/logstash/bin/logstash -f syslog.conf

重新開啟一個視窗,檢視服務是否啟動:
[root@elk-node1 ~]# netstat -ntlp|grep 514
tcp6 0 0 192.168.1.160:514 :::* LISTEN 17842/java
[root@elk-node1 ~]# vim /etc/rsyslog.conf
#*.* @@remote-host:514                                                           【在此行下面新增如下內容】
*.* @@192.168.1.160:514

[root@elk-node1 ~]# systemctl restart rsyslog

回到原來的視窗(即上面採集檔案的執行終端),就會出現資料:

[root@elk-node1 ~]# /opt/logstash/bin/logstash -f syslog.conf
Settings: Default filter workers: 1
Logstash startup completed
{
           "message" => "Stopping System Logging Service...\n",
          "@version" => "1",
        "@timestamp" => "2016-11-13T10:35:30.000Z",
              "type" => "system-syslog",
              "host" => "192.168.1.160",
          "priority" => 30,
         "timestamp" => "Nov 13 18:35:30",
         "logsource" => "elk-node1",
           "program" => "systemd",
          "severity" => 6,
          "facility" => 3,
    "facility_label" => "system",
    "severity_label" => "Informational"
}
........
........

再次新增到總檔案file.conf中:

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

    file {
       path => "/var/log/elasticsearch/huanqiu.log"
       type => "es-error" 
       start_position => "beginning"
       codec => multiline {
           pattern => "^\["
           negate => true
           what => "previous"
       }
    }
    file {
       path => "/var/log/nginx/access_json.log"
       codec => json
       start_position => "beginning"
       type => "nginx-log"
    }
    syslog {
        type => "system-syslog"
        host => "192.168.1.160"
        port => "514"
    }
}


output {

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

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

執行總檔案(先測試下總檔案配置是否有誤,然後先kill之前在後臺啟動的file.conf檔案,再次執行):
[root@elk-node1 ~]# /opt/logstash/bin/logstash -f file.conf --configtest
Configuration OK
[root@elk-node1 ~]# /opt/logstash/bin/logstash -f file.conf &

測試:
向日志中新增資料,看elasticsearch和kibana的變化:
[root@elk-node1 ~]# logger "hehehehehehe1"
[root@elk-node1 ~]# logger "hehehehehehe2"
[root@elk-node1 ~]# logger "hehehehehehe3"
[root@elk-node1 ~]# logger "hehehehehehe4"
[root@elk-node1 ~]# logger "hehehehehehe5"

新增到kibana介面中:

 

6)TCP日誌的收集

編寫日誌收集檔案,並執行:(有需要的話,可以將下面收集檔案的配置彙總到上面的總檔案file.conf裡,進而輸入到elasticsearch介面裡和kibana裡檢視)
[root@elk-node1 ~]# cat tcp.conf
input {
tcp {
host => "192.168.1.160"
port => "6666"
}
}
output {
stdout {
codec => "rubydebug"
}
}

[root@elk-node1 ~]# /opt/logstash/bin/logstash -f tcp.conf

開啟另外一個視窗,測試一(安裝nc命令:yum install -y nc):
[root@elk-node1 ~]# nc 192.168.1.160 6666 </etc/resolv.conf

回到原來的視窗(即上面採集檔案的執行終端),就會出現資料:
[root@elk-node1 ~]# /opt/logstash/bin/logstash -f tcp.conf
Settings: Default filter workers: 1
Logstash startup completed
{
        "message" => "",
       "@version" => "1",
   "@timestamp" => "2016-11-13T11:01:15.280Z",
              "host" => "192.168.1.160",
              "port" => 49743
}

測試二:
[root@elk-node1 ~]# echo "hehe" | nc 192.168.1.160 6666
[root@elk-node1 ~]# echo "hehe" > /dev/tcp/192.168.1.160/6666

回到之前的執行埠,在去檢視,就會顯示出來:

[root@elk-node1 ~]# /opt/logstash/bin/logstash -f tcp.conf 
Settings: Default filter workers: 1
Logstash startup completed
....... { "message" => "hehe", "@version" => "1", "@timestamp" => "2016-11-13T11:39:58.263Z", "host" => "192.168.1.160", "port" => 53432 } { "message" => "hehe", "@version" => "1", "@timestamp" => "2016-11-13T11:40:13.458Z", "host" => "192.168.1.160", "port" => 53457 }

7)使用filter
編寫檔案:

[root@elk-node1 ~]# 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-node1 ~]# /opt/logstash/bin/logstash -f grok.conf 
Settings: Default filter workers: 1
Logstash startup completed
55.3.244.1 GET /index.html 15824 0.043                    #輸入這個,下面就會自動形成字典的形式
{
       "message" => "55.3.244.1 GET /index.html 15824 0.043",
      "@version" => "1",
    "@timestamp" => "2016-11-13T11:45:47.882Z",
          "host" => "elk-node1",
        "client" => "55.3.244.1",
        "method" => "GET",
       "request" => "/index.html",
         "bytes" => "15824",
      "duration" => "0.043"
}

其實上面使用的那些變數在程式中都有定義:

[root@elk-node1 ~]# cd /opt/logstash/vendor/bundle/jruby/1.9/gems/logstash-patterns-core-2.0.2/patterns/
[root@elk-node1 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-node1 patterns]# cat grok-patterns
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" ]
      }
}

8)mysql慢查詢

收集檔案:

[root@elk-node1 ~]# cat mysql-slow.conf
input {
    file {
        path => "/root/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"
    }
}

執行檢測:
上面需要的/root/slow.log是自己上傳的,然後自己插入資料儲存後,會顯示:

[root@elk-node1 ~]# /opt/logstash/bin/logstash -f mysql-slow.conf
Settings: Default filter workers: 1
Logstash startup completed
{
    "@timestamp" => "2016-11-14T06:53:54.100Z",
       "message" => "# Time: 161114 11:05:18",
      "@version" => "1",
          "path" => "/root/slow.log",
          "host" => "elk-node1",
          "type" => "mysql-slowlog",
          "tags" => [
        [0] "_grokparsefailure"
    ]
}
{
    "@timestamp" => "2016-11-14T06:53:54.105Z",
       "message" => "# User@Host: test[test] @  [124.65.197.154]\n# Query_time: 1.725889  Lock_time: 0.000430 Rows_sent: 0  Rows_examined: 0\nuse test_zh_o2o_db;\nSET timestamp=1479092718;\nSELECT trigger_name, event_manipulation, event_object_table, action_statement, action_timing, DEFINER FROM information_schema.triggers WHERE BINARY event_object_schema='test_zh_o2o_db' AND BINARY event_object_table='customer';\n# Time: 161114 12:10:30",
      "@version" => "1",
          "tags" => [
        [0] "multiline",
        [1] "_grokparsefailure"
    ],
          "path" => "/root/slow.log",
          "host" => "elk-node1",
          "type" => "mysql-slowlog"
}
.........
.........

======================================================================
接下來描述會遇見到的一個問題:
一旦我們的elasticsearch出現問題,就不能進行日誌採集處理了!
這種情況下該怎麼辦呢?

解決方案;
可以在client和elasticsearch之間新增一箇中介軟體作為快取,先將採集到的日誌內容寫到中介軟體上,然後再從中介軟體輸入到elasticsearch中。
這就完美的解決了上述的問題了。

(4)ELK中使用redis作為中介軟體,快取日誌採集內容

1)redis的配置和啟動

[root@elk-node1 ~]# vim /etc/redis.conf               #修改下面兩行內容
daemonize yes
bind 192.168.1.160
[root@elk-node1 ~]# systemctl start redis
[root@elk-node1 ~]# lsof -i:6379
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
redis-ser 19474 redis 4u IPv4 1344465 0t0 TCP elk-node1:6379 (LISTEN)
[root@elk-node1 ~]# redis-cli -h 192.168.1.160
192.168.1.160:6379> info
# Server
redis_version:2.8.19
.......

2)編寫從Client端收集資料的檔案

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

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

3)執行收集資料的檔案,並輸入資料hello redis 

[root@elk-node1 ~]# /opt/logstash/bin/logstash -f redis-out.conf
Settings: Default filter workers: 1
Logstash startup completed             #下面輸入資料hello redis
hello redis

4)在redis中檢視資料

[root@elk-node1 ~]# redis-cli -h 192.168.1.160
192.168.1.160:6379> info
# Server
.......
.......
# Keyspace
db6:keys=1,expires=0,avg_ttl=0                   #在最下面一行,顯示是db6
192.168.1.160:6379> select 6
OK
192.168.1.160:6379[6]> keys *
1) "demo"
192.168.1.160:6379[6]> LINDEX demo -1
"{\"message\":\"hello redis\",\"@version\":\"1\",\"@timestamp\":\"2016-11-14T08:04:25.981Z\",\"host\":\"elk-node1\"}"

5)繼續隨便寫點資料

[root@elk-node1 ~]# /opt/logstash/bin/logstash -f redis-out.conf 
Settings: Default filter workers: 1
Logstash startup completed
hello redis
123456
asdf
ert
wang
shi
bo
guohuihui
as
we
r
g

asdfjkdfsak
5423wer
34rt3
6y
7uj
u
io9
sdjfhsdk890
huanqiu
huanqiuchain
hqsb
asda    

6)在redis中檢視

在redis中檢視長度:
[root@elk-node1 ~]# redis-cli -h 192.168.1.160
192.168.1.160:6379> info
# Server
redis_version:2.8.19
.......
.......
# Keyspace
db6:keys=1,expires=0,avg_ttl=0      #顯示是db6
192.168.1.160:6379> select 6
OK
192.168.1.160:6379[6]> keys *
1) "demo"
192.168.1.160:6379[6]> LLEN demo
(integer) 24

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

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

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

執行:
[root@elk-node1 ~]# /opt/logstash/bin/logstash -f redis-in.conf --configtest
Configuration OK
[root@elk-node1 ~]# /opt/logstash/bin/logstash -f redis-in.conf &

在redis中檢視,發現資料已被讀出:
192.168.1.160:6379[6]> LLEN demo
(integer) 0

=============================溫馨提示===========================

redis預設只有16個資料庫, 也就是說最多隻能有16個db, 即db01-db15
但是key值可以設定不同, 也就是針對不同日誌的key字首可以設定不同.
比如: 
key => "nginx.log"的值最多可以設定16個db, 即db01-db15
key => "mysql.log"的值最多可以設定16個db, 即db01-db15
key => "tomcat.log"的值最多可以設定16個db, 即db01-db15

登陸elasticsearch介面檢視:

 

8)接著,將收集到的所有日誌寫入到redis中。這了重新定義一個新增redis快取後的總檔案shipper.conf。(可以將之前執行的總檔案file.conf停掉)

[root@elk-node1 ~]# vim shipper.conf
input {
    file {
      path => "/var/log/messages"
      type => "system"
      start_position => "beginning"
    }
 
    file {
       path => "/var/log/elasticsearch/huanqiu.log"
       type => "es-error"
       start_position => "beginning"
       codec => multiline {
           pattern => "^\["
           negate => true
           what => "previous"
       }
    }
    file {
       path => "/var/log/nginx/access_json.log"
       codec => json
       start_position => "beginning"
       type => "nginx-log"
    }
    syslog {
        type => "system-syslog"
        host => "192.168.1.160"
        port => "514"
    }
 
}
 
 
output {
   if [type] == "system"{
     redis {
        host => "192.168.1.160"
        port => "6379"
        db => "6"
        data_type => "list"
        key => "system"
     }
   }
 
    if [type] == "es-error"{
      redis {
        host => "192.168.1.160"
        port => "6379"
        db => "6"
        data_type => "list"
        key => "demo"
        }
     }
    if [type] == "nginx-log"{    
       redis {
          host => "192.168.1.160"
          port => "6379"
          db => "6"
          data_type => "list"
          key => "nginx-log"
       }
    }
    if [type] == "system-syslog"{
       redis {
          host => "192.168.1.160"
          port => "6379"
          db => "6"
          data_type => "list"
          key => "system-syslog"
       }    
     }
}

執行上面的檔案(提前將上面之前啟動的file.conf檔案的執行給結束掉!)
[root@elk-node1 ~]# /opt/logstash/bin/logstash -f shipper.conf --configtest
Configuration OK
[root@elk-node1 ~]# /opt/logstash/bin/logstash -f shipper.conf
Settings: Default filter workers: 1
Logstash startup completed

在redis中檢視:
[root@elk-node1 ~]# redis-cli -h 192.168.1.160
192.168.1.160:6379> info
# Server
redis_version:2.8.19
.......
.......
# Keyspace
db6:keys=1,expires=0,avg_ttl=0                      #顯示是db6
192.168.1.160:6379> select 6
OK
192.168.1.160:6379[6]> keys *
1) "demo"
2) "system"
192.168.1.160:6379[6]> keys *
1) "nginx-log"
2) "demo"
3) "system"

另開一個視窗,新增點日誌:
[root@elk-node1 ~]# logger "12325423"
[root@elk-node1 ~]# logger "12325423"
[root@elk-node1 ~]# logger "12325423"
[root@elk-node1 ~]# logger "12325423"
[root@elk-node1 ~]# logger "12325423"
[root@elk-node1 ~]# logger "12325423"

又會增加日誌:
192.168.1.160:6379[6]> keys *
1) "system-syslog"
2) "nginx-log"
3) "demo"
4) "system"

其實可以在任意的一臺ES中將資料從redis讀取到ES中。
下面我們們在elk-node2節點,將資料從redis讀取到ES中:

編寫檔案:

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

      redis {
        type => "es-error"
        host => "192.168.1.160"
        port => "6379"
        db => "6"
        data_type => "list"
        key => "es-error"
        }
       redis {
          type => "nginx-log"
          host => "192.168.1.160"
          port => "6379"
          db => "6"
          data_type => "list"
          key => "nginx-log"
       }
       redis {
          type => "system-syslog"
          host => "192.168.1.160"
          port => "6379"
          db => "6"
          data_type => "list"
          key => "system-syslog"
       }    

}


output {

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

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

執行:
[root@elk-node2 ~]# /opt/logstash/bin/logstash -f file.conf --configtest
Configuration OK
[root@elk-node2 ~]# /opt/logstash/bin/logstash -f file.conf &

去redis中檢查,發現資料已經被讀出到elasticsearch中了。
192.168.1.160:6379[6]> keys *
(empty list or set)

同時登陸logstash和kibana看,發現可以正常收集到日誌了

可以執行這個 去檢視nginx日誌
[root@elk-node1 ~]# ab -n10000 -c1 http://192.168.1.160/

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

==============logstash配置java環境===============
由於新版的ELK環境要求java1.8,但是有些伺服器由於業務程式碼自身限制只能用java6或java7。
這種情況下,要安裝Logstash,就只能單獨配置Logstas自己使用的java環境了。

操作如下:
0) 使用rpm包安裝logstash

1)安裝java8,參考:http://www.cnblogs.com/kevingrace/p/7607442.html

2)在/etc/sysconfig/logstash檔案結尾新增下面兩行內容:
[root@cx-app01 ~]# vim /etc/sysconfig/logstash
.......
JAVA_CMD=/usr/local/jdk1.8.0_172/bin 
JAVA_HOME=/usr/local/jdk1.8.0_172

3)在/opt/logstash/bin/logstash.lib.sh檔案新增下面一行內容:
[root@cx-app02 ~]# vim /opt/logstash/bin/logstash.lib.sh
.......
export JAVA_HOME=/usr/local/jdk1.8.0_172

4) 然後使用logstash收集日誌,就不會報java環境錯誤了。

==================配置範例===================

如下的配置範例:
192.168.10.44為elk的master節點,同時也是redis節點
  
[root@client-node01 opt]# pwd
/opt
[root@client-node01 opt]# cat redis-in.conf
input {
    file {
       path => "/usr/local/tomcat8/logs/catalina.out"
       type => "tomcat8-logs"
       start_position => "beginning"
       codec => multiline {
           pattern => "^\["           //表示收集以"["開頭的日誌資訊
           negate => true
           what => "previous"
       }
    }
}
  
output {
    if [type] == "tomcat8-logs"{
       redis {
          host => "192.168.10.44"
          port => "6379"
          db => "1"
          data_type => "list"
          key => "tomcat8-logs"
       } 
     }
}
  
[root@client-node01 opt]# cat redis-input.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@client-node01 opt]# cat 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@client-node01 opt]# /opt/logstash/bin/logstash -f /opt/redis-in.conf --configtest
Configuration OK
[root@client-node01 opt]# /opt/logstash/bin/logstash -f /opt/redis-input.conf --configtest
Configuration OK
[root@client-node01 opt]# /opt/logstash/bin/logstash -f /opt/file.conf --configtest
Configuration OK
  
啟動logstash
[root@client-node01 opt]# /opt/logstash/bin/logstash -f /opt/redis-in.conf &
[root@client-node01 opt]# /opt/logstash/bin/logstash -f /opt/redis-input.conf &
[root@client-node01 opt]# /opt/logstash/bin/logstash -f /opt/file.conf &
  
這時候,當/usr/local/tomcat8/logs/catalina.out和/var/log/messages檔案裡有新日誌資訊寫入時,就會觸發動作,
在redis裡就能檢視到相關資訊,並檢視寫入到es裡。

=========================================================================================================
溫馨提示:
當客戶機的日誌資訊收集後,經過redis剛讀到es資料庫裡後,如果沒有新資料寫入,則預設在es的訪問介面裡是看不到
資料的,只有當日志檔案裡有新的日誌寫入後才會觸發資料展示的動作,即es的訪問介面(http://192.168.10.44:9200/_plugin/head/)
裡才能看到日誌資料的展示效果。
==========================================================================================================
  
假設想上面兩個檔案裡寫入測試資料
[root@client-node01 opt]# echo "hellohellohellohello" >> /var/log/messages
[root@client-node01 opt]# echo "[hahahahahahhahahahahahahahahahahahah]" >> /usr/local/tomcat8/logs/catalina.out
  
到redis裡發現有相關的key,很快就會讀到es裡。可以配置到kibana裡觀察。
  
可以先測試下日誌資訊是否寫到redis裡?然後再測試下資料是否從redis讀到es裡?一步步確定資料去向。
 
注意上面redis-in.conf檔案中的下面設定,使用正則匹配,收集以哪些字元開頭的日誌資訊:
pattern => "^\["                    表示收集以"["開頭的日誌資訊
pattern => "^2018"                  表示收集以"2018"開頭的日誌資訊
pattern => "^[a-zA-Z0-9]"           表示收集以字母(大小寫)或數字開頭的日誌資訊
pattern => "^[a-zA-Z0-9]|[^ ]+"     表示收集以字母(大小寫)或數字或空格的日誌資訊

相關文章