本文介绍如何利用腾讯云容器服务 TKE 的日志功能对日志进行采集、存储与查询,分析各类功能用法与场景,给出一些最佳实践建议。php
注: 本文仅适用于 TKE 集群。nginx
TKE 的日志功能入口在 集群运维-日志规则
,更多关于如何为 TKE 集群启用日志采集与基础用法,参考官方文档 日志采集。正则表达式
TKE 集群开启日志采集后,tke-log-agent 做为 DaemonSet 部署在每一个节点上,负责根据采集规则采集节点上容器的日志,而后上报到 CLS 日志服务,由 CLS 进行统一存储、检索与分析:docker
在 TKE 使用日志采集时,须要在 集群运维-日志规则
里新建日志采集规则,首先须要肯定采集的目标数据源是什么,下面介绍支持的 3 种类型数据源及其各自使用场景与建议。后端
最简单也是最推荐的方式是将 Pod 内容器的日志输出到标准输出,日志内容就会由容器运行时 (docker, containerd) 来管理,有如下几点好处:架构
kubectl logs
查看日志内容。采集配置示例:框架
不少时候业务经过写日志文件的方式来记录日志,使用容器跑业务时,日志文件被写到容器内:运维
/var/lib/docker
(建议给此路径挂盘,避免与系统盘混用),容器中止后日志会被清理。/var/lib/kubelet
路径下,此路径一般没有单独挂盘,也就是会使用系统盘;因为使用了日志采集,有统一存储的能力,不推荐再挂载其它持久化存储来存日志文件(如云硬盘CBS, 对象存储COS, 共享存储CFS)。许多开源日志采集器须要给 Pod 日志文件路径挂载 volume 才能采集,使用 TKE 的日志采集则不须要,因此若是将日志输出到容器内的文件里,不须要关心是否挂载 volume。ide
采集配置示例:url
若是业务将日志写入日志文件,但又想容器中止以后还能保留原始日志文件,好有个备份,避免采集异常时致使日志彻底丢失,这时能够给日志文件路径挂载 hostPath,日志文件会落盘到宿主机指定目录,而且容器中止后不会清理日志文件。
因为不会自动清理日志文件,有同窗就可能会担忧日志会被重复采集,好比 Pod 调度走又调度回来,日志文件被写在以前相同路径。是否会重复采集,这里分两种状况:
/data/log/nginx/access.log
。此时不会重复采集,由于采集器会记住以前采集过的日志文件的位点,只采集增量部分。因此,通常不会重复采集,若是日志框架会对日志进行自动轮转,建议采集规则不要使用通配符 "*" 来匹配日志文件。
采集配置示例:
知道了采集哪里的数据以后,咱们还须要知道采集到的日志往哪里存。根据前面讲的技术架构能够知道,TKE 日志采集与云上的 CLS 日志服务集成,日志数据也将统一上报到日志服务。日志服务经过日志集和日志主题来对日志进行管理,日志集是 CLS 的项目管理单元,能够包含多个日志主题;通常将同一个业务的日志放在一个同一日志集,同一业务中的同一类的应用或服务使用相同日志主题,在 TKE 中,日志采集规则与日志主题是一一对应的;TKE 建立日志采集规则时选择消费端,就须要指定日志集与日志主题,日志集一般提早建立好,日志主题一般选择自动建立:
建立好后能够根据状况对自动建立的日志主题进行重命名,方便后续检索时找到日志所在的日志主题:
有了日志的原始数据,咱们还须要告诉日志服务如何去解析日志,以方便后续对其进行检索。在建立日志采集规则时,须要配置日志的解析格式,下面针对各项配置给出分析与建议。
首先,咱们须要肯定日志的抓取模式,支持 5 种:单行文本、JSON、分隔符、多行文本和彻底正则。
推荐使用 JSON,由于 JSON 格式自己就将日志给结构化了,日志服务能够提取 JSON 的 key 做为字段名,value 做为对应的字段值,再也不须要根据业务日志输出格式配置复杂的匹配规则,日志示例:
{"remote_ip":"10.135.46.111","time_local":"22/Jan/2019:19:19:34 +0800","body_sent":23,"responsetime":0.232,"upstreamtime":"0.232","upstreamhost":"unix:/tmp/php-cgi.sock","http_host":"127.0.0.1","method":"POST","url":"/event/dispatch","request":"POST /event/dispatch HTTP/1.1","xff":"-","referer":"http://127.0.0.1/my/course/4","agent":"Mozilla/5.0 (Windows NT 10.0; WOW64; rv:64.0) Gecko/20100101 Firefox/64.0","response_code":"200"}
使用 JSON 抓取模式的前提是业务的日志自己是以 JSON 格式输出的,若是不是 JSON 格式,但切换到使用 JSON 格式输出成本不大,就建议进行切换,若是实在很差切换,再考虑其它抓取模式。
若是日志内容是以固定格式输出的单行文本,考虑使用 "分隔符" 或 "彻底正则" 抓取模式。"分隔符" 适用简单格式,日志中每一个字段值都以固定的字符串分隔开,好比用 ":::" 隔开,某一条日志内容是:
10.20.20.10 ::: [Tue Jan 22 14:49:45 CST 2019 +0800] ::: GET /online/sample HTTP/1.1 ::: 127.0.0.1 ::: 200 ::: 647 ::: 35 ::: http://127.0.0.1/
能够配置 ":::" 自定义分隔符,而且为每一个字段按顺序配置字段名,示例:
"彻底正则" 适用复杂格式,使用正则表达式来匹配日志的格式。如日志内容为:
10.135.46.111 - - [22/Jan/2019:19:19:30 +0800] "GET /my/course/1 HTTP/1.1" 127.0.0.1 200 782 9703 "http://127.0.0.1/course/explore?filter%5Btype%5D=all&filter%5Bprice%5D=all&filter%5BcurrentLevelId%5D=all&orderBy=studentNum" "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:64.0) Gecko/20100101 Firefox/64.0" 0.354 0.354
正则表达式就能够设置为:
(\S+)[^\[]+(\[[^:]+:\d+:\d+:\d+\s\S+)\s"(\w+)\s(\S+)\s([^"]+)"\s(\S+)\s(\d+)\s(\d+)\s(\d+)\s"([^"]+)"\s"([^"]+)"\s+(\S+)\s(\S+).*
日志服务会使用 ()
捕获组来区分每一个字段,咱们还须要为每一个字段设置字段名,配置示例:
若是日志没有固定的输出格式,则考虑使用 "单行文本" 或 "多行文本" 的抓取模式。使用这两种模式,不会对日志内容自己进行结构化处理,不会提取日志字段,每条日志的时间戳也固定由日志采集的时间决定,检索的时候也只能进行简单的模糊查询。这两种模式的区别在于日志内容是单行仍是多行,若是是单行最简单,不须要设置任何匹配条件,每行都是一条单独的日志;若是是多行则须要设置首行正则表达式,也就是匹配每条日志第一行的正则,当某行日志匹配上预先设置的首行正则表达式,就认为是一条日志的开头,而下一个行首出现做为该条日志的结束标识符。假如多行日志内容是:
10.20.20.10 - - [Tue Jan 22 14:24:03 CST 2019 +0800] GET /online/sample HTTP/1.1 127.0.0.1 200 628 35 http://127.0.0.1/group/1 Mozilla/5.0 (Windows NT 10.0; WOW64; rv:64.0) Gecko/20100101 Firefox/64.0 0.310 0.310
那么首行正则表达式就能够设置为: \d+\.\d+\.\d+\.\d+\s-\s.*
有些不重要或不关心的日志能够选择将其过滤掉,下降成本。
若是使用 "JSON"、"分隔符" 或 "彻底正则" 的抓取模式,日志内容会进行结构化处理,能够经过指定字段来对要保留的日志进行正则匹配:
对于 "单行文本" 和 "多行文本" 抓取模式,因为日志内容没有进行结构化处理,没法指定字段来过滤,一般直接使用正则来对要保留的完整日志内容进行模糊匹配:
须要注意的是,匹配内容必定记住是用正则而不是完整匹配,好比想只保留 a.test.com
域名的日志,匹配的表达式应该写 a\.test\.com
而不是 a.test.com
。
每条日志都须要有个时间戳,这个时间戳主要用于检索,在检索的时候能够选择时间范围。默认状况下,日志的时间戳由采集的时间决定,也能够进行自定义,选择某个字段做为时间戳,这样在某些状况下可能更精确些,好比在建立采集规则以前,服务已经运行了一段时间,若是不设置自定义时间格式,采集时会将以前的旧日志的时间戳设置为当前的时间,致使时间不许确。
如何进行自定义呢?因为 "单行文本" 和 "多行文本" 抓取模式不会对日志内容进行结构化处理,也就没有字段能够指定为时间戳,没法自定义时间格式解析。其它的抓取模式均可以支持,具体作法时关闭 "使用采集时间",而后选取要做为时间戳的字段名称,并配置时间格式。
假如使用日志的 time
字段做为时间戳,其中一条日志 time
的值为 2020-09-22 18:18:18
,时间格式就能够设置为 %Y-%m-%d %H:%M:%S
, 示例:
更多时间格式配置参考日志服务官方文档 配置时间格式。
须要注意的是,日志服务时间戳暂时只支持精确到秒,也就是若是业务日志的时间戳字段精确到了毫秒,将没法使用自定义时间戳,只能使用默认的采集时间做为时间戳,不过期间戳精确到毫秒后续将会获得支持。
日志采集规则配好了,采集器就会自动开始采集日志并上报到日志服务,而后就能够在 日志服务-检索分析
中查询日志了,支持 Lucene 语法,但前提是须要开启索引,有如下 3 类索引:
查询示例:
日志服务支持将日志投递到 COS 对象存储和 Ckafka (腾讯云托管的 Kafka),能够在日志主题里设置投递:
能够用在如下场景: