ELK

 

  對頗具規模的Web服務進行日誌收集、存儲、分析處理等html

  ELK:ElasticSearch、Logstash、Kibanajava

  ElasticSearch:是一個基於Lucene實現的開源的分佈式、RestFul的全文本搜索引擎此外它仍是一個分佈式實時文檔存儲其中每一個文檔的每一個field均是被索引的數據且可被搜索也是一個帶實時分析功能的分佈式搜索引擎可以擴展至數以百計的節點實時處理PB級的數據node

  架構:redis

    對於大規模的日誌收集,都會專門的服務器用來將日誌數據集中到一塊兒進行整合。通常會在各個生產日誌的節點上安裝日誌收集agent,而後經過agent向服務端發送日誌數據。可是若是全部agent同時將日誌發送給服務端,就算先不看服務端的性能,僅看網絡帶寬就是一個大問題,因此通常會在agent和服務端之間在放置一個消息隊列(能夠是redis、AMQP、kafka等)緩衝一下,而後服務端再一條一條的到隊列中獲取日誌數據;數據庫

  名詞解釋apache

    官網信息https://www.elastic.co/guide/en/elasticsearch/reference/7.3/glossary.html#glossary-termjson

    在Elasticsearch中存儲數據的行爲就叫作索引(indexing)vim

    索引(index)這個詞在Elasticsearch中有着不一樣的含義,因此有必要在此作一下區分:api

      索引(名詞):如上文所述,一個索引(index)就像是傳統關係數據庫中的數據庫,它是相關文檔存儲的地方,index的複數是indices indexes瀏覽器

      索引(動詞):「索引一個文檔」表示把一個文檔存儲到索引(名詞)裏,以便它能夠被檢索或者查詢。這很像SQL中的INSERT關鍵字,差異是,若是文檔已經存在,新的文檔將覆蓋舊的文檔。

      倒排索引:傳統數據庫爲特定列增長一個索引,例如B-Tree索引來加速檢索。ElasticsearchLucene使用一種叫作倒排索引(inverted index)的數據結構來達到相同目的。也能夠理解爲根據某個詞找某個或某些文檔;

    文檔document):文檔是Lucene索引和搜索的原子單位,它包含一個或多個域,是域的容器,基於JSON格式表示;

    映射mapping):原始內容存儲爲文檔以前須要事先進行分析,例如切詞、過濾某些詞等;映射就是用於定義此分析機制應該如何實現;

      示例:顯示特定字段的類型;

        ~]# curl  'http://192.168.80.136:9200/students/_mapping/?pretty'

        {

            "students" : {

                "mappings" : {

                    "properties" : {

                        "age" : {

                            "type" : "long"

                        },

                        "courses" : {

                          "type" : "text",

                          "fields" : {

                              "keyword" : {

                                  "type" : "keyword",

                                  "ignore_above" : 256

                              }

                          }

                      },

                      "first_name" : {

                          "type" : "text",

                          "fields" : {

                              "keyword" : {

                                  "type" : "keyword",

                                  "ignore_above" : 256

                              }

                          }

                      },

                      "gender" : {

                          "type" : "text",

                          "fields" : {

                              "keyword" : {

                                  "type" : "keyword",

                                  "ignore_above" : 256

                              }

                          }

                      },

                      "last_name" : {

                          "type" : "text",

                          "fields" : {

                              "keyword" : {

                                  "type" : "keyword",

                                  "ignore_above" : 256

                              }

                           }

                        }

                    }

                }

            }

        }

      域由其名稱和一個或多個值組成

    Note:ES對每一個文檔會取得其全部域的全部值生成一個名爲_all的域若是在query_string未指定查詢的域則在_all域上執行查詢操做

 

    在Elasticsearch中,文檔歸屬於一種類型(type),而這些類型存在於索引(index)中,且一個索引中能夠有多種類型,咱們能夠畫一些簡單的對比圖來類比傳統關係型數據庫:

      Relational DB -> Databases -> Tables -> Rows -> Columns

      Elasticsearch -> Indices   -> Types  -> Documents -> Fields

    切詞對一段文字進行切割能夠詞一句話也能夠是一個詞而後以切割出來的詞或句來進行搜索或者是搜索相應的詞或句時對其進行匹配

    域

      索引選項用於經過倒排索引來控制文本是否可被索引

        Index.ANALYZED:分析(切詞)並單獨做爲索引項;

        Index.Not_ANALYZED:不分析(不切詞),把整個內容當作一個索引項;

        Index.ANALYZED_NORMS:相似於Index.ANALYZED,但不存儲切詞的Norms(加權基準)信息;

        Index.Not_ANALYZED_NORMS:相似於Index.Not_ANALYZED,但不存儲切詞的Norms信息;

        Index.NO:不對此域的值進行索引所以不能被搜索

      存儲選項是否須要存儲域的真實值

        store.YES:存儲真實值(原值,切詞之後原詞的形式(好比大小寫));

        store.NO:不存儲真實值

      文檔和域的加權操做

        權重大的會在搜索結果中被優先顯示;默認都是同樣的;

    搜索引擎進行搜索的流程

      獲取原始內容 --> 構建文檔 --> 文檔分析 --> 建立索引 --> 用戶查詢 --> 構建查詢 --> 運行查詢(與建立索引密切相關) --> 返回結果 --> 展現給用戶

        咱們可使用Lucene建立索引可是它不獲取且不提供供用戶使用的搜索頁面因此咱們能夠將它當作一個庫能夠經過調用它的API接口來實現索引建立相關的功能對於搜索界面咱們可使用ElasticSearch來實現

          查詢Lucene索引時它返回的是一個有序的scoreDOC對象;查詢時,Lucene會對每一個文檔計算出其score

        Lucene的查詢

          IndexSearcher中的search方法

            TermQuery:對索引中的特定項進行搜索Term是索引中的最小索引片斷,每一個Term包含了一個域名和一個文本值;

          例子

            title This is a pen;

            owner:Tom;

            des:It is blue;

 

            titleThis is a book;

            owner:Jack

            des:It has 400 pages;

            當咱們進行搜索時就能夠指定在title或者owner範圍內搜索指定內容

          TermRangeQuery:在索引中的多個特定項中進行搜索,能搜索指定的多個域;

          NumericRangeQuery:對數值範圍進行搜索

          PrefixQuery:用於搜索以指定字符串開頭的項

          BooleanQuery:用於實現組合搜索ANDORNOT

          WildcardQuery:使用通配符進行查詢

          FuzzyQuery:模糊查詢,好比查詢與指定內容類似的內容;

  Elasticsearch致力於隱藏分佈式系統的複雜性。如下這些操做都是在底層自動完成的:

    將你的文檔分區到不一樣的容器或者分片(shards)中,它們能夠存在於一個或多個節點中。

    將分片均勻的分配到各個節點,對索引和搜索作負載均衡。

    冗餘每個分片,防止硬件故障形成的數據丟失。

    將集羣中任意一個節點上的請求路由到相應數據所在的節點。

    不管是增長節點,仍是移除節點,分片均可以作到無縫的擴展和遷移。

  ES的集羣組件

    Cluster:ES的集羣名稱。節點就是靠此名稱來決定加入到哪一個集羣中,且一個節點只能加入到一個集羣中;

    Node:運行了單個ES實例的主機即爲節點用於存儲數據參與集羣索引及搜索操做;經過節點名標識此節點;

    Shard:將索引分割成多個shard,存儲在多個節點中;從而減小單個節點的磁盤IO的壓力;默認狀況下ES會將一個索引分割成5shard,固然,用戶也能夠自定義,可是肯定以後不能夠再修改shard的數量;

      shard有兩種類型:primary shardreplica

        primary shard用於文檔存儲默認切割成5primary shard;ES還會爲每一個primary shard提供副本primary shard不可用是其副本就會提高爲primary shard,這個副本就是replica;其replica也可用於查詢時的負載均衡;每一個primary shardreplica數量也能夠自定義;

    ES集羣狀態

      green:正常狀態

      red:故障狀態

      yellow:修復狀態

  ES Cluster的工做過程

    啓動時,ES的各個節點會經過組播(默認)或單播在TCP協議的9300端口查找同一集羣中的其餘節點,並與之創建通訊;而且選舉出一個主節點,負責管理集羣狀態,以及在集羣範圍內決定各shard的分佈方式,這對用戶是透明的,也就是說每一個節點均可以接收和相應用戶的請求;

ES經過http協議使用9200接受客戶的查詢請求

    ES的安裝

      1.準備環境

        安裝ES須要安裝JDK,使用OpenJDK或者OracleJDK都是能夠的

        ~]# yum install java-1.8.0-openjdk.x86_64 -y

              ~]# yum install java-1.8.0-openjdk-devel.x86_64 -y

        ~]# yum install java-1.8.0-openjdk-headless.x86_64 -y

        配置JAVA的環境變量

      2.下載ES軟件包

        官網下載地址https://www.elastic.co/cn/downloads/elasticsearch/elasticsearch-7.3.0-x86_64.rpm

        ~]# yum install ./elasticsearch-7.3.0-x86_64.rpm  我下載的是rpm

        ~]# sudo systemctl daemon-reload

        ~]# sudo systemctl enable elasticsearch.service

      3.編輯配置文件

        ~]# vim /etc/elasticsearch/elasticsearch.yml

          cluster.name: myes        集羣名稱

          node.name: node3         節點名稱

          http.port: 9200            監聽端口

          network.host: 192.168.80.129   綁定的主機地址

          discovery.seed_hosts: ["192.168.80.129", "192.168.80.136"]  初始主機列表

          cluster.initial_master_nodes: ["node3 ", "node2 "]  使用一組符合主節點條件的初始節點引導集羣

      更多參數請參考官網https://www.elastic.co/guide/en/elasticsearch/reference/current/settings.html

      4.啓動ES

        ~]# sudo systemctl start elasticsearch.service

        Note:多個節點重複以上步驟便可

  ESRestFul API

    1.檢查集羣節點索引等健康與否以及獲取及相應狀態

    2.管理集羣節點索引及元數據

      查詢數據

        查詢方式

          1.經過RestFul request API查詢,也成爲query string;

          2.經過發送REST request body進行

            分爲兩類

              query DSL:執行full-text查詢時基於相關度來評判其查詢結果

                執行過程相對複雜且不會被緩存; 

              filter DSL:執行exact查詢時基於其結果yes」或「no」進行評判;

                速度快且結果能夠緩存; 

        示例

        ~]# curl -XGET 'http://192.168.80.136:9200/students/_search/?pretty'

        {

             "took" : 24,

             "timed_out" : false,

            "_shards" : {

                 "total" : 1,

                 "successful" : 1,

                 "skipped" : 0,

                 "failed" : 0

             },

             "hits" : {

                 "total" : {

                     "value" : 1,

                     "relation" : "eq"

                 },

                 "max_score" : 1.0,

                 "hits" : [

                   {

                       "_index" : "students",

                       "_type" : "class1",

                       "_id" : "1",

                       "_score" : 1.0,

                       "_source" : {

                           "first_name" : "Jing",

                           "last_name" : "Guo",

                           "gender" : "Male",

                           "age" : 25,

                          "courses" : "Xainglong shiba zhang"

                       }

                   }

                ]

             }

         }

        ~]# curl -H "Content-Type: application/json"  -XGET 'http://192.168.80.136:9200/students/_search/?pretty' -d '

        {                            

             "query": { "match_all":{} }

        }'           結果同上

      多索引、多類型查詢:

        /_search:查詢全部索引

        /INDEX_NAME/_search:單索引查詢

        /INDEX_NAME1,INDEX_NAME2/_search:多索引查詢

        /g*,w*/_search:通配索引查詢

        /INSEX_NAME/TYPE1,TYPE2/_search:多類型查詢

    3.執行CRUD(增刪查改)操做

      示例

        建立文檔

        ~]# curl -H "Content-Type: application/json"  -XPUT 'http://192.168.80.136:9200/students/class1/1?pretty' -d '

        {                     

             "first_name":"Jing",

             "last_name":"Guo",

            "gender":"Male",

             "age":25,                        

             "courses":"Xainglong shiba zhang"

        }'

        查看

        ~]# curl -XGET 'http://192.168.80.136:9200/students/class1/1?pretty'

        {

             "_index" : "students",

             "_type" : "class1",

            "_id" : "1",

             "_version" : 1,

             "_seq_no" : 0,

             "_primary_term" : 1,

             "found" : true,

             "_source" : {

                 "first_name" : "Jing",

                 "last_name" : "Guo",

                 "gender" : "Male",

                 "age" : 25,

                 "courses" : "Xainglong shiba zhang"

             }

        }

        更新

          PUT方法會直接覆蓋文檔內容若是隻是更新部份內容須要使用_update API;

        ~]# curl -H "Content-Type:application/json" -XPOST 'http://192.168.80.136:9200/students/class1/1/_update?pretty' -d '

        > {

        >   "doc":{"age":28}

        > }'

        {

             "_index" : "students",

             "_type" : "class1",

             "_id" : "1",

             "_version" : 2,

             "result" : "updated",

             "_shards" : {

                 "total" : 2,

                 "successful" : 1,

                 "failed" : 0

             },

             "_seq_no" : 2,

             "_primary_term" : 1

        }

        刪除

        ~]#  curl -XDELETE 'http://192.168.80.136:9200/students/class1/2'

          {"_index":"students","_type":"class1","_id":"2","_version":2,"result":"deleted","_shards":{"total":2,"successful":1,"failed":0},"_seq_no":3,"_primary_term":1}

 

    4.執行各類高級操做好比paging、filtering

  ES的請求格式

    向Elasticsearch發出的請求的組成部分與其它普通的HTTP請求是同樣的:

    curl -X<VERB> '<PROTOCOL>://<HOST>:<PORT>/<PATH>?<QUERY_STRING>' -d '<BODY>'

      VERB HTTP方法:GET, POST, PUT, HEAD, DELETE

      PROTOCOL http或者https協議(只有在Elasticsearch前面有https代理的時候可用)

      HOST Elasticsearch集羣中的任何一個節點的主機名,若是是在本地的節點,那麼就叫localhost

      PORT Elasticsearch HTTP服務所在的端口,默認爲9200

      PATH API路徑(例如_count將返回集羣中文檔的數量),PATH能夠包含多個組件,例如_cluster/stats或者_nodes/stats/jvm

      QUERY_STRING 一些可選的查詢請求參數,例如?pretty參數將使請求返回更加美觀易讀的JSON數據

      BODY 一個JSON格式的請求主體(若是請求須要的話)

    舉例說明,爲了計算集羣中的文檔數量,咱們能夠這樣作:

      curl -H "Content-Type: application/json"  -XGET 'http://192.168.80.136:9200/_search?pretty' -d '

      {

           "query": {

                 "match_all": {}

           }

      }

      '

    Elasticsearch返回一個相似200 OKHTTP狀態碼和JSON格式的響應主體(除了HEAD請求)。上面的請求會獲得以下的JSON格式的響應主體:

      {

           "took" : 0,

           "timed_out" : false,

           "_shards" : {

               "total" : 0,

               "successful" : 0,

               "skipped" : 0,

               "failed" : 0

           },

           "hits" : {

               "total" : {

                 "value" : 0,

                 "relation" : "eq"

             },

             "max_score" : 0.0,

             "hits" : [ ]

          }

      }

    咱們看不到HTTP頭是由於咱們沒有讓curl顯示它們,若是要顯示,使用curl命令後跟-i參數:

      curl -i -XGET 'localhost:9200/'

    示例:

      ~]# curl  -XGET 'http://192.168.80.136:9200/_cat/nodes?v'  顯示字段名

      ~]# curl  -XGET 'http://192.168.80.129:9200/_cat/nodes?help'   顯示幫助信息

    Note:ES有不少的API具體參見官網https://www.elastic.co/guide/en/elasticsearch/reference/current/rest-apis.html

  ESPlugins

    插件擴展的功能添加自定義的映射類型自定義分析器本地腳本自定義發現方式等;

    安裝插件的方式

      1.直接將插件放置到plugins目錄(/usr/share/elasticsearch/plugins)

      2.使用plugin(/usr/share/elasticsearch/bin/elasticsearch-plugin)命令進行添加插件

      有關插件的文檔https://www.elastic.co/guide/en/elasticsearch/plugins/7.3/index.html   https://www.elastic.co/guide/en/kibana/current/kibana-plugins.html

 

  Logstash:負責數據的收集

    官網簡介https://www.elastic.co/guide/en/logstash/current/introduction.html

    能夠經過Agent在各個產生日誌的服務器上收集數據而後再經過Agent將數據統一發送到Logstash服務器中進行統一處理再存儲到ElasticSearch

    支持多種數據獲取機制經過TCP/UDP協議文件、syslog、Windows EventLogsSTDIN;獲取到數據後,它還支持對數據進行過濾修改等操做;

    使用JRuby語言開發所以安裝環境須要JVM;

    Logstash的許多功能都是使用插件完成的因此Logstash必須加載各類插件從而完成其各類功能

      插件類型輸入插件編碼插件過濾插件輸出插件

      工做流程:input|filter|output

      各類插件https://www.elastic.co/guide/en/logstash-versioned-plugins/current/index.html

 

    安裝Logstash:

      1.環境搭建

        安裝JDK(前面已經介紹了,就不贅述了!)

      2.下載軟件包並安裝

        下載地址https://www.elastic.co/cn/downloads/logstash

        ~]# yum install ./logstash-7.3.0.rpm

      3.測試

        ~]# /usr/share/logstash/bin/logstash -e 'input { stdin { } } output { stdout {} }'

 

        Ctrl+D退出

      更多參數https://www.elastic.co/guide/en/logstash/current/running-logstash-command-line.html

      4.配置文件:/etc/logstash/以及/etc/logstash/conf.d/(自定義的配置信息建議放在這裏且以".conf"結尾

        配置文件的框架

          input {

            ……

          }

          filter {

            ……

          }

          output {

            ……

          }

 

  Logstash的插件

    input插件

      file:從指定的文件中讀取事件流;使用FileWatchRuby Gem)監視文件是否變化且能夠同時監視多個文件,還能夠保存文件的讀取位置,以方便之後接着讀取(存儲在.sincedb,其記錄了每一個被監視的文件的inode、major、minornumberpos);

        默認以單行數據爲一個事件做爲一次讀取可是能夠經過編碼器將文本中的多行合併成一行進行一次讀取

      示例

        ~]# cat /etc/logstash/conf.d/file.conf

        input {

          file {

            path => ["/var/log/messages"]

            type => "system"

            start_position => "beginning"

          }

        }

 

        output {

          stdout {

            codec => rubydebug

          }

        }

        ~]# /usr/share/logstash/bin/logstash -f /etc/logstash/conf.d/file.conf

          運行此命令就會將/var/log/messages中全部的信息都輸出到STDOUT

      udp:經過udp協議從網絡鏈接讀取Message其必備的參數爲port(本身監聽的端口號)和host(本身監聽的地址);

        若是使用udp做爲輸入插件則在被收集端還應該有一個與其對應的軟件來完成將其數據主動發送到收集端Logstash端)中,可使用nc或者collectd(位於epel源中)中的network插件(經過Server配置段指定Logstash的地址便可)完成相應的功能;固然還有不少其餘的軟件可使用;

          Note:Logstashinput{}要使用collectd專用的編碼器(codec => collectd {});

 

 

      redis插件

        從redis讀取數據,支持redis channellists兩種方式

      filter插件

        用於在將event(事件)經過output發出以前對其進行某些處理操做;

      grok插件

        用於分析並結構化文本數據的插件;是Logstash中將非結構日誌數據轉化爲結構化可查詢數據的不二之選;

        結構化方式

          經過將數據的各個字段進行從新命名來實現數據的結構化好比apache的日誌其中字段依次是客戶端的IP地址用戶訪問時間方法、URL、版本狀態碼大小、referer以及客戶端代理;grok就是經過將各個字段定義爲某個名稱,而後在輸出時用各個鍵值對錶示其數據結構形式;

          ip => 192.168.80.123

          user => liubocheng

          ……

        文件/usr/share/logstash/vendor/bundle/jruby/2.5.0/gems/logstash-patterns-core-4.1.2/patterns/grok-patterns中就包含了其支持的各類形式而且也支持自定義格式

 

 

      output插件

        redis插件

        示例

          1.配置redis.conf

            vim /etc/redis.conf

              port 6379

              bind 0.0.0.0

          2.配置被收集端的Logstash

            ~]# cat /etc/logstash/conf.d/redis.conf

            input {

              file {

                path => ["/var/log/messages"]

                type => "system"

                start_position => "beginning"

              }

            }

 

            output {

              redis {

                port => "6379"

                host => ["127.0.0.1"]

                data_type => "list"

                key => "logstash-%{type}"

              }

            }

          3.配置收集端的Logstash

            ~]# cat /etc/logstash/conf.d/redis.conf

            input {

              redis {

                port => "6379"

                host => "192.168.80.129"

                data_type => "list"

                key => "logstash-system"

              }

            }

 

            output {

              stdout {

                codec => rubydebug

              }

            }

          4.在收集端執行命令進行測試

            ~]# /usr/share/logstash/bin/logstash -f /etc/logstash/conf.d/redis.conf

          5.將收集的數據存儲到ES

            ~]# cat /etc/logstash/conf.d/redis.conf

            input {

              redis {

                port => "6379"

                host => "192.168.80.129"

                data_type => "list"

                key => "logstash-system"

              }

            }

 

            filter {

                mutate {

                    rename => { "[host][name]" => "host" }

                }

            }

            output {

              elasticsearch {

                hosts => ["192.168.80.129:9200"]

                id => "redis"

                index => "logstash-%{+YYYY.MM.dd}"

              }

            }

          Notelumberjack能夠代替客戶端的Logstash做爲發送數據的Agent,由於Logstash做爲客戶端Agent過重量級了;

 

      安裝Kibana:

        1.下載並安裝軟件包

          https://www.elastic.co/cn/downloads/kibana

          ~]# yum install ./kibana-7.3.0-x86_64.rpm -y

        2.配置文件

          ~]# vim /etc/kibana/kibana.yml

            server.port: 5601

            server.host: "node2.guowei.com"    

              指定Kibana服務器將綁定到的地址。IP地址和主機名都是有效值。要容許來自遠程用戶的鏈接

            server.name: "node2.guowei.com"   

              指定節點名稱能夠是任意字符

            elasticsearch.hosts: ["http://node2.guowei.com:9200"]

              指定ES的監聽地址

            kibana.index: ".mykibana"   

              KibanaElasticsearch中使用索引來存儲保存的搜索、可視化和儀表盤。若是索引不存在,Kibana將建立一個新索引。

            xpack.security.enabled: false   

              配置kibana的安全機制,測試時能夠關閉。

        3.啓動Kibana

          systemctl start kibana.service

        4.在瀏覽器中鍵入http://192.168.80.129:5601便可鏈接至Kibana

 

      借鑑文章:https://es.xiaoleilu.com/index.html

 

      根據馬哥視頻作的學習筆記,若有錯誤,歡迎指正;侵刪

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息