分享

分布式系统中的日志落地经验总结

 WindySky 2019-02-28

在过去的2年多的时间里,随着在公司推进容器云,陆陆续续的和日志打了不少交道,在这里做一个总结:

为什么需要日志

日志如何接收与存储

日志如何收集

日志收集客户端分析

日志的标准化

日志报警

日志归档

其他问题

为什么需要日志

日志的作用我觉得有三点:

故障排错

数据分析

业务审计

1,关于故障排错,当线上发生异常,查看应用的错误日志、堆栈信息、代理层的访问日志是非常有帮助的,不同级别的日志能够很好的帮助我们定位到故障点,而访问日志则能让我们知道异常情况发生在哪个环节,是client到代理,还是代理到后端。这也是降低MTTD的一个很好的工具。

2,对日志数据的分析,一方面能协助分析问题、定位故障,另一方面还可以帮我们更好的了解系统运行状态甚至是了解我们的用户。比如基于HTTP状态码和响应时间可以分析出系统的稳定性和性能状况。而基于访问日志的来源IP可以分析出用户地域属性、而基于日志量级的时间分布可以了解到系统和用户的活跃时间范围。

3,上面两种多数是最近几个月的热数据,需要实时查看和分析,也有一部分需要保存的更久,以满足合规、审计等的需求。比如有些备案就要求不同级别的日志保存不同的时长以备随时调用查看。

日志的收集与存储

在分布式系统中,众多服务分散部署在成百上千台甚至成千上万台服务器上,要想快速方便的实现上述的查找、分析和归档功能,就需要有一个集中的日志系统,通过日志收集器将各类日志进行统一汇总,存储,这样不仅能方便查找所有的日志,还有可能在众多日志数据中挖掘到一些意想不到的关联关系。

有了这个定位接下来就可以开始详细的规划了,首先是日志服务器的选型,有经典的ELK,有商业的splunk,但我们并没有采取上述两种,splunk功能完全符合,但对大量级的日志而言成本偏高,ELK中的kibana也在高版本中开始商业化,这让我们开始寻找替代方案,graylog便是一种。它的绝大多数功能都是免费的,并且性能优越,上图:

graylog也采用Elasticsearch作为存储和索引以保障性能,MongoDB用来存储少量的自身配置信息,master-node模式具有很好的扩展性,UI上自带的基础查询与分析功能比较实用且高效,支持LDAP、权限控制并有丰富的日志类型和标准(如syslog,GELF)并支持基于日志的报警。

在日志接收方面通常是网络传输,可以是TCP也可以是UDP,在实际生产环境量级较大多数采用UDP,也可以通过MQ来消费日志。

不同日志有不同的收集方式,总结下来有如下几种:

服务器系统日志、登录日志可通过rsyslog传输到统一服务器

$ head /etc/rsyslog.conf

*.* @your-log-server-addr:port;RSYSLOG_SyslogProtocol23Format

1

2

访问日志,如access.log这类文本,可经过日志收集器传输

应用日志,可通过落地文本后,再经过日志收集器传输;也可以直接经网络发送到日志服务器或消息队列应用日志,可通过落地文本后,再经过日志收集器传输;也可以直接经网络发送到日志服务器或消息队列

docker日志,除了将日志挂载到宿主机上然后通过收集器传输之外,还可以在docker的配置中可设置不同logdriver将日志以不同渠道输出,我不推荐如gelf这类driver,因为它虽然可以无缝对接日志平台,但配置不灵活,如需变更还需要重启docker daemon(默认情况下),而且在实际使用中发现gelf在性能上也存在问题。demo:docker日志,除了将日志挂载到宿主机上然后通过收集器传输之外,还可以在docker的配置中可设置不同logdriver将日志以不同渠道输出,但我不推荐如gelf等driver,因为它虽然可以无缝对接日志平台,但配置不灵活,如需变更还需要重启docker daemon(默认情况下),而且在实际使用中发现性能上也存在问题,demo:

docker版本要求在1.8以上。

$ docker --version

Docker version 1.12.0, build 8eab29e

修改配置文件/usr/lib/systemd/system/docker.service 

ExecStart=/usr/bin/dockerd --storage-driver=overlay --graph=/data/dockerapp \

--log-driver=gelf \

--log-opt gelf-address=udp://xxx.com:9999 \

--log-opt tag=docker \

--log-opt env=pro \

--log-opt gelf-compression-type=gzip \

--log-opt gelf-compression-level=1

1

2

3

4

5

6

7

8

9

10

kubernetes,如果是在公有云如Google Cloud上面的Stackdriver Logging

日志收集器主要有:

Logstash

Filebeat

Fluentd

Fluent-bit

Logstash功能强大,但性能消耗也大,相对比较重,更适合作为中间环节,elastic后来推出的Filebeat更适合,它的性能好且资源占用少。而Fluentd作为CNCF指定用品,在17年初用了一段时间,觉得性能不是很好,它基于磁盘或内存的buffer优化空间也非常有限,但随着加入CNCF后市场占比更多,也推出了Fluent-bit消耗1/10的资源。

这些收集器可以以daemonset的方式部署,确保每个节点上有且只有一个实例在收集日志。

日志标准化

上述只能实现日志的收集、存储和展示,但想要更好的分析,就需要用到日志标准化,对不同日志、不同类型做不同的管理。如为方便快速查找某个系统在过去一段时间的访问质量,对需要对代理层日志中的HTTP状态码做清晰明了的界定。对于应用程序我们在日志中的通用字段包含:

环境信息(如;dev,test,beta)

团队信息(类似namespace)

应用名

时间戳

日志级别

为提高可扩展性,在应用日志和Nginx日志都以json格式输出,这样就省去如logstash等组件的加工环节,同时也可基于json中的字段对日志做处理,如生产环境下logLevel=debug级别的日志不做处理,对size过大的做截断。

对访问日志,可添加的就更多了,如:

log-format-upstream: '{ "message":"$remote_addr $host $request_time $status", "remote_addr":

"$remote_addr", "domain_name": "$host", "remote_user": "$remote_user", "http_tracker_id":

"$http_tracker_id", "time_local": "$time_local", "request_proto":

"$server_protocol", "request_path": "$request_uri","request_args": "$args","response_status":"$status","request_time":"$request_time","body_bytes_sent":"$body_bytes_sent","request_length":"$request_length",

"http_referer":"$http_referer","http_user_agent": "$http_user_agent","upstream_addr":"$upstream_addr",

"upstream_connect_header_response_time":"$upstream_connect_time $upstream_header_time

$upstream_response_time","upstream_status":"$upstream_status","http_x_forwarded_for":

"$http_x_forwarded_for" }'

1

2

3

4

5

6

7

8

但注意,在日志量级较大的情况下如果字段设置过多会对日志收集器有一些性能压力。

日志报警

graylog自身支持对日志的报警,如某个域名\应用在某个时间段内的错误日志数如果超过某个阈值就报警。

日志归档

graylog商业版自带归档功能,如果自己做可以通过消息队列将日志数据再存入到HDFS中一份。

总结

其他问题

日志依赖ES和Luence,后者对每个字段要求最大为32kb,超出的将不再保存。可以设置ignore_above =256 对过大字段不做解析y,也可以在收集端过滤较大日志,如filebeat上设置:max_bytes = 327660

注意日志生成时间与日志存入时间的区分,避免组件或网络故障后的日志时间显示不准确。

关于日志标准化的推广,可以对不同语言可以做不同的包,供开发团队直接引用。

反思之前为了确保日志不随着pod删除而删除,将日志文本化并挂载到宿主机上再做消费,这样会导致2份IO,且违反12因子中的日志事件原则,当前完全基于docker的json-file日志消费目前已经较为成熟,可以考虑直接使用该方案。

graylog对日志字段有一定的要求,除syslog外,其他应用入口比如必须包含“short_message”这样的一个字段,这个不太友好。

参考:

[1]:https://gist.github.com/StevenACoffman/4e267f0f60c8e7fcb3f77b9e504f3bd7

[2]:https://docs./v0.12/articles/kubernetes-fluentd

--------------------- 

作者:按时睡觉 

来源:CSDN 

原文:https://blog.csdn.net/weixin_43181696/article/details/84060710 

版权声明:本文为博主原创文章,转载请附上博文链接!

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多