kubelet为cadvisor添加namespace/pod/container标签示例详解

 更新时间:2023年09月03日 10:42:23   作者:a朋  
这篇文章主要为大家介绍了kubelet为cadvisor添加namespace/pod/container标签示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

kubelet内嵌了cadvisor

在kubernetes中,kubelet中内嵌了cadvisor,prometheus对cadvisor指标的拉取时,使用的是kubelet的endpoints,只是metric_path改为/metrics/cadvisor。

kubelet在集成cadvisor的同时,还其添加了namespace、pod、container标签,用于定位它在kubernetes资源中的具体位置。

container_spec_cpu_period{
    container="prometheus", 
    endpoint="https-metrics", 
    id="/kubepods.slice/kubepods-burstable.slice/kubepods-burstable-pod304f6c86_d20b_45aa_95ad_db5edc2e8b43.slice/cri-containerd-cbde185ec5c5d6ff6928b10e9dc21de7548aec0e0bcbdff25a9ebf80a9fd3adf.scope", 
    image=“prometheus:latest", 
    instance=“192.168.0.1:10250", 
    job="kubelet", 
    metrics_path="/metrics/cadvisor", 
    name="cbde185ec5c5d6ff6928b10e9dc21de7548aec0e0bcbdff25a9ebf80a9fd3adf",     
    namespace="monitoring", 
    node=“node01", 
    pod="prometheus-k8s-0", 
    service="kubelet"}    100000

那么kubelet是如何为cadvisor添加这些标签的,cadvisor中有没有采集这些信息呢?

一.cadvisor的指标标签

为了验证cadvisor自身的采集能力,将cadvisor单独部署到kubernetes,配置其拉取的job=cadvisor,拉取到的指标如下:

container_cpu_usage_seconds_total{
    container_env_HOSTNAME="prometheus-k8s-0”, 
    container_env_KUBERNETES_PORT="tcp://10.233.0.1:443”, 
    container_env_KUBERNETES_PORT_443_TCP="tcp://10.233.0.1:443”, 
    container_env_KUBERNETES_PORT_443_TCP_ADDR="10.233.0.1”, 
    container_env_KUBERNETES_PORT_443_TCP_PORT="443”, 
    container_env_KUBERNETES_PORT_443_TCP_PROTO="tcp”, 
    container_env_KUBERNETES_SERVICE_HOST="10.233.0.1”, 
    …
    container_label_io_cri_containerd_kind="container”, 
    container_label_io_kubernetes_container_name="prometheus”,     // 容器名称
    container_label_io_kubernetes_pod_name="prometheus-k8s-0”,     // pod名称
    container_label_io_kubernetes_pod_namespace="monitoring”,      // namespace
    container_label_io_kubernetes_pod_uid="304f6c86-d20b-45aa-95ad-db5edc2e8b43”, 
    container_label_maintainer="The Prometheus Authors <prometheus-developers@googlegroups.com>”, 
    ...
    cpu="cpu00”, 
    endpoint="http”, 
    id="/kubepods.slice/kubepods-burstable.slice/kubepods-burstable-pod304f6c86_d20b_45aa_95ad_db5edc2e8b43.slice/cri-containerd-cbde185ec5c5d6ff6928b10e9dc21de7548aec0e0bcbdff25a9ebf80a9fd3adf.scope”, 
    image=“prometheus:latest”, 
    instance="10.233.123.70:8080”, 
    job="cadvisor”, 
    name="cbde185ec5c5d6ff6928b10e9dc21de7548aec0e0bcbdff25a9ebf80a9fd3adf”, 
    service="cadvisor"}    709.899183253

可以看到拉取的指标中的label:

  • container_env_*:

    • cadvisor采集了容器内的环境变量信息,并将其添加到指标的label中;
  • container_label_io_*:

    • cadvisor采集了容器的label信息,并将其添加到指标的label中;
    • 这些label信息包含了容器的container名称、所在的pod、所在的namespace信息;

也就是说,cadvisor可以采集到容器的container/pod/namespace信息。

那这些信息是从何而来的呢,看cadvisor的代码:

  • 对cadvisor采集的指标,使用containerLabelsFunc函数添加额外的标签;
  • containerLabelsFunc默认=DefaultContainerLabels;
// cadvisor/metrics/prometheus.go
func NewPrometheusCollector(i infoProvider, f ContainerLabelsFunc, includedMetrics container.MetricSet, now clock.Clock, opts v2.RequestOptions) *PrometheusCollector {
    if f == nil {
        f = DefaultContainerLabels        // 默认的添加标签的函数
    }
    c := &PrometheusCollector{
        infoProvider:        i,
        containerLabelsFunc: f,
        ...
    }
    if includedMetrics.Has(container.CpuUsageMetrics) {
        c.containerMetrics = append(c.containerMetrics, []containerMetric{
            {
                name:      "container_cpu_user_seconds_total",
                help:      "Cumulative user cpu time consumed in seconds.",
                valueType: prometheus.CounterValue,
                getValues: func(s *info.ContainerStats) metricValues {
                    return metricValues{
                        {
                            value:     float64(s.Cpu.Usage.User) / float64(time.Second),
                            timestamp: s.Timestamp,
                        },
                    }
                },
            }, 
        ...
    }
    return c    
}

看一下DefaultContainerLabels函数的实现:

  • 对container.spec中的label,添加了container_label_*前缀,这些label将被添加到最终的指标标签中;
  • 对container.spec中的env,添加了container_label_env_*前缀,这些label将被添加到最终的指标标签中;
// cadvisor/metrics/prometheus.go
const (
   // ContainerLabelPrefix is the prefix added to all container labels.
   ContainerLabelPrefix = "container_label_"
   // ContainerEnvPrefix is the prefix added to all env variable labels.
   ContainerEnvPrefix = "container_env_"
   // LabelID is the name of the id label.
   LabelID = "id"
   // LabelName is the name of the name label.
   LabelName = "name"
   // LabelImage is the name of the image label.
   LabelImage = "image"
)
func DefaultContainerLabels(container *info.ContainerInfo) map[string]string {
   set := map[string]string{LabelID: container.Name}
   if len(container.Aliases) > 0 {
      set[LabelName] = container.Aliases[0]
   }
   if image := container.Spec.Image; len(image) > 0 {
      set[LabelImage] = image
   }
   for k, v := range container.Spec.Labels {
      set[ContainerLabelPrefix+k] = v          // container_label_*
   }
   for k, v := range container.Spec.Envs {
      set[ContainerEnvPrefix+k] = v            // container_env_*
   }
   return set
}

最后,再看一下containerInfo的spec中的label和env是什么样子:

"labels":{
    "io.kubernetes.container.name":"node-exporter",
    "io.kubernetes.pod.name":"node-exporter-gw4qg",
    "io.kubernetes.pod.namespace":"monitoring",
    "io.kubernetes.pod.uid":"2ac69f2e-cb3c-4e4f-b890-183e457ef891"
},
"env": [
  "HOSTNAME=node01",
  "KUBERNETES_SERVICE_PORT=443",
  "KUBERNETES_PORT_443_TCP=tcp://10.233.0.1:443",
  "KUBERNETES_SERVICE_HOST=10.233.0.1",
  "KUBERNETES_PORT_443_TCP_PORT=443",
  "KUBERNETES_SERVICE_PORT_HTTPS=443",
  "KUBERNETES_PORT=tcp://10.233.0.1:443",
  "KUBERNETES_PORT_443_TCP_ADDR=10.233.0.1",
  ...
],

cadvisor对原始的label和env添加了前缀,返回给prometheus:

  • 对label:

    • 原始的label=“io.kubernetes.container.name”,加上前缀,变成:container_label_io_kubernetes_container_name;
  • 对env:

    • 原始的env=HOSTNAME,加上前缀,变成:container_env_HOSTNAME;

二. kubelet集成cadvisor的指标标签

kubelet在集成cadvisor时,自定义了为指标额外添加标签的逻辑containerLabelsFunc,没有使用DefaultContainerLabels

kubelet传入的函数=containerPrometheusLabelsFunc:

// kubernetes/pkg/kubelet/server/server.go
r.RawMustRegister(metrics.NewPrometheusCollector(prometheusHostAdapter{s.host}, containerPrometheusLabelsFunc(s.host), includedMetrics, clock.RealClock{}, cadvisorOpts))

containerPrometheusLabelsFunc函数的代码实现如下:

  • 从containerInfo.Spec.label中,提取io.kubernetes.pod.name的值,作为pod名称的label-value;
  • 从containerInfo.Spec.label中,提取io.kubernetes.pod.namespace的值,作为namespace名称的label-value;
  • 从containerInfo.Spec.label中,提取io.kubernetes.container.name的值,作为container名称的label-value;
// kubernetes/pkg/kubelet/server/server.go
func containerPrometheusLabelsFunc(s stats.Provider) metrics.ContainerLabelsFunc {
   // containerPrometheusLabels maps cAdvisor labels to prometheus labels.
   return func(c *cadvisorapi.ContainerInfo) map[string]string {
      // Prometheus requires that all metrics in the same family have the same labels,
      // so we arrange to supply blank strings for missing labels
      var name, image, podName, namespace, containerName string
      if len(c.Aliases) > 0 {
         name = c.Aliases[0]
      }
      image = c.Spec.Image
      if v, ok := c.Spec.Labels[kubelettypes.KubernetesPodNameLabel]; ok {    // io.kubernetes.pod.name
         podName = v
      }
      if v, ok := c.Spec.Labels[kubelettypes.KubernetesPodNamespaceLabel]; ok {    // io.kubernetes.pod.namespace
         namespace = v
      }
      if v, ok := c.Spec.Labels[kubelettypes.KubernetesContainerNameLabel]; ok {    // io.kubernetes.container.name
         containerName = v
      }
      // Associate pod cgroup with pod so we have an accurate accounting of sandbox
      if podName == "" && namespace == "" {
         if pod, found := s.GetPodByCgroupfs(c.Name); found {
            podName = pod.Name
            namespace = pod.Namespace
         }
      }
      set := map[string]string{
         metrics.LabelID:    c.Name,
         metrics.LabelName:  name,
         metrics.LabelImage: image,
         "pod":              podName,        // pod名称
         "namespace":        namespace,        // namespace
         "container":        containerName,    // container名称
      }
      return set
   }
}

三. 总结

cadvisor通过容器的接口,查询到spec.labels的信息(包含container/pod/namespace)后,

  • 对于普通的cadvisor:

    • 使用默认的DefaultContainerLabels函数添加标签,为label添加container_label_前缀;
  • 对于kubelet集成的cadvisor:

    • 使用自定义的containerPrometheusLablesFunc函数添加标签,将原始的标签变为container=/pod=/namespace=;

以上就是kubelet为cadvisor添加namespace/pod/container标签示例详解的详细内容,更多关于kubelet cadvisor标签添加的资料请关注脚本之家其它相关文章!

相关文章

  • Kubernetes Deployment升级与回退实现过程

    Kubernetes Deployment升级与回退实现过程

    文章介绍了如何使用Kubernetes的`kubectl set image --record`命令进行版本更新,以及如何使用`kubectl rollout undo`命令快速回退到稳定版本,以实现应用的持续交付和故障回退,Kubernetes的Deployment机制通过声明式管理确保服务的高可用性和连续性
    2026-01-01
  • K8S Operator部署及自定义详解

    K8S Operator部署及自定义详解

    这篇文章主要为大家介绍了K8S Operator部署及自定义详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-04-04
  • Ubuntu22.04的Kubernetes环境中加载桥接网络模块方式

    Ubuntu22.04的Kubernetes环境中加载桥接网络模块方式

    在Ubuntu 22.04的Kubernetes环境中,解决sysctl: cannot stat /proc/sys/net/bridge/bridge-nf-call-iptables错误的步骤包括加载br_netfilter模块、持久化配置、设置sysctl参数以及验证配置,同时,确保Kubernetes组件和CNI插件依赖这些参数,防火墙配置也要同步
    2026-01-01
  • 如何在 K8S 中使用 Values 文件定制不同环境下的应用配置

    如何在 K8S 中使用 Values 文件定制不同环境下的应用配置

    Kubernetes是一个开源的容器编排平台,它可以自动化容器的部署、扩展和管理,在 K8s 中,应用程序通常以容器的形式运行,这些容器被组织在不同的资源对象中,这篇文章主要介绍了如何在 K8S 中使用 Values 文件定制不同环境下的应用配置,需要的朋友可以参考下
    2025-03-03
  • kubectl top如何查看资源占用

    kubectl top如何查看资源占用

    文章介绍了如何安装和使用metricserver来监控Kubernetes集群中的节点和Pod资源使用情况,包括CPU和内存的计量单位以及如何通过这些指标来管理资源请求和限制,同时,文章还讨论了在Docker容器中使用jps命令和释放ptrace权限的配置问题
    2026-03-03
  • k8s pod和service网络暴露详解

    k8s pod和service网络暴露详解

    这篇文章主要介绍了借助iptables的路由转发功能,打通k8s集群内的pod和service网络,与外部网络联通,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-11-11
  • Kubernetes中创建命名空间实现方法

    Kubernetes中创建命名空间实现方法

    这篇文章主要为大家介绍了Kubernetes中创建命名空间实现方法详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-11-11
  • K8S删除pod的4种方法小结

    K8S删除pod的4种方法小结

    在Kubernetes集群环境中工作时,有时会遇到需要从一个工作节点中删除pod的情况,下面这篇文章主要给大家介绍了关于K8S删除pod的4种方法,需要的朋友可以参考下
    2024-01-01
  • kubeadm更新kubernetes证书实现方式

    kubeadm更新kubernetes证书实现方式

    Kubernetes证书管理在Kubernetes集群中,证书的到期问题是运维人员需要关注的重要问题,证书过期会导致kubelet报错,影响集群的正常访问,为了避免证书过期,需要提前进行续期操作,本文将介绍基于kubeadm安装的Kubernetes集群证书续期操作的详细步骤
    2026-02-02
  • 在Kubernetes集群中搭建Istio微服务网格的过程详解

    在Kubernetes集群中搭建Istio微服务网格的过程详解

    这篇文章主要介绍了在Kubernetes集群中搭建Istio微服务网格,我们采用default配置档部署istio网格,istioctl install命令不指定任何配置档默认就是呀default配置档,需要的朋友可以参考下
    2022-05-05

最新评论