共计 6107 个字符,预计需要花费 16 分钟才能阅读完成。
Ingress(Nginx)日志长久化与可视化(多图预警)
[toc]
前言
晚期咱们通常会应用 goaccess 或 awstat 来对 nginx 等拜访日志进行剖析和统计, 但随着统计分析的多样性以及后续拜访日志的实时监控等定制化的需要越来越强烈,goaccess 或 awstat 越来越不能满足咱们的需要. 所以咱们急切须要更加灵便的日志统计分析工具, 能辅助咱们对拜访日志进行统计、剖析和监控. 这时候, 随着 elk/efk 的广泛应用,nginx 等拜访日志也将纳入到 elk 体系当中, 同时 elk 也能满足咱们对日志的统计与剖析、监控的多样化需要.
先上图
部署架构
如图, 以下是 1 个很简略的架构, 也没有做缓冲和聚合, 如果对日志的要求比拟高, 能够在两头退出 redis 或 Kafka 等.
为什么 ingress 或者 nginx 的日志要转换成 json 格局呢?
我这边简略的解释一下:, 次要是 2 个起因:
1: 便于联合 elasticseach 做实时监控和报警.
比方间接监控 status 字段, 如果 1 分钟间断呈现 20 次 4XX 报错就间接报警, 如果不转换的化, 你还须要进一步解析 access 日志, 这样带来了很多的不便.
2: 便于联合 elk 做可视化剖析.
能够组合不同的字段, 对不同的需要定制不同的可视化报表.
部署步骤
一、ingress 长久化步骤
1. 自建 kubernetes 的 ingress 长久化
ingress 部署参考: https://www.pvcreate.com/index.php/archives/205/
(1) ingress 增加 PVC 用于 ingress 日志存储
kubectl apply -f ingress-nfs.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: ingress-nfs
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 10Gi
storageClassName: nfs-client-local
(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-controller
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 中.
(1) 通过阿里云控制台为 ingress 增加 nas 存储
(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 中创立, 也能够在内部创立好.
二、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;
三、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
四、kibana 接入 elasticsearch 与可视化配置
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 秒以上的接口呈现次数
五、踩坑指南
可视化 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"
}
}'