Skip to content

基于 Kubernetes 的云原生 DevOps 第 15 章 可观察性和监控

🏷️ Kubernetes 《基于 Kubernetes 的云原生 DevOps》


Nothing is ever completely right aboard a ship.

-- William Langewiesche, The Outlaw Sea


15.1 什么是可观察性?

什么是监控?

当我们在开发运维环境中谈论监控时,一般指的是自动监控。

自动监控是通过程序化的方式检查网站或服务的可用性或行为(通常是定期检查),并通过某种自动化的方式来向人类工程师报告是否有问题。

黑盒监控

最简单的监控网站的方法就是访问主页并检查 HTTP 状态码( 200 表示请求成功)。你可以使用命令行 HTTP 客户端(例如 httpiecurl )来检查。如果客户端的退出状态不是零,则说明获取网站出现问题。

更为复杂的监控检查可能会寻找页面上某些特定的文本。这种方式能够捕捉到配置错误但仍可正常运行的 Web 服务器的问题。

比静态页面更复杂的情况

更复杂的页面需要更复杂的监控。

  • 世界各地的用户都可以使用我的应用程序吗?还是仅限某些地区?
  • 大部分用户加载需要多长时间?
  • 下载速度较慢的用户呢?
  • 网站上所有的功能都能按预期工作吗?
  • 某些功能是否允许缓慢或者压根不能用,有多少用户受到影响?
  • 如果依赖第三方服务,那么当该外部服务出现故障或不可用时,我的应用程序会如何处理?
  • 如果我的云提供商出现故障,情况会怎样?

黑盒监控的局限性

无论这些检查多么复杂,它们仍属于同一类别的监控,即黑盒监控。顾名思义,黑盒监控仅观察系统的外部行为,不会尝试观察系统内部的情况。

有一点很肯定,与完全没有任何监控的系统相比,实施任何类型的监控都是巨大的进步。然而,黑盒监控存在一些局限性。

  • 只能监测可预测的故障(例如网站没有响应)。
  • 只能检查暴露在外部的系统行为。
  • 黑盒检查是被动式和反应式的检查,仅在出现问题后才能发现。
  • 只能监测出“哪里出了问题?”,但不能进一步找出问题的原因。

“正常”指什么?

在运维中,我们习惯于使用 正常运行时间( uptime 来测量应用程序的弹性和可用性,通常以百分比衡量。

通常,你可能觉得 9 越多越好。但是,这忽略了重要的一点:

如果用户不满意,再多 9 也没用。
-- Charity Majors

如果用户不满意,再多 9 也没用

我们常说,凡是被衡量的东西都会被最大化。因此,在决定衡量什么时请务必谨慎。如果你的服务不适合用户,则无论内部指标如何都无关紧要,因为你的服务已经完蛋了。服务引发用户不满的因素多种多样,即使表面上看来服务仍在正常运行也无济于事。

云原生应用程序永远不会“正常”

尽管你可以继续使用更复杂的规则和阈值,来决定服务状态何时正常何时宕机,但事实上,这个问题本身存在着无法弥补的缺陷。云原生应用程序这类的分布式系统永远都不会“正常”,部分降级是它的恒定常态

这类问题又名 “灰色故障( Gray Failure )” 。灰色故障的定义表明它很难检测到,尤其是从单个角度或单个观察结果来看。

日志

大多数应用程序都会生成某种日志。日志是一系列记录,一般都带有某种时间戳,用以表明记录的生成时间以及顺序。

如果应用程序遇到错误,通常日志会记录这个事实以及一些可能有助于运维人员找出问题发生原因的信息。

通常,来自多个应用程序和服务的日志会被汇总到一个中央数据库(例如 Elasticsearch ),为故障排除提供查询和图表。 LogstashKibana 等工具,或 SplunkLoggly 等托管服务可以帮助你收集和分析大量日志数据。

日志记录的局限性

日志记录什么或不记录什么,是由程序员在编写应用程序时决定的。因此,日志只能回答问题,或发现可以提前预知的问题。

此外,从日志中提取信息也很难,因为每个应用程序记录日志的格式都不相同,而运维人员经常需要针对每种类型的日志记录编写自定义的解析器,将其转换为方便使用的数字或事件数据。

通常,日志中的信噪比都很高。

日志很难伸缩

日志可能会占用大量网络带宽,并且日志聚合器也可能成为瓶颈。

许多托管的日志记录提供商还会根据你生成的日志量收费。

自托管日志记录解决方案也是如此,存储的数据越多,所需承担的硬件、存储以及网络资源费用就越高,而且为了保证日志聚合正常工作需要付出的工程时间就越多。

Kubernetes 中的日志记录有用吗?

如果你使用日志记录,则不要使用纯文本记录,应该使用某种形式的结构化数据,例如 JSON,它可以自动被解析。

尽管集中式日志聚合(ELK 之类的服务)对 Kubernetes 应用程序很有用,但仅靠日志还不够。

指标

更复杂的收集服务信息的方法是使用指标。顾名思义,指标是某种事物的数字度量标准。根据应用程序,相关的指标可能包括:

  • 当前正在处理的请求数。
  • 每分钟(或每秒、每小时)处理的请求数。
  • 处理请求时遇到的错误数。
  • 处理请求时所花费的平均时间(或高峰时期的响应时间,或 99 百分位响应时间)。

收集有关基础设施以及应用程序的指标也很有用:

  • 各个进程或容器的 CPU 使用率。
  • 节点或服务器的磁盘 I/O 活动。
  • 计算机、集群或负载均衡器的入/出网络流量。

指标能够找出原因

指标打开了监控的新维度,使得监控不再是简单的工作或不工作的问题。我们可以通过各种方式轻松地处理指标:绘制图表、做统计或预定义发出预警的阈值。

此外,指标还可以找出问题的原因。

指标有助于预测问题的出现

在你或你的用户注意到某个问题之前,某些指标的上升可能表明问题已经出现。

有些系统甚至使用机器学习技术来分析指标、监测异常及其原因。

从内部监控应用程序的指标

指标允许应用程序的开发人员根据他们对系统实际工作方式(以及故障)的了解,导出系统不常为人知的关键信息:

不要再实施应用程序的逆向工程,应该从内部开始监控应用程序。
-- Kelsey Hightower, Monitorama 2016

PrometheusstatsdGraphite 等工具,或者 DatadogNew RelicDynatrace 等托管服务被广泛用于收集和管理指标数据。

跟踪

跟踪是监控工具箱中的另一项实用技术。在分布式系统中跟踪尤其重要。指标和日志可以让你了解系统中每个组件的运行状况,而跟踪则可以记录某个用户请求的整个生命周期

一些流行的分布式跟踪工具包括 ZipkinJaegerLightStep 等。

OpenTracing 框架(云原生计算基金会的一部分)旨在为分布式跟踪提供一组标准的 API 和库。

可观察性

由于监控一词对不同的人来说具有不同的含义,从简单的黑盒检查到指标、日志和跟踪的组合,这些都可以叫做监控,因此人们越来越普遍地使用可观察性一词作为涵盖所有这些技术的统称。

系统的可观察性可以衡量系统的良好运行程度,以及发现系统内部运行情况的难易程度。

有人说可观察性是监控的超集,而有些人则认为可观察性反映了与传统监控完全不同的思维方式。

区分这些术语的最有效方法是:监控可以告诉你系统是否正常运行;而可观察性则可以帮助你发现为什么系统无法正常运行。

可观察性表示对系统的理解

一般而言,可观察性表示对系统的理解,即理解你的系统可以做什么以及如何做。

此外,可观察性也表示数据。

软件是不透明的

在默认情况下,软件是不透明的;它必须生成数据,人们才能理解它在做什么。在可观察的系统中,人们能够回答“系统是否正常工作?”之类的问题,而且如果回答是否定的,则可以诊断出影响的范围并找出问题所在。
-- Christine Spang (Nylas)

建立可观察性文化

一般来说,可观察性与文化有关。开发运维的主要宗旨是在开发代码与大规模生产环境中运行代码之间形成闭环。可观察性是创造这种闭环的主要工具。开发人员和运维人员要紧密合作,对服务进行观测,然后找出使用和提供信息的最佳方法:

可观察性团队的目标不是收集日志、指标或跟踪。它的目标是基于事实和反馈建立工程的文化,并将这种文化传播到更广泛的组织中。
-- Brian Knox (DigitalOcean)

15.2 可观测性流水线

从实践的角度看,如何建立可观测性呢?通常,我们需要以特定的方式将多个数据源(日志、指标等)连接到各种不同的数据存储。

这种情况并不理想。首先,这种做法很难扩展。你拥有的数据源和存储越多,他们之间的连接就越多,连接之间的流量也就越多。而你不应该在稳定所有这些不同类型的连接上投入任何工程时间。其次,系统与特定解决方案或提供商的集成越紧密,修改或尝试其他方案的难度就越大。

有一种解决该问题的方法日益流行,那就是可观察性流水线:

可观察性流水线可以将数据源从目标解耦出来,并在二者之间提供缓冲。如此一来,可观察性数据就更易于消费。我们不再需要弄清楚容器、虚拟机和基础设施发送了哪些数据,发送到哪里以及如何发送。所有数据只需发送到流水线,然后由流水线进行过滤并将数据发送到正确的位置。这样我们也可以更灵活地添加或删除数据接收器,而且流水线还在数据生产者和消费者之间提供了缓冲。
-- Tyler Treat

可观察性流水线带来了巨大的优势。添加新数据源只需将其连接到流水线即可。同样,新的可视化或报警服务也只是流水线的消费者。

由于流水线会缓冲数据,因此数据不会再出现丢失的现象。如果流量突然增加并导致指标数据过载,则流水线会缓冲这些数据,而不会丢失样本。

使用可观察性流水线需要一种标准的指标格式,最好使用 JSON 或其它一些合理的序列化数据格式来记录应用程序结构化的日志。而且应当从一开始就建立结构化的数据,而不是发送原始的文本日志,稍后再使用脆弱的正则表达式进行解析。

15.3 Kubernetes 中的监控

外部的黑盒检查

黑盒监控只能告诉你应用程序是否已经宕机。但这仍然是非常有用的信息。

监控需要模仿用户行为

最重要的可观察性任务应该是从你自己的基础设置外部的某个点上监控服务的可用性。有许多第三方服务可以执行这种监控(有时称为监控即服务Monitoring as a service, MaaS ),包括 Uptime RobotPingdomWormly

不要自行构建监控基础架构

这些服务大多数都提供免费套餐或非常便宜的订阅,而且支付的这些服务费用最终都可以计入运营费用。不要尝试自行构建外部监控基础设施。不值得这么做。Uptime Robot 专业版一年的订阅费还不够支付工程师一小时的费用。

在选择外部监控提供商时,你需要考察一下几个关键的功能:

  • 监测 HTTP/HTTPS。
  • 监测 TLS 证书是否失效或已过期。
  • 关键字匹配(当关键字缺失或存在时发出警报)。
  • 通过 API 自动创建或更新检查。
  • 通过电子邮件、短信、Webhook 或其它一些简单的机制发出警报。

本书始终坚持基础设施即代码的理念,因此这里也应该使用代码自动执行外部监视检查。

内部健康检查

应用程序弹性越好,越难通过黑盒监控检测到这些故障。为了解决这个问题,应用程序可以自行展开健康检查,并且应该这么做。某个功能或服务的开发人员最了解怎样才能保持健康,而且他们可以编写代码检查结果,并通过容器外部(例如 HTTP 端点)的监控公开结果。

用户是否满意

Kubernetes 为我们提供了一种简单的机制用户检查应用程序的存活或就绪状态,因此,这是一个不错的起点。

更高级的就绪探针应该搞清楚:“应用程序需要什么才能完成工作?”

服务和断路器

当应用程序监测到下游故障时,它将自行退出服务(通过就绪检查),以防止问题得到解决之前,收到更多的请求。

优雅地降级

断路器对于尽快解决问题很有用,但设计服务时应当避免因一个或多个组件服务不可用而导致整个系统故障。相反,你应该让系统优雅地降级,即使它们无法完成应当承担的所有工作,但也仍然可以完成其中的部分工作。

15.4 小结

  • 黑盒监控通过观察系统的外部行为,监测可预测的故障。
  • 分布式系统暴露了传统监控的局限性,因为分布式系统没有完全正常运行或完全宕机的状态,部分降级的服务是它们的恒定状态。换句话说,这条船上没有完全正确的东西。
  • 日志对于事件发生后的故障排除很有用,但是很难扩展。
  • 指标开辟了一个新维度,不再简单地表示工作/不工作之别,它提供的连续数字类型的时间序列数据涉及到系统的方方面面。
  • 指标可以帮助你发现问题的原因,并在服务中断之前发现出现问题的趋势。
  • 跟踪能够记录某个请求生命周期内的各个事件以及准确的时间,以帮助你调试性能问题。
  • 可观察性是传统的监控、日志记录、指标和跟踪以及其它了解系统的方式的结合。
  • 可观察性还代表了根据事实和反馈向工程团队文化的转变。
  • 通过外部黑盒检查来检查面向用户的服务是否正常非常重要,但不要尝试构建自己的服务,请使用 Uptime Robot 等第三方监控服务。
  • 如果用户不满意,再多的 9 也没用。