Filter internal Kubernetes labels from Prometheus metrics

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.
This commit is contained in:
Tobias Schmidt 2016-08-20 18:04:34 -04:00
parent 1ec1c241d5
commit 12c248315f
2 changed files with 89 additions and 2 deletions

View File

@ -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 {

View File

@ -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)
}
}