在上一篇日志系统EFK后续:monitor报警监控中,我们基本完成了efk监控报警系统的搭建和测试。接下来,在将日志源切换为在线日志时出现了一个大问题。fluentd的CPU使用率居高不下,Kafka中的告警消息增长极快,瞬间有几十万条消息。我们尝试将在线日志级别调整为INFO后,问题并没有得到缓解。同时,钉钉告警消息不断刷新。fluent-bit不支持尾读,而我们的日志保留30天(后续考虑是保留7天,剩下的会压缩),一开始的读取量真的很大,fluent-bitoffsets之前也出现过,所以我们决定使用fluentd来进行日志的收集和转发。fluentd收集器先将fluentd升级到1.6版本,修改对应的配置文件1.fluentd:v1.6FROMfluent/fluentd:v1.6-debian-1#FROMfluent/fluentd:v1.2#添加es插件、kafka插件USERrootRUNfluent-gem安装fluent-plugin-elasticsearchRUNfluent-gem安装fluent-plugin-kafkaRUNfluent-gem安装fluent-plugin-rewrite-tag-filterCMDexecfluentd-c/fluentd/etc/${FLUENTD_CONF}-p/fluentd/plugins$FLUENTD_OPT2.fluentd.conflog_levelerror#tail收集日志并解析@typetailpath"#{ENV['tailInputPath']}"exclude_path"#{ENV['tailExcludePath']}"pos_file"#{ENV['tailPosFile']}"tagfb.dapengpath_keytailKey#refresh_interval5sread_from_headtruemultiline_flush_interval10s@typemultilineformat_firstline/^\d{2}-\d{2}\d{2}:\d{2}:\d{2}\d{3}/format1/^(?^\d{2}-\d{2}\d{2}:\d{2}:\d{2}\d{3})(?[^]+|检查空闲连接线程)(?[^]+)\[(?\w*)\]-(?.*)/@typerecord_transformerenable_rubyhostname生产标签${record["tailKey"].split('/')[3]}remove_keystailKey@typegrep关键级别模式/^\w+$/@typegrep关键sessionTid模式/^[0-9a-f]{16}$/@typecopy@typekafka2brokers"#{ENV['kafkaHost']}:9092"topic_keyefkdefault_topicefk<缓冲区efk>flush_interval5s@typejsoncompression_codecgziprequired_acks-1max_send_retries3@typerewrite_tag_filterkeylevelpattern/^ERROR$/tagerror.fb.dapeng@typekafka2经纪人"#{ENV['kafkaHost']}:9092"topic_keyefk_errordefault_topicefk_errorflush_interval5s@typejsoncompression_codecgziprequired_acks-1max_send_retries3@typekafka_groupbrokers"#{ENV['kafkaHost']}:9092"consumer_groupefk_consumer主题efk格式jsonstart_from_beginningfalsemax_wait_time5max_bytes1500000#kafka_group中消息的主题就是对应事件的标签@typeelasticsearchhosts"#{ENV['esHost']}:9092"index_namedapeng_log_indextype_namedapeng_log#content_typeapplication/x-ndjsonbuffer_typefilebuffer_path/tmp/buffer_filebuffer_chunk_limit10mbuffer_queue_limit512flush_modeintervalflush_interval5srequest_timeout5sflush_thread_count2reload_on_failuretrueresurrect_after30sreconnect_on_errortruewith_transporter_logtruelogstash_formattruelogstash_prefixdapeng_log_indextemplate_namedapeng_log_indextemplate_file/fluentd/etc/template.jsonnum_threads2utc_indexfalse3.dc-all.yml环境变量配置-tail/log/var*Path/%Y-%m-%d.log-tailExcludePath=["/var/logs/*/fluent*.log","/var/logs/*/console.log","/var/logs/*/gc*.log"]-tailPosFile=/fluentd/etc/logs.pos-kafkaHost=kafkaserverIP-esHost=esserverIPfluentd1.4后支持"#{ENV['env_key']}"获取环境变量env_key的值这里我们选择流利的tail输入,监控文件使用strftime,*.%Y-%m-%d.log只监控当天的日志。这样就可以使用read_from_head从头开始读了,不用担心读太多,也不用担心尾读导致日志切换的时候,当monitor列表有一个没有更新的刷新周期refresh_interval,日志文件开头的部分日志丢失。rsync同步文件坑切换fluentd收集日志后,kafka消息量减少,但还是不够用。而报警信息还在反复刷屏。通过观察,发现告警中存在重复数据。也就是说fluentd收集了重复的日志,因为我们是定时通过rsync把线上环境的日志同步到efk所在环境的。这时候,怀疑rsync每次同步的时候是不是都复制了一遍。虽然文件名没变,但是每次同步后fluentd可能会从头读取,导致日志重复。首先tail-f监听对应的日志文件,发现rsync同步了之后,监控文件没有变化。再次关闭监控后,发现文件确实发生了变化。同时,我们查看Kafka中的消息数,发现每次文件同步后,efk_error的offset都会增加相同的量,这就解释了为什么钉钉告警消息每次都会重复warnings。这时基本确定是rsync的问题导致fluentd每次同步后都从头开始采集。通过查询rsync的文档,找到了append参数,这样只会在同步的时候添加。定量同步,而不是更新整个文件。rsync-a--append/src//dist/那么问题就顺理成章地解决了。通过es-head查询发现日志顺序问题。logtime时序有问题。查看fluentd插件fluent-plugin-elasticsearch的文档,找到如下解决方案:1.修改fluentd中es输出配置,增加time_keylogtime,es默认排序@timestamp,记录日志输出到es的时间,time_key将logtime的值赋值给@timestamp注意:实际测试中加入time_keylogtime会导致fluentd自动创建的索引名出现问题。在模板的配置中,*所代表的时间固定为某一天。2.修改es-head查询默认带上logtime排序参考:https://github.com/fluent/flu...https://download.samba.org/pu...https://github.com/uken/fluen...