jason2006xu
作者jason2006xu2022-07-25 09:56
技术经理, 昆仑银行

云原生全栈监控

字数 8279阅读 1050评论 3赞 9

云原生全栈监控

作者:JasonXu 某城商行

前言

当前全球企业云化、数字化进程持续加速,容器、微服务等云原生技术在软件架构中快速渗透, IT 架构云化、复杂化持续驱动性能监控市场。企业云化、数字化持续转型,以及为了考虑系统的弹性、效率,企业软件开发中大量云原生技术的应用推动全球 IT 监控市场快速变化,如何全面、有效的对容器、 K8s 、微服务进行监控是当下云原生技术面临的重要课题。

背景和挑战

云化产品通常采用服务化框架,由一系列维服务组成,且微服务是可以独立运行的进程,不同服务可使用不同开发语言,可能分布部署在几千台服务器上,甚至可能横跨多个不同的数据中心,服务间使用轻量的通信机制;服务之间存在复杂的调用关系,对运维人员理解系统的行为或分析系统性能带来巨大挑战 如:

(1) 容器是否正常运行。
(2) K8S 是否正常运行。
(3) 微服务是正常。
( 4 )业务调用出现问题,如何快速找出哪个服务发生失败?
( 5 )某个业务调用耗时较长,如何快速找到性能瓶颈点?
( 6 )如何快速获取某次调用的业务日志进行分析定位?

解决方案

概述

云原生监控体系包括: Healthchecks 、 Metrics 、 Logging 、 Tracing 。 Healthchecks :健康检查可以定期检查某个应用的存活状态; Metrics :度量指标监控,在离散的时间点上产生数值点; Logging :日志监控; Tracing :调用链监控。

各种监控工具适用场景如下图所示:

健康检查

微服务架构,为了保证所有服务可用,当服务发生问题时能及时摘除有问题的服务需要定期检测服务可用性,即健康检查。通常健康健康检查包括 TCP 与 HTTP 两种。即定时发送 TCP 或 HTTP 请求,根据响应来确定服务是否可用。一般通过 TCP 定期请求来判定网络层是否正常,而通过 Http 请求判断应用层是否正常。服务要配置好请求接口,检测服务定期向指定的接口发送 http 请求,并根据接口响应码和响应时间判断。 Spring boot 的 end port /health 可以检查应用的健康状态,举例说,当我们访问 http://localhost:8088/health 时,可以看到 HealthEndPoint 给我们提供默认的监控结果,包含 磁盘检测和数据库检测。

{

"status": "UP",

"diskSpace": {

"status": "UP",

"total": 398458875904,

"free": 315106918400,

"threshold": 10485760

},

"db": {

"status": "UP",

"database": "MySQL",

"hello": 1

}

}

容器监控

容器监控使用 Prometheus- cAdvisor , cAdvisor 是谷歌专为监控容器性能状态设计的一个开源工具, cAdvisor 提供有 Push 和 Pull 两种获取性能数据的接口。 Push 接口指的是由 cAdvisor 主动将数据周期性的推送到远端的存储服务中, Influxdb 与 cAdvisor 的对接就是通过这个接口完成的。而 Pull 接口则允许外部访问服务随时主动从 cAdvisor 获取到当时时刻的性能数据,然后自行处理, Prometheus 与 cAdvisor 的对接用的是这种方法。基于容器的微服务监控和原始的监控是有很大区别的,因为服务的实例生存周期很短,分分钟可能就会有容器的生灭。微服务的容器与宿主机的监控离不开 CPU, 内存 , 磁盘 , 网卡这些基础的性能指标,对于宿主机的监控来说,我们可以依然使用原始的监控方式,每个宿主机安装一个代理来采集服务器的性能指标,代理在采集性能指标的时候可以打上 时间戳]和相应的标签来区分不同 性能指标的数据维度( metric ),然后将监控数据汇总到 时间序列数据库,里面的数据可以对接目前一些开源的组件来进行可视化的展示,也可以对接报警服务(结合报警服务的报警策略)进行报警。容器的监控自然就和宿主机不太一样了,我们不能说给每个容器镜像内部都集成一个监控代理( agent ) , 这样的话侵入性太强 , 不易于维护。 Prometheus有很多的 Exporter 可以用来采集监控数据,例如我们想采集 Kubernetes 上所有容器( pod )的性能指标的话, Promethus 可以通过直接配置多个 Kubernetes ApiServer 的 Endpoints 来监控整个 Kubernetes 集群。

K8S 监控

K8S 集群层面选择使用 Prometheus 。集群层面的监控又分为 Node 、 K8S 基础组件、 K8S 资源对象三大类。

1 、对于 Node 的监控, Prometheus 提供了 node-exporter ,可采集到 CPU 、内存、磁盘 IO 、磁盘使用率、网络包量、带宽等数据;
2 、 K8S 基础组件类的 kubelet 、 kube-apiserver 、 kube-controller-manager 和 kube-scheduler 等,都提供了 metrics 接口暴露自身的运行时的监控数据,这些数据都可被部署在 K8S 集群中的 Prometheus 直接拉取到;
3 、结合 cadvisor 和 kube-state-metrics ,可直接采集到 K8S 中 Pod 的 CPU 、内存、磁盘 IO 、网络 IO 等数据。由 CoreOS 开源的 Kube-Prometheus 项目,极大简化了 Prometheus 的安装部署运维工作。

基于 Kubernetes 实现的微服务应用级的监控插件,如下图:

在 Kubernetes 的 master 节点,也就是安装 apiserver 的那台服务器上运行一个监控插件,该插件可以通过一个 kubernetes 提供的官方客户端来访问 apiserver, 首先我们要告知插件要监控哪个 namespace 下的哪个 service ,然后,插件通过和 apiserver 进行交互获取某个 service 下所有 Pods 的实例,插件会并发访问所有 pod 提供的 /metrics 接口( Path 可配) , 并给每个 pod 的返回数据( json 格式,遵守一定的数据格式契约)打上 pod_name 的标签来标识每个 pod 返回的 metrics ,打上 pod_name 标签的同时也会打上 service_name 的标签用来区分具体是哪个 service 的监控数据。 Kubernetes 主要提供了如下 5 种服务发现模式和 Prometheus 进行集成 :Node 、 Pod 、 Endpoints 、 Service 、 Ingress 。监控 K8S 将使用 Prometheus federation 的形式, k8s 集群外部的 Prometheus 从 k8s 集群中 Prometheus 拉取监控数据,外部的 Prometheus 才是监控数据的存储。 k8s 集群中部署 Prometheus 的数据存储层可以简单的使用 emptyDir, 数据只保留 24 小时 ( 或更短时间 ) 即可,部署在 k8s 集群上的这个 Prometheus 实例即使发生故障也可以放心的让它在集群节点中漂移。

1 )创建 namespace 取名 ns-monitor
2 )在 k8s 中部署 node-exporter
Node-exporter 用于采集 kubernetes 集群中各个节点的物理指标,比如: Memory 、 CPU 等。可以直接在每个物理节点是直接安装,这里我们使用 DaemonSet 部署到每个节点上,使用 hostNetwork: true 和 hostPID: true 使其获得 Node 的物理指标信息,配置 tolerations 使其在 master 节点也启动一个 pod 。

创建 node-exporter.yml 文件

3-1 )创建编辑 rabc.yml
rbac.yml 定义了 Prometheus 容器访问 k8s apiserver 所需的 ServiceAccount 和 ClusterRole 及 ClusterRoleBinding
3-2 )创建编辑 configmap.yml 进行 configmap 中的 prometheus 的配置文件。
3-3 ) prometheus-deploy.yml 定义 Prometheus 的部署
3-4 ) prometheus-svc.yml 定义 Prometheus 的 Service
需要将 Prometheus 以 NodePort, LoadBalancer 或使用 Ingress 暴露到集群外部,这样外部的 Prometheus 才能访问它
3-5 )使用 yml 文件创建对象
kubectl create -f rbac.yml
kubectl create -f configmap.yml
kubectl create -f prometheus-deploy.yml
kubectl create -f prometheus-svc.yml
4 )配置配置 Prometheus Federation
完成 Kubernetes 集群上的 Prometheus 的部署之后,下面将配置集群外部的 Prometheus 使其从集群内部的 Prometheus 拉取数据。 实际上只需以静态配置的形式添加一个 job 就可以。
5 )配置 pushgateway

日志监控

Fluentd 是一个通用的信息收集、整理、转发的流式数据处理工具。默认情况下 Docker 会将所有容器输出到系统控制台的内容重定向到以容器 ID 命名的一个本地目录中,只需要定期采集所有这些目录的内容就能一字不漏的将容器的输出捕获出来,这种方式的侵入性很小,但由于是周期性的收集,日志在汇聚端(例如 Kibana )的展示会有一定的延时,延时长度与日志收集的周期相关。相反的,如果使用 Docker 的日志驱动(启动 docker 后台服务时指定参数– log-driver=fluentd )将获得实时性很好的汇聚端日志展示,但由于日志直接发送到了远端的 Fluentd 服务,会使得在本地主机上的 docker logs 命令失效。两种方式的共性在于:不论通过哪一种方式,收集到的日志都能够以容器名称、镜像、标签等对容器使用十分友好的维度进行检索。 Kubernetes 集群本身不提供日志收集的解决方案,我们采用 fluentd-->kafka-->logstash-->elasticsearch-->kibana 的方式,直接在应用程序中将日志信息推送到采集后端。

调用链监控

调用链定义:在系统完成一次业务调用的过程中,把服务之间的调用信息 ( 时间、接口、层次、结果 ) 打点到日志中,然后将所有的打点数据连接为一个树状链条就产生了一个调用链。跟踪系统把过程中产生的日志信息进行分析处理,将业务端到端的执行完整的调用过程进行还原,根据不同维度进行统计分析;从而标识出有异常的服务调用,能够快速分析定界到出异常的服务;同时可根据数据统计分析系统性能瓶颈。

Dapper, a Large-Scale Distributed Systems Tracing Infrastructure描述了其中的原理和一般性的机制。模型中包含的术语也很多,理解最主要的两个即可:
· Trace :一次完整的分布式调用跟踪链路。
· Span :跨服务的一次调用; 多个 Span 组合成一次 Trace 追踪记录。
下面通过一次用户服务请求来完成调用链过程模拟:

左图为一个和 5 台服务器相关的一个服务,包括:前端( A ),两个中间层( B 和 C ),以及两个后端( D 和 E )。当一个用户(这个用例的发起人)发起一个请求时,首先到达前端,然后发送两个 RPC 到服务器 B 和 C 。 B 会马上做出反应,但是 C 需要和后端的 D 和 E 交互之后再返还给 A ,由 A 来响应最初的请求。右表示对应 Span 的管理关系。每个节点是一个 Span ,表示一个调用。至少包含 Span 的名、父 SpanId 和 SpanId 。节点间的连线下表示 Span 和父 Span 的关系。所有的 Span 属于一个跟踪,共用一个 TraceId 。从图上可以看到对前端 A 的调用 Span 的两个子 Span 分别是对 B 和 C 调用的 Span , D 和 E 两个后端服务调用的 Span 则都是 C 的子 Span 。跟踪系统根据用户请求每次生成的全局唯一的 ID ( TraceId ), TraceId 在 span 间传递,将不同服务的“孤立的”日志串在一起,重组还原出更多有价值的信息。如今调用链系统有很多实现,用的比较多的如 zipkin ,还有已经加入 CNCF 基金会并且的用的越来越多的 Jaeger 。

调用链模型格式

为了能将一系列埋点串接成一个完整的调用链,并区分不同请求的调用链日志信息,同时信息中需要包含请求状态与时长,对于不同业务应用可能需要有特殊的信息记录到日志中;所以调用链日志信息 (Span) 应包含如下内容:

一次业务请求调用链模型:

对于 Trace 而言,最基础的能力是能够记录请求在多个服务之间调用的传播、依赖关系并进行可视化。而从 Trace 本身的数据特点而言,它是规则化、标准化且带有依赖关系的访问日志,因此可以基于 Trace 去计算并挖掘更多的价值。下面是 SLS OpenTelemetry Trace 的实现架构,核心是通过数据编排计算 Trace 原始数据并得到聚合数据,并基于 SLS 提供的接口实现各类 Trace 的附加功能。例如:

  1. 依赖关系:这是绝大部分的 Trace 系统都会附带的功能,基于 Trace 中的父子关系进行聚合计算,得到 Trace Dependency
  2. 服务 / 接口黄金指标: Trace 中记录了服务 / 接口的调用延迟、状态码等信息,基于这些数据可以计算出 QPS 、延迟、错误率等黄金指标。
  3. 上下游分析:基于计算的 Dependency 信息,按照某个 Service 进行聚合,统一 Service 依赖的上下游的指标
  4. 中间件分析: Trace 中对于中间件(数据库 /MQ 等)的调用一般都会记录成一个个 Span ,基于这些 Span 的统计可以得到中间件的 QPS 、延迟、错误率。

告警相关:通常基于服务 / 接口的黄金指标设置监控和告警,也可以只关心整体服务入口的告警(一般对父 Span 为空的 Span 认为是服务入口调用)。

· Metrics :

o 通常都是 range 查询,每次查询某一个单一的指标 / 时间线,或者一组时间线进行聚合,例如统一某个应用所有机器的平均 CPU

o 时序类的查询一般 QPS 都较高(主要有很多告警规则),为了适应高 QPS 查询,需要把数据的聚合性做好

o 对于这类数据都会有专门的时序引擎来支撑,目前主流的时序引擎基本上都是用类似于 LSM Tree 的思想来实现,以适应高吞吐的写入和查询( Update 、 Delete 操作很少)

o 同时可观测性数据还有一些共性的特点,例如高吞吐写入(高流量、 QPS ,而且会有 Burst )、超大规模查询特点、时间访问特性(冷热特性、访问局部性等)。

业务调用链路监控

Skywalking 是一款比较优秀的开源的应用性能监控工具,支持对分布式系统的监控、跟踪和诊断。它提供了如下的主要功能特性:


Service Topology监控
调用链路监控可以从两个角度去看待。通过给服务添加探针并产生实际的调用之后,我们可以通过 Skywalking 的前端 UI 查看服务之间的调用关系。我们简单模拟一次服务之间的调用。新建两个服务, service-provider 以及 service-consumer ,服务之间简单的通过 Feign Client 来模拟远程调用。


从图中可以看到 :
· 有两个服务节点: provider & consumer
· 有一个数据库节点: localhost 【 mysql 】
· 一个注册中心节点
consumer 消费了 provider 提供出来的接口。

一个系统的拓扑图让我们清晰的认识到系统之间的应用的依赖关系以及当前状态下的业务流转流程。细心的可能发现图示节点 consumer 上有一部分是红色的,红色是什么意思呢?

红色代表当前流经 consumer 节点的请求有一断时间内是响应异常的。当节点全部变红的时候证明服务现阶段内就彻底不可用了。运维人员可以通过 Topology 迅速发现某一个服务潜在的问题,并进行下一步的排查并做到预防。

Skywalking Trace监控

Skywalking 通过业务调用监控进行依赖分析,提供给我们了服务之间的服务调用拓扑关系、以及针对每个 endpoint 的 trace 记录。
我们在之前看到 consumer 节点服务中发生了错误,让我们一起来定位下错误是发生在了什么地方又是什么原因呢?


在每一条 trace 的信息中都可以看到当前请求的时间、 GloableId 、以及请求被调用的时间。我们分别看一看正确的调用和异常的调用。

Trace调用链路监控

图示展示的是一次正常的响应,这条响应总耗时 19ms ,它有 4 个 span :

· span1 /getStore = 19ms 响应的总流转时间
· span2 /demo2/stores = 14ms feign client 开始调用远程服务后的响应的总时间
· span3 /stores = 14ms 接口服务响应总时间
· span4 Mysql = 1ms 服务提供端查询数据库的时间
这里 span2 和 span3 的时间表现相同,其实是不同的,因为这里时间取了整。

在每个 Span 中可以查看当前 Span 的相关属性。

· 组件类型 : SpringMVC 、 Feign
· Span状态 : false
· HttpMethod: GET
· Url :

http://192.168.16.125:10002/demo2/stores

这是一次正常的请求调用 Trace 日志,可能我们并不关心正常的时候,毕竟一切正常不就是我们期待的么!我们再来看下,异常状态下我们的 Trace 以及 Span 又是什么样的呢。

发生错误的调用链中 Span 中的 is error 标识变为 true ,并且在名为 Logs 的 TAB 中可以看到错误发生的具体原因。根据异常情况我们就可以轻松定位到影响业务的具体原因,从而快速定位问题,解决问题。通过 Log 我们看到连接被拒,那么可能是我们的网络出现了问题(可能性小,因为实际情况如果网络出现问题我们连这个 trace 都看不到了),也有可能是服务端配置问题无法正确建立连接。通过异常日志,我们迅速就找到了问题的关键。

服务性能监控

服务性能可以实现以下关键指标:
1 、关键业务指标:响应时间、 Apex 、吞吐率、错误率
2 、事务:耗时百分比、响应时间、吞吐量、 Apdex 、错误率、调用次数
3 、数据库: SQL 耗时、平均响应时间、吞吐率、 SQL 语句执行计划、代码堆栈
4 、 NoSQL : Memcached/Redis/MogooDB 的操作总耗时、平均响应时间、吞吐率
5 、外部应用: HTTP/Thrif/Dubbo/Web Service 的响应时间占比、平均响时间、响应总时间、吞吐率、错误率
6 、 MQ : RabbitMQ/JMS/ActiveMQ 生产者、消费者的消息总数、每分钟消息数、平均消息发送时间、总流量
7 、 JVM :内存使用量、线程、 HTTP 会话

如果觉得我的文章对您有用,请点赞。您的支持将鼓励我继续创作!

9

添加新评论3 条评论

JAGXUJAGXU存储运维管理, ZTZQ
2022-11-21 15:22
感谢分享!
彤晓鲁彤晓鲁项目经理, H3C
2022-08-30 11:19
感谢分享
h123aixh123aix网络工程师, ji
2022-08-04 14:37
感谢分享!
Ctrl+Enter 发表

本文隶属于专栏

最佳实践
不同的领域,都有先行者,实践者,用他们的最佳实践来加速更多企业的建设项目落地。

日志分析平台选型优先顺序调研

发表您的选型观点,参与即得50金币。

作者其他文章

相关文章

相关问题

相关资料