ELK實際上就是ElasticSearch,Logstash,Kibana的縮寫,是日誌收集分析的一種解決方案。html
elk是目前比較新也發展比較快的一套數據分析套件,其中Elasticsearch是用來做爲存儲和查詢引擎的,kibana則是位於其之上的一個UI(更偏向於聚合彙總分析),而logstash則是屬於ETL工具(數據的提取轉換插入)。
在具體的使用過程當中,目前以爲logstash算是比較雞肋的,由於適用的場景有限,並且要擴展必須本身實現。我的建議,若是對es比較熟悉的,徹底能夠不須要用這個。本身用es加個river插件,那個效果也不錯。前端
ELK簡單架構
java
日誌收集系統架構總體架構
linux
簡單來說他具體的工做流程就是Logstash agent監控並過濾日誌,將過濾後的日誌內容發給Redis(這裏的redis只處理隊列不作存儲),Logstash index將日誌收集在一塊兒交給全文搜索服務ElasticSearch,能夠用ElasticSearch進行自定義搜索,經過Kibana來結合 自定義搜索進行頁面展現nginx
此外 logstash 的收集方式分爲 standalone 和 centralized。
standalone 是全部功能都在一個服務器上面,自發自收,centralized 就是集中收集,一臺服務器接收全部shipper(我的理解就是logstash agent)的日誌。
其實 logstash自己不分 什麼 shipper 和 collector ,只不過就是配置文件不一樣而已,咱們此次按照集中的方式來測試git
這裏的Logstash分爲index和agent兩種角色,也能夠說是收集方式分爲standalone和centralized兩種。standalone是全部功能都在一個服務器上面,自發自收,centralized就是集中收集,一臺服務器接收全部shipper(我的理解就是logstash agent)的日誌。(其實logstash自己不分什麼shipper和collector ,只不過就是配置文件不一樣而已)。Logstash的agent和indexer分開部署,多臺agent負責監控、過濾日誌,index負責收集日誌並將日誌交給ElasticSearch作搜索,經過Kibana來結合自定義搜索進行頁面展現。Redis其實是起到了緩衝消峯的做用,不然併發訪問量大的時候ES會被拖垮的github
192.168.0.1 logstash index,ElasticSearch,kibana,JDK
192.168.0.2 logstash agent,JDK
192.168.0.3 redisweb
由於上一篇文章已經寫過Docker如何安裝ES環境了,這裏咱們直接繼承上一次安裝好的Docker鏡像,因此重點只介紹Logstash和Kibana的安裝,本文只是簡單的單機ELK環境,後續會逐步完善ELK+Redis的環境,甚至會把ELK單獨拆開三個Docker鏡像使用redis
安裝Logstash(本文使用的是logstash的1.5.4版本)docker
# 下載Logstash $ curl -O https://download.elastic.co/logstash/logstash/logstash-1.5.4.tar.gz # 解壓ES壓縮包 $ tar -zxvf logstash-1.5.4.tar.gz # 在{LOGSTASH_HOME}下新建一個conf目錄,在裏面新建一個配置文件logstash.conf $ cd logstash-1.5.4 $ mkdir conf $ cd conf # 編輯logstash.conf以下面的配置 $ vi logstash.conf # 啓動logstash $ cd {LOGSTASH_HOME}/bin/ $ ./logstash -f ../conf/logstash.conf
注意
由於Java的默認heap size,回收機制等緣由,logstash從1.4.0開始再也不使用jar運行方式.
logstash.conf配置文件
input { # 來自控制檯 stdin { type => "web" # ES索引的type codec => "json" # 輸入格式是json } # 來自文件 file { # 文件所在的絕對路徑 path => "/software/logstash-1.5.4/test.log" # ES索引的type type => "system" # 文件格式是json codec => "json" # 從文件的什麼位置開始採集 start_position => "beginning" } } output { # 輸出到控制檯 stdout { codec => rubydebug } # 輸出到ES elasticsearch { # 不使用logstash內嵌的ES embedded => false codec => "json" protocol => "http" host => "10.211.55.4" port => 9200 # 指定建立的索引名稱 index => "birdlogstash" } }
test.log文件內容,放在{LOGSTASH_HOME}目錄下
bird hello bird test bird bye
安裝Kibana(本文使用的是kibana的4.1.2版本)
# 下載Kibana $ curl -O https://download.elastic.co/kibana/kibana/kibana-4.1.2-linux-x64.tar.gz # 解壓ES壓縮包 $ tar -zxvf kibana-4.1.2-linux-x64.tar.gz # 重命名一下 $ mv kibana-4.1.2-linux-x64 kibana-4.1.2 # 啓動Kibana $ cd {KIBANA_HOME}/bin $ ./kibana # 訪問http://192.168.1.120:5601/ 配置一個ElasticSearch索引 # 在logstach裏面添加數據
注意
若是Kibana和ES不在同一臺機器上,須要在kibana.yml文件中指定ES集羣的地址 # The Elasticsearch instance to use for all your queries. elasticsearch_url: "http://10.211.55.4:9200"
Dockerfile文件
############################################ # version : birdben/elk:v1 # desc : 當前版本安裝的elk ############################################ # 設置繼承自咱們建立的 elasticsearch 鏡像 FROM birdben/elasticsearch:v1 # 下面是一些建立者的基本信息 MAINTAINER birdben (191654006@163.com) # 設置環境變量,全部操做都是非交互式的 ENV DEBIAN_FRONTEND noninteractive # 添加 supervisord 的配置文件,並複製配置文件到對應目錄下面。(supervisord.conf文件和Dockerfile文件在同一路徑) COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf RUN echo "export LC_ALL=C" # 設置 ES 的環境變量,若讀者有其餘的環境變量須要設置,也能夠在這裏添加。 ENV LOGSTASH_HOME /software/logstash-1.5.4 ENV KIBANA_HOME /software/kibana-4.1.2 # 複製 logstash-1.5.4, kibana-4.1.2 文件到鏡像中(logstash-1.5.4, kibana-4.1.2文件夾要和Dockerfile文件在同一路徑) ADD logstash-1.5.4 /software/logstash-1.5.4 ADD kibana-4.1.2 /software/kibana-4.1.2 # 解決環境問題,不然logstash沒法從log文件中採集日誌。具體環境: Logstash 1.5, Ubuntu 14.04, Oracle JDK7 RUN ln -s /lib/x86_64-linux-gnu/libcrypt.so.1 /usr/lib/x86_64-linux-gnu/libcrypt.so # 掛載/logstash目錄 VOLUME ["/logstash"] # 容器須要開放Kibana的5601端口 EXPOSE 5601 # 執行supervisord來同時執行多個命令,使用 supervisord 的可執行路徑啓動服務。 CMD ["/usr/bin/supervisord"]
Dockerfile源文件連接:
https://github.com/birdben/birdDocker/blob/master/elk/Dockerfile
supervisor配置文件內容
# 配置文件包含目錄和進程 # 第一段 supervsord 配置軟件自己,使用 nodaemon 參數來運行。 # 第二段包含要控制的 2 個服務。每一段包含一個服務的目錄和啓動這個服務的命令。 [supervisord] nodaemon=true [program:sshd] command=/usr/sbin/sshd -D [program:elasticsearch] command=/bin/bash -c "exec ${ES_HOME}/bin/elasticsearch -DFOREGROUND" [program:logstash] # 指定配置文件時,必定要使用絕對路徑,相對路徑是很差用的,這個坑已經踩過兩次了。。 command=/software/logstash-1.5.4/bin/logstash -f /logstash/logstash.conf [program:kibana] command=/software/kibana-4.1.2/bin/kibana
注意
# 以前一直在supervisor使用以下配置來啓動logstash,可是發現logstash剛啓動起來本身就掛了,而後不斷的在嘗試重啓。後來發現是配置文件沒有找到,由於使用supervisor來配置服務的命令時,指定配置文件時,必定要使用絕對路徑,相對路徑是很差用的,這個坑已經踩過兩次了。。這裏再次鄙視一下本身。。 INFO success: logstash entered RUNNING state, process has stayed up for > than 1 seconds (startsecs) INFO exited: logstash (exit status 1; not expected) INFO spawned: 'logstash' with pid 12 INFO exited: logstash (exit status 1; not expected) INFO spawned: 'logstash' with pid 13 INFO exited: logstash (exit status 1; not expected) INFO gave up: logstash entered FATAL state, too many start retries too quickly # 這裏使用supervisorctl status查看supervisor監控的全部服務,就會發現ES沒有處於被監控狀態 $ supervisorctl status logstash FATAL Exited too quickly (process log may have details) sshd RUNNING pid 6, uptime 0:01:49 elasticsearch RUNNING pid 8, uptime 0:01:49
控制檯終端
# 構建鏡像 $ docker build -t="birdben/elk:v1" . # 執行已經構件好的鏡像 $ docker run -p 9999:22 -p 9200:9200 -p 9300:9300 -p 5601:5601 -t -i -v /docker/logstash:/logstash "birdben/elk:v1"
測試Logstash
# 這裏咱們要測試幾種方式的logstash輸入和輸出 logstash啓動的參數 -e:表明控制檯以字符串的方式輸入conf配置 -f:表明指定文件的方式conf配置 ############## logstash從控制檯讀取 ############## # 只在CMD啓動的進程export設置變量,而不是將變量賦值命令寫入/etc/profile等腳本里,所以經過ssh方式登陸容器得到的shell是沒有這個變量的,因此ssh登陸要提早設置JAVA_HOME環境變量 $ export JAVA_HOME=/software/jdk7 # 測試運行前端輸出 $ {LOGSTASH_HOME}/bin/logstash -e 'input { stdin { } } output { stdout {} }' Logstash startup completed hello 2015-12-20T08:17:06.312Z c7f05b587d11 hello # 也可使用rubydebug的形式輸出到控制檯 $ {LOGSTASH_HOME}/bin/logstash -e 'input { stdin { } } output { stdout {codec=>rubydebug} }' Logstash startup completed hello { "message" => "hello", "@version" => "1", "@timestamp" => "2015-12-20T13:35:38.996Z", "host" => "40421a32fbc5" } # 還能夠將控制檯的輸入,輸出到ES而且建立對應的索引 $ {LOGSTASH_HOME}/bin/logstash -e 'input { stdin { type => "web" codec => "json" } } output { stdout { codec => rubydebug } elasticsearch { embedded => false codec => "json" protocol => "http" host => "10.211.55.4" port => 9200 } }' Logstash startup completed {"name":"bird"} { "name" => "bird", "@version" => "1", "@timestamp" => "2015-12-20T13:35:38.996Z", "type" => "web", "host" => "40421a32fbc5" } # 執行以後,能夠查詢ES的索引,會自動建立一個logstash的索引,而且會有一個對應的屬性name,它的值是bird $ curl -XPOST 'http://10.211.55.4:9200/_search?pretty' -d '{"query":{"match_all":{}}}' ############## logstash從文件中讀取 ############## $ {LOGSTASH_HOME}/bin/logstash -f /logstash/logstash.conf # 從文件中讀取日誌,可能會遇到下面的問題 NotImplementedError: block device detection unsupported or native support failed to load from org/jruby/RubyFileTest.java:67:in `blockdev?' from (irb):1:in `evaluate' from org/jruby/RubyKernel.java:1107:in `eval' from org/jruby/RubyKernel.java:1507:in `loop' from org/jruby/RubyKernel.java:1270:in `catch' from org/jruby/RubyKernel.java:1270:in `catch' from /home/ubuntu/logstash-1.5.0-rc3/lib/logstash/runner.rb:77:in `run' from org/jruby/RubyProc.java:271:in `call' from /home/ubuntu/logstash-1.5.0-rc3/lib/logstash/runner.rb:131:in `run' from org/jruby/RubyProc.java:271:in `call' from /home/ubuntu/logstash-1.5.0-rc3/vendor/bundle/jruby/1.9/gems/stud-0.0.19/lib/stud/task.rb:12:in `initialize' # 上面的問題緣由是環境問題,解決方案是先執行下面的語句,而後在運行logstash ln -s /lib/x86_64-linux-gnu/libcrypt.so.1 /usr/lib/x86_64-linux-gnu/libcrypt.so # 參考文章: https://github.com/elastic/logstash/issues/3127#issuecomment-101068714 # 改好上面的問題以後logstash就會將文件的內容讀取並輸出到ES,使用下面的語句進行查詢,就能夠看到以前test.log中的3行記錄,被ES建立了3條索引記錄 $ curl -XPOST 'http://10.211.55.4:9200/_search?pretty' -d '{"query":{"match_all":{}}}'
測試Kibana
# 瀏覽器直接訪問 http://10.211.55.4:5601 # 若是ES尚未索引,你須要告訴它你打算探索哪一個 Elasticsearch 索引。第一次訪問 Kibana 的時候,你會被要求定義一個 index pattern 用來匹配一個或者多個索引名。好了。這就是你須要作的所有工做。之後你還能夠隨時從 Settings 標籤頁添加更多的 index pattern。 # 由於咱們在Logstash配置了從log文件中讀取數據而且輸出到ES的索引上,配置文件中已經指定了索引的名稱"birdlogstash",這樣咱們在Kibana只要指定這個索引名稱就能夠了,同理咱們也能夠在Logstash中改爲按照日期分割的方式,Kibana也能夠按照這種方式來配置。 # 指定建立的索引名稱 index => "birdlogstash" # 指定建立的索引名稱(按照索引類型和日期分割) index => "logstash-%{type}-%{+YYYY.MM.dd}" # 默認狀況下,Kibana 會鏈接運行在 localhost 的 Elasticsearch。要鏈接其餘 Elasticsearch 實例,修改 kibana.yml 裏的 Elasticsearch URL,而後重啓 Kibana。如何在生產環境下使用 Kibana,閱讀生產環境部署章節。 http://kibana.logstash.es/content/kibana/v4/production.html
參考文章: