1. 程式人生 > >Docker實戰(九):Docker安裝ELK環境

Docker實戰(九):Docker安裝ELK環境

Docker安裝ELK環境

ELK實際上就是ElasticSearch,Logstash,Kibana的縮寫,是日誌收集分析的一種解決方案。

  • Elasticsearch一個開源的搜尋引擎框架(支援群集架構方式)
  • Logstash整合各種收集日誌外掛,還是一個比較優秀的正則切割日誌工具
  • Kibana一個免費的web應用,支援在web端檢視ES的搜尋結果

elk是目前比較新也發展比較快的一套資料分析套件,其中Elasticsearch是用來作為儲存和查詢引擎的,kibana則是位於其之上的一個UI(更偏向於聚合彙總分析),而logstash則是屬於ETL工具(資料的提取轉換插入)。
在具體的使用過程中,目前覺得logstash算是比較雞肋的,因為適用的場景有限,而且要擴充套件必須自己實現。個人建議,如果對es比較熟悉的,完全可以不需要用這個。自己用es加個river外掛,那個效果也不錯。

ELK簡單架構
ELK_Simple

日誌收集系統架構整體架構
日誌收集系統架構

簡單來講他具體的工作流程就是Logstash agent監控並過濾日誌,將過濾後的日誌內容發給redis(這裡的redis只處理佇列不做儲存),Logstash index將日誌收集在一起交給全文搜尋服務ElasticSearch,可以用ElasticSearch進行自定義搜尋,通過Kibana來結合 自定義搜尋進行頁面展示

此外 logstash 的收集方式分為 standalone 和 centralized。
standalone 是所有功能都在一個伺服器上面,自發自收,centralized 就是集中收集,一臺伺服器接收所有shipper(個人理解就是logstash agent)的日誌。
其實 logstash本身不分 什麼 shipper 和 collector ,只不過就是配置檔案不同而已,我們這次按照集中的方式來測試

這裡的Logstash分為index和agent兩種角色,也可以說是收集方式分為standalone和centralized兩種。standalone是所有功能都在一個伺服器上面,自發自收,centralized就是集中收集,一臺伺服器接收所有shipper(個人理解就是logstash agent)的日誌。(其實logstash本身不分什麼shipper和collector ,只不過就是配置檔案不同而已)。Logstash的agent和indexer分開部署,多臺agent負責監控、過濾日誌,index負責收集日誌並將日誌交給ElasticSearch做搜尋,通過Kibana來結合自定義搜尋進行頁面展示。Redis實際上是起到了緩衝消峰的作用,否則併發訪問量大的時候ES會被拖垮的

192.168.0.1 logstash index,ElasticSearch,kibana,JDK
192.168.0.2 logstash agent,JDK
192.168.0.3 redis

因為上一篇文章已經寫過Docker如何安裝ES環境了,這裡我們直接繼承上一次安裝好的Docker映象,所以重點只介紹Logstash和Kibana的安裝,本文只是簡單的單機ELK環境,後續會逐步完善ELK+Redis的環境,甚至會把ELK單獨拆開三個Docker映象使用

安裝Logstash(本文使用的是logstash的1.5.4版本)
# 下載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執行方式.

  • 以前方式:
    java -jar logstash-1.3.3-flatjar.jar agent -f logstash.conf
  • 現在方式:
    bin/logstash -f logstash.conf
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原始檔連結:
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

參考文章: