簡單的ELK搭建

1. 前言

針對nginx的訪問日誌需要進行一個近實時的監控,以便統計用戶的訪問情況,包括用戶的請求IP,請求數據等。因爲服務器是和負載均衡用的是阿里雲的,阿里雲本身也有提供針對負載均衡的日誌統計功能,但是作爲一個通用日誌其是有嚴重缺陷的:

  • 無法收集用戶自定義的請求頭(我們的實際情況是通過一個自定義的請求頭來做用戶的身份識別,請求頭有用戶的唯一識別信息
  • 無法獲取到用戶的請求數據($request_body) (很多時候,當出現異常訪問的時候,是需要通過查詢用戶的訪問數據的,特別像搜索這種業務模塊時

由於存在上面比較嚴重的缺點,基本上阿里雲的日誌對我來說就有點雞肋(食之無味,棄之可惜,你不得不同意他除了上面兩點缺點外,日誌的其他方面都是做得不錯的)。因此我決定自己動手搭建符合自己業務的ELK日誌服務。

之前我是有搭建過ELK的經驗的,但是沒在生產環境試過,起初在搭建的時候我考慮到可能會有以下幾個問題:

  1. Elasticsearch對內存的佔用情況
  2. 收集nginx訪問日誌,相當於需要打開nginx的access日誌開關,硬盤的讀寫情況,硬盤的佔用,會不會影響到用戶。
  3. 日誌收集對應用服務器的影響

我現在還是在一兩臺服務器開啓了日誌收集,做一個灰度測試。

2. Elasticsearch搭建

2.1 Elasticsearch下載安裝

Elasticsearch的安裝比較簡單,直接下載解壓縮即可

  • 官網地址:https://www.elastic.co/cn/downloads/elasticsearch
### 下載
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.4.2-linux-x86_64.tar.gz

### 解壓縮:
tar -zxvf elasticsearch-7.4.2-linux-x86_64.tar.gz

2.2 Elasticsearch配置

1. 修改cluster-name和node-name

cluster.name: my-application
node.name: node-1
node.master: true
node.data: true

2. 修改網絡相關

network.host: 0.0.0.0  ## 0.0.0.0允許所有的ip,這裏我是爲了方便,後面可以根據實際情況填寫
http.port: 9200  ## default
transport.tcp.port: 9300  ## defalut

在這裏插入圖片描述

3. 修改head插件的跨域問題

# 以下的兩個配置是爲了解決跨域問題,在head插件訪問es的時候報跨域了
http.cors.enabled: true
http.cors.allow-origin: "*"

4. 發現配置

# Pass an initial list of hosts to perform discovery when this node is started:
# The default list of hosts is ["127.0.0.1", "[::1]"]
discovery.seed_hosts: ["192.168.1.57"]  ## 可被發現的節點IP集合
cluster.initial_master_nodes: ["node-1", "node-2"]

5. 解決es啓動時的報錯問題,.ElasticSearch集羣啓動錯誤,錯誤的原因是:因爲Centos6不支持SecComp,而ES默認bootstrap.system_call_filter爲true進行檢測,所以導致檢測失敗

bootstrap.memory_lock: false
bootstrap.system_call_filter: false

2.3 問題

1. 外網訪問不了9200的Elasticsearch?

  1. 配置防火牆端口
  2. 修改elasticsearch.yml,主要是要修改host(我改成0.0.0.0,方便調試,後期穩定之後會再修改)

2. 啓動報錯

  • vm.max_map_count過小,java虛擬機的virtual memory過小

在/etc/sysctl.conf最後加入一行vm.max_map_count=262144數量根據實際情況定
在這裏插入圖片描述

  • max user threads過小(root和dves兩個用戶的max user threads不一樣)

針對這個問題,可以通過ulimit -a查看目前可支持的max user threads
在這裏插入圖片描述

修改 max user process

Linux系統爲每一個用戶都設置了一個最大進程數,這個特性可以讓我們控制服務器上現有用戶可以創建的進程數量

  1. 修改方式1:

修改/etc/security/limits.conf文件,添加以下配置

## 針對所有用戶的可開啓最大線程數爲4096
*  soft      nproc      4096
*  hard      nproc      4096
  1. 修改方式2:

修改/etc/security/limits.d/90-nproc.conf文件,添加以下配置(先把其他默認的給註釋掉):

*          soft    nproc     4096  ## 非root用戶配置爲4096,這個對es來說夠用了
root       soft    nproc     unlimited  ## root用戶配置最大 128354

針對這兩種修改方式解釋下,我是在 /etc/security/limits.d/90-nproc.conf這個文件下修改的。對於max user process的配置,Linux系統默認先讀取/etc/security/limits.conf中的信息,如果/etc/security/limits.d/目錄下還有配置文件的話,也會依次遍歷讀取,最終/etc/security/limits.d/的配置會覆蓋/etc/security/limits.conf的相同配置信息

3. FileBeat搭建

3.1 Filebeat下載安裝

curl -L -O https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-7.4.2-x86_64.rpm

rpm -vi filebeat-7.4.2-x86_64.rpm

安裝完成,filebeat命令已配置到service服務中,配置文件在/etc/filebeat,日誌文件在/var/log/filebeat/filebeat,注意,每次重啓filebeat的時候,該日誌文件都會重新生成,這個時候若如果你是通過tail命令來觀察的,需要結束當前的tail命令再重複執行一次tail命令 tail -900f filebeat

3.2 Filebeat收集nginx訪問日誌

3.2.1 nginx的訪問日誌格式及配置

nginx訪問日誌是如何配置的,我這裏不細說,我只是說下我是如何配置的,如果對nginx的訪問日誌配置不熟悉的,可以查看這個:ngx_http_log_module

1. 日誌格式

因爲我們最終要通過Kibana進行展示的,我們需要對訪問日誌的每個字段都進行解析,所以我們就需要確定nginx的日誌是json格式的

## 這個是寫在http模塊的
log_format json_main  '{"@times" : "$time_iso8601",' ## 該time作爲Kibana的date類型,在創建Kibana的index_pattern時作爲時間篩選的key
                        '"userAgent" : "$http_user_agent",'
                        '"remoteAddr" : "$remote_addr", '
                        '"realIp" : "$http_x_forwarded_for", '
                        '"requestUri" : "$request", '
                        '"status" : "$status", '
                        '"referer" : "$http_referer", '
                        '"requestTime" : "$request_time", '
                        '"requestBody" : "$request_body", '  ## 請求數據
                        '"domoCustom" :  "$http_domo_custom"}';  ## 自定義請求頭
2. 打開請求日誌

對map模塊有興趣的可以查看這裏:ngx_http_map_module

## 這個在server模塊
access_log /opt/nginx/logs/requestLog.log  json_main  if=$myUri;

## /opt/nginx/logs/requestLog.log:這個是日誌收集的地方,若該日誌不存在,在reload或重啓nginx的是,會自動創建
## json_main:`log_format`定義的日誌格式名
## if=$myUri:一個判斷,如果`$myUri`爲0或者空字符串,則該日誌不收集。這個的作用可以過濾掉一些我們不想收集的日誌信息,我是根據請求頭來設置的。

## 這個寫在http模塊,使用map這個內置模塊,可以通過判斷`$request`這個
## 內置變量是否符合下面的判斷,然後把0或1賦值給`$myUri`.
## 這裏我的用法就是,如果是OPTIONS請求爲0不記錄日誌信息,
## 如果是`/api/qiqyu`這個第三方的請求也爲0不記錄日誌信息
## 其他的`/api/`正則的則爲1記錄日誌信息
## 非上面集中情況的一律爲0不記錄相應的日誌信息
 map $request $myUri {
       ~OPTIONS 0;
       ~/api/qiyu/ 0;
       ~/api/ 1;
       default 0;
  }

reloadnginx之後就能在/opt/nginx/logs/requestLog.log這個文件夾下看到相應的日誌了
在這裏插入圖片描述

3.3 Filebeat配置

3.3.1 基本配置文件配置

在這裏插入圖片描述

vim /etc/filebeat/filebeat.yml 
1. Filebeat inputs
- type: log

  # Change to true to enable this input configuration.
  enabled: true  ## 打開開關
  exclude_lines: ['^DBG']  ## 忽略的行
  # Paths that should be crawled and fetched. Glob based paths.
  paths:
    #- /var/log/*.log
    - /opt/nginx/logs/requestLog.log  ## 配置從哪裏按行讀取日誌
        #- c:\programdata\elasticsearch\logs\*
  ## 如果要讓filebeat輸入json格式的數據,除了nginx的日誌本身是json格式
  ## 的外,還必須在filebeat中配置一下設置
  json.keys_under_root: true
  json.overwrite_keys: true
  json.add_error_key: true
  json.message_key: message  ## 如果message在啓動的時候報錯,可以改成"json"(帶雙引號)	
2. Elasticsearch template setting
setup.ilm.enabled: false  ## 這個必須要配置成false,否則自定義index就不會生效
setup.template.enabled: false  ## 關掉filebeat默認的es模板
setup.template.overwrite: true ## 表示我們自定義的模板和index會覆蓋默認的
setup.template.fields: "/etc/filebeat/self/fields.yml"  ## 自定義的fields.yml,這個文件不熟悉的話就別瞎折騰了,我直接從原來的copy了一份而已
setup.template.name: "nginx-access-log"  ## 模板名,這個和後面要創建的es模板名保持一致
setup.template.pattern: "nginx-access-log-*"  ## 模板對應的pattern,也是對應的index,這些都是有規律的。因爲你模板名是`nginx-access-log`,則你接下來的自定義索引名就最好是`nginx-access-log-%{[agent.version]}-%{+yyyy.MM.dd}`,pattern的正則就是`nginx-access-log-*`
3. Dashboards(這個配置可不配,主要是看你的filebeat是否安裝了默認看板,這個安裝後會生效的前提是:你必須使用filebeat的默認模板,默認索引,一旦你執行了上面第二步,這裏的配置就不會生效)
setup.dashboards.enabled: true
setup.dashboards.index: "nginx-access-log-*"
4. Kibana
setup.kibana:
  host: "192.168.1.57:5601"
  # Kibana Host
  # Scheme and port can be left out and will be set to the default (http and 5601)
  # In case you specify and additional path, the scheme is required: http://localhost:5601/path
  # IPv6 addresses should always be defined as: https://[2001:db8::1]:5601
  #host: "localhost:5601"
5. Outputs(Elasticsearch)
#-------------------------- Elasticsearch output ------------------------------
output.elasticsearch:
  # Array of hosts to connect to.
  hosts: ["192.168.1.57:9200"]
  ## 這裏的index的前綴要和上面第二步配置的模板名保持一致,而且,index的名字中不能包含大寫字母,這是我的教訓來着
  index: "nginx-access-log-%{[agent.version]}-%{+yyyy.MM.dd}"
  # Optional protocol and basic auth credentials.
  #protocol: "https"
  #username: "elastic"
  #password: "changeme"

3.3.2 啓用nginx模塊

其實對於filebeat中,它提供了多個模塊,比如nginx,mysql等,這些能夠讓我們快速地上手filebeat。但是我一直搞不懂這些模塊的用途是什麼,明明我可以在filebeat.yml中配置的。nginx的模塊格式如下:

我雖然安裝了該模塊,但是該模塊我是關掉的,一方面是我對該模塊的理解不夠,我不啓用該模塊也能正常收集日誌,另一方面,開啓該模塊的時候,在收集日誌的時候會不定時地報錯Provided Grok expressions do not match field value:

# Module: nginx
# Docs: https://www.elastic.co/guide/en/beats/filebeat/7.4/filebeat-module-nginx.html

- module: nginx
  # Access logs
  access:
    enabled: false
    var.paths: ["/opt/nginx/logs/requestLog.log"]

   # Set custom paths for the log files. If left empty,
    # Filebeat will choose the paths depending on your OS.
    #var.paths:

  # Error logs
  error:
    enabled: false

    # Set custom paths for the log files. If left empty,
    # Filebeat will choose the paths depending on your OS.
    #var.paths:
安裝過程

在配置好filebeat.ymt後執行如下命令:

filebeat modules enable nginx

3.3.3 啓動filebeat模塊

filebeat setup
service filebeat start

4. Kibana搭建

4.1 Kibana下載安裝

注意:如果es是7版本,那麼kibana的版本也要是7,兩者之間的大版本要互相對應

wget https://artifacts.elastic.co/downloads/kibana/kibana-7.4.2-linux-x86_64.tar.gz

## 解壓縮後即可使用
tar -zxvf kibana-7.4.2-linux-x86_64.tar.gz

4.2 Kibana配置

vim kibana.yml
## 端口號,默認5601
#server.port: 5601
## 指定kibana指定的IP
server.host: "192.168.1.57"
## 因爲我的kibana和Elasticsearch是在同一臺機器上的,所以我不需要去配置es的IP和端口等信息,kibana會自動在本機尋找
#elasticsearch.hosts: ["http://localhost:9200"]

4.2.1 自定義Elasticsearch的template

這個template_nameindex_patterns要和前面我們在Elasticsearch中配置的一致。除了template_nameindex_patterns要修改外,還有一個要修改的地方就是mapping,這個因人而異,我覺得默認的mapping輸出太多我不需要用到的東西,所以纔去簡化的,其餘的都保持默認。新建好template後重啓filebeat即可。重啓filebeat之前建議把nginx的訪問日誌也清空掉,免得有髒數據影響

mapping信息:
{
  "_meta": {
    "beat": "filebeat",
    "version": "7.4.2"
  },
  "dynamic_templates": [
    {
      "labels": {
        "path_match": "labels.*",
        "mapping": {
          "type": "keyword"
        },
        "match_mapping_type": "string"
      }
    },
    {
      "container.labels": {
        "path_match": "container.labels.*",
        "mapping": {
          "type": "keyword"
        },
        "match_mapping_type": "string"
      }
    },
    {
      "dns.answers": {
        "path_match": "dns.answers.*",
        "mapping": {
          "type": "keyword"
        },
        "match_mapping_type": "string"
      }
    },
    {
      "fields": {
        "path_match": "fields.*",
        "mapping": {
          "type": "keyword"
        },
        "match_mapping_type": "string"
      }
    },
    {
      "docker.container.labels": {
        "path_match": "docker.container.labels.*",
        "mapping": {
          "type": "keyword"
        },
        "match_mapping_type": "string"
      }
    },
    {
      "kubernetes.labels.*": {
        "path_match": "kubernetes.labels.*",
        "mapping": {
          "type": "keyword"
        },
        "match_mapping_type": "*"
      }
    },
    {
      "kubernetes.annotations.*": {
        "path_match": "kubernetes.annotations.*",
        "mapping": {
          "type": "keyword"
        },
        "match_mapping_type": "*"
      }
    },
    {
      "docker.attrs": {
        "path_match": "docker.attrs.*",
        "mapping": {
          "type": "keyword"
        },
        "match_mapping_type": "string"
      }
    },
    {
      "cef.extensions": {
        "path_match": "cef.extensions.*",
        "mapping": {
          "type": "keyword"
        },
        "match_mapping_type": "string"
      }
    },
    {
      "kibana.log.meta": {
        "path_match": "kibana.log.meta.*",
        "mapping": {
          "type": "keyword"
        },
        "match_mapping_type": "string"
      }
    },
    {
      "strings_as_keyword": {
        "mapping": {
          "ignore_above": 1024,
          "type": "keyword"
        },
        "match_mapping_type": "string"
      }
    }
  ],
  ## 這裏是指是否要指定一個key作爲date類型來進行時間篩選,如果不爲true,
  ## 後面你就無法根據@times進行時間篩選
  "date_detection": true
}

在這裏插入圖片描述

在這裏插入圖片描述

4.2.2 devtool工具查詢

在未建立kibana的index_pattern之前,我們是無法在discover發現面板上去查看自己的數據的,這個時候我們並不着急去創建index_pattern,我們要先驗證一下日式數據是否已成功收集。打開kibana的dev tool

在這裏插入圖片描述

1. 查看目前es中的索引,確認我們的自定義索引是否已生成
get _cat/indices?v

這個索引出現了表明索引已自動生成了
在這裏插入圖片描述

2. 查看該索引目前的數據,是否符合我們預期
GET /nginx-access-log-7.4.2-2019.11.18/_search

數據結果是json格式的,而且我們需要的數據都有,符合我們的預期。
在這裏插入圖片描述

4.2.3 自定義index_pattern

在上面的步驟確認好之後,就可以創建kibana的index_pattern

在這裏插入圖片描述
在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述

4.2.3 Discover功能

選擇剛我們創建的index_pattern就可以看到和我們index_pattern格式相對應的數據了
在這裏插入圖片描述

4.2.4 Visualize功能

新建一個可視化的圖表,它裏面幫我們內嵌了多個圖表,但數據源都不是我們自定義的數據,可以參考,但是沒多大意義,我們可以自己創建。
在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述

4.2.5 Dashboard功能

多個 Visualize放在一起就是一個面板,這裏不多贅述,沒什麼技術含量

5. 參考鏈接

開始使用Filebeat
快速開始Elasticsearch
Es的官網教學
自定義index template
Filebeat自定義index的一個坑
Filebeat模塊與配置
Linux修改max user threads
ElkStack運維手冊
Es中文手冊
nginx中文地址

6. 總結

搭建這個簡單的ELK還是花費了我一些時間的,一方面主要是我太久沒接觸ES,另一方面我對filebeat和kibana一直都是一知半解的狀態。在搭建的過程中,沒有像我上面寫得那麼順利,一路磕磕碰碰,遇到很多問題,最後通過查詢大量資料加上自己的理解才終於搞定。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章