本文转载自微信公众号“twt企业IT社区”,作者twt社区。转载本文请联系twt企业IT社区公众号。优化首先要确立一个目标,优化要实现什么样的目标,期望满足什么样的需求,解决业务增长过程中出现的什么问题。监控平台的建立是为了获取系统对于Kubernetes集群和运行的业务系统的真实性能。结合现有系统当前的真实性能,可以设置合理的优化指标,基本的基线指标可以合理评估当前的Kubernetes容器和业务系统。表现。本文介绍如何构建有效的监控平台。1、监控平台建设的所有优化指标均建立在对系统充分了解的基础上。基于Kubernetes的常规监控方案大概有3种。我们采用更主流的解决方案,这也降低了部署成本和集成后的复杂性Spend。我们选择的主流方案是Prometheus+Grafana+cAdvisor+(待部署:Prometheus-operator,met-ric-server),通过Prometheus提供相关数据,Prometheus定时获取数据与Grafana展示,异常告警使用AlertManager.在实际部署过程中,也可以考虑使用Kube-prometheus项目(见注1),节省整体部署的大量工作。下面是官方的架构图,涉及到以下组件:PrometheusOperatorPrometheusAlertmanagerPrometheusnode-exporterPrometheusAdapterforKubernetesMetricsAPIskube-state-metricsGrafana上图中的Service和ServiceMonitor是Kubernetes资源。一个ServiceMonitor可以通过labelSelector匹配一种Service,Prometheus也可以通过labelSelector匹配多个ServiceMonitor。主要监控范围分为:资源监控、性能监控、任务监控、事件告警监控等,因为本文主要讲性能优化,所以重点放在性能监控上,但优化是一项全方位的工作,所以还会涉及到资源、健康、事件、日志等,以及每个监控类型的告警管理。*注1:项目地址如下。部署方式请参考项目介绍,此处不再赘述:https://github.com/coreos/kube-prometheus2。数据采集??各个维度的数据采集主要通过以下方式:部署cAdvisor(见注2)采集容器相关的性能指标数据,使用Prometheus通过metrics接口抓取;各种监控和日志收集代理也可以根据需要部署在独立的容器中,随着容器在Pod中开始监控,根据实际需要收集各种数据;通过Prometheus-node-exporter收集宿主机的性能指标数据,通过exporter通过暴露的metrics接口使用Prometheus抓取应用的网络性能(Http、Tcp等)数据,并使用Prometheus抓取k8S资源对象的状态指标数据通过kube-state-metrics通过暴露的metrics接口,通过etcd、kubelet、kube-apiserver、kube-controller-manager、kube通过暴露的metrics接口与Prometheus抓取-暴露的metricsscheduler本身会获取节点上k8S集群相关的一些特征指标数据。*注2:node-exporter:负责收集主机信息和操作系统信息,作为容器运行在监控主机上。cAdvisor:负责收集容器信息,作为容器运行在监控主机上。3.资源监控描述资源监控主要分为这几类:比如:CPU、内存、网络、磁盘等信息监控(其他也监控GPU等),以及各个组件服务的资源使用情况,自定义告警阈值等(内部可以获取简单的告警,复杂的告警指标需要根据集群和业务特点,通过获取参数或者编写PromQL进行计算),建立全方位的监控指标(主要监控指标项可以参考Kube-prometheus部署后的相关信息,这里不再赘述),主要监控项如下;容器CPU、Mem、Disk、Network等资源占用情况;Node、Pod相关性能指标数据;容器进程本身主动暴露各种索引数据;各组件性能指标涉及组件如:ECTD、APIServer、ControllerManager、Scheduler、Kubelet等;4.主要指标监控主要监控指标基于Google提出的四个指标:延迟(Latency)、流量(Traffic)、错误数(Errors)、饱和度(Saturation)。在实际操作中,可以使用USE或RED(见注3和注4)作为测量方法。USE用于资源,RED用于服务。它们在不同的监控场景中以不同的维度来描述,它们可以组合起来描述大多数的监控场景。指标,合理使用以下监控指标可以帮助用户判断当前K8S集群的实际运行情况,并可以根据指标变化反复优化各项参数和服务,以达到更好的状态。更详细的监控指标信息请参考Kube-Prometheus相关监控信息。4.1Cadvisor索引集合cAdvisor提供的容器索引(详见参考文献1)最终由Linux底层cgroup提供。就像节点指标一样,但我们主要关注的是CPU/内存/网络/磁盘。1.CPU(Utilization)对于ContainerCPU利用率,K8S为每个容器提供了多个指标:#过去10秒容器CPU的平均负载container_cpu_load_average_10s#累计用户CPU时间(即未在内核中花费的时间)container_cpu_user_seconds_total#Cumulative系统CPU消耗时间(即在内核中花费的时间)container_cpu_system_seconds_total#累计CPU消耗时间container_cpu_usage_seconds_total#容器CPU份额container_spec_cpu_quota#容器CPU配额container_spec_cpu_shares#查询显示CPU总和(rate(container_cpu_usage_seconds_total[5m]))by(container_name)#过去10秒容器CPU的平均负载值container_cpu_load_average_10s{container="",id="/",image="",name="",namespace="",pod=""}#累计系统CPUconsumptiontimesum(rate(container_cpu_usage_seconds_total{name=~".+"}[1m]))by(name)*100#所有容器的CPU使用率总和,累加后每个CPU使用率除以esum(rate(container_cpu_usage_seconds_total{container_name="webapp",pod_name="webapp-rc-rxli1"}[1m]))/(sum(container_spec_cpu_quota{container_name="webapp",pod_name="webapp-rc-rxli1"}/100000))2.CPU(饱和度)sum(速率(包含r_cpu_cfs_throttled_seconds_total[5m]))by(container_name)3.memorycAdvisor中提供的内存指标可以在官网找到。以下是内存指标(除非另有说明,均以字节为单位):#CacheUsagecontainer_memory_cache#RSS内存,即常驻内存集,分配给进程使用的是实际物理内存,而不是缓存在虚拟机上的虚拟内存磁盘。RSS内存包括所有分配的栈内存和堆内存,以及加载到物理内存的共享内存库占用的内存空间,但不包括进入交换分区container_memory_rss#container虚拟内存使用的内存。虚拟内存(swap)是指使用磁盘来模拟内存的使用。当物理内存即将用完或达到一定比例时,可以将一些不用的内存数据交换到硬盘上存储,需要的时候再转移到物理内存中。container_memory_swap#当前内存使用量,包括所有已使用的内存,是否被访问(包括缓存、rss、swap等)累计内存分配失败次数container_memory_failures_total#内存分配失败次数.container_failcnt(Utilizationrate)通过PromQL具体条件查询容器中job的内存使用情况:container_memory_usage_bytes{instance="10.10.2.200:3002",job="panamax",name="PMX_UI"}18kubelet是通过container_memory_working_set_bytes来判断是否OOM的,所以使用workingset来评估容器内存使用情况是比较合理的。在下面的查询中,我们需要过滤“POD”容器,也就是这个容器的父cgroup,会跟踪pod中所有容器的统计信息。sum(container_memory_working_set_bytes{name!~"POD"})byname5.对于异常获取内存(饱和)OOM没有直接的指标项,因为在OOM后Container会被kill掉,可以灵活使用如下查询获取,这里使用label_join结合kube-state-metrics指标:sum(container_memory_working_set_bytes)by(container_name)/sum(label_join(kube_pod_con-tainer_resource_limits_memory_bytes,"container_name","","container"))by(container_name)6.磁盘(利用率)在处理磁盘I/O时,我们跟踪所有磁盘利用率通过搜索、阅读和写作。Cadvisor有以下指标可以作为基础指标:#容器磁盘执行I/O秒数container_fs_io_time_seconds_total#容器磁盘累计加权I/O时间container_fs_io_time_weighted_seconds_total#查询容器文件系统读取速率(字节/秒)sum(rate(container_fs_writes_bytes_total{image!=""}[1m]))without(device)#查询容器文件系统写入速率(字节/秒)秒)sum(rate(container_fs_writes_bytes_total{image!=""}[1m]))without(device)最基本的磁盘I/O利用率是读取/写入的字节数,将这些结果相加得到每个容器的整体磁盘I/O利用率:sum(rate(container_fs_reads_bytes_total[5m]))by(container_name,device)7.Network(utilization)容器的网络利用率,可以选择以bytes或datapackage为单位。网络指标有点不同,因为所有网络请求都是在Pod级别而不是在容器级别发出的。以下查询将按pod名称显示每个pod的网络利用率:Cumulativecountofpacketlosscontainer_network_transmit_packets_dropped_total#Receivebytes(1m)sum(rate(container_network_receive_bytes_total{id="/"}[1m]))by(id)#Uploadbytes(1m)sum(rate(container_network_transmit_bytes_total{id="/"}[1m]))by(id)8.网络(饱和度)在无法知道确切的网络带宽的情况下,无法明确定义网络的饱和度,可以考虑丢弃数据包。表示当前已经饱和,看下面参数:#接收container_network_receive_packets_dropped_total时累计丢包数#container_network_transmit_packets_dropped_total发送时累计丢包数*注3:对于cAdvisor容器资源,USE方法指标比较简单如下:Utilization:UtilizationrateSaturation:饱和度Error:Error*注4:USE方法的定义:Resource:所有服务器功能组件(CPU,Disk,Services等)Utilization:资源忙于服务工作的平均时间Saturation:Time需要排队不能提供服务Errors:错误事件统计RED方法的解释:Rate:每秒的请求数。错误:失败的请求数。参考1:关于cAdvisor更详细的参数信息可以从地址获取,也可以结合更适合自己集群的监控指标:https://github.com/google/cadvisor/blob/master/docs/storage/prometheus.md参考2:关于Node_exporter,有兴趣的可以参考Prometheus项目中Node_exporter的说明,如下:https://github.com/prometheus/node_exporter5。事件告警监控监控Event转换过程的变化信息,以下只是部分Alarm信息,Kube-Prometheus项目中告警指标最多,相关告警事件也可以从第三方导入:#Therearejobs执行失败:kube_job_status_failed{job="kubernetes-service-endpoints",k8s_app="kube-state-metrics"}==1#集群节点状态错误:kube_node_status_condition{condition="Ready",status!="true"}==1#集群节点内存或磁盘资源不足:kube_node_status_condition{condition=~”OutOfDisk|MemoryPressure|DiskPressure”,status!=”false”}==1#集群中存在故障PVC:kube_persistentvolumeclaim_status_phase{phase=”Failed”}==1#集群中有一个Pod启动失败:kube_pod_status_phase{phase=~”Failed|Unknown”}==1#pod容器最近30分钟重启过:changes(kube_pod_container_status_restarts[30米])>06。日志监控日志也是K8S集群和容器/应用服务非常重要的数据来源,从日志和信息中也可以获取各种指标,主流方式常驻Agent用于收集日志信息,并将相关信息发送到Kafka集群,最后写入ES。Grafana也是用来统一展示各种指标的。加载宿主机本地卷,使用Agent(Filebeat或Fluentd)收集宿主机部署的所有容器的dump日志,发送到远程ES集群处理;另一种是为业务组(或Pod)收集容器内部日志,系统/业务日志可以独立存储,日志收集容器可以独立部署Sidecar方式收集日志。对于DaemonSet和Sidecar这两种日志采集方式,您可以根据实际需要选择部署;通过部署在各个Node上的Agent收集日志。Agent会将数据收集到LogstashServer集群中,然后Logstash对其进行处理清洗后发送到Kafka集群中,再将数据存储到Elasticsearch中。后期可以通过Grafana或者KibanaShow来完成,这也是比较主流的方式。6.2日志场景需要采集的各种日志主要分为以下几种场景:1.宿主系统内核日志采集:一方面是宿主系统内核日志,可以辅助开发/运维分析以及诊断一些常见的问题,例如:LinuxKernelPanic中涉及的其他致命异常(Attemptedtokilltheidletask,Attemptedtokillinit,killinginterrupthandler),这些情况需要导致它关闭的程序或任务,通常异常可能是任何意外情况;另外一方面是各种Driver异常,比如:Driver内核对象异常或者一些使用GPU的场景,各种硬件驱动异常可能是比较常见的错误;然后是文件系统异常,一些特定的场景(比如:虚拟机,特定的文件格式),其实经常会出现问题。这些问题出现后,开发者没有很好的监控和诊断方法。在这部分中,您实际上可以检查主机内核日志中的一些异常。2、组件日志收集:K8S集群中的各个组件是集群非常重要的部分,包括内部组件和外部组件如:APIServer、Controller-man-ger、Kubelet、ECTD等,会产生大量的日志日志数量可用于各种错误分析和性能优化,还可以帮助用户分析K8S集群各组件的资源使用情况分析和异常情况分析;还有各种第三方插件的日志(尤其是网络插件或者一些厂商贡献的算法),也是优化分析的重点;3、业务日志收集:业务日志分析也是优化中非常重要的一环。业务系统的特性(如:web类、微服务类、API接口类、基础组件类)都需要日志来收集分析,结合后面资源预测和业务部署的章节,可以更好的把握业务特性,创建合理的发布配置和Pod配置,并根据业务访问、活动周期、业务高峰、调用关系的日志分析优化整个流程。
