Ingress(Nginx)日誌持久化與可視化(多圖預警)

Ingress(Nginx)日誌持久化與可視化(多圖預警)

[toc]php

前言

早期咱們一般會使用goaccess或awstat來對nginx等訪問日誌進行分析和統計,但隨着統計分析的多樣性以及後續訪問日誌的實時監控等定製化的需求愈來愈強烈,goaccess或awstat愈來愈不能知足咱們的需求.因此咱們急迫須要更加靈活的日誌統計分析工具,能輔助咱們對訪問日誌進行統計、分析和監控.這時候,隨着elk/efk的普遍應用,nginx等訪問日誌也將歸入到elk體系當中,同時elk也能知足咱們對日誌的統計與分析、監控的多樣化需求.

先上圖
Alt text
Alt text
Alt text
Alt text
Alt textnginx

部署架構

如圖,如下是1個很簡單的架構,也沒有作緩衝和聚合,若是對日誌的要求比較高,能夠在中間加入redis或Kafka 等.redis

Alt text

爲何ingress或者nginx的日誌要轉換成json格式呢?
我這邊簡單的解釋一下:,主要是2個緣由:
1:便於結合elasticseach作實時監控和報警.
好比直接監控status字段,若是1分鐘連續出現20次4XX報錯就直接報警,若是不轉換的化,你還須要進一步解析access日誌,這樣帶來了不少的不便.
2:便於結合elk作可視化分析.
能夠組合不一樣的字段,對不一樣的需求定製不一樣的可視化報表.json

部署步驟

1、ingress持久化步驟

1. 自建kubernetes的ingress持久化

ingress部署參考: https://www.pvcreate.com/index.php/archives/205/
Alt textvim

(1) ingress添加PVC用於ingress日誌存儲

kubectl apply -f ingress-nfs.yamlsegmentfault

apiVersion: v1      
kind: PersistentVolumeClaim      
metadata:      
  name: ingress-nfs      
spec:      
  accessModes:      
  - ReadWriteMany      
  resources:      
    requests:      
      storage: 10Gi      
  storageClassName: nfs-client-local

Alt text

(2) ingress添加掛載

kubectl edit deployments.apps ingress-nginx-controller後端

......      
        volumeMounts:      
        - mountPath: /data/log/ingress/      
          name: ingress-nfs      
      ......      
      volumes:      
      - name: ingress-nfs      
        persistentVolumeClaim:      
          claimName: ingress-nfs
(3) ingress修改日誌格式和存儲位置

kubectl edit configmaps ingress-nginx-controllerapi

access-log-path: /data/log/ingress/access_$hostname.log      
  error-log-path: /data/log/ingress/error.log      
  log-format-upstream: '{"@timestamp": "$time_iso8601","remote_addr": "$remote_addr","x-forward-for":      
    "$proxy_add_x_forwarded_for","request_id": "$req_id","remote_user": "$remote_user","bytes_sent":      
    $bytes_sent,"request_time": $request_time,"status": $status,"vhost": "$host","request_proto":      
    "$server_protocol","path": "$uri","request_query": "$args","request_length": $request_length,"duration":      
    $request_time,"method": "$request_method","http_referrer": "$http_referer","http_user_agent":      
    "$http_user_agent","upstream-sever":"$proxy_upstream_name","proxy_alternative_upstream_name":"$proxy_alternative_upstream_name","upstream_addr":"$upstream_addr","upstream_response_length":$upstream_response_length,"upstream_response_time":$upstream_response_time,"upstream_status":$upstream_status}'
2. 阿里雲kubernetes的ingress持久化

因爲阿里雲kubernetes上的ingress默認已經部署,同時官方也是建議使用AliyunLogConfig自動接入日誌服務和可視化.咱們考慮到自定義以及其餘緣由,採用了自定義接入ingress日誌存儲,也就是說將ingress存儲到nas中,同時發送到elasticsearch中.架構

Alt text

(1) 經過阿里雲控制檯爲ingress添加nas存儲

Alt text
Alt text
Alt text

(2) ingress添加掛載

kubectl edit deployments.apps -n kube-system nginx-ingress-controller併發

...      
        volumeMounts:      
        - mountPath: /data      
          name: nfs-oss      
...      
      volumes:      
      - name: nfs-oss      
        persistentVolumeClaim:      
          claimName: ingress-log
(3) ingress修改日誌格式和存儲位置

kubectl edit configmaps ingress-nginx-controller
修改內容和上面自建kubernetes的ingress一致,須要注意的是若是ingress的日誌路徑定義爲/data/log/ingress/access.log,必定要注意掛載的目錄要存在,也就是說你在修改configmaps以前要確保/data/log/ingress提早建立,能夠進入pod中建立,也能夠在外部建立好.

2、Nginx日誌格式修改

除了ingress之外,若是你的nginx也須要同步推送到elasticsearch中的話,也須要修改nginx的日誌格式爲json,值得注意的是有部分參數ingress和nginx是不一致的,好比ingress中支持req_id而nginx中沒有該參數.同時如下參數是添加到nginx.conf的http全局參數當中,添加在server段中無效的.
vim nginx.conf

log_format json '{"@timestamp": "$time_iso8601","remote_addr": "$remote_addr","x-forward-for":"$proxy_add_x_forwarded_for","remote_user": "$remote_user","bytes_sent":$bytes_sent,"request_time": $request_time,"status": $status,"vhost": "$host","request_proto":"$server_protocol","path": "$uri","request_query": "$args","request_length": $request_length,"duration":$request_time,"method": "$request_method","http_referrer": "$http_referer","http_user_agent":"$http_user_agent","upstream_addr":"$upstream_addr","upstream_response_length":$upstream_response_length,"upstream_response_time":$upstream_response_time,"upstream_status":"$upstream_status"}';      
      
        access_log  /data/log/nginx/access.log  json;

3、filebeat解析Ingress/Nginx日誌

filebeat的安裝很簡單,這邊就不作贅述,我這邊主要貼下filebeat的配置文件.
filebeat.yml

setup.template.name: "local-app"      
setup.template.pattern: "local-app-*"      
setup.template.enabled: true      
setup.ilm.enabled: false      
filebeat.config:      
  inputs:      
    path: /data/www/apps/filebeat/inputs.d/*.yml      
    reload.enabled: true      
    reload.period: 10s      
  modules:      
    path: /data/www/apps/filebeat/modules.d/*.yml      
    reload.enabled: false      
output.elasticsearch:      
  protocol: "https"      
  ssl.verification_mode: none      
  hosts: ['192.168.1.100:9200']      
  username: "elastic"      
  password: "123456"      
  index: "local-app-%{[fields.appName]}-%{+yyyy.MM.dd}"

nginx_ingress.yml

- type: log      
      
    enable: true      
    tail_files: true      
    # 若是設置爲true,Filebeat從文件尾開始監控文件新增內容,把新增的每一行文件做爲一個事件依次發送,      
    # 而不是從文件開始處從新發送全部內容      
    paths:      
      - /data/log/nginx/access*.log      
    tags: [app, nginx-local]      
    fields:      
      appName: nginx-local      
      
    json.keys_under_root: true      
    #keys_under_root可讓字段位於根節點,默認爲false      
        
    json.overwrite_keys: true      
    #對於同名的key,覆蓋原有key值      
        
    json.message_key: message      
    #message_key是用來合併多行json日誌使用的,若是配置該項還須要配置multiline的設置,後面會講      
      
    json.add_error_key: true      
    #將解析錯誤的消息記錄儲存在error.message字段中      
        
    json.ignore_decoding_error: true      
    #用於指定是否JSON解碼錯誤應該被記錄到日誌中。若是設爲true,錯誤將被記錄

要注意的是,若是配置了multiline,會開啓合併多條json日誌的功能,若是不須要該功能請務必注釋掉該yml中關於multiline的配置。(因爲我在nginx/ingress中的access的json日誌都是一行,因此在nginx日誌當中不須要配置multiline配置)
multiline配置:

#將'['做爲新的一行的標識,若是message中不碰到'[',則合併爲一條日誌      
  multiline.pattern: ^\[      
  multiline.negate: true      
  multiline.match: after

同時配置:

processors:      
      - decode_json_fields:      
          fields: ['message']      
          target: json

4、kibana接入elasticsearch與可視化配置

kibana的安裝配置此處再也不說明.
添加索引按照界面一步步操做便可.
Alt text
Alt text

幾個典型圖形配置示例
Alt text

(1)PV
Alt text
(2)UV
Alt text
(3)Top10(接口訪問量)
Alt text
Alt text
(4)Top10(客戶端IP訪問佔比)
Alt text
Alt text
(5)Top10(最慢接口)
Alt text
Alt text
(6)後端upstream佔比
Alt text
Alt text
(7)實時流量
Alt text
Alt text
(8)客戶端訪問佔比
Alt text
Alt text
(9)平均併發數
Alt text
Alt text
(10)異常狀態碼統計
Alt text
Alt text
Alt text
(11)總流量
Alt text
(12)接口異常響應碼
Alt text
Alt text
Alt text
(13)接口訪問耗時佔比
Alt text
Alt text
Alt text
(14)每10秒接口訪問平均耗時
Alt text
Alt text
(15)每10秒接口訪問最大耗時
Alt text
Alt text
(16)狀態碼統計
Alt text
Alt text
(17)訪問量趨勢圖
Alt text
Alt text
(18)超過30秒以上的接口
Alt text
Alt text
(19)超過30秒以上的接口出現次數
Alt text
Alt text
Alt text

5、踩坑指南

可視化Metrics沒法獲取耗時(duration)字段

Top10(最慢接口)舉例,獲取Top10耗時最慢的url組成1個表格,可是我在Metrics怎麼都找不到duration字段或者request_time字段,經過排查得知,Metrics字段通常是數值型字段,對數值型字段求和、求最大值、求平均值等.可是我在ingress定義的字段都是字符串,因此同步到elasticsearch中也是字符串,因此在kibana的Metrics中也沒法找到duration字段.既然找到問題癥結了,咱們就開始修正.從新修改ingress的confimap配置,從新在kibana添加索引.固然添加索引以前,我先刪除了原來的索引從新添加.固然這個方法比較粗暴!!還有其餘方法能夠解決.
(1)若是是logstash可使用mutate對字段進行轉換

mutate {       
 convert => ["name-of-field", "integer"]       
}

(2)官方沒有提供字符串轉數值,但咱們能夠建立1個新的索引,同時把原來的elasticsearch格式化數值後導入便可.

#建立新索引並格式化duration字段      
curl -H 'Content-Type: application/json' -XPUT "http://localhost:9200/ingress_new"      
curl  -H 'Content-Type: application/json' -XPOST "http://localhost:9200/ingress_new/ingress_old/_mapping?pretty" -d '       
{      
    "ingress_old": {      
            "properties": {      
                "duration": {      
                    "type": "double",      
                    "store": "true",      
                    "ignore_malformed": "true"      
                }      
            }      
        }      
  }      
      
#從舊索引中導入數據      
curl  -X POST "localhost:9200/_reindex" -H 'Content-Type: application/json' -d'      
{      
  "source": {      
    "index": "ingress_old"      
    "size": 5000      
  },      
  "dest": {      
    "index": "ingress_new"      
    "routing": "=cat"      
  }      
}'
相關文章
相關標籤/搜索