Murre:一个轻量化的K8S监控工具

admin 2024年2月27日13:55:24评论11 views字数 5154阅读17分10秒阅读模式
Murre是一个为k8s提供按需、可扩展的容器监控指标工具。Murre直接从每个K8s节点上的kubelet组件获取容器或节点的CPU和内存资源指标,并使用来自每个PodSpec的相关K8s请求和限制来丰富资源信息。
Murre:一个轻量化的K8S监控工具
极简主义。我知道这个词很夸张,但请耐心听我说。基本上,你只需拥有那些能给你的生活带来价值和意义的东西,把其他的都拿走。极简主义是关于清除多余的东西,把你的时间和精力用在最有价值的事情上,因为我们在生活中只有有限的精力、时间和空间。
最好的软件开发者本质上都是极简主义者。极简主义并不意味着写更少的代码,而是写优雅而紧凑的代码,并做好一件事。在这个意义上,极简主义意味着设计使用尽可能少的硬件和软件资源的系统——因为你能做到。而且你认为事情应该是这样的。
像许多开发人员一样,我们将这种方法应用到我们设计和构建的所有软件中。
当我们希望为客户提供K8s节点资源和使用指标时,我们就开始构建Murre项目。作为一家构建全面的Kuberenetes应用程序监控解决方案的公司,需求很明确。我们希望监控和导出集群基础设施层中的资源——采集每个节点上容器的CPU、内存和磁盘使用情况。
听起来很简单,对吧?问题是,作为一个嵌入Kubernetes集群核心的监控平台,我们总是带着极简主义的标志。我们的目标是尽可能做到轻量化——这也意味着如果没有必要的话,我们更倾向于不在集群上安装任何第三方工具。
因此,我们开始了k8s节点指标的采集工作。但不会在集群中安装众所周知的Metric Server[https://kubernetes-sigs.github.io/metrics-server/]。

常规的K8s指标监控方法

我们经常看到客户在监控被k8抽象过的物理层资源(CPU、内存、磁盘等)时遇到困难。Kubernetes生态系统包括一些附加组件,用于聚合和采集来自Kubernetes集群的监控数据。Metrics Server就是这些实用的附加组件之一。
Metrics Server是一个集群范围的资源使用数据聚合器。它从Summary API收集容器或节点的CPU或内存消耗等指标,这些指标由Kubelet在每个节点上提供。但是,它是一个附加组件,这意味着它不是开箱即用的,也不是默认部署在标准托管的Kubernetes平台上。
Metrics Server的目标是可扩展而且高效,对于一个典型的100个节点的集群,它要要大约100m的CPU和200 MiB的内存。它只允许在内存中存储接近实时的指标,支持对CPU或内存使用情况进行专项检查,或者通过监控服务进行定期查询,以便在较长时间内保留数据。
虽然它的设计可以很好地扩展K8s集群,但也会存在问题。在集群中运行第三方服务意味着你必须不时对其进行维护和故障排除。它可能会崩溃,占用比预期更多的资源,或者无法工作。Metrics Server存在的问题,对一个已经高负载的集群来说可谓是雪上加霜。还会让我们的服务严重依赖Metric Server存在单点故障。

选择轻量化

首先,我们通过直接在集群中的每个节点上使用Linux操作系统工具(如top、ps等)来读取节点的资源。这解决了一个难题,即不需要任何预安装或维护就能对节点资源监控。然而,它确实带来了效率问题。top和ps等工具的输出需要解析。它们也是Linux而不是K8s工具,因此需要上层来理解进程资源,并将其转化为我们的客户所了解和理解的容器资源。
Metrics Server是以集中式方式构建的,每个集群就一个。那么,它如何从所有不同的节点获得所需的所有指标呢?快速浏览一下代码就能清楚地找到答案——只需查询每个节点上运行的Kubelet。突然之间,这一切都变得有意义了,因为K8s本身也必须查询节点资源,以便Kubelet工作流能够运行!

Kubelet是什么?

Kubelet是一个运行在Kubernetes集群的每个节点上的进程,并根据请求为给定节点创建、销毁或更新pod及其容器。基本上,Kubelet是运行在每个节点上的主要“节点代理”,它使用PodSpecs(描述pod的YAML或JSON对象)工作。使用通过各种机制(主要是通过apiserver)提供的PodSpecs,并确保这些PodSpecs中描述的容器正常运行。
在Kubernetes中,调度、抢占和驱逐是集群功能的重要组成部分。调度是指确保pod与节点匹配,以便Kubelet可以运行容器。抢占是终止低优先级pod的过程,以便高优先级pod可以调度到节点上,而驱逐是终止节点上的一个或多个pod的过程。
Kubelet在这些主要场景中发挥着关键作用。例如,一个称为节点压力驱逐的场景。Kubernetes经常检查节点资源,如磁盘压力、CPU或内存不足(OOM)。如果节点中的资源(如CPU或内存)消耗达到一定阈值,Kubelet将开始驱逐pod以释放资源。
这正是Kubelet必须不断获取Kubernetes资源指标来完成其工作的原因,并将这些指标提供给其他可能也需要这些信息的服务。太好了!因此,如果Kubelet已经向Metrics Server公开了它的指标API,这意味着我们自己也可以使用这个API。
真是一石二鸟啊!我们可以直接调用该API获取指标数据,而无需在集群上部署Metrics Server,但是我们也可以在每个节点内部查询——而无需离开节点。

深入Kubelet源码

我们开始研究Kubelet源码,以便弄清楚它如何获得K8s资源指标,以及它如何将这些数据作为API公开。我们发现Kubelet不仅读取每个集群节点上的资源使用情况,而且还使用Prometheus格式的度量标准公开数据——这也是我们希望看到的!
Kubelet API没有文档,但是从它的源码中我们找到了接口。还有更多不用于度量/统计的API,但这些超出了本文研究的范围。当然还有更多的特性有待发掘,但我们现在将专注于K8s的指标。
你可以在这里找到一些指标定义
pkg/kubelet/server/server.go:
Murre:一个轻量化的K8S监控工具
为了访问kubelet API,我们可以看到数据:
Murre:一个轻量化的K8S监控工具
Kubelet的一些API返回json,一些输出实际的度量数据。以下是一些值得注意的地方:
/metrics/cadvisor:该接口源自cadvisor,它提供了容器资源消耗的所有度量,例如:CPU、内存、文件系统、网络。
  • /metrics/resource:该接口列出容器资源(CPU,内存),和cadvisor接口类似,但也提供pod级和节点级资源使用情况。
  • /stats/summary:该接口以JSON格式提供聚合的资源消耗数据。默认情况下,它将描述所有资源(CPU、内存、文件系统和网络,就像cadvisor接口一样),但是你可以传递一个only_cpu_and_memory=true的标志作为请求参数,则只获得CPU和内存数据。
    下面是接口的响应结构:
type Summary struct {
// Overall node stats.
Node NodeStats `json:"node"`
// Per-pod stats.
Pods []PodStats `json:"pods"`
}

// NodeStats holds node-level unprocessed sample stats.
type NodeStats struct {
// Reference to the measured Node.
NodeName string `json:"nodeName"`
// Stats of system daemons tracked as raw containers.
// The system containers are named according to the SystemContainer* constants.
SystemContainers []ContainerStats `json:"systemContainers,omitempty" patchStrategy:"merge" patchMergeKey:"name"`
// The time at which data collection for the node-scoped (i.e. aggregate) stats was (re)started.
StartTime metav1.Time `json:"startTime"`
// Stats pertaining to CPU resources.
CPU *CPUStats `json:"cpu,omitempty"`
// Stats pertaining to memory (RAM) resources.
Memory *MemoryStats `json:"memory,omitempty"`
// Stats pertaining to network resources.
Network *NetworkStats `json:"network,omitempty"`
// Stats pertaining to total usage of filesystem resources on the rootfs used by node k8s components.
// NodeFs.Used is the total bytes used on the filesystem.
Fs *FsStats `json:"fs,omitempty"`
// Stats about the underlying container runtime.
Runtime *RuntimeStats `json:"runtime,omitempty"`
// Stats about the rlimit of system.
Rlimit *RlimitStats `json:"rlimit,omitempty"`
}

// PodStats holds pod-level unprocessed sample stats.
type PodStats struct {
// Reference to the measured Pod.
PodRef PodReference `json:"podRef"`
// The time at which data collection for the pod-scoped (e.g. network) stats was (re)started.
StartTime metav1.Time `json:"startTime"`
// Stats of containers in the measured pod.
Containers []ContainerStats `json:"containers" patchStrategy:"merge" patchMergeKey:"name"`
// Stats pertaining to CPU resources consumed by pod cgroup (which includes all containers' resource usage and pod overhead).
CPU *CPUStats `json:"cpu,omitempty"`
// Stats pertaining to memory (RAM) resources consumed by pod cgroup (which includes all co
  • /pods:该接口提供有关在节点上运行的pod的信息,以及完整的pod规格和状态。还可以使用K8s客户端的podLister接口获取该数据。虽然有用,但这个特定的数据与我们的资源度量监控无关。
  • /metrics:这个接口公开了与Kubelet自己的内部统计数据相关的指标。了解下就可以了,它不会用于我们的需求。

现在看看Murre项目

Murre是一个OSS(开源软件)工具,它可以帮助你获得容器的CPU和内存指标,而不需要在集群上安装任何东西。它的工作方式与metrics-server相同,只是不存储指标。使用Murre,你可以过滤特定的命名空间,pod甚至容器名称,以专注于你想要的确切指标。
Murre利用3种不同的API来获取并提供这些指标所需的数据:
1、NodeList: 为了发现和维护所有可用节点的列表。
2、/metrics/cadvisor:获得容器实际的资源使用指标。如前所述,这个API用于每个节点。
3、PodList:用K8s对每个容器的资源请求和限制来丰富数据。
下面是Murre的处理流程:
Murre:一个轻量化的K8S监控工具

项目地址:

https://github.com/groundcover-com/murre
https://github.com/groundcover-com/murre/blob/main/images/demo.gif

原文始发于微信公众号(LemonSec):Murre:一个轻量化的K8S监控工具

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年2月27日13:55:24
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Murre:一个轻量化的K8S监控工具http://cn-sec.com/archives/2529793.html

发表评论

匿名网友 填写信息