1。Prefacekubectltop可以很方便地查看节点和pod的实时资源使用情况:比如CPU和内存。本文将介绍其数据链路和实现原理,同时使用kubectltop对k8s中的监控系统进行讲解,从而一窥全貌。最后对一些常见问题进行说明:为什么kubectltop会报错?kubectltopnode是怎么计算的,和直接在节点上top有什么区别?kubectltoppod是怎么计算的,包括暂停?kubectltoppod和exec进入pod后看到的top不一样吗?为什么kubectltoppod和dockerstats获取的值不一样?以下命令运行环境为:k8s1.8k8s1.132.使用kubectltop是基本命令,但需要部署配套组件获取监控值1.8以下:部署heapter1.8以上:部署metric-serverkubectltopnode:查看节点使用情况kubectltoppod:查看pod的使用情况如果不指定pod名称,将显示namespace下的所有pod。--containers可以显示pod中所有容器指标含义:与k8s中的request和limit一致,CPU单位为100m=0.1内存单位1Mi=1024Kipod内存值是它的实际使用情况,也是判断的依据设置限制时oom。一个pod的使用量等于其所有业务容器的总和,不包括暂停容器,其值等于cadvisr中的container_memory_working_set_bytes指标节点。指标节点的值不等于该节点上所有pod值的总和,也不等于机器上直接运行top或free见值3.实现原理3.1数据链路调度组件使用的数据比如kubectltop,k8sdashboard,和HPA是一样的。数据链接如下:使用heapster时:apiserver会在hepaster服务内部通过proxy直接将metric请求转发给集群。使用metrics-server时:apiserver通过/apis/metrics.k8s.io/地址访问metric这里可以对比一下kubectgetpod时的日志:3.2metricapi可以查到,heapster使用代理转发,metric-都是server而普通的pod使用的是api/xx的资源接口。heapster采用的代理方式是有问题的:proxy只是一个代理请求,一般用于故障排除。不够稳定,版本不可控。heapster的接口不能像apiserver那样也有完整的认证和客户端集成。如果两边都维护,成本很高。比如genericapiserverpod的监控数据是核心指标(HPA调度),应该和pod本身具有相同的状态,即metrics应该作为资源存在,比如metrics.k8s.io的形式被称为MetricApi,所以官方从1.8版本开始逐渐抛弃heapster,并在上面提出了Metricapi的概念,而metrics-server是这个概念的官方实现,用于从kubelet下载获取指标,取代之前的heapster3.3kube-aggregator加上metrics-server组件,收集需要的数据,暴露接口,但是此时heapster和heapster没有区别,最关键的一步是如何打印Requests到/apis/metrics。来自apiserver的k8s.io被转发到metrics-server组件?解决方案是:kube-aggregator。kube-aggregator是apiserver的强大扩展。它允许k8s开发者编写自己的服务,并在k8sapi中注册这个服务,即扩展API。其实metric-server在1.7版本就已经完成了,只是在等待kube-aggregator的出现。kube-aggregator是apiserver中的实现。默认情况下不启用某些k8s版本。您可以添加这些配置以启用它。其核心功能是动态注册、发现摘要和安全代理。比如metric-server注册pod和node时:3.4监控系统当metricapi这个概念被提出的时候,官方也提出了一个新的监控系统。监控资源分为两种:Coremetrics(核心指标):从Kubelet、cAdvisor等获取测量数据,然后通过metrics-server提供给Dashboard、HPAcontroller等。自定义指标:APIcustom.metrics.k8s.io由PrometheusAdapter提供,可以支持Prometheus收集的任何指标。核心指标只包括node和pod的cpu和内存。一般来说,核心指标对HPA来说已经足够了,但是如果要基于自定义指标实现HPA:比如请求qps/5xx错误数,就需要使用自定义指标。目前Kubernetes中的自定义指标一般都是由Prometheus提供,然后使用k8s-prometheus-adapter聚合到apiserver,达到和核心指标一样的效果。3.5前面提到kubelet中,heapster和metric-server都只是数据的传递和聚合,都是调用kubelet的api接口获取的数据,而cadvisor模块其实就是在kubelet代码中收集指标,你可以访问node节点上的10255端口(1.11版本后为10250端口)获取监控数据:KubeletSummarymetrics:127.0.0.1:10255/metrics,暴露node和pod汇总数据Cadvisormetrics:127.0.0.1:10255/metrics/cadvisor,exposing容器维度数据示例,容器内存使用:虽然Kubelet提供了metric接口,但实际的监控逻辑还是由内置的cAdvisor模块负责。演化过程如下:从k8s1.6开始,kubernetes开始将cAdvisor集成到kubelet中,不再需要单独的从k8s1.7开始,kubeletmetricsAPI不再包含cadvisormetrics,而是提供了一个独立的API接口用于summary。从k8s1.12开始,k8s中删除了cadvisor监控的端口,所有的监控数据由kubeletAPI统一至此,k8s范围内的监控系统就结束了。3.6cadvisorCadvisor由Google开源,使用Go开发。Cadvisor不仅可以收集一台机器上所有正在运行的容器的信息,包括CPU使用率、内存使用率、网络吞吐量和文件系统使用率,还提供基本的查询接口和http接口,方便其他组件抓取数据。在K8S中作为默认启动项集成在Kubelet中,是k8s官方的标准配置。cadvisor获取的数据结构示例:核心逻辑是通过newmemoryStorage和sysfs实例创建manager实例。管理器的接口定义了很多获取容器和机器信息的函数。cadvisor指标解读:cgroup-v1(https://www.kernel.org/doc/Documentation/cgroup-v1/memory.txt)cadvisor在获取指标时实际上调用了runc/libcontainer库,libcontainer是对cgroup的封装文件,也就是说,cadvsior只是一个转发或者说,它的数据来自于cgroup文件。3.7cgroupcgroup文件中的值是监控数据的最终来源,比如memusage的值,来自/sys/fs/cgroup/memory/docker/[containerId]/memory.usage_in_bytes如果没有内存限制,limit=machine_mem,否则来自/sys/fs/cgroup/memory/docker/[id]/memory.limit_in_bytesmemoryusage=memory.usage_in_bytes/memory.limit_in_bytes一般情况下cgroup文件夹的内容包括CPU,内存,disk,network等信息:比如memory下几个常用指标的含义:memory.stat中的信息最全:原理到此结束,下面是kubectltop的前几个问题:4.问题4.1为什么kubectltop会报错一般情况下top错误有以下几种。kubectltoppod-v=10可以看到具体的调用日志:如果没有部署heapster或者metric-server,或者pod运行异常,可以查看对应的pod日志。,采集指标前,报notfound错误,默认不超过1分钟,可以查看kubelet的10255端口是否开放,默认会使用这个只读端口获取指标,而你也可以使用heapster或者metric-在server配置中添加证书,替换为10250认证端口4.2如何计算kubectltoppodmemory,包括pausecontainer?每次启动pod,都会有一个暂停容器。既然是容器,肯定有资源消耗(一般在2-3M以内)内存),在cgroup文件中,业务容器和暂停容器都在同一个pod文件夹下。而cadvisor在查询pod的内存使用情况时,首先获取的是pod下的容器列表,然后逐个获取容器的内存使用情况。但是这里的容器列表是不包含pause的,所以toppod的最终结果是不包含pause容器的。pod的内存使用量计算kubectltoppod得到的内存使用量,并不是cadvisor中的container_memory_usage_bytes,而是container_memory_working_set_bytes,计算方式为:container_memory_usage_bytes=container_memory_rss+container_memory_cache+kernelmemorycontainer_memory_working_set_bytes=container_memory_usage_bytes–total_inactive_file(未激活的匿名缓存页)container_memory_working_set_bytes是容器实际使用的内存量,也是limit受限时的oom判断依据。cadvisor中的container_memory_usage_bytes对应cgroup中的memory.usage_in_bytes文件,但是container_memory_working_set_bytes没有具体的文件,其计算逻辑在cadvisor的代码中,如下:同理,node的内存使用量也是container_memory_working_set_bytes。4.3kubectltopnode如何计算,和直接在节点上top有什么区别kubectltopnode得到的cpu和memory值并不是节点上所有pod的总和,所以不要直接相加。topnode是机器上cgroup根目录下的汇总统计。在机器上top命令直接看到的值不能直接和kubectltop节点对比,因为计算逻辑不一样,比如内存。大概的对应关系是(前者在机器上是top,后者是kubectltop):rss+cache=(in)active_anon+(in)active_file4.4kubectltoppodandexec进入pod后看到top。即使限制了pod,pod中top看到的内存和cpu总量仍然是机器总量,不是pod的可分配进程RSS是进程使用的所有物理内存(file_rss+anon_rss),即Anonymouspages+Mappedapges(包括共享内存)cgroupRSS是(anonymousandswapcachememory),不包括共享内存。两者都不包含文件cache4.5为什么kubectltoppod和dockerstats获取的值不一样?dockerstatsdockerID可以看到容器当前的使用情况:如果你的pod中只有一个容器,你会发现dockerstats的值不等于kubectltop的值,既不是container_memory_usage_bytes也不是container_memory_working_set_bytes。因为dockerstats和cadvisor的计算方式不同,所以整体的值会比kubectltop小:计算逻辑是:dockerstats=container_memory_usage_bytes-container_memory_cache5.后记一般情况下我们不需要关心node的使用情况或者一直是pod,因为有集群自动伸缩(cluster-autoscaler)和pod水平伸缩(HPA)来应对这两类资源变化。资源指标的含义更适合使用prometheus持久化cadvisor数据,用于回溯历史或发送告警。其他补充:虽然kubectltophelp显示支持Storage,但是直到1.16版本还是不支持heapster。1.13之前需要metric-server。这部分kubectltophelp的输出是错误的。只提到heapsterk8sdashboard中的监控图中默认使用heapster。切换到metric-server后,数据会出现异常。需要额外部署一个metric-server-scraperpod进行接口转换。详情参考pr:https://github.com/kubernetes/dashboard/pull/3504六。参考https://github.com/kubernetes-sigs/metrics-server/issues/193https://github.com/kubernetes/kubernetes/pull/83247https://www.cnblogs.com/liuhongru/p/11215447.htmlhttpshttps://github.com/DirectXMan12/k8s-prometheus-adapter/blob/master/docs/walkthrough.md#quantity-valueshttps://github.com/fabric8io/kansible/blob/master/vendor/k8s.io/kubernetes/docs/design/resources.mdhttps://erdong.site/linux/system/computer-unit-conversion.htmlhttps://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#meaning-of-cpuhttps://access.redhat.com/documentation/zh-cn/red_hat_enterprise_linux/6/html/resource_management_guide/sec-memoryhttps://www.kernel.org/doc/Documentation/cgroup-v1/memory.txthttps://www.cnblogs.com/liuhongru/p/11215447.htmlhttps://github.com/moby/moby/issues/10824https://github.com/docker/cli/拉/80
