From de6f3b6af7bb1fa333b22143b8cedf72122eded2 Mon Sep 17 00:00:00 2001 From: Tariq Ibrahim Date: Tue, 18 Dec 2018 07:17:34 -0800 Subject: [PATCH] expose kubernetes service cluster ip (#4940) Signed-off-by: tariqibrahim Signed-off-by: tariqibrahim --- discovery/kubernetes/service.go | 14 +++++- discovery/kubernetes/service_test.go | 69 +++++++++++++++++++++++----- docs/configuration/configuration.md | 6 ++- 3 files changed, 74 insertions(+), 15 deletions(-) diff --git a/discovery/kubernetes/service.go b/discovery/kubernetes/service.go index 5fe4c0490..c369328d2 100644 --- a/discovery/kubernetes/service.go +++ b/discovery/kubernetes/service.go @@ -140,6 +140,8 @@ const ( serviceAnnotationPrefix = metaLabelPrefix + "service_annotation_" servicePortNameLabel = metaLabelPrefix + "service_port_name" servicePortProtocolLabel = metaLabelPrefix + "service_port_protocol" + serviceClusterIPLabel = metaLabelPrefix + "service_cluster_ip" + serviceExternalNameLabel = metaLabelPrefix + "service_external_name" ) func serviceLabels(svc *apiv1.Service) model.LabelSet { @@ -169,11 +171,19 @@ func (s *Service) buildService(svc *apiv1.Service) *targetgroup.Group { for _, port := range svc.Spec.Ports { addr := net.JoinHostPort(svc.Name+"."+svc.Namespace+".svc", strconv.FormatInt(int64(port.Port), 10)) - tg.Targets = append(tg.Targets, model.LabelSet{ + labelSet := model.LabelSet{ model.AddressLabel: lv(addr), servicePortNameLabel: lv(port.Name), servicePortProtocolLabel: lv(string(port.Protocol)), - }) + } + + if svc.Spec.Type == apiv1.ServiceTypeExternalName { + labelSet[serviceExternalNameLabel] = lv(svc.Spec.ExternalName) + } else { + labelSet[serviceClusterIPLabel] = lv(svc.Spec.ClusterIP) + } + + tg.Targets = append(tg.Targets, labelSet) } return tg diff --git a/discovery/kubernetes/service_test.go b/discovery/kubernetes/service_test.go index e75cc4a53..f193d2667 100644 --- a/discovery/kubernetes/service_test.go +++ b/discovery/kubernetes/service_test.go @@ -44,6 +44,8 @@ func makeMultiPortService() *v1.Service { Port: int32(30901), }, }, + Type: v1.ServiceTypeClusterIP, + ClusterIP: "10.0.0.1", }, } } @@ -62,6 +64,8 @@ func makeSuffixedService(suffix string) *v1.Service { Port: int32(30900), }, }, + Type: v1.ServiceTypeClusterIP, + ClusterIP: "10.0.0.1", }, } } @@ -70,6 +74,26 @@ func makeService() *v1.Service { return makeSuffixedService("") } +func makeExternalService() *v1.Service { + return &v1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "testservice-external", + Namespace: "default", + }, + Spec: v1.ServiceSpec{ + Ports: []v1.ServicePort{ + { + Name: "testport", + Protocol: v1.ProtocolTCP, + Port: int32(31900), + }, + }, + Type: v1.ServiceTypeExternalName, + ExternalName: "FooExternalName", + }, + } +} + func TestServiceDiscoveryAdd(t *testing.T) { n, c, w := makeDiscovery(RoleService, NamespaceDiscovery{}) @@ -79,15 +103,19 @@ func TestServiceDiscoveryAdd(t *testing.T) { obj := makeService() c.CoreV1().Services(obj.Namespace).Create(obj) w.Services().Add(obj) + obj = makeExternalService() + c.CoreV1().Services(obj.Namespace).Create(obj) + w.Services().Add(obj) }, - expectedMaxItems: 1, + expectedMaxItems: 2, expectedRes: map[string]*targetgroup.Group{ "svc/default/testservice": { Targets: []model.LabelSet{ { "__meta_kubernetes_service_port_protocol": "TCP", - "__address__": "testservice.default.svc:30900", - "__meta_kubernetes_service_port_name": "testport", + "__address__": "testservice.default.svc:30900", + "__meta_kubernetes_service_cluster_ip": "10.0.0.1", + "__meta_kubernetes_service_port_name": "testport", }, }, Labels: model.LabelSet{ @@ -96,6 +124,21 @@ func TestServiceDiscoveryAdd(t *testing.T) { }, Source: "svc/default/testservice", }, + "svc/default/testservice-external": { + Targets: []model.LabelSet{ + { + "__meta_kubernetes_service_port_protocol": "TCP", + "__address__": "testservice-external.default.svc:31900", + "__meta_kubernetes_service_port_name": "testport", + "__meta_kubernetes_service_external_name": "FooExternalName", + }, + }, + Labels: model.LabelSet{ + "__meta_kubernetes_service_name": "testservice-external", + "__meta_kubernetes_namespace": "default", + }, + Source: "svc/default/testservice-external", + }, }, }.Run(t) } @@ -135,13 +178,15 @@ func TestServiceDiscoveryUpdate(t *testing.T) { Targets: []model.LabelSet{ { "__meta_kubernetes_service_port_protocol": "TCP", - "__address__": "testservice.default.svc:30900", - "__meta_kubernetes_service_port_name": "testport0", + "__address__": "testservice.default.svc:30900", + "__meta_kubernetes_service_cluster_ip": "10.0.0.1", + "__meta_kubernetes_service_port_name": "testport0", }, { "__meta_kubernetes_service_port_protocol": "UDP", - "__address__": "testservice.default.svc:30901", - "__meta_kubernetes_service_port_name": "testport1", + "__address__": "testservice.default.svc:30901", + "__meta_kubernetes_service_cluster_ip": "10.0.0.1", + "__meta_kubernetes_service_port_name": "testport1", }, }, Labels: model.LabelSet{ @@ -175,8 +220,9 @@ func TestServiceDiscoveryNamespaces(t *testing.T) { Targets: []model.LabelSet{ { "__meta_kubernetes_service_port_protocol": "TCP", - "__address__": "testservice.ns1.svc:30900", - "__meta_kubernetes_service_port_name": "testport", + "__address__": "testservice.ns1.svc:30900", + "__meta_kubernetes_service_cluster_ip": "10.0.0.1", + "__meta_kubernetes_service_port_name": "testport", }, }, Labels: model.LabelSet{ @@ -189,8 +235,9 @@ func TestServiceDiscoveryNamespaces(t *testing.T) { Targets: []model.LabelSet{ { "__meta_kubernetes_service_port_protocol": "TCP", - "__address__": "testservice.ns2.svc:30900", - "__meta_kubernetes_service_port_name": "testport", + "__address__": "testservice.ns2.svc:30900", + "__meta_kubernetes_service_cluster_ip": "10.0.0.1", + "__meta_kubernetes_service_port_name": "testport", }, }, Labels: model.LabelSet{ diff --git a/docs/configuration/configuration.md b/docs/configuration/configuration.md index 48e26fe11..fa1b1e483 100644 --- a/docs/configuration/configuration.md +++ b/docs/configuration/configuration.md @@ -694,9 +694,11 @@ service port. Available meta labels: * `__meta_kubernetes_namespace`: The namespace of the service object. -* `__meta_kubernetes_service_name`: The name of the service object. -* `__meta_kubernetes_service_label_`: The label of the service object. * `__meta_kubernetes_service_annotation_`: The annotation of the service object. +* `__meta_kubernetes_service_cluster_ip`: The cluster IP address of the service. (Does not apply to services of type ExternalName) +* `__meta_kubernetes_service_external_name`: The DNS name of the service. (Applies to services of type ExternalName) +* `__meta_kubernetes_service_label_`: The label of the service object. +* `__meta_kubernetes_service_name`: The name of the service object. * `__meta_kubernetes_service_port_name`: Name of the service port for the target. * `__meta_kubernetes_service_port_number`: Number of the service port for the target. * `__meta_kubernetes_service_port_protocol`: Protocol of the service port for the target.