ELK Stack(ElasticSearch, Logstash, Kibana)
Elasticsearch(端口9200)
是個開源分布式搜索引擎,它的特點有:分布式,零配置,自動發現,索引自動分片,索引副本機制,文檔,節點,集群,restful風格接口,多數據源,自動搜索負載等。 Logstash
是一個完全開源的工具,他可以對你的日志進行收集、過濾,並將其存儲供以后使用(如,搜索)。 Kibana
也是一個開源和免費的工具,Kibana可以為 Logstash 和 ElasticSearch 提供的日志分析友好的 Web 界面,可以幫助您匯總、分析和搜索重要數據日志。
ELK官網:https://www.elastic.co/ ELK官網文檔:https://www.elastic.co/guide/index.html ELK中文指南:https://kibana.logstash.es/content/ Elasticsearch 管理:https://www.elastic.co/guide/en/elasticsearch/guide/current/administration.html
平台實現架構如下
ElasticSearch簡介
ElasticSearch是一個基於Lucene的搜索服務器。它提供了一個分布式多用戶能力的全文搜索引擎,基於RESTful web接口。
Elasticsearch是用Java開發的,並作為Apache許可條款下的開放源碼發布,是當前流行的企業級搜索引擎。設計用於雲計算中,能夠達到實時搜索,穩定,可靠,快速,安裝使用方便。
我們建立一個網站或應用程序,並要添加搜索功能,令我們受打擊的是:搜索工作是很難的。
我們希望我們的搜索解決方案要快
我們希望有一個零配置和一個完全免費的搜索模式
我們希望能夠簡單地使用JSON通過HTTP的索引數據
我們希望我們的搜索服務器始終可用
我們希望能夠一台開始並擴展到數百
我們要實時搜索,我們要簡單的多租戶
我們希望建立一個雲的解決方案。
Elasticsearch旨在解決所有這些問題和更多的問題。
ElasticSearch(ES)概念
cluster
一個集群,集群中有多個節點,其中有一個為主節點,這個主節點是可以通過選舉產生的,主從節點是對於集群內部來說的。
ES的一個概念就是去中心化,字面上理解就是無中心節點,這是對於集群外部來說的,因為從外部來看ES集群,在邏輯上是個整體,你與任何一個節點的通信和與整個ES集群通信是等價的。
shards
索引分片,ES可以把一個完整的索引分成多個分片,這樣的好處是可以把一個大的索引拆分成多個,分布到不同的節點上。構成分布式搜索。分片的數量只能在索引創建前指定,並且索引創建后不能更改。
replicas
索引副本,ES可以設置多個索引的副本,副本的作用一是提高系統的容錯性,當某個節點某個分片損壞或丟失時可以從副本中恢復。二是提高ES的查詢效率,ES會自動對搜索請求進行負載均衡。
recovery
數據恢復或叫數據重新分布,ES在有節點加入或退出時會根據機器的負載對索引分片進行重新分配,掛掉的節點重新啟動時也會進行數據恢復。
river
ES的一個數據源,也是其它存儲方式(如:數據庫)同步數據到ES的一個方法。它是以插件方式存在的一個ES服務,通過讀取river中的數據並把它索引到ES中,官方的river有couchDB的,RabbitMQ的,Twitter的,Wikipedia的。
gateway
ES索引快照的存儲方式,ES默認是先把索引存放到內存中,當內存滿了時再持久化到本地硬盤。gateway對索引快照進行存儲,當這個ES集群關閉再重新啟動時就會從gateway中讀取索引備份數據。
ES支持多種類型的gateway,有本地文件系統(默認),分布式文件系統,Hadoop的HDFS和amazon的s3雲存儲服務。
discovery.zen
ES的自動發現節點機制,ES是一個基於p2p的系統,它先通過廣播尋找存在的節點,再通過多播協議來進行節點之間的通信,同時也支持點對點的交互。
Transport
ES內部節點或集群與客戶端的交互方式,默認內部是使用tcp協議進行交互,同時它支持http協議(json格式)、thrift、servlet、memcached、zeroMQ等的傳輸協議(通過插件方式集成)。
ELK日志分析平台搭建
| 192.168.0.90 | nginx server | nginx/java1.8/logstash-1.5.3 |
| 192.168.0.91 | redis server | redis/java1.8/logstash-1.5.3 |
| 192.168.0.92 | ELK | elasticsearch-1.7.2/kibana-4.1.1/logstash-1.5.3 |
| 192.168.0.93 | ELK | elasticsearch-1.7.2/kibana-4.1.1/logstash-1.5.3 |
安裝ElasticSearch
安裝配置java環境依賴 #rpm -ivh jdk-8u111-linux-x64.rpm #echo "export JAVA_HOME=/usr/java/latest" >> /etc/profile #echo "export PATH=$JAVA_HOME/bin:$PATH" >>/etc/profile #source /etc/profile
安裝配置ElasticSearch
#tar -zxf elasticsearch-1.7.2.tar.gz -C /usr/local/
#ln -s /usr/local/elasticsearch-1.7.2/ /usr/local/elasticsearch
/usr/local/elasticsearch/bin/elasticsearch #啟動腳本
/usr/local/elasticsearch/config/elasticsearch.yml #配置文件
根據如下內容,修改es配置文件
# grep ^[a-z] /usr/local/elasticsearch-1.7.2/config/elasticsearch.yml
cluster.name: gtms-cluster es cluster名稱(cluster間通過組播通信)
node.name: "elk92" es節點名稱【另外一台elk93,除了此項,兩台es其他配置相同】
node.master: true 是否允許選舉master
node.data: true 是否允許存儲數據
index.number_of_shards: 5 索引分片數
index.number_of_replicas: 1 索引副本數
path.conf: /usr/local/elasticsearch/config/ es配置文件路徑
path.data: /elk/data 數據目錄
path.work: /elk/work 工作目錄
path.logs: /elk/logs log目錄
path.plugins: /elk/plugins plug目錄
bootstrap.mlockall: true 鎖住內存
#mkdir -p /elk/{data,work,logs,plugins}
啟動es
# /usr/local/elasticsearch/bin/elasticsearch (默認前台執行)
# curl http://192.168.0.92:9200 (驗證成功)
{
"status" : 200,
"name" : "elk92",
"cluster_name" : "gtms-es-cluster",
"version" : {
"number" : "1.7.2",
"build_hash" : "e43676b1385b8125d647f593f7202acbd816e8ec",
"build_timestamp" : "2015-09-14T09:49:53Z",
"build_snapshot" : false,
"lucene_version" : "4.10.4"
},
"tagline" : "You Know, for Search"
}
為方便管理,安裝起停命令腳本,及加入chkconfig
#git clone https://github.com/elasticsearch/elasticsearch-servicewrapper.git
#mv elasticsearch-servicewrapper/service/ /usr/local/elasticsearch/bin
#/usr/local/elasticsearch/bin/service/elasticsearch install
#chkconfig --list elasticsearch
elasticsearch 0:off 1:off 2:on 3:on 4:on 5:on 6:off
#/etc/init.d/elasticsearch
Usage: /etc/init.d/elasticsearch [ console | start | stop | restart | condrestart | status | install | remove | dump ]
Commands:
console Launch in the current console.
start Start in the background as a daemon process.
stop Stop if running as a daemon or in another console.
restart Stop if running and then start.
condrestart Restart only if already running.
status Query the current status.
install Install to start automatically when system boots.
remove Uninstall.
dump Request a Java thread dump if running.
# vi /usr/local/elasticsearch/bin/service/elasticsearch.conf
set.default.ES_HEAP_SIZE=512 默認1024M,根據實際情況調低內存,解決內存容量小導致服務無法啟動
ElasticSearch交互管理
ELK API Java API node client Transport client RESTful API Javascript .NET PHP Perl Python Ruby curl
通過curl方式
curl -X<VERB> '<PROTOCOL>://<HOST>/<PATH>?<QUERY_STRING>' -d '<BODY>'
VERB HTTP方法 GET/POST/PUT/HEAD/DELETE
PROTOCOL http/https(es前有代理)
QUERY_STRING 可選的請求參數,例如?pretty參數將使請求返回更加美觀易讀的JSON數據
BODY 一個JSON格式的請求主體
# curl -XGET 'http://192.168.0.92:9200/_count?pretty' -d ' {"query":"match_all":{}}}'
{
"count" : 0,
"_shards" : {
"total" : 0,
"successful" : 0,
"failed" : 0
}
}
# curl -XGET http://192.168.0.92:9200/_cluster/health?pretty ==>通過此方式可以實現cluster監控
| 單台時 | 啟動另一台ES后 |
| { "cluster_name" : "gtms-es-cluster", "status" : "green", "timed_out" : false, "number_of_nodes" : 1, "number_of_data_nodes" : 1, "active_primary_shards" : 0, "active_shards" : 0, "relocating_shards" : 0, "initializing_shards" : 0, "unassigned_shards" : 0, "delayed_unassigned_shards" : 0, "number_of_pending_tasks" : 0, "number_of_in_flight_fetch" : 0 } |
{ "cluster_name" : "gtms-es-cluster", "status" : "green", "timed_out" : false, "number_of_nodes" : 2, "number_of_data_nodes" : 2, "active_primary_shards" : 0, "active_shards" : 0, "relocating_shards" : 0, "initializing_shards" : 0, "unassigned_shards" : 0, "delayed_unassigned_shards" : 0, "number_of_pending_tasks" : 0, "number_of_in_flight_fetch" : 0 } |
elasticsearch集群管理插件head(如果集群大了管理有問題)
head插件安裝
# /usr/local/elasticsearch/bin/plugin -i mobz/elasticsearch-head
-> Installing mobz/elasticsearch-head...
Trying https://github.com/mobz/elasticsearch-head/archive/master.zip...
Downloading .......................................................
...................................................................
.........DONE
Installed mobz/elasticsearch-head into /elk/plugins/head
瀏覽器http://192.168.0.92:9200/_plugin/head
marvel插件(開發用免費)
marvel插件(開發用免費) marvel 是 Elastic.co 公司推出的商業監控方案,也是用來監控 Elasticsearch 集群實時、歷史狀態的有力用具,便於性能優化以及故障診斷。
監控主要分為六個層面,分別是集群層、節點層、索引層、分片層、事件層、Sense。 集群層:主要對集群健康情況進行匯總,包括集群名稱、集群狀態、節點數量、索引個數、分片數、總數據量、集群版本等信息。同時,對節點、索引整體情況分別展示。 節點層:主要對每個節點的 CPU 、內存、負載、索引相關的性能數據等信息進行統計,並進行圖形化展示。 索引層:展示的信息與節點層類似,主要從索引的角度展示。 分片層:從索引、節點兩個角度展示分片的分布情況,並提供 playback 功能演示分片分配的歷史過程。 事件層:展示集群相關事件,如節點脫離、加入,Master 選舉、索引創建、Shard 分配等。 Sense:輕量級的開發界面,主要用於通過 API 查詢數據,管理集群 安裝marvel插件 # /usr/local/elasticsearch/bin/plugin -i elasticsearch/marvel/latest -> Installing elasticsearch/marvel/latest... Trying http://download.elasticsearch.org/elasticsearch/marvel/marvel-latest.zip... Downloading ...........................................................
........................DONE Installed elasticsearch/marvel/latest into /elk/plugins/marvel http://192.168.0.92:9200/_plugin/marvel 右上角dashboards--->sence
| post /index-demo/test { "user":"gtms", "messages":"hello world!" } |
{ "_index": "index-demo", "_type": "test", "_id": "AVsq51umX6MYL3f6wZ0-", "_version": 1, "created": true } |
| GET /index-demo/test/AVsq51umX6MYL3f6wZ0- | { "_index": "index-demo", "_type": "test", "_id": "AVsq51umX6MYL3f6wZ0-", "_version": 1, "found": true, "_source": { } } |
| GET /index-demo/test/AVsq51umX6MYL3f6wZ0-/_source | { "user": "gtms", "messages": "hello world!" } |
| GET /index-demo/test/_search?q=hello | { "took": 5, "timed_out": false, "_shards": { "total": 5, "successful": 5, "failed": 0 }, "hits": { "total": 1, "max_score": 0.15342641, "hits": [ { "_index": "index-demo", "_type": "test", "_id": "AVsq51umX6MYL3f6wZ0-", "_score": 0.15342641, "_source": { "user": "gtms", "messages": "hello world!" } } ] } } |
經過上述操作后,再來看下,es上的索引及分片情況
logstash(需java環境)
需要在每台需要收集節點上安裝(即此測試在nginx server、redis server(yum 安裝logstash)上安裝)
logstash yum安裝(生產yum就可以了) #rpm --import https://packages.elasticsearch.org/GPG-KEY-elasticsearch #vi /etc/yum.repos.d/logstash.repo [logstash-1.5] name=Elastic repository for 1.5.x packages baseurl= https://packages.elasticsearch.org/logstash/1.5/centos gpgcheck=1 gpgkey= https://packages.elasticsearch.org/GPG-KEY-elasticsearch enabled=1 autorefresh=1 type=rpm-md logstash 源碼解包安裝(本次測試使用此種) #tar -zxvf logstash-1.5.3.tar.gz -C /usr/local/ #ln -s /usr/local/logstash-1.5.3/ /usr/local/logstash #/usr/local/logstash/bin/logstash -e 'input { stdin{} } output { stdout{} }' 等待輸入 [# /usr/local/logstash/bin/logstash -e 'input { stdin{} } output { stdout{codec => rubydebug} }'] test hello 2017-02-26T19:33:01.024Z node93 test hello Logstash startup completed test again hello 2017-02-26T19:33:28.237Z node93 test again hello # /usr/local/logstash/bin/logstash -e 'input { stdin{} } output { elasticsearch { host=> "192.168.0.92" protocol =>"http" } }' '[DEPRECATED] use `require 'concurrent'` instead of `require 'concurrent_ruby'` Logstash startup completed
==>輸入hello world后瀏覽,生成了,logstash-2017.04.02的索引
接下來
a、在nginx sevrer上安裝nginx服務並配置 log(略)
b、在redis sevrer上安裝redis並開啟服務(略)
配置logstash收集nginx,發送給ES
The settings you can configure vary according to the plugin type. For information about each plugin, see Input Plugins, Output Plugins, Filter Plugins, and Codec Plugins.
https://www.elastic.co/guide/en/logstash/1.5/input-plugins.html
https://www.elastic.co/guide/en/logstash/1.5/output-plugins.html
https://www.elastic.co/guide/en/logstash/1.5/filter-plugins.html
https://www.elastic.co/guide/en/logstash/1.5/codec-plugins.html
創建/etc/logstash目錄並創建3個logstash文件logstash_www.conf/logstash_bbs.conf/logstash_blog.conf # cat logstash_www.conf (其他2個相應修改) input{ file { path => "/usr/local/nginx/logs/www_access.log" } } output{ file { path => "/tmp/www_access.log" } elasticsearch { host => "192.168.0.92" protocol => "http" index => "node90_www_accesslog-%{+YYYY.MM.dd}" } }
# /usr/local/logstash/bin/logstash agent -f /etc/logstash/logstash_www.conf -l /var/log/logstash.log &
# /usr/local/logstash/bin/logstash agent -f /etc/logstash/logstash_blog.conf -l /var/log/logstash.log &
# /usr/local/logstash/bin/logstash agent -f /etc/logstash/logstash_bbs.conf -l /var/log/logstash.log &
分別進行訪問10次,使產生accesslog,然后查看es平台(3個索引只有當產生相應日志后才產生)
刪除es分片,停止logstash進程后
測試使用包含配置文件方式啟動1個logstash進程
# /usr/local/logstash/bin/logstash agent -f /etc/logstash/ -l /etc/logstash/logstash.log &
==>只訪問了其中一個站點,es上便產生了node90_www_accesslog-2017.04.02 node90_bolg_accesslog-2017.04.02 node90_bbs_accesslog-2017.04.02 三個索引文件
==>curl 其他站點后,發現3個索引都在進行變動
==>由此推斷,此種方式輸出方式使用了同一個管道
配置logstash收集nginx,發送給redis server,並配置es上的logstash到redis server上取日志
nginx server及redis配置
| # cat logstash_www.conf
# /usr/local/logstash/bin/logstash agent -f /etc/logstash/logstash_www.conf -l /var/log/logstash.log & |
# cat logstash.conf yum安裝方式使用單一配置文件啟動方式 #/opt/logstash/bin/logstash -f /etc/logstash/conf.d/www.conf -l /var/log/logstash.log & |
| 其他結論 =>同上一個測試原理相同,對於www blog bbs日志,如果需要在es上建立單獨的索引 1、nginx server上需建立不同的logstash配置文件並各自起logstash進程 2、在redis server端也需要對應nginx server上不同的logstash配置文件建立對應的logstash配置文件,並各自起進程 #如果在工作中建立不同的配置文件並起多個進程似乎不太合理(所以,需要使用filter,但是日志不能用type字段) #當然如果對同類型的日志建立一個es索引問題也不大,即www bbs blog配置為一個key,redis上根據此文件建立一個es索引 即按如下配置 |
|
| # cat /etc/logstash/logstash.conf |
# cat /etc/logstash/conf.d/logstash.conf input{ redis{ data_type => "list" key => "access" host =>"192.168.0.91" port => "6379" db => "1" } } output{ file { path => "/tmp/messages" } elasticsearch { host => "192.168.0.92" protocol => "http" index => "access-%{+YYYY.MM.dd}" } } |
上述配置,傳輸到es上日志以整條作為message字段,不利於檢索,接下來配置nginx www日志json輸出格式,將日志記錄根據字段分割
# vi /usr/local/nginx/conf/nginx.conf 增加如下日志log_format
log_format logstash_json '{ "@timestamp": "$time_iso8601", '
'"remote_addr": "$remote_addr", '
'"referer": "$http_referer", '
'"request": "$request", '
'"status": $status, '
'"bytes":$body_bytes_sent, '
'"agent": "$http_user_agent", '
'"x_forwarded": "$http_x_forwarded_for", '
'"upstr_addr": "$upstream_addr",'
'"upstr_host": "$upstream_http_host",'
'"ups_resp_time": "$upstream_response_time" }';
# vi /usr/local/nginx/conf/extra/www.conf 將www的access log記錄為新建的logstash_json格式
server
{
listen 80;
server_name www.gtms.org;
location / {
root html/www;
index index.html;
}
access_log logs/www_access.log logstash_json;
}
# cat logstash.conf 修改logstash.conf 以json的codec方式輸入日志,后重啟logstash input{ file { path => [ "/usr/local/nginx/logs/www_access.log","/usr/local/nginx/logs/bbs_access.log","/usr/local/nginx/logs/blog_access.log"] codec => "json" } } output{ redis { data_type => "list" key => "access" host =>"192.168.0.91" port => "6379" db => "1" } }
接下來進行測試,先刪除之前關於nginx的訪問日志
先curl www.gtms.org
再curl bbs.gtms.org
可以看到,3條message是未進行json code,而message為空的,在message后面的字段中有根據json code分割的字段
對於進行json codec的我們可以方便的進行檢索了,但是es的時間有問題,如果使用kibana就沒問題了
kibana安裝配置
#tar -zxf kibana-4.1.1-linux-x64.tar.gz -C /usr/local/ #ln -s /usr/local/kibana-4.1.1-linux-x64/ /usr/local/kibana # vi /usr/local/kibana/config/kibana.yml elasticsearch_url: "http://192.168.0.93:9200"
# /usr/local/kibana/bin/kibana 嘗試前台登陸,如果沒有報錯加&后台運行
http://kibanaIP:5601
根據es上的index創建一個index patten
保存后可以對此索引進行檢索操作 (篩選條件寫法可以用AND OR)
status:[300 TO 400]
status:200 AND remote_addr:192.168.0.102







