共计 3527 个字符,预计需要花费 9 分钟才能阅读完成。
作者 | 悟鹏、陶醉
起源 | 阿里巴巴云原生公众号
《Kubernetes 稳定性保障手册》系列文章:
- Kubernetes 稳定性保障手册 — 极简版
- Kubernetes 稳定性保障手册 — 日志专题(本文)
不管对于软件的用户还是开发者,日志都是很重要的信息源。日志能够用来表征软件的运行状态,在软件运行不合乎预期时提供丰盛的信息,也能够用在开发阶段调试软件,不便定位问题。
软件的生命周期波及到 开发 和 运行 两个阶段,日志的生成是在软件的开发阶段,日志的应用集中在软件的运行阶段。
在开发阶段规范化日志,有助于运行阶段通过标准化办法剖析日志、配置日志监控和告警。
在运行阶段通过标准化办法应用日志,有助于低成本把握程序的运行态行为,及时感知异样,促成开发阶段的迭代效率。
在软件的生命周期中,运行阶段时长占比会远大于开发阶段,即对日志的应用时长会远大于开发阶段写日志逻辑的时长。在开发阶段利用良好的日志标准,会对软件生命周期的失常运行和疾速迭代带来很大帮忙:
复杂度剖析
程序中的元素能够形象为两局部:本身逻辑,依赖。两类元素之间的交互为:本身逻辑闭环,本身逻辑与依赖交互。
从长期角度来看,交互环节出问题的概率会比本身逻辑出问题的概率高,因而要重点关注交互环节的日志逻辑。
同时,对日志的治理须要意识到 _谁会应用这些日志,_通常有 4 类角色:
- 用户
- 维护者
- 平安人员
- 审计人员
用户从黑盒角度应用软件,通过日志理解软件以后的运行状态,关注重点是软件失常的状态。
维护者从白盒角度应用软件,开发角色通过日志调试软件,SRE 角色通过日志及时感知软件的异样状态,并通过日志上下文剖析异样起因。
平安人员通过剖析日志,理解歹意登录、异样删除等危险。
审计人员通过审计日志、利用日志,确认业务、架构的合规性。
根据上述不同的应用场景,咱们能够梳理出几类日志类别,进一步加强开发和运行阶段对日志的了解:
开发阶段
最佳实际
了解了日志使用者关注的重点后,开发阶段写日志时,举荐应用如下最佳实际:
应用 structured logs
- 不应用 format strings
应用 info 和 error 表征日志级别
info 又可细化为多个级别,0~10,信息的重要性顺次升高 (也能够参考《Kubernetes: sig-instrumentation/logging.md》
- 0:用户想要看到的信息
- 1:维护者关注的白盒行为信息
- 10:维护者调试用的信息
应用具备过滤器能力的 log lib,通过 logger 主动过滤敏感信息
- 参见《KEP: Kubernetes system components logs sanitization》
日志通过 stdout/stderr 输入,敞开不必要的文本日志
- 防止额定的磁盘占用、IO 耗费、日志清理工作的保护等
对于 golang,能够思考应用 klog 作为 logger 实现。
FAQ
为什么应用 structured logs?
structured logs 是一种结构化的日志格局,构造如下,其中 msg 表征通用的事件,多对的 k=v 用来具化事件:
msg k=v k=v … k=v
示例:
“Pod status updated” pod=”kube-system/kubedns” status=”ready”
对于开发阶段,structured logs 通过固化的构造和字段语义,帮助开发者思考程序逻辑状态,有助于进一步控制程序复杂度和了解程序逻辑。
对于运行阶段,structured logs 中的 k 人造具备索引的属性,便于进行查问和剖析。也能够思考将 msg 规范化,减少 事件 语义,通过限度 msg 语义来加强 msg 的作用。
为什么不应用 debug/warning/critical/fatal?
通过缩小日志类型,升高应用和保护累赘。
debug 能够融入到 info 级别。
warning/critical 对于用户和维护者都是含糊的词,对于要采取的口头通常不具备指导意义。warning/critical 和 error 相似,表征程序运行过程中呈现了预期外的景象,此时程序要么主动解决,要么交由内部人工染指判断。若由程序主动解决,那么用户和维护者感知到这类景象即可,info 能够满足。若须要交由内部人工染指,那么 error 就能够满足。对于问题的严重性,可放在运行阶段,通过异样具体的信息来表征,如 ServiceUnavailable、Unauthorized 等。
fatal 是将 error 和 panic 两类逻辑封装了起来,在开发过程中可能会带来执行逻辑上的不清晰,如决定是否 panic 的逻辑须要放在最顶层逻辑中,若在顶层逻辑之下调用 fatal,可能会带来资源泄露、程序运行复杂度减少等问题。
为什么不应用 format strings?
format strings 是形如如下的构造:
klog.V(4).Infof(“Got a Retry-After %ds response for attempt %d to %v”, seconds, retries, url)
这种构造将 通用事件 和 具体内容 耦合在一起,不利于开发阶段升高了解程序逻辑的老本,也不便于应用阶段通过标准化的形式进行查问、剖析,减少日志的应用老本。
一种改善形式:
klog.V(4).InfoS(“got a retry-after response when requesting url”, “attempt”, retries, “after seconds”, seconds, “url”, url)
为什么要应用具备过滤器能力的 log lib?
开发过程中,可能会因为忽略而将敏感信息输入到日志中,如明码、token 等信息。为了防止敏感信息泄露,须要增强 code review,同时也能够思考在 logger 中配置过滤器,主动进行敏感信息的过滤,参见《KEP: Kubernetes system components logs sanitization》。
对于 golang,能够思考应用 klog 作为 logger 实现,并配合 Kubernetes/component-base: sanitization 进行应用。
运行阶段
最佳实际
运行阶段是对日志的应用,包含如下 4 个阶段:
- 采集
- 查问
- 剖析
- 告警
因为日志服务对程序的运行以及后续的经营极为重要,倡议采纳托管型的日志产品来满足运行阶段对日志的应用需要,如阿里云的 SLS 产品。
若在多个 region 部署集群,且集群的组件雷同,在应用日志产品时,须要确保每个 region 中日志项目名称规定的一致性。以阿里云 SLS 产品为例,若须要别离收集多个 region 的日志,则 project、logstore 的名称须要在多个 region 中放弃雷同的规定,目标是便于通过对立的办法对不同集群的日志做查问和剖析。
通常状况下,日志产品会提供上述 4 个阶段的服务,具体的应用办法能够参见对应日志产品的文档,下述针对告警做重点剖析。
告警
告警要满足如下指标:
- 覆盖面全
- 要害告警及时感知
基于开发阶段的日志标准,可对 error 级别的告警做对立告警,将告警信息对立到低优先级的告诉渠道,如表征一般告警的钉钉群。
若要及时感知到要害告警,须要从如下 2 个方面动手:
- 定义「要害告警」特色
- 分级告警,与相应的告诉渠道联合
定义「要害告警」的特色是个 长期 、 继续欠缺 的过程,有 通用要害告警 和 业务要害告警。
通用要害告警 与业务耦合度小,如机器级别的要害告警 (宕机、内存压力大、load 过低等)、托管服务的要害告警 (master 组件 panic/OOM、master 组件内存压力大等),这部分告警配置能够作为根底服务,作为集群交付的一部分。
业务要害告警 与业务耦合度大,须要与业务长期保护,重点关注「业务交互环节」的告警。
告诉渠道通常会有如下几类:
- IM 群 (如钉钉群等)
- 短信
- 电话
- webhook
这些告诉渠道对人触达的及时性不同,电话触达性最好,短信其次,而后是 IM 群。webhook 实质上是条通道,能够对接不同的 IM 群或短信、电话渠道。
举荐如下三种告警级别:
配置告警是个长期、一直迭代的过程,为了有助于告警有效性的迭代,配置每条告警时,能够思考应用如下表格,规范化每条告警的配置,并深刻思考告警配置的有效性:
FAQ
如何事后配置未模拟出的异样?
业务依赖的 OpenAPI/SDK/Lib 等通常都会有错误码列表,如 阿里云:API 谬误核心、Lib 中的 errors 文件等。能够基于该已知信息,枚举依赖的 OpenAPI/SDK 中对业务有显著负面影响的状态码做分级告警,如 ServiceUnavailable/Forbbiden/Unauthorized 等。
欢送大家留言交换应用 Kubernetes 过程中的稳定性保障问题,以及对稳定性保障的期待工具或服务。大家也可通过邮箱分割作者,进一步深刻交换:flyer.zyf@alibaba-inc.com