详解云原生全栈监控
发布时间:2022-08-03 11:55:11 所属栏目:云计算 来源:互联网
导读:前言 当前全球企业云化、数字化进程持续加速,容器、微服务等云原生技术在软件架构中快速渗透,IT 架构云化、复杂化持续驱动性能监控市
前言 当前全球企业云化、数字化进程持续加速,容器、微服务等云原生技术在软件架构中快速渗透,IT 架构云化、复杂化持续驱动性能监控市场。企业云化、数字化持续转型,以及为了考虑系统的弹性、效率,企业软件开发中大量云原生技术的应用推动全球 IT 监控市场快速变化,如何全面、有效的对容器、K8s、微服务进行监控是当下云原生技术面临的重要课题。 背景和挑战 云化产品通常采用服务化框架,由一系列微服务组成,且微服务是可以独立运行的进程,不同服务可使用不同开发语言,可能分布部署在几千台服务器上,甚至可能横跨多个不同的数据中心,服务间使用轻量的通信机制;服务之间存在复杂的调用关系,对运维人员理解系统的行为或分析系统性能带来巨大挑战 如: (1)容器是否正常运行 (2)K8S是否正常运行。 (3)微服务是正常 (5)业务调用出现问题,如何快速找出哪个服务发生失败? (6)某个业务调用耗时较长,如何快速找到性能瓶颈点? (7)如何快速获取某次调用的业务日志进行分析定位? 解决方案 概述 云原生监控体系包括: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 } } 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 容器监控 容器监控使用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 1. 2. 3. 4. 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。 (编辑:平顶山站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |