diff --git a/discovery/kubernetes/pod.go b/discovery/kubernetes/pod.go index 74e39d41f1..986fcb8be5 100644 --- a/discovery/kubernetes/pod.go +++ b/discovery/kubernetes/pod.go @@ -23,6 +23,7 @@ import ( "github.com/go-kit/kit/log" "github.com/go-kit/kit/log/level" "github.com/prometheus/common/model" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/pkg/api" apiv1 "k8s.io/client-go/pkg/api/v1" "k8s.io/client-go/tools/cache" @@ -147,8 +148,21 @@ const ( podNodeNameLabel = metaLabelPrefix + "pod_node_name" podHostIPLabel = metaLabelPrefix + "pod_host_ip" podUID = metaLabelPrefix + "pod_uid" + podControllerKind = metaLabelPrefix + "pod_controller_kind" + podControllerName = metaLabelPrefix + "pod_controller_name" ) +// GetControllerOf returns a pointer to a copy of the controllerRef if controllee has a controller +// https://github.com/kubernetes/apimachinery/blob/cd2cae2b39fa57e8063fa1f5f13cfe9862db3d41/pkg/apis/meta/v1/controller_ref.go +func GetControllerOf(controllee metav1.Object) *metav1.OwnerReference { + for _, ref := range controllee.GetOwnerReferences() { + if ref.Controller != nil && *ref.Controller { + return &ref + } + } + return nil +} + func podLabels(pod *apiv1.Pod) model.LabelSet { ls := model.LabelSet{ podNameLabel: lv(pod.ObjectMeta.Name), @@ -159,6 +173,16 @@ func podLabels(pod *apiv1.Pod) model.LabelSet { podUID: lv(string(pod.ObjectMeta.UID)), } + createdBy := GetControllerOf(pod) + if createdBy != nil { + if createdBy.Kind != "" { + ls[podControllerKind] = lv(createdBy.Kind) + } + if createdBy.Name != "" { + ls[podControllerName] = lv(createdBy.Name) + } + } + for k, v := range pod.Labels { ln := strutil.SanitizeLabelName(podLabelPrefix + k) ls[model.LabelName(ln)] = lv(v) diff --git a/discovery/kubernetes/pod_test.go b/discovery/kubernetes/pod_test.go index 38fd1f8145..a9e1a98389 100644 --- a/discovery/kubernetes/pod_test.go +++ b/discovery/kubernetes/pod_test.go @@ -23,6 +23,10 @@ import ( "k8s.io/client-go/pkg/api/v1" ) +func makeOptionalBool(v bool) *bool { + return &v +} + func makeMultiPortPods() *v1.Pod { return &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ @@ -31,6 +35,13 @@ func makeMultiPortPods() *v1.Pod { Labels: map[string]string{"testlabel": "testvalue"}, Annotations: map[string]string{"testannotation": "testannotationvalue"}, UID: types.UID("abc123"), + OwnerReferences: []metav1.OwnerReference{ + { + Kind: "testcontrollerkind", + Name: "testcontrollername", + Controller: makeOptionalBool(true), + }, + }, }, Spec: v1.PodSpec{ NodeName: "testnode", @@ -146,6 +157,8 @@ func TestPodDiscoveryBeforeRun(t *testing.T) { "__meta_kubernetes_pod_host_ip": "2.3.4.5", "__meta_kubernetes_pod_ready": "true", "__meta_kubernetes_pod_uid": "abc123", + "__meta_kubernetes_pod_controller_kind": "testcontrollerkind", + "__meta_kubernetes_pod_controller_name": "testcontrollername", }, Source: "pod/default/testpod", }, diff --git a/docs/configuration/configuration.md b/docs/configuration/configuration.md index d123f19114..7aeba68689 100644 --- a/docs/configuration/configuration.md +++ b/docs/configuration/configuration.md @@ -694,6 +694,8 @@ Available meta labels: * `__meta_kubernetes_pod_node_name`: The name of the node the pod is scheduled onto. * `__meta_kubernetes_pod_host_ip`: The current host IP of the pod object. * `__meta_kubernetes_pod_uid`: The UID of the pod object. +* `__meta_kubernetes_pod_controller_kind`: Object kind of the pod controller. +* `__meta_kubernetes_pod_controller_name`: Name of the pod controller. #### `endpoints`