ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Kubernetes CRI 容器指标(Container Metrics)API 深度解析:从 cAdvisor 集成到运行时原生统计的演进

Kubernetes CRI 容器指标(Container Metrics)API 深度解析:从 cAdvisor 集成到运行时原生统计的演进 Kubernetes CRI 容器指标Container MetricsAPI 深度解析从 cAdvisor 集成到运行时原生统计的演进【免费下载链接】communityKubernetes Community Documentation项目地址: https://gitcode.com/GitHub_Trending/com/community本文以 Kubernetes Community 仓库中 contributors/devel/sig-node/cri-container-stats.md 为骨架结合 CRIContainer Runtime Interface 设计文档与 SIG Node 会议记录系统梳理 Kubernetes 如何通过 CRI 从容器运行时获取 CPU、内存、文件系统三类资源指标帮助读者理解 CRI 指标 API 的完整消息结构、时间戳设计动机以及 Kubelet 的消费方式与版本演进脉络。引言容器指标为什么需要进入 CRI容器运行时接口CRIContainer Runtime Interface为容器运行时接入 Kubernetes 提供了统一抽象CRI 期望运行时向 Kubelet 提供容器的资源使用统计信息。在 CRI 出现之前这项能力并不在运行时接口的职责范围内——Kubelet 依赖的是一个独立开源库 cAdvisor 来获取容器指标。任何接入 Kubernetes 的容器运行时例如早期的 Docker 和 Rkt都必须为 cAdvisor 添加对应的包才能支持跟踪容器与镜像文件系统的指标。这意味着运行时集成者需要同时理解 cAdvisor 的内部实现与 Kubernetes 的集成方式集成点分散、维护成本高。既然 CRI 已经成为运行时集成的统一抽象很自然的演进方向就是把提供容器指标这一能力并入 CRI从而消除一个独立的集成点。从仓库中的 Kubelet 开发指南 可以看到Kubelet 通过 CRI 与运行时如containerd交互将声明式的 Kubernetes API 翻译为命令式的 CRI API 调用指标能力正是这条交互链路上的一环。背景cAdvisor 时代的指标获取方式在 CRI 提供指标能力之前容器指标获取的典型链路是Kubelet 内嵌运行 cAdvisor 库由 cAdvisor 负责收集容器与镜像文件系统的指标指标聚合后通过 Kubelet 的Summary APIstats/summary定义于staging/src/k8s.io/kubelet/pkg/apis/stats/v1alpha1/types.go对外暴露供监控管道及其他组件消费每个需要接入 Kubernetes 的容器运行时都要在 cAdvisor 中新增对应包以支持跟踪容器和镜像文件系统的指标。这套机制的代价是运行时与指标收集深度耦合任何新运行时接入都要改动 cAdvisor 代码。SIG Node 2017 年的会议记录sig-node/archive/meeting-notes-2017.md中也讨论了这一痛点——即便是容器统计改由 CRI 提供后CRI-O 等实现仍需要运行 cAdvisor 来监控文件系统等指标社区曾讨论是否应让 cAdvisor 的指标收集逻辑可配置以便按传入配置收集不同运行时的统计信息而不是每接入一个运行时就去修改 cAdvisor 代码。指标职责划分Pod 级归 cAdvisor容器级归 CRIKubelet 负责依据 Pod 所属的QoSQuality of Service等级创建 Pod 级 cgroup并将该 cgroup 作为父 cgroup 传递给运行时确保 Pod 使用的所有资源Pod sandbox、容器等都被计入该 cgroup。因此Kubelet 有能力借助内建的 cAdvisor在Pod 级别跟踪资源使用情况CRI 的 API 增强则聚焦于容器级别的指标。这一划分在 CRI 1.5 时期已见端倪SIG Node 2017 年初的会议记录显示社区计划核心指标从运行时通过 CRI 获取而为了支撑完整的/summaryAPI其余指标仍通过 cAdvisor 收集同时有成员提出长期来看 Kubelet 将基于节点/Pod 级指标做决策而 Pod 级指标正是由容器指标推导而来见 sig-node/archive/meeting-notes-2017.md。也就是说CRI 容器指标并非要取代所有监控数据源而是接管容器级核心资源指标这一层。CRI 容器指标 API两个 RPCCRI 在容器指标上暴露了两个 gRPC 方法protobuf 定义见仓库关联文档其正式定义对应staging/src/k8s.io/cri-api/pkg/apis/runtime/v1的api.proto// ContainerStats returns stats of the container. If the container does not // exist, the call returns an error. rpc ContainerStats(ContainerStatsRequest) returns (ContainerStatsResponse) {} // ListContainerStats returns stats of all running containers. rpc ListContainerStats(ListContainerStatsRequest) returns (ListContainerStatsResponse) {}两者的语义差异清晰ContainerStats针对单个容器查询统计信息若容器不存在调用会返回错误ListContainerStats批量列出所有运行中容器的统计信息适合 Kubelet 周期性全量拉取的场景。SIG Node 2019 年会议记录中提到的 PR #80105。消息结构详解三类资源与时间戳设计ContainerStats消息承载三类资源的使用统计CPU、内存、文件系统。完整 protobuf 定义如下// ContainerStats provides the resource usage statistics for a container. message ContainerStats { // Information of the container. ContainerAttributes attributes 1; // CPU usage gathered from the container. CpuUsage cpu 2; // Memory usage gathered from the container. MemoryUsage memory 3; // Usage of the writable layer. FilesystemUsage writable_layer 4; } // CpuUsage provides the CPU usage information. message CpuUsage { // Timestamp in nanoseconds at which the information were collected. Must be 0. int64 timestamp 1; // Cumulative CPU usage (sum across all cores) since object creation. UInt64Value usage_core_nano_seconds 2; } // MemoryUsage provides the memory usage information. message MemoryUsage { // Timestamp in nanoseconds at which the information were collected. Must be 0. int64 timestamp 1; // The amount of working set memory in bytes. UInt64Value working_set_bytes 2; } // FilesystemUsage provides the filesystem usage information. message FilesystemUsage { // Timestamp in nanoseconds at which the information were collected. Must be 0. int64 timestamp 1; // The underlying storage of the filesystem. StorageIdentifier storage_id 2; // UsedBytes represents the bytes used for images on the filesystem. // This may differ from the total bytes used on the filesystem and may not // equal CapacityBytes - AvailableBytes. UInt64Value used_bytes 3; // InodesUsed represents the inodes used by the images. // This may not equal InodesCapacity - InodesAvailable because the underlying // filesystem may also be used for purposes other than storing images. UInt64Value inodes_used 4; }对每个字段做逐一拆解ContainerStats容器统计信息attributes容器的标识信息ContainerAttributescpu容器 CPU 使用情况memory容器内存使用情况writable_layer可写层文件系统使用情况即容器镜像之上的可写层占用。CpuUsageCPU 使用情况timestamp信息采集时刻的时间戳单位纳秒必须大于 0usage_core_nano_seconds自对象创建以来的累计CPU 使用量所有核求和单位为核·纳秒。注意它是累计值而非瞬时速率消费方通过两次采样之差除以时间间隔来计算 CPU 利用率。MemoryUsage内存使用情况timestamp同上纳秒时间戳必须大于 0working_set_bytes工作集内存大小单位字节。工作集是内核内存回收机制下不会被优先回收的内存视图Kubelet 的驱逐eviction决策正是基于该类指标展开这也解释了为什么容器指标需要保证一定的新鲜度见下文。FilesystemUsage文件系统使用情况timestamp纳秒时间戳必须大于 0storage_id文件系统对应的底层存储标识StorageIdentifierused_bytes文件系统上镜像所占用的字节数。注释明确指出该值可能不同于文件系统总占用字节也可能不等于CapacityBytes - AvailableBytes因为底层文件系统可能同时被其他用途占用inodes_used镜像占用的 inode 数。同样它可能不等于InodesCapacity - InodesAvailable因为底层文件系统可能还服务于镜像存储以外的用途。为什么每个资源都带时间戳每个资源使用消息都包含采集时间戳这一设计是刻意的。原因在于不同资源指标的采集成本差异很大——例如文件系统指标天然比 CPU/内存指标采集代价更高更新频率可能更低。带有时间戳后消费方能够判断数据的陈旧程度stale/fresh而运行时则可以灵活调整不同资源的采集与更新节奏不必为了让所有指标保持一致而牺牲采集效率。文档进一步点明虽然 CRI 不规定统计信息的刷新频率但 Kubelet 对部分资源如内存工作集需要最低限度的新鲜度保证以便在资源压力下及时回收驱逐。相关要求正在被制定并将纳入 CRI。为什么是带时间戳的缓存统计而不是按需统计文档引用了一个关键设计决策请求带时间戳的缓存统计cached stats with timestamps而非按需实时计算。背后原因可从 SIG Node 会议记录窥见一斑——sig-node/archive/meeting-notes-2017.md 中记录了 containerd 的实践containerd 本身提供容器指标但按需采集on-demand由 cri-containerd/Kubelet 负责控制轮询周期并决定是否缓存统计结果。按需统计在高频轮询下会产生额外开销而缓存统计配合时间戳让消费方在数据足够新与采集成本可控之间取得平衡同时把采集节奏的控制权留给运行时。演进状态1.7 落地 API1.8 接入 Kubelet文档给出了明确的版本演进时间线Kubernetes 1.7容器指标调用被加入 CRI。这与 CRI 概述文档 的 v1.7 状态更新一致——CRI 已被扩展以支持从运行时收集容器指标同时该版本中 Docker CRI 集成转正 GA、旧的非 CRI Docker 集成被完全移除。回溯到 1.5 版本社区已知问题列表中明确写着容器指标尚未在 CRI 中定义issue #27097可见该 API 是 1.5 之后逐步补齐的能力Kubernetes 1.8Kubelet 获得可选开关可以通过 CRI 统计来消费容器指标。Kubelet 依据pkg/kubelet/cadvisor.go中的UsingLegacyCadvisorStats函数定义于pkg/kubelet/cadvisor/util.go判断应该使用哪个指标源——即决定是走 CRI 从运行时获取还是回退到传统的 cAdvisor 采集路径。换句话说1.7 定义了运行时如何上报1.8 打通了Kubelet 如何消费。从仓库中的 E2E 节点测试记录contributors/devel/sig-testing/monitoring.md可以看到/stats/summary端点是否如实上报资源使用情况本身就是 NodeConformance 测试的断言对象这印证了 Summary API 作为最终出口在测试体系中的地位。设计权衡与社区实践要点综合文档与 SIG Node 会议讨论可以总结出以下关键设计原则供运行时实现者与监控组件开发者参考Pod 级指标与容器级指标分离Pod 级指标由 Kubelet 基于 QoS cgroup 借助 cAdvisor 聚合CRI 只负责容器级核心指标避免重复造轮子最小指标集原则CRI 只纳入满足 Kubelet 需求所必需的指标CPU、内存、可写层文件系统需求演进时再逐步扩展 API而非一次性铺开缓存统计 时间戳统计信息可缓存、可滞后但必须携带采集时间戳消费方自行判断新鲜度Kubelet 对关键资源如内存工作集关系驱逐决策保留新鲜度要求累计值而非瞬时值CPU 用量以自创建以来的累计核·纳秒数上报由消费方计算差值得到利用率规避瞬时采样抖动文件系统口径谨慎对待used_bytes与inodes_used专指镜像占用不代表文件系统总占用或容量差监控组件不可直接套用容量公式。结语CRI 容器指标 API 是 Kubernetes 运行时抽象演进的关键一环它把容器级资源统计从 cAdvisor 的旁路集成收敛为运行时自身的职责让运行时接入 Kubernetes 时只需实现统一的 gRPC 接口即可同时交付生命周期管理与资源统计能力。对运行时开发者而言理解ContainerStats/ListContainerStats的语义与三类资源消息的时间戳约定是实现合规 CRI 实现的前提对监控与 SRE 工程师而言把握缓存统计、累计值、镜像专用口径这几个要点才能正确解读来自 Kubelet Summary API 的容器指标。延伸阅读可继续阅读 CRI 完整接口文档、CRI 网络规范 以及 SIG Node 开发文档索引 获取更多上下文容器指标在 CRI 1.5 时期尚未定义的历史问题#27097与后续演进过程可参考 SIG Node 2017 年会议记录。【免费下载链接】communityKubernetes Community Documentation项目地址: https://gitcode.com/GitHub_Trending/com/community创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表