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"      
  }      
}'
相关文章
相关标签/搜索