cAdvisor Go 客户端实战:使用官方 REST API Client 采集机器与容器监控数据
2026/9/20 22:39:01 网站建设 项目流程
  • 可观测性
  • 指标监控
  • 云原生

【免费下载链接】cadvisor

Analyzes resource usage and performance characteristics of running containers.

项目地址:https://gitcode.com/gh_mirrors/ca/cadvisor
点击查看免费下载

cAdvisor(Container Advisor)在分析运行中容器的资源使用与性能特征时,对外暴露了一套 REST API。官方在仓库的 client 目录中提供了一套 Go 语言实现的 REST API 客户端,它把api/v1.3下的机器信息、容器信息、子容器与事件等端点封装成可直接调用的 Go 方法。本文以 client/README.md 为主线,结合 client/client.go 源码、client/client_test.go 测试与 info/v1 数据结构,带你掌握如何在自己的 Go 项目中初始化客户端、查询机器与容器监控数据,并理解其底层 HTTP 调用机制。

快速开始:创建 cAdvisor 客户端

官方客户端的使用方式非常简洁。在 Go 项目中引入github.com/google/cadvisor/client包后,通过NewClient创建客户端实例,参数是 cAdvisor REST 端点的根地址:

import "github.com/google/cadvisor/client" client, err := client.NewClient("http://192.168.59.103:8080/")

其中192.168.59.103:8080需要替换为你实际部署的 cAdvisor 服务地址(cAdvisor 默认监听8080端口)。docs/clients.md 中给出了相同的引入方式与调用client.MachineInfo()的最小示例。

从 client/client.go 的源码可以看到,NewClient在构造时会做两件事:

  1. URL 规范化:如果传入的 URL 末尾没有/,会自动补上,避免后续路径拼接出错;
  2. 拼接 API 版本前缀:客户端内部实际访问的是${url}api/v1.3/,也就是说所有请求都指向 cAdvisor 的 v1.3 版本 REST 接口,这一前缀在 newClient 中通过fmt.Sprintf("%sapi/v1.3/", url)生成,并保存在Client结构体的baseURL字段中。

Client结构体本身只有两个字段(client/client.go#L37-L41):baseURLhttpClient,默认复用http.DefaultClient,无需额外配置即可开始使用。

查询机器信息:MachineInfo

MachineInfo()方法返回整台宿主机(cAdvisor 所在节点)的基础信息,封装为v1.MachineInfo结构体,所有字段都会被填充完整:

mInfo, err := client.MachineInfo()

client/README.md 给出了一个典型的返回值示例(Go 调试器格式):

(*v1.MachineInfo)(0xc208022b10)({ NumCores: (int) 4, MemoryCapacity: (int64) 2106028032, Filesystems: ([]v1.FsInfo) (len=1 cap=4) { (v1.FsInfo) { Device: (string) (len=9) "/dev/sda1", Capacity: (uint64) 19507089408 } } })

对应到实际数据模型,MachineInfo定义在 lib/model/machine.go#L182-L251,通过 info/v1/machine.go#L55 的别名导出为v1.MachineInfo。其核心字段包括:

字段JSON 键含义
NumCoresnum_cores机器 CPU 核心数(含超线程逻辑核)
NumPhysicalCoresnum_physical_cores物理核心数
NumSocketsnum_socketsCPU 插槽数
CpuFrequencycpu_frequency_khz核心最大时钟频率(KHz)
MemoryCapacitymemory_capacity机器内存总量(字节)
SwapCapacityswap_capacity交换分区总量(字节)
HugePageshugepages大页信息列表
Filesystemsfilesystems文件系统列表(见下)
DiskMapdisk_map磁盘设备信息映射
NetworkDevicesnetwork_devices网络设备列表
TopologytopologyCPU/内存 NUMA 拓扑层次
MachineID/SystemUUID/BootID同名机器、系统与启动标识
CloudProvider/InstanceType/InstanceID同名云厂商、实例类型与实例 ID

上例中的Filesystems[]v1.FsInfo切片,每个元素对应一块文件系统(lib/model/machine.go#L21-L40),关键字段有Device(块设备名,如/dev/sda1)、Capacity(文件系统总字节数)、Type(设备类型)、Inodes(可用 inode 数)。DeviceMajor/DeviceMinor用于与 blkio 统计关联,序列化为 JSON 时会被省略(json:"-")。

在 client/client_test.go#L67-L92 的TestGetMachineinfo中,测试通过httptest模拟/api/v1.3/machine端点,构造了包含NumCores: 8MemoryCapacity: 31625871360与磁盘映射的返回数据,然后调用client.MachineInfo()并用reflect.DeepEqual校验结果,可以直观看到该方法的预期行为。

查询容器信息:ContainerInfo

要获取某个具体容器的完整信息,使用ContainerInfo方法。它接收容器名称(绝对路径)和一个查询请求ContainerInfoRequest

request := v1.ContainerInfoRequest{NumStats: 10} sInfo, err := client.ContainerInfo("/docker/d9d3eb10179e6f93a...", &request)

返回值为v1.ContainerInfo结构体(lib/model/container.go#L141-L152),其中ContainerReference内嵌字段唯一标识该容器(IdNameAliasesNamespace),Spec描述容器的规格(CPU/内存/网络/文件系统限制等),Stats是按时间序列排列的历史统计数据切片,Subcontainers则列出直接的子容器引用。

理解 ContainerInfoRequest 查询参数

ContainerInfoRequest定义在 lib/model/container.go#L110-L124,控制返回数据的时间范围与采样数量,是控制请求开销的关键:

字段JSON 键含义与默认值
NumStatsnum_stats返回的最大统计样本数;-1表示返回当前所有可用统计;默认 60
Startstart查询起始时间(time.Time),省略时视为时间起点
Endend查询结束时间,省略时默认为当前时间

如果你不指定任何字段,也可以直接调用 info/v1/container.go#L38-L42 中定义的DefaultContainerInfoRequest(),它返回NumStats: 60的默认请求,即最近 60 个统计样本。

底层调用细节

ContainerInfo的实现(client/client.go#L95-L103)会拼接出api/v1.3/containers/{name}的 URL(见 containerInfoURL),然后将查询参数以 JSON 形式 POST 给服务端(详见下文 HTTP 层)。测试 TestGetContainerInfo 用NumStats: 3的请求查询/some/container,并断言服务端收到的 POST 体与预期请求完全一致,验证了请求参数的序列化与传递链路。

递归查询子容器:SubcontainersInfo

ContainerInfo只返回单个容器不同,SubcontainersInfo递归返回指定容器及其内部所有子容器的信息(client/client.go#L105-L115):

request := v1.ContainerInfoRequest{NumStats: 10} sInfo, err := client.SubcontainersInfo("/docker", &request)

请求/docker会返回 Docker 运行时下的所有容器及其嵌套子容器。该方法与ContainerInfo的差异在于:

  • 请求的端点不同:api/v1.3/subcontainers/{name}(见 subcontainersInfoURL);
  • 返回类型不同:返回的是[]v1.ContainerInfo切片,其中第一个元素是所查容器自身的信息,其后跟随各层级的子容器信息,每个元素的Subcontainers字段都会被填充。

测试 TestGetSubcontainersInfo 模拟了父容器/some/container及其两个子容器sub1sub2的返回数据,验证客户端能正确解析出 3 个ContainerInfo且顺序与内容均无误。

更多客户端能力:Docker 容器与事件

除 README 重点讲解的三种方法外,client/client.go 还提供了面向 Docker 与事件的两组实用 API。

Docker 专属查询

  • DockerContainer(name, query):按名称查询单个 Docker 容器(client/client.go#L119-L133)。底层访问api/v1.3/docker/{name},由于该端点返回的是map[string]v1.ContainerInfo,方法内部会校验 map 中恰好只有一个元素并取出;
  • AllDockerContainers(query):查询全部 Docker 容器(client/client.go#L136-L147),访问api/v1.3/docker/,将返回的 map 转换为[]v1.ContainerInfo切片。

事件查询:静态与流式

事件 API 支持两种模式(事件类型定义见 info/v1/container.go#L134-L139,包括oomoomKillcontainerCreationcontainerDeletion):

// 静态:返回满足条件的所有历史事件 einfo, err := staticClient.EventStaticInfo("?oom_events=true") // 流式:持续将发生的事件送入 channel einfo := make(chan *info.Event) go func() { err = streamingClient.EventStreamingInfo( "?creation_events=true&stream=true&oom_events=true&deletion_events=true", einfo) }() for ev := range einfo { // 处理每个事件 }
  • EventStaticInfo(client/client.go#L60-L68)访问api/v1.3/events/{name},一次性返回满足条件的[]*v1.Event
  • EventStreamingInfo(client/client.go#L72-L78)通过 getEventStreamingData 保持连接,用json.Decoder逐条解码事件流并送入传入的 channel,直至连接关闭;注意流式模式要求请求参数中包含stream=true,否则无法正确解析事件流。

仓库中的 client/clientexample/main.go 是一个完整的可运行示例,它依次演示了静态事件查询(?oom_events=true)与流式事件订阅(同时订阅创建、删除与 OOM 事件),可直接作为事件客户端的使用模板。

底层实现:统一的 HTTP 请求处理与错误语义

所有查询方法最终都汇聚到httpGetJSONData(client/client.go#L169-L202),理解它有助于排查调用中的各类异常:

  1. 请求方式:若携带postData(即ContainerInfoRequest查询参数),则以application/json发起 POST;否则发起 GET(如机器信息);
  2. 响应校验:读取响应体后,若 HTTP 状态码不是 200,直接返回包含响应正文的错误信息,例如request "..." failed with error: "..."(对应测试 TestRequestFails 验证的失败场景);
  3. JSON 反序列化:将响应体json.Unmarshal到目标结构体,失败时错误信息中会附带原始响应正文,便于定位服务端返回异常数据的问题;
  4. 网络层错误:请求发送失败、响应体为空等情况均会被包装为带明确上下文(所请求的信息名与 URL)的错误返回。

因此在实践中,每个客户端方法的调用都应检查err是否为nil,并且可以根据错误字符串中是否包含目标 URL 或响应正文快速判断是网络问题、服务端 500 还是数据格式不匹配。

如何在自己的 Go 项目中使用

cAdvisor 客户端是一个普通 Go 包,可以直接集成到你的监控、调度或运维平台中:

import ( "fmt" "github.com/google/cadvisor/client" v1 "github.com/google/cadvisor/info/v1" ) func main() { client, err := client.NewClient("http://localhost:8080/") if err != nil { panic(err) } // 机器信息 mInfo, err := client.MachineInfo() if err == nil { fmt.Printf("cores=%d memory=%d\n", mInfo.NumCores, mInfo.MemoryCapacity) } // 最近 60 个统计样本(默认值) req := v1.DefaultContainerInfoRequest() cInfo, err := client.ContainerInfo("/", &req) if err == nil { fmt.Printf("container %s, stats samples: %d\n", cInfo.Name, len(cInfo.Stats)) } // 递归查询子容器 subs, err := client.SubcontainersInfo("/docker", &req) if err == nil { fmt.Printf("docker subcontainers: %d\n", len(subs)) } }

MachineInfo可用于节点层面的容量评估与资源总量展示;ContainerInfo适合按容器查询其 CPU/内存/网络等历史统计(如容器级监控面板的数据源);SubcontainersInfo("/docker", ...)则是枚举某个运行时下全部容器清单的便捷途径。与 v2 客户端(见 client/v2/client.go)相比,v1 客户端直接对应 cAdvisor 的api/v1.3接口,返回结构以「机器/容器 + 历史统计序列」的经典模型呈现,是理解 cAdvisor 数据模型的良好起点。

验证与测试

仓库为客户端提供了完善的测试覆盖(client/client_test.go):

  • cadvisorTestClient工具函数(client/client_test.go#L34-L63)用httptest.NewServer构造本地 mock 服务,并校验 POST 请求体的NumStatsStartEnd是否与预期一致;
  • TestGetMachineinfo验证机器信息 JSON 解析的正确性;
  • TestGetContainerInfoTestGetSubcontainersInfo使用 info/v1/test 的GenerateRandomContainerInfo生成随机容器数据,并通过ContainerInfo.Eq()(lib/model/container.go#L160-L190)进行带时间容差的深度比较;
  • TestRequestFails验证服务端返回 500 时客户端错误信息的正确性。

这些测试既保证了客户端的可靠性,也为我们阅读数据结构、理解请求参数语义提供了现成的参考样例。你可以在仓库根目录执行go test ./client/...来运行客户端相关的全部测试(需要 Go 环境)。

  • 可观测性
  • 指标监控
  • 云原生

【免费下载链接】cadvisor

Analyzes resource usage and performance characteristics of running containers.

项目地址:https://gitcode.com/gh_mirrors/ca/cadvisor
点击查看免费下载

相关推荐

上一篇:开源项目推荐:watermark-dom
下一篇:终极指南:如何快速掌握llama2.c模型导出 - PyTorch到C格式转换全流程

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询