mirror of https://github.com/k3s-io/k3s
Merge pull request #31064 from soundcloud/grobie/filter-internal-labels
Automatic merge from submit-queue Filter internal Kubernetes labels from Prometheus metrics **What this PR does / why we need it**: Kubernetes uses Docker labels as storage for some internal labels. The majority of these labels are not meaningful metric labels and a few of them are even harmful as they're not static and cause wrong aggregation results. This change provides a custom labels func to only attach meaningful labels to cAdvisor exported metrics. **Which issue this PR fixes** google/cadvisor#1312 **Special notes for your reviewer**: Depends on google/cadvisor#1429. Once that is merged, I'll update the vendor update commit. **Release note**: ```release-note Remove environment variables and internal Kubernetes Docker labels from cAdvisor Prometheus metric labels. Old behavior: - environment variables explicitly whitelisted via --docker-env-metadata-whitelist were exported as `container_env_*=*`. Default is zero so by default non were exported - all docker labels were exported as `container_label_*=*` New behavior: - Only `container_name`, `pod_name`, `namespace`, `id`, `image`, and `name` labels are exposed - no environment variables will be exposed ever via /metrics, even if whitelisted ``` --- Given that we have full control over the exported label set, I shortened the pod_name, pod_namespace and container_name label names. Below an example of the change (reformatted for readability). ``` # BEFORE container_cpu_cfs_periods_total{ container_label_io_kubernetes_container_hash="5af8c3b4", container_label_io_kubernetes_container_name="sync", container_label_io_kubernetes_container_restartCount="1", container_label_io_kubernetes_container_terminationMessagePath="/dev/termination-log", container_label_io_kubernetes_pod_name="popularsearches-web-3165456836-2bfey", container_label_io_kubernetes_pod_namespace="popularsearches", container_label_io_kubernetes_pod_terminationGracePeriod="30", container_label_io_kubernetes_pod_uid="6a291e48-47c4-11e6-84a4-c81f66bdf8bd", id="/docker/68e1f15353921f4d6d4d998fa7293306c4ac828d04d1284e410ddaa75cf8cf25", image="redacted.com/popularsearches:42-16-ba6bd88", name="k8s_sync.5af8c3b4_popularsearches-web-3165456836-2bfey_popularsearches_6a291e48-47c4-11e6-84a4-c81f66bdf8bd_c02d3775" } 72819 # AFTER container_cpu_cfs_periods_total{ container_name="sync", pod_name="popularsearches-web-3165456836-2bfey", namespace="popularsearches", id="/docker/68e1f15353921f4d6d4d998fa7293306c4ac828d04d1284e410ddaa75cf8cf25", image="redacted.com/popularsearches:42-16-ba6bd88", name="k8s_sync.5af8c3b4_popularsearches-web-3165456836-2bfey_popularsearches_6a291e48-47c4-11e6-84a4-c81f66bdf8bd_c02d3775" } 72819 ``` Feedback requested on: * Label names. Other suggestions? Should we keep these very long ones? * Do we need to export io.kubernetes.pod.uid? It makes working with the metrics a bit more complicated and the pod name is already unique at any time (but not over time). The UID is aslo part of `name`. As discussed with @timstclair, this should be added to v1.4 as the current labels are harmful. PTAL @jimmidyson @fabxc @vishhpull/6/head
commit
feb4d2004a
|
@ -1095,208 +1095,208 @@
|
|||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/api",
|
||||
"Comment": "v0.23.2-89-g2ed7198",
|
||||
"Rev": "2ed7198f77395ee9a172878a0a7ab92ab59a2cfd"
|
||||
"Comment": "v0.24.0-alpha1-1-gd84e075",
|
||||
"Rev": "d84e0758ab16ee68598702793119c9a7370c1522"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/cache/memory",
|
||||
"Comment": "v0.23.2-89-g2ed7198",
|
||||
"Rev": "2ed7198f77395ee9a172878a0a7ab92ab59a2cfd"
|
||||
"Comment": "v0.24.0-alpha1-1-gd84e075",
|
||||
"Rev": "d84e0758ab16ee68598702793119c9a7370c1522"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/client/v2",
|
||||
"Comment": "v0.23.2-89-g2ed7198",
|
||||
"Rev": "2ed7198f77395ee9a172878a0a7ab92ab59a2cfd"
|
||||
"Comment": "v0.24.0-alpha1-1-gd84e075",
|
||||
"Rev": "d84e0758ab16ee68598702793119c9a7370c1522"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/collector",
|
||||
"Comment": "v0.23.2-89-g2ed7198",
|
||||
"Rev": "2ed7198f77395ee9a172878a0a7ab92ab59a2cfd"
|
||||
"Comment": "v0.24.0-alpha1-1-gd84e075",
|
||||
"Rev": "d84e0758ab16ee68598702793119c9a7370c1522"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/container",
|
||||
"Comment": "v0.23.2-89-g2ed7198",
|
||||
"Rev": "2ed7198f77395ee9a172878a0a7ab92ab59a2cfd"
|
||||
"Comment": "v0.24.0-alpha1-1-gd84e075",
|
||||
"Rev": "d84e0758ab16ee68598702793119c9a7370c1522"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/container/common",
|
||||
"Comment": "v0.23.2-89-g2ed7198",
|
||||
"Rev": "2ed7198f77395ee9a172878a0a7ab92ab59a2cfd"
|
||||
"Comment": "v0.24.0-alpha1-1-gd84e075",
|
||||
"Rev": "d84e0758ab16ee68598702793119c9a7370c1522"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/container/docker",
|
||||
"Comment": "v0.23.2-89-g2ed7198",
|
||||
"Rev": "2ed7198f77395ee9a172878a0a7ab92ab59a2cfd"
|
||||
"Comment": "v0.24.0-alpha1-1-gd84e075",
|
||||
"Rev": "d84e0758ab16ee68598702793119c9a7370c1522"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/container/libcontainer",
|
||||
"Comment": "v0.23.2-89-g2ed7198",
|
||||
"Rev": "2ed7198f77395ee9a172878a0a7ab92ab59a2cfd"
|
||||
"Comment": "v0.24.0-alpha1-1-gd84e075",
|
||||
"Rev": "d84e0758ab16ee68598702793119c9a7370c1522"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/container/raw",
|
||||
"Comment": "v0.23.2-89-g2ed7198",
|
||||
"Rev": "2ed7198f77395ee9a172878a0a7ab92ab59a2cfd"
|
||||
"Comment": "v0.24.0-alpha1-1-gd84e075",
|
||||
"Rev": "d84e0758ab16ee68598702793119c9a7370c1522"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/container/rkt",
|
||||
"Comment": "v0.23.2-89-g2ed7198",
|
||||
"Rev": "2ed7198f77395ee9a172878a0a7ab92ab59a2cfd"
|
||||
"Comment": "v0.24.0-alpha1-1-gd84e075",
|
||||
"Rev": "d84e0758ab16ee68598702793119c9a7370c1522"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/container/systemd",
|
||||
"Comment": "v0.23.2-89-g2ed7198",
|
||||
"Rev": "2ed7198f77395ee9a172878a0a7ab92ab59a2cfd"
|
||||
"Comment": "v0.24.0-alpha1-1-gd84e075",
|
||||
"Rev": "d84e0758ab16ee68598702793119c9a7370c1522"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/devicemapper",
|
||||
"Comment": "v0.23.2-89-g2ed7198",
|
||||
"Rev": "2ed7198f77395ee9a172878a0a7ab92ab59a2cfd"
|
||||
"Comment": "v0.24.0-alpha1-1-gd84e075",
|
||||
"Rev": "d84e0758ab16ee68598702793119c9a7370c1522"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/events",
|
||||
"Comment": "v0.23.2-89-g2ed7198",
|
||||
"Rev": "2ed7198f77395ee9a172878a0a7ab92ab59a2cfd"
|
||||
"Comment": "v0.24.0-alpha1-1-gd84e075",
|
||||
"Rev": "d84e0758ab16ee68598702793119c9a7370c1522"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/fs",
|
||||
"Comment": "v0.23.2-89-g2ed7198",
|
||||
"Rev": "2ed7198f77395ee9a172878a0a7ab92ab59a2cfd"
|
||||
"Comment": "v0.24.0-alpha1-1-gd84e075",
|
||||
"Rev": "d84e0758ab16ee68598702793119c9a7370c1522"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/healthz",
|
||||
"Comment": "v0.23.2-89-g2ed7198",
|
||||
"Rev": "2ed7198f77395ee9a172878a0a7ab92ab59a2cfd"
|
||||
"Comment": "v0.24.0-alpha1-1-gd84e075",
|
||||
"Rev": "d84e0758ab16ee68598702793119c9a7370c1522"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/http",
|
||||
"Comment": "v0.23.2-89-g2ed7198",
|
||||
"Rev": "2ed7198f77395ee9a172878a0a7ab92ab59a2cfd"
|
||||
"Comment": "v0.24.0-alpha1-1-gd84e075",
|
||||
"Rev": "d84e0758ab16ee68598702793119c9a7370c1522"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/http/mux",
|
||||
"Comment": "v0.23.2-89-g2ed7198",
|
||||
"Rev": "2ed7198f77395ee9a172878a0a7ab92ab59a2cfd"
|
||||
"Comment": "v0.24.0-alpha1-1-gd84e075",
|
||||
"Rev": "d84e0758ab16ee68598702793119c9a7370c1522"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/info/v1",
|
||||
"Comment": "v0.23.2-89-g2ed7198",
|
||||
"Rev": "2ed7198f77395ee9a172878a0a7ab92ab59a2cfd"
|
||||
"Comment": "v0.24.0-alpha1-1-gd84e075",
|
||||
"Rev": "d84e0758ab16ee68598702793119c9a7370c1522"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/info/v1/test",
|
||||
"Comment": "v0.23.2-89-g2ed7198",
|
||||
"Rev": "2ed7198f77395ee9a172878a0a7ab92ab59a2cfd"
|
||||
"Comment": "v0.24.0-alpha1-1-gd84e075",
|
||||
"Rev": "d84e0758ab16ee68598702793119c9a7370c1522"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/info/v2",
|
||||
"Comment": "v0.23.2-89-g2ed7198",
|
||||
"Rev": "2ed7198f77395ee9a172878a0a7ab92ab59a2cfd"
|
||||
"Comment": "v0.24.0-alpha1-1-gd84e075",
|
||||
"Rev": "d84e0758ab16ee68598702793119c9a7370c1522"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/machine",
|
||||
"Comment": "v0.23.2-89-g2ed7198",
|
||||
"Rev": "2ed7198f77395ee9a172878a0a7ab92ab59a2cfd"
|
||||
"Comment": "v0.24.0-alpha1-1-gd84e075",
|
||||
"Rev": "d84e0758ab16ee68598702793119c9a7370c1522"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/manager",
|
||||
"Comment": "v0.23.2-89-g2ed7198",
|
||||
"Rev": "2ed7198f77395ee9a172878a0a7ab92ab59a2cfd"
|
||||
"Comment": "v0.24.0-alpha1-1-gd84e075",
|
||||
"Rev": "d84e0758ab16ee68598702793119c9a7370c1522"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/manager/watcher",
|
||||
"Comment": "v0.23.2-89-g2ed7198",
|
||||
"Rev": "2ed7198f77395ee9a172878a0a7ab92ab59a2cfd"
|
||||
"Comment": "v0.24.0-alpha1-1-gd84e075",
|
||||
"Rev": "d84e0758ab16ee68598702793119c9a7370c1522"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/manager/watcher/raw",
|
||||
"Comment": "v0.23.2-89-g2ed7198",
|
||||
"Rev": "2ed7198f77395ee9a172878a0a7ab92ab59a2cfd"
|
||||
"Comment": "v0.24.0-alpha1-1-gd84e075",
|
||||
"Rev": "d84e0758ab16ee68598702793119c9a7370c1522"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/manager/watcher/rkt",
|
||||
"Comment": "v0.23.2-89-g2ed7198",
|
||||
"Rev": "2ed7198f77395ee9a172878a0a7ab92ab59a2cfd"
|
||||
"Comment": "v0.24.0-alpha1-1-gd84e075",
|
||||
"Rev": "d84e0758ab16ee68598702793119c9a7370c1522"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/metrics",
|
||||
"Comment": "v0.23.2-89-g2ed7198",
|
||||
"Rev": "2ed7198f77395ee9a172878a0a7ab92ab59a2cfd"
|
||||
"Comment": "v0.24.0-alpha1-1-gd84e075",
|
||||
"Rev": "d84e0758ab16ee68598702793119c9a7370c1522"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/pages",
|
||||
"Comment": "v0.23.2-89-g2ed7198",
|
||||
"Rev": "2ed7198f77395ee9a172878a0a7ab92ab59a2cfd"
|
||||
"Comment": "v0.24.0-alpha1-1-gd84e075",
|
||||
"Rev": "d84e0758ab16ee68598702793119c9a7370c1522"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/pages/static",
|
||||
"Comment": "v0.23.2-89-g2ed7198",
|
||||
"Rev": "2ed7198f77395ee9a172878a0a7ab92ab59a2cfd"
|
||||
"Comment": "v0.24.0-alpha1-1-gd84e075",
|
||||
"Rev": "d84e0758ab16ee68598702793119c9a7370c1522"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/storage",
|
||||
"Comment": "v0.23.2-89-g2ed7198",
|
||||
"Rev": "2ed7198f77395ee9a172878a0a7ab92ab59a2cfd"
|
||||
"Comment": "v0.24.0-alpha1-1-gd84e075",
|
||||
"Rev": "d84e0758ab16ee68598702793119c9a7370c1522"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/summary",
|
||||
"Comment": "v0.23.2-89-g2ed7198",
|
||||
"Rev": "2ed7198f77395ee9a172878a0a7ab92ab59a2cfd"
|
||||
"Comment": "v0.24.0-alpha1-1-gd84e075",
|
||||
"Rev": "d84e0758ab16ee68598702793119c9a7370c1522"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/utils",
|
||||
"Comment": "v0.23.2-89-g2ed7198",
|
||||
"Rev": "2ed7198f77395ee9a172878a0a7ab92ab59a2cfd"
|
||||
"Comment": "v0.24.0-alpha1-1-gd84e075",
|
||||
"Rev": "d84e0758ab16ee68598702793119c9a7370c1522"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/utils/cloudinfo",
|
||||
"Comment": "v0.23.2-89-g2ed7198",
|
||||
"Rev": "2ed7198f77395ee9a172878a0a7ab92ab59a2cfd"
|
||||
"Comment": "v0.24.0-alpha1-1-gd84e075",
|
||||
"Rev": "d84e0758ab16ee68598702793119c9a7370c1522"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/utils/cpuload",
|
||||
"Comment": "v0.23.2-89-g2ed7198",
|
||||
"Rev": "2ed7198f77395ee9a172878a0a7ab92ab59a2cfd"
|
||||
"Comment": "v0.24.0-alpha1-1-gd84e075",
|
||||
"Rev": "d84e0758ab16ee68598702793119c9a7370c1522"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/utils/cpuload/netlink",
|
||||
"Comment": "v0.23.2-89-g2ed7198",
|
||||
"Rev": "2ed7198f77395ee9a172878a0a7ab92ab59a2cfd"
|
||||
"Comment": "v0.24.0-alpha1-1-gd84e075",
|
||||
"Rev": "d84e0758ab16ee68598702793119c9a7370c1522"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/utils/docker",
|
||||
"Comment": "v0.23.2-89-g2ed7198",
|
||||
"Rev": "2ed7198f77395ee9a172878a0a7ab92ab59a2cfd"
|
||||
"Comment": "v0.24.0-alpha1-1-gd84e075",
|
||||
"Rev": "d84e0758ab16ee68598702793119c9a7370c1522"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/utils/oomparser",
|
||||
"Comment": "v0.23.2-89-g2ed7198",
|
||||
"Rev": "2ed7198f77395ee9a172878a0a7ab92ab59a2cfd"
|
||||
"Comment": "v0.24.0-alpha1-1-gd84e075",
|
||||
"Rev": "d84e0758ab16ee68598702793119c9a7370c1522"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/utils/sysfs",
|
||||
"Comment": "v0.23.2-89-g2ed7198",
|
||||
"Rev": "2ed7198f77395ee9a172878a0a7ab92ab59a2cfd"
|
||||
"Comment": "v0.24.0-alpha1-1-gd84e075",
|
||||
"Rev": "d84e0758ab16ee68598702793119c9a7370c1522"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/utils/sysinfo",
|
||||
"Comment": "v0.23.2-89-g2ed7198",
|
||||
"Rev": "2ed7198f77395ee9a172878a0a7ab92ab59a2cfd"
|
||||
"Comment": "v0.24.0-alpha1-1-gd84e075",
|
||||
"Rev": "d84e0758ab16ee68598702793119c9a7370c1522"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/utils/tail",
|
||||
"Comment": "v0.23.2-89-g2ed7198",
|
||||
"Rev": "2ed7198f77395ee9a172878a0a7ab92ab59a2cfd"
|
||||
"Comment": "v0.24.0-alpha1-1-gd84e075",
|
||||
"Rev": "d84e0758ab16ee68598702793119c9a7370c1522"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/validate",
|
||||
"Comment": "v0.23.2-89-g2ed7198",
|
||||
"Rev": "2ed7198f77395ee9a172878a0a7ab92ab59a2cfd"
|
||||
"Comment": "v0.24.0-alpha1-1-gd84e075",
|
||||
"Rev": "d84e0758ab16ee68598702793119c9a7370c1522"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/version",
|
||||
"Comment": "v0.23.2-89-g2ed7198",
|
||||
"Rev": "2ed7198f77395ee9a172878a0a7ab92ab59a2cfd"
|
||||
"Comment": "v0.24.0-alpha1-1-gd84e075",
|
||||
"Rev": "d84e0758ab16ee68598702793119c9a7370c1522"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/certificate-transparency/go",
|
||||
|
|
|
@ -33,7 +33,9 @@ import (
|
|||
cadvisorapi "github.com/google/cadvisor/info/v1"
|
||||
cadvisorapiv2 "github.com/google/cadvisor/info/v2"
|
||||
"github.com/google/cadvisor/manager"
|
||||
"github.com/google/cadvisor/metrics"
|
||||
"github.com/google/cadvisor/utils/sysfs"
|
||||
"k8s.io/kubernetes/pkg/kubelet/types"
|
||||
"k8s.io/kubernetes/pkg/util/runtime"
|
||||
)
|
||||
|
||||
|
@ -70,7 +72,27 @@ func init() {
|
|||
}
|
||||
}
|
||||
|
||||
// Creates a cAdvisor and exports its API on the specified port if port > 0.
|
||||
func containerLabels(c *cadvisorapi.ContainerInfo) map[string]string {
|
||||
set := map[string]string{metrics.LabelID: c.Name}
|
||||
if len(c.Aliases) > 0 {
|
||||
set[metrics.LabelName] = c.Aliases[0]
|
||||
}
|
||||
if image := c.Spec.Image; len(image) > 0 {
|
||||
set[metrics.LabelImage] = image
|
||||
}
|
||||
if v, ok := c.Spec.Labels[types.KubernetesPodNameLabel]; ok {
|
||||
set["pod_name"] = v
|
||||
}
|
||||
if v, ok := c.Spec.Labels[types.KubernetesPodNamespaceLabel]; ok {
|
||||
set["namespace"] = v
|
||||
}
|
||||
if v, ok := c.Spec.Labels[types.KubernetesContainerNameLabel]; ok {
|
||||
set["container_name"] = v
|
||||
}
|
||||
return set
|
||||
}
|
||||
|
||||
// New creates a cAdvisor and exports its API on the specified port if port > 0.
|
||||
func New(port uint, runtime string) (Interface, error) {
|
||||
sysFs, err := sysfs.NewRealSysFs()
|
||||
if err != nil {
|
||||
|
@ -108,7 +130,7 @@ func (cc *cadvisorClient) exportHTTP(port uint) error {
|
|||
return err
|
||||
}
|
||||
|
||||
cadvisorhttp.RegisterPrometheusHandler(mux, cc, "/metrics", nil)
|
||||
cadvisorhttp.RegisterPrometheusHandler(mux, cc, "/metrics", containerLabels)
|
||||
|
||||
// Only start the http server if port > 0
|
||||
if port > 0 {
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
// +build cgo,linux
|
||||
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cadvisor
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
info "github.com/google/cadvisor/info/v1"
|
||||
"github.com/google/cadvisor/metrics"
|
||||
"k8s.io/kubernetes/pkg/kubelet/types"
|
||||
)
|
||||
|
||||
func TestContainerLabels(t *testing.T) {
|
||||
container := &info.ContainerInfo{
|
||||
ContainerReference: info.ContainerReference{
|
||||
Name: "/docker/f81ad5335d390944e454ea19ab0924037d57337c19731524ad96eb26e74b6c6d",
|
||||
Aliases: []string{"k8s_POD.639b2af2_foo-web-315473031-e40e2_foobar_a369ace2-5fa9-11e6-b10f-c81f66e5e84d_851a97fd"},
|
||||
},
|
||||
Spec: info.ContainerSpec{
|
||||
Image: "qux/foo:latest",
|
||||
Labels: map[string]string{
|
||||
"io.kubernetes.container.hash": "639b2af2",
|
||||
types.KubernetesContainerNameLabel: "POD",
|
||||
"io.kubernetes.container.restartCount": "0",
|
||||
"io.kubernetes.container.terminationMessagePath": "",
|
||||
types.KubernetesPodNameLabel: "foo-web-315473031-e40e2",
|
||||
types.KubernetesPodNamespaceLabel: "foobar",
|
||||
"io.kubernetes.pod.terminationGracePeriod": "30",
|
||||
types.KubernetesPodUIDLabel: "a369ace2-5fa9-11e6-b10f-c81f66e5e84d",
|
||||
},
|
||||
Envs: map[string]string{
|
||||
"foo+env": "prod",
|
||||
},
|
||||
},
|
||||
}
|
||||
want := map[string]string{
|
||||
metrics.LabelID: "/docker/f81ad5335d390944e454ea19ab0924037d57337c19731524ad96eb26e74b6c6d",
|
||||
metrics.LabelName: "k8s_POD.639b2af2_foo-web-315473031-e40e2_foobar_a369ace2-5fa9-11e6-b10f-c81f66e5e84d_851a97fd",
|
||||
metrics.LabelImage: "qux/foo:latest",
|
||||
"namespace": "foobar",
|
||||
"container_name": "POD",
|
||||
"pod_name": "foo-web-315473031-e40e2",
|
||||
}
|
||||
|
||||
if have := containerLabels(container); !reflect.DeepEqual(want, have) {
|
||||
t.Errorf("want %v, have %v", want, have)
|
||||
}
|
||||
}
|
|
@ -89,8 +89,11 @@ func RegisterHandlers(mux httpmux.Mux, containerManager manager.Manager, httpAut
|
|||
return nil
|
||||
}
|
||||
|
||||
func RegisterPrometheusHandler(mux httpmux.Mux, containerManager manager.Manager, prometheusEndpoint string, containerNameToLabelsFunc metrics.ContainerNameToLabelsFunc) {
|
||||
collector := metrics.NewPrometheusCollector(containerManager, containerNameToLabelsFunc)
|
||||
// RegisterPrometheusHandler creates a new PrometheusCollector, registers it
|
||||
// on the global registry and configures the provided HTTP mux to handle the
|
||||
// given Prometheus endpoint.
|
||||
func RegisterPrometheusHandler(mux httpmux.Mux, containerManager manager.Manager, prometheusEndpoint string, f metrics.ContainerLabelsFunc) {
|
||||
collector := metrics.NewPrometheusCollector(containerManager, f)
|
||||
prometheus.MustRegister(collector)
|
||||
mux.Handle(prometheusEndpoint, prometheus.Handler())
|
||||
}
|
||||
|
|
|
@ -25,13 +25,14 @@ import (
|
|||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
// This will usually be manager.Manager, but can be swapped out for testing.
|
||||
// infoProvider will usually be manager.Manager, but can be swapped out for testing.
|
||||
type infoProvider interface {
|
||||
// Get information about all subcontainers of the specified container (includes self).
|
||||
// SubcontainersInfo provides information about all subcontainers of the
|
||||
// specified container including itself.
|
||||
SubcontainersInfo(containerName string, query *info.ContainerInfoRequest) ([]*info.ContainerInfo, error)
|
||||
// Get information about the version.
|
||||
// GetVersionInfo provides information about the version.
|
||||
GetVersionInfo() (*info.VersionInfo, error)
|
||||
// Get information about the machine.
|
||||
// GetMachineInfo provides information about the machine.
|
||||
GetMachineInfo() (*info.MachineInfo, error)
|
||||
}
|
||||
|
||||
|
@ -56,8 +57,8 @@ func fsValues(fsStats []info.FsStats, valueFn func(*info.FsStats) float64) metri
|
|||
return values
|
||||
}
|
||||
|
||||
// A containerMetric describes a multi-dimensional metric used for exposing
|
||||
// a certain type of container statistic.
|
||||
// containerMetric describes a multi-dimensional metric used for exposing a
|
||||
// certain type of container statistic.
|
||||
type containerMetric struct {
|
||||
name string
|
||||
help string
|
||||
|
@ -71,21 +72,29 @@ func (cm *containerMetric) desc(baseLabels []string) *prometheus.Desc {
|
|||
return prometheus.NewDesc(cm.name, cm.help, append(baseLabels, cm.extraLabels...), nil)
|
||||
}
|
||||
|
||||
type ContainerNameToLabelsFunc func(containerName string) map[string]string
|
||||
// ContainerLabelsFunc defines all base labels and their values attached to
|
||||
// each metric exported by cAdvisor.
|
||||
type ContainerLabelsFunc func(*info.ContainerInfo) map[string]string
|
||||
|
||||
// PrometheusCollector implements prometheus.Collector.
|
||||
type PrometheusCollector struct {
|
||||
infoProvider infoProvider
|
||||
errors prometheus.Gauge
|
||||
containerMetrics []containerMetric
|
||||
containerNameToLabels ContainerNameToLabelsFunc
|
||||
containerLabelsFunc ContainerLabelsFunc
|
||||
}
|
||||
|
||||
// NewPrometheusCollector returns a new PrometheusCollector.
|
||||
func NewPrometheusCollector(infoProvider infoProvider, f ContainerNameToLabelsFunc) *PrometheusCollector {
|
||||
// NewPrometheusCollector returns a new PrometheusCollector. The passed
|
||||
// ContainerLabelsFunc specifies which base labels will be attached to all
|
||||
// exported metrics. If left to nil, the DefaultContainerLabels function
|
||||
// will be used instead.
|
||||
func NewPrometheusCollector(i infoProvider, f ContainerLabelsFunc) *PrometheusCollector {
|
||||
if f == nil {
|
||||
f = DefaultContainerLabels
|
||||
}
|
||||
c := &PrometheusCollector{
|
||||
infoProvider: infoProvider,
|
||||
containerNameToLabels: f,
|
||||
infoProvider: i,
|
||||
containerLabelsFunc: f,
|
||||
errors: prometheus.NewGauge(prometheus.GaugeOpts{
|
||||
Namespace: "container",
|
||||
Name: "scrape_error",
|
||||
|
@ -533,10 +542,38 @@ func (c *PrometheusCollector) Collect(ch chan<- prometheus.Metric) {
|
|||
}
|
||||
|
||||
const (
|
||||
containerLabelPrefix = "container_label_"
|
||||
containerEnvPrefix = "container_env_"
|
||||
// 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"
|
||||
)
|
||||
|
||||
// DefaultContainerLabels implements ContainerLabelsFunc. It exports the
|
||||
// container name, first alias, image name as well as all its env and label
|
||||
// values.
|
||||
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
|
||||
}
|
||||
for k, v := range container.Spec.Envs {
|
||||
set[ContainerEnvPrefix+k] = v
|
||||
}
|
||||
return set
|
||||
}
|
||||
|
||||
func (c *PrometheusCollector) collectContainersInfo(ch chan<- prometheus.Metric) {
|
||||
containers, err := c.infoProvider.SubcontainersInfo("/", &info.ContainerInfoRequest{NumStats: 1})
|
||||
if err != nil {
|
||||
|
@ -545,56 +582,32 @@ func (c *PrometheusCollector) collectContainersInfo(ch chan<- prometheus.Metric)
|
|||
return
|
||||
}
|
||||
for _, container := range containers {
|
||||
baseLabels := []string{"id"}
|
||||
id := container.Name
|
||||
name := id
|
||||
if len(container.Aliases) > 0 {
|
||||
name = container.Aliases[0]
|
||||
baseLabels = append(baseLabels, "name")
|
||||
}
|
||||
image := container.Spec.Image
|
||||
if len(image) > 0 {
|
||||
baseLabels = append(baseLabels, "image")
|
||||
}
|
||||
baseLabelValues := []string{id, name, image}[:len(baseLabels)]
|
||||
|
||||
if c.containerNameToLabels != nil {
|
||||
newLabels := c.containerNameToLabels(name)
|
||||
for k, v := range newLabels {
|
||||
baseLabels = append(baseLabels, sanitizeLabelName(k))
|
||||
baseLabelValues = append(baseLabelValues, v)
|
||||
}
|
||||
}
|
||||
|
||||
for k, v := range container.Spec.Labels {
|
||||
baseLabels = append(baseLabels, sanitizeLabelName(containerLabelPrefix+k))
|
||||
baseLabelValues = append(baseLabelValues, v)
|
||||
}
|
||||
for k, v := range container.Spec.Envs {
|
||||
baseLabels = append(baseLabels, sanitizeLabelName(containerEnvPrefix+k))
|
||||
baseLabelValues = append(baseLabelValues, v)
|
||||
labels, values := []string{}, []string{}
|
||||
for l, v := range c.containerLabelsFunc(container) {
|
||||
labels = append(labels, sanitizeLabelName(l))
|
||||
values = append(values, v)
|
||||
}
|
||||
|
||||
// Container spec
|
||||
desc := prometheus.NewDesc("container_start_time_seconds", "Start time of the container since unix epoch in seconds.", baseLabels, nil)
|
||||
ch <- prometheus.MustNewConstMetric(desc, prometheus.GaugeValue, float64(container.Spec.CreationTime.Unix()), baseLabelValues...)
|
||||
desc := prometheus.NewDesc("container_start_time_seconds", "Start time of the container since unix epoch in seconds.", labels, nil)
|
||||
ch <- prometheus.MustNewConstMetric(desc, prometheus.GaugeValue, float64(container.Spec.CreationTime.Unix()), values...)
|
||||
|
||||
if container.Spec.HasCpu {
|
||||
desc = prometheus.NewDesc("container_spec_cpu_period", "CPU period of the container.", baseLabels, nil)
|
||||
ch <- prometheus.MustNewConstMetric(desc, prometheus.GaugeValue, float64(container.Spec.Cpu.Period), baseLabelValues...)
|
||||
desc = prometheus.NewDesc("container_spec_cpu_period", "CPU period of the container.", labels, nil)
|
||||
ch <- prometheus.MustNewConstMetric(desc, prometheus.GaugeValue, float64(container.Spec.Cpu.Period), values...)
|
||||
if container.Spec.Cpu.Quota != 0 {
|
||||
desc = prometheus.NewDesc("container_spec_cpu_quota", "CPU quota of the container.", baseLabels, nil)
|
||||
ch <- prometheus.MustNewConstMetric(desc, prometheus.GaugeValue, float64(container.Spec.Cpu.Quota), baseLabelValues...)
|
||||
desc = prometheus.NewDesc("container_spec_cpu_quota", "CPU quota of the container.", labels, nil)
|
||||
ch <- prometheus.MustNewConstMetric(desc, prometheus.GaugeValue, float64(container.Spec.Cpu.Quota), values...)
|
||||
}
|
||||
desc := prometheus.NewDesc("container_spec_cpu_shares", "CPU share of the container.", baseLabels, nil)
|
||||
ch <- prometheus.MustNewConstMetric(desc, prometheus.GaugeValue, float64(container.Spec.Cpu.Limit), baseLabelValues...)
|
||||
desc := prometheus.NewDesc("container_spec_cpu_shares", "CPU share of the container.", labels, nil)
|
||||
ch <- prometheus.MustNewConstMetric(desc, prometheus.GaugeValue, float64(container.Spec.Cpu.Limit), values...)
|
||||
|
||||
}
|
||||
if container.Spec.HasMemory {
|
||||
desc := prometheus.NewDesc("container_spec_memory_limit_bytes", "Memory limit for the container.", baseLabels, nil)
|
||||
ch <- prometheus.MustNewConstMetric(desc, prometheus.GaugeValue, specMemoryValue(container.Spec.Memory.Limit), baseLabelValues...)
|
||||
desc = prometheus.NewDesc("container_spec_memory_swap_limit_bytes", "Memory swap limit for the container.", baseLabels, nil)
|
||||
ch <- prometheus.MustNewConstMetric(desc, prometheus.GaugeValue, specMemoryValue(container.Spec.Memory.SwapLimit), baseLabelValues...)
|
||||
desc := prometheus.NewDesc("container_spec_memory_limit_bytes", "Memory limit for the container.", labels, nil)
|
||||
ch <- prometheus.MustNewConstMetric(desc, prometheus.GaugeValue, specMemoryValue(container.Spec.Memory.Limit), values...)
|
||||
desc = prometheus.NewDesc("container_spec_memory_swap_limit_bytes", "Memory swap limit for the container.", labels, nil)
|
||||
ch <- prometheus.MustNewConstMetric(desc, prometheus.GaugeValue, specMemoryValue(container.Spec.Memory.SwapLimit), values...)
|
||||
}
|
||||
|
||||
// Now for the actual metrics
|
||||
|
@ -603,9 +616,9 @@ func (c *PrometheusCollector) collectContainersInfo(ch chan<- prometheus.Metric)
|
|||
if cm.condition != nil && !cm.condition(container.Spec) {
|
||||
continue
|
||||
}
|
||||
desc := cm.desc(baseLabels)
|
||||
desc := cm.desc(labels)
|
||||
for _, metricValue := range cm.getValues(stats) {
|
||||
ch <- prometheus.MustNewConstMetric(desc, cm.valueType, float64(metricValue.value), append(baseLabelValues, metricValue.labels...)...)
|
||||
ch <- prometheus.MustNewConstMetric(desc, cm.valueType, float64(metricValue.value), append(values, metricValue.labels...)...)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue