与Cadvisor相爱相杀的日子

2020-08-25

介绍

Cadvisor使用Go语言开发,利用Linux的cgroups获取容器的资源使用信息,在K8S中集成在Kubelet里作为默认启动项,官方标配。

问题1:Kubelet内置Cadvisor暴露的TCP指标value全为0?

相关issue:https://github.com/kubernetes/kubernetes/issues/60279
开发者明确表达:
upload successful

问题2:Cadvisor暴露的指标不含PodIP?如何与其他系统如CAT做联动查询?

相关issue:https://github.com/google/cadvisor/issues/2591

此issue由笔者所提,笔者的公司用CAT做应用监控,开发们收到资源告警,只能得到对应的PodName,而CAT搜集的是应用的IP,无法联动查询

原来,cadvisor确实缓存了容器的IP,通过docker inspect命令,但是在暴露Metric给Prometheus时未带上此IP,于是笔者修改了一下代码,
在本地通过docker启动镜像时,可以拿到IP,但当发到k8s中,发现无法得到PodIP,继续查阅源码,发现如下代码:

    // Obtain the IP address for the container.
    // If the NetworkMode starts with 'container:' then we need to use the IP address of the container specified.
    // This happens in cases such as kubernetes where the containers doesn't have an IP address itself and we need to use the pod's address
    ipAddress := ctnr.NetworkSettings.IPAddress
    networkMode := string(ctnr.HostConfig.NetworkMode)
    if ipAddress == "" && strings.HasPrefix(networkMode, "container:") {
        containerID := strings.TrimPrefix(networkMode, "container:")
        c, err := client.ContainerInspect(context.Background(), containerID)
        if err != nil {
            return nil, fmt.Errorf("failed to inspect container %q: %v", id, err)
        }
        ipAddress = c.NetworkSettings.IPAddress
    }

不知道是测试人员的疏漏还是啥缘故?虽然代码里写了kubernetes中部署的容器可以拿到IP,但实际无法拿到,也得到开发者肯定的答复
upload successful

最终,开发者建议我用Kube-state-metrics,然后通过Prometheus的Join语法关联查询得到IP,经过实践,可以满足需求,Join语法如下:

container_cpu_usage_rate{container="prism", namespace="dev"}  * on(pod) group_left(pod_ip, instance) kube_pod_info{namespace="dev"}

Prometheus支持一对多、多对一、和多对多的指标关联,可查询官方文档确认使用方式。