k8s 中容器资源的监控
在 promethues 中如何配置采集容器指标
- 采用 promethues 的 kubernetes_sd_configs 中 node 级别的 role
- job_name: kubernetes-nodes-cadvisor
honor_timestamps: false
scrape_interval: 30s
scrape_timeout: 10s
metrics_path: /metrics
scheme: https
kubernetes_sd_configs:
- role: node
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
insecure_skip_verify: true
relabel_configs:
- separator: ;
regex: __meta_kubernetes_node_label_(.+)
replacement: $1
action: labelmap
- separator: ;
regex: (.*)
target_label: __metrics_path__
replacement: /metrics/cadvisor
action: replace
cadvisor 架构图
cadvisor 中 POD
- 在查看 cadvisor 代码时发现有一种 container_name==”POD” 的容器,查了下是 k8s 中的 pause pod
下面追踪下打 tag 的过程: 以 pod cpu 使用率为例
kubelet 最终 tag
- 对应 cadvisor 指标为 container_cpu_usage_seconds_total, 可以看到最终查询出来的有如下 tag
- 那我们会好奇标识 app 或 service 的 tag:pod,pod_name,container,container_name 是如何打上去的呢
访问集成在 kubelet 中的 cadvisor 的 tag
- curl localhost:4194/metrics
- 可以发现除了 cpu 是 container_cpu_usage_seconds_total 指标特有的 tag 之外, 还有 id,name,namespace,pod_name,container_name,image 这几个 tag
- 上述 tag 作为 cadvisor 通用 tag 会附加在每一个 metric 上面
- 其实在裸的 cadvisor 中只有 id,image,name 三个 tag 原始 cadvisor 打 tag
- namespace,pod_name,container_name 等属性是 k8s 才有的,cadvisor 肯定无法感知 pod 信息, 说明是 k8s 注入的
kubelet 内置的 cadvisor 中使用了自定义的 PrometheusLabelsFunc
以 k8s 1.15 版本为例
代码在:E:go_pathsrcgithub.comkuberneteskubernetespkgkubeletserverserver.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 {podName = v}
if v, ok := c.Spec.Labels[kubelettypes.KubernetesPodNamespaceLabel]; ok {namespace = v}
if v, ok := c.Spec.Labels[kubelettypes.KubernetesContainerNameLabel]; ok {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_name": podName,
"pod": podName,
"namespace": namespace,
"container_name": containerName,
"container": containerName,
}
return set
}
}
k8s 1.15 1.16 版本对于 pod 和 pod_name 的变化
- 经过观察发现 1.15 的 pod pod_name 都有,1.16 只有 pod
- 这是因为 在 k8s 1.16 版本为了统一 cadvisor 和 kube-stats 指标 tag 做了变更[这个 pr] (https://github.com/kubernetes…
kubelet 启动时可以使用 –node-labels 注入 node 级别 tag
--node-labels=os.name=xxxx,os.version=xxxx,os.architecture=amd64,
- 这些 tag 会转化为 promethues metric 命名方式 xxx_xxx
- 最后追加为 os_version=xxx,os_architecture=amd64