基於elk 實現nginx日誌收集與數據分析。

一。背景html

      前端web服務器爲nginx,採用filebeat + logstash + elasticsearch + granfa 進行數據採集與展現,對客戶端ip進行地域統計,監控服務器響應時間等。前端

 

二。業務總體架構:linux

      nginx日誌落地——》filebear——》logstash——》elasticsearch——》grafna(展現)nginx

三。先上個效果圖,慢慢去一步步實現git

如上只是簡單的幾個實用的例子,實際上有多維度的數據以後還能夠定製不少須要的內容,如終端ip訪問數,國家、地區佔比,訪問前十的省份,請求方法佔比,referer統計,user_agent統計,慢響應時間統計,更有世界地圖座標展現等等,只要有數據就能多維度進行展現。這裏提供模板搜索位置你們能夠查找參考:https://grafana.com/dashboardsgithub

四,準備條件web

須要具有以下條件:正則表達式

1.nginx日誌落地,須要主要落地格式,以及各個字段對應的含義。json

2.安裝filebeat。 filebeat輕量,功能相比較logstash而言比較單一。ruby

3.安裝logstash 做爲中繼服務器。這裏須要說明一下的是,起初設計階段並無計劃使用filebeat,而是直接使用logstash發往elasticsearch,可是當前端機數量增長以後logstash數量也隨之增長,同時發往elasticsearch的數量增大,logstash則會拋出因爲elasticsearch 限制致使的錯誤,你們遇到後搜索相應錯誤的代碼便可。爲此只採用logstash做爲中繼。

4.elasticsearch 集羣。坑點是index templates的建立會影響新手操做 geoip模塊。後文會有。

5.grafana安裝,取代傳統的kibana,grafana有更友好、美觀的展現界面。

 

五。實現過程

1.nginx日誌落地配置

  nginx日誌格式、字段的內容和順序都是高度可定製化的,將須要收集的字段內容排列好。定義一個log_format

  定義的形勢實際上直接決定了logstash配置中對於字段抽取的模式,這裏有兩種可用,一種是直接在nginx日誌中拼接成json的格式,在logstash中用codec => "json"來轉換,

  一種是常規的甚至是默認的分隔符的格式,在logstash中須要用到grok來進行匹配,這個會是相對麻煩些。兩種方法各有優勢。直接拼接成json的操做比較簡單,可是在轉碼過程當中

  會遇到諸如 \x 沒法解析的狀況。 這裏我也遇到過,若有必要後續會詳談。採用grok來匹配的方法相對難操做,可是準確性有提高。咱們這裏採用的是第一種方法,下面logstash部分

  也會給出採用grok的例子。   nginx日誌中日誌格式定義以下:

 

log_format access_json   '{"timestamp":"$time_iso8601",'
                        '"hostname":"$hostname",'
                        '"ip":"$remote_addrx",'
                        '"request_method":"$request_method",'
                        '"domain":"XXXX",'
                        '"size":$body_bytes_sent,'
                        '"status": $status,'
                        '"responsetime":$request_time,'
                        '"sum":"1"'
                        '}';

 

2.filebeat配置文件

   關於filebeat更多內容請參考https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-overview.html

   配置文件內容:filebeat.yml  這裏應該不會遇到坑。

filebeat.prospectors:
- input_type: log
  paths:
    - /data0/logs/log_json/*.log      #nginx日誌路徑

output.logstash:
    hosts: ["xxxx.xxxx.xxxx.xxx:12121"]   #logstash 服務器地址

  

3.logstahs配置文件內容:

這裏是針對json已經拼接號,直接進行json轉碼的狀況:

須要注意以下:

   1)date模塊必須有,不然會形成數據沒法回填致使最終的圖像出現鋸齒狀影響穩定性(緣由是排列時間並非日誌產生的時間,而是進入logstash的時間)。這裏後面的  yyyy-MM-dd'T'HH:mm:ssZZ   須要根據你日誌中的日期格式進行匹配匹配規則見:https://www.elastic.co/guide/en/logstash/current/plugins-filters-date.html  

 2)須要說明的是我下面去掉了好多的字段(remove_field),緣由是咱們數據量大,es服務器有限。 能夠根據須要隨時調整收集的字段。

 3)  geoip 僅須要指定源ip字段名稱便可,fields並非必須的,我加入的緣由仍是因爲資源有限致使的。

input {
    beats {
    port => 12121
    host => "10.13.0.80"
    codec => "json"
    }
}

filter {
    date {
      match => [ "timestamp", "yyyy-MM-dd'T'HH:mm:ssZZ" ]
      #timezone => "Asia/Shanghai"
      #timezone => "+00:00"
    }
    mutate {
      convert => [ "status","integer" ]
      convert => [ "sum","integer" ]
      convert => [ "size","integer" ]
      remove_field => "message"
      remove_field => "source"
      remove_field => "tags"
      remove_field => "beat"
      remove_field => "offset"
      remove_field => "type"
      remove_field => "@source"
      remove_field => "input_type"
      remove_field => "@version"
      remove_field => "host"
      remove_field => "client"
      #remove_field => "request_method"
      remove_field => "size"
      remove_field => "timestamp"
      #remove_field => "domain"
      #remove_field => "ip"
    }
    geoip {
      source => "ip"
      fields => ["country_name", "city_name", "timezone","region_name","location"]
    }
}

output {
    elasticsearch {
       hosts => ["xxx:19200","xxx:19200","xxx:19200"]
       user => "xxx"
       password => "xxx"
       index => "logstash-suda-alllog-%{+YYYY.MM.dd}"
       flush_size => 10000
       idle_flush_time => 35
    }
}

  下面給出一個採用grok的例子:

       其中match內的內容不用參考個人,須要根據你的字段個數,以及格式來定製。 這裏實際上是正則表達式。自帶了一部分幾乎就能夠知足全部的需求了無需本身寫了,能夠參考:https://github.com/elastic/logstash/blob/v1.4.0/patterns/grok-patterns  直接用便可。

input {
  file {
  type => "access"
  path => ["/usr/local/nginx/logs/main/*.log"]
  }
}
 
filter {
  if [type] == "access" {
  if [message] =~ "^#" {
    drop {}
  }
 
 
  grok {
    match => ["message", "\[%{HTTPDATE:log_timestamp}\] %{HOSTNAME:server_name} \"%{WORD:request_method} %{NOTSPACE:query_string} HTTP/%{NUMBER:httpversion}\" \"%{GREEDYDATA:http_user_agent}\" %{NUMBER:status} %{IPORHOST:server_addr} \"%{IPORHOST:remote_addr}\" \"%{NOTSPACE:http_referer}\" %{NUMBER:body_bytes_sent} %{NUMBER:time_taken} %{GREEDYDATA:clf_body_bytes_sent} %{NOTSPACE:uri} %{NUMBER:m_request_time}"]
  }
 
 
  date {
    match => [ "log_timestamp", "dd/MMM/yyyy:mm:ss:SS Z" ]
    timezone => "Etc/UTC"
  }
     
  mutate {
  convert => [ "status","integer" ]
  convert => [ "body_bytes_sent","integer" ]
  convert => [ "m_request_time","float" ]
  }

 在提供一個高級的用法:

 ruby:強大的模塊, 能夠進行諸如時間轉換,單位計算等,多個能夠用分號隔開。

  ruby {
  code => "event.set('logdateunix',event.get('@timestamp').to_i);event.set('request_time', event.get('m_request_time') / 1000000 )"  
  }
 
  mutate {
   add_field => {
        "http_host" => "%{server_name}"
        "request_uri" => "%{uri}"
        }

在windowns上使用lgostsh須要注意的是:(win上收集iis的日誌,我想正常環境是不會用到的,可是我確實用到了。。。。。。)

path路徑必定要採用 linux中的分割符來拼接路徑,用win的格式則正則不能實現,你們能夠測試下。其餘配置則無區別。

input {
  file {
    type => "access"
    path => ["C:/WINDOWS/system32/LogFiles/W3SVC614874788/*.log"]
  }
}

 

4.elasticsearch配置,集羣的安裝以及啓動,調優這裏很少說(說不完),須要注意的一個是,geoip location的格式,我這裏採用的是index templates來實現的以下:

最重要的是 "location" 定義 (不然geoip_location字段格式有問題,沒法拼接成座標),其餘能夠根據狀況自定:

{
  "order": 0,
  "version": 50001,
  "index_patterns": [
    "suda-*"
  ],
  "settings": {
    "index": {
      "number_of_shards": "5",
      "number_of_replicas": "1",
      "refresh_interval": "200s"
    }
  },
  "mappings": {
    "_default_": {
      "dynamic_templates": [
        {
          "message_field": {
            "path_match": "message",
            "mapping": {
              "norms": false,
              "type": "text"
            },
            "match_mapping_type": "string"
          }
        },
        {
          "string_fields": {
            "mapping": {
              "norms": false,
              "type": "text",
              "fields": {
                "keyword": {
                  "ignore_above": 256,
                  "type": "keyword"
                }
              }
            },
            "match_mapping_type": "string",
            "match": "*"
          }
        }
      ],
      "properties": {
        "@timestamp": {
          "type": "date"
        },
        "geoip": {
          "dynamic": true,
          "properties": {
            "ip": {
              "type": "ip"
            },
            "latitude": {
              "type": "half_float"
            },
 "location": { "type": "geo_point" },
            "longitude": {
              "type": "half_float"
            }
          }
        },
        "@version": {
          "type": "keyword"
        }
      }
    }
  },
  "aliases": {}
}

  

5   grafana 安裝以及模板建立,這個比較簡單,安裝完直接寫語句便可附一個例子以下:

 

這裏的變量須要自定義:

 

 經過上面應該可以完成一個完整的收集和展現狀況,這裏實際上提供了一種可行的方法,並麼有太大的具體操做。

 但願多多交流

推薦內容:kibana中文指南(有ibook版本,看着挺方便) 三斗室著

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

       https://grafana.com/dashboards

       https://grafana.com/

相關文章
相關標籤/搜索