[toc]php
早期咱們一般會使用goaccess或awstat來對nginx等訪問日誌進行分析和統計,但隨着統計分析的多樣性以及後續訪問日誌的實時監控等定製化的需求愈來愈強烈,goaccess或awstat愈來愈不能知足咱們的需求.因此咱們急迫須要更加靈活的日誌統計分析工具,能輔助咱們對訪問日誌進行統計、分析和監控.這時候,隨着elk/efk的普遍應用,nginx等訪問日誌也將歸入到elk體系當中,同時elk也能知足咱們對日誌的統計與分析、監控的多樣化需求.
先上圖
nginx
如圖,如下是1個很簡單的架構,也沒有作緩衝和聚合,若是對日誌的要求比較高,能夠在中間加入redis或Kafka 等.redis
爲何ingress或者nginx的日誌要轉換成json格式呢?
我這邊簡單的解釋一下:,主要是2個緣由:
1:便於結合elasticseach作實時監控和報警.
好比直接監控status字段,若是1分鐘連續出現20次4XX報錯就直接報警,若是不轉換的化,你還須要進一步解析access日誌,這樣帶來了不少的不便.
2:便於結合elk作可視化分析.
能夠組合不一樣的字段,對不一樣的需求定製不一樣的可視化報表.json
ingress部署參考: https://www.pvcreate.com/index.php/archives/205/ vim
kubectl apply -f ingress-nfs.yaml
segmentfault
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: ingress-nfs spec: accessModes: - ReadWriteMany resources: requests: storage: 10Gi storageClassName: nfs-client-local
kubectl edit deployments.apps ingress-nginx-controller
後端
...... volumeMounts: - mountPath: /data/log/ingress/ name: ingress-nfs ...... volumes: - name: ingress-nfs persistentVolumeClaim: claimName: ingress-nfs
kubectl edit configmaps ingress-nginx-controller
api
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}'
因爲阿里雲kubernetes上的ingress默認已經部署,同時官方也是建議使用AliyunLogConfig自動接入日誌服務和可視化.咱們考慮到自定義以及其餘緣由,採用了自定義接入ingress日誌存儲,也就是說將ingress存儲到nas中,同時發送到elasticsearch中.架構
kubectl edit deployments.apps -n kube-system nginx-ingress-controller
併發
... volumeMounts: - mountPath: /data name: nfs-oss ... volumes: - name: nfs-oss persistentVolumeClaim: claimName: ingress-log
kubectl edit configmaps ingress-nginx-controller
修改內容和上面自建kubernetes的ingress一致,須要注意的是若是ingress的日誌路徑定義爲/data/log/ingress/access.log
,必定要注意掛載的目錄要存在,也就是說你在修改configmaps以前要確保/data/log/ingress
提早建立,能夠進入pod中建立,也能夠在外部建立好.
除了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;
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
kibana的安裝配置此處再也不說明.
添加索引按照界面一步步操做便可.
幾個典型圖形配置示例
(1)PV
(2)UV
(3)Top10(接口訪問量)
(4)Top10(客戶端IP訪問佔比)
(5)Top10(最慢接口)
(6)後端upstream佔比
(7)實時流量
(8)客戶端訪問佔比
(9)平均併發數
(10)異常狀態碼統計
(11)總流量
(12)接口異常響應碼
(13)接口訪問耗時佔比
(14)每10秒接口訪問平均耗時
(15)每10秒接口訪問最大耗時
(16)狀態碼統計
(17)訪問量趨勢圖
(18)超過30秒以上的接口
(19)超過30秒以上的接口出現次數
以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" } }'