This commit is contained in:
Samarth Bagga 2026-02-02 12:36:42 -06:00 committed by GitHub
commit 7845add6fd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 154 additions and 1 deletions

View file

@ -20,6 +20,7 @@ import (
"log/slog"
"net"
"strconv"
"strings"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/model"
@ -196,6 +197,8 @@ const (
serviceLoadBalancerIP = metaLabelPrefix + "service_loadbalancer_ip"
serviceExternalNameLabel = metaLabelPrefix + "service_external_name"
serviceType = metaLabelPrefix + "service_type"
serviceLoadBalancerIPs = metaLabelPrefix + "service_loadbalancer_ips"
serviceLoadBalancerHostnames = metaLabelPrefix + "service_loadbalancer_hostnames"
)
func serviceLabels(svc *apiv1.Service) model.LabelSet {
@ -234,7 +237,30 @@ func (s *Service) buildService(svc *apiv1.Service) *targetgroup.Group {
}
if svc.Spec.Type == apiv1.ServiceTypeLoadBalancer {
labelSet[serviceLoadBalancerIP] = lv(svc.Spec.LoadBalancerIP)
if len(svc.Status.LoadBalancer.Ingress) > 0 {
ips := make([]string, 0, len(svc.Status.LoadBalancer.Ingress))
hostnames := make([]string, 0, len(svc.Status.LoadBalancer.Ingress))
for _, ing := range svc.Status.LoadBalancer.Ingress {
if ing.IP != "" {
ips = append(ips, ing.IP)
}
if ing.Hostname != "" {
hostnames = append(hostnames, ing.Hostname)
}
}
if len(ips) > 0 {
labelSet[serviceLoadBalancerIPs] = lv(strings.Join(ips, ","))
if len(ips) == 1 {
labelSet[serviceLoadBalancerIP] = lv(ips[0])
}
}
if len(hostnames) > 0 {
labelSet[serviceLoadBalancerHostnames] = lv(strings.Join(hostnames, ","))
}
} else if svc.Spec.LoadBalancerIP != "" {
labelSet[serviceLoadBalancerIPs] = lv(svc.Spec.LoadBalancerIP)
labelSet[serviceLoadBalancerIP] = lv(svc.Spec.LoadBalancerIP)
}
}
tg.Targets = append(tg.Targets, labelSet)

View file

@ -113,6 +113,56 @@ func makeLoadBalancerService() *v1.Service {
}
}
func makeLoadBalancerServiceWithStatusIPs(name string, ips []string) *v1.Service {
ing := make([]v1.LoadBalancerIngress, 0, len(ips))
for _, ip := range ips {
ing = append(ing, v1.LoadBalancerIngress{IP: ip})
}
return &v1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: "default",
},
Spec: v1.ServiceSpec{
Ports: []v1.ServicePort{{
Name: "testport",
Protocol: v1.ProtocolTCP,
Port: int32(32001),
}},
Type: v1.ServiceTypeLoadBalancer,
ClusterIP: "10.0.0.1",
},
Status: v1.ServiceStatus{
LoadBalancer: v1.LoadBalancerStatus{Ingress: ing},
},
}
}
func makeLoadBalancerServiceWithStatusHostnames(name string, hosts []string) *v1.Service {
ing := make([]v1.LoadBalancerIngress, 0, len(hosts))
for _, h := range hosts {
ing = append(ing, v1.LoadBalancerIngress{Hostname: h})
}
return &v1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: "default",
},
Spec: v1.ServiceSpec{
Ports: []v1.ServicePort{{
Name: "testport",
Protocol: v1.ProtocolTCP,
Port: int32(32002),
}},
Type: v1.ServiceTypeLoadBalancer,
ClusterIP: "10.0.0.1",
},
Status: v1.ServiceStatus{
LoadBalancer: v1.LoadBalancerStatus{Ingress: ing},
},
}
}
func TestServiceDiscoveryAdd(t *testing.T) {
t.Parallel()
n, c := makeDiscovery(RoleService, NamespaceDiscovery{})
@ -173,6 +223,7 @@ func TestServiceDiscoveryAdd(t *testing.T) {
"__meta_kubernetes_service_port_number": "31900",
"__meta_kubernetes_service_cluster_ip": "10.0.0.1",
"__meta_kubernetes_service_loadbalancer_ip": "127.0.0.1",
"__meta_kubernetes_service_loadbalancer_ips": "127.0.0.1",
},
},
Labels: model.LabelSet{
@ -185,6 +236,82 @@ func TestServiceDiscoveryAdd(t *testing.T) {
}.Run(t)
}
func TestServiceDiscoveryLoadBalancerRealWorld(t *testing.T) {
t.Parallel()
n, c := makeDiscovery(RoleService, NamespaceDiscovery{})
metallbV4 := makeLoadBalancerServiceWithStatusIPs("svc-metallb-v4", []string{"1.2.3.4"})
metallbDual := makeLoadBalancerServiceWithStatusIPs("svc-metallb-dual", []string{"2001:1:2:3:4::", "1.2.3.4"})
eks := makeLoadBalancerServiceWithStatusHostnames("svc-eks", []string{"example-lb-name-abc.elb.eu-central-1.test.com"})
k8sDiscoveryTest{
discovery: n,
afterStart: func() {
c.CoreV1().Services(metallbV4.Namespace).Create(context.Background(), metallbV4, metav1.CreateOptions{})
c.CoreV1().Services(metallbDual.Namespace).Create(context.Background(), metallbDual, metav1.CreateOptions{})
c.CoreV1().Services(eks.Namespace).Create(context.Background(), eks, metav1.CreateOptions{})
},
expectedMaxItems: 3,
expectedRes: map[string]*targetgroup.Group{
"svc/default/svc-metallb-v4": {
Targets: []model.LabelSet{
{
"__meta_kubernetes_service_port_protocol": "TCP",
"__address__": "svc-metallb-v4.default.svc:32001",
"__meta_kubernetes_service_type": "LoadBalancer",
"__meta_kubernetes_service_port_name": "testport",
"__meta_kubernetes_service_port_number": "32001",
"__meta_kubernetes_service_cluster_ip": "10.0.0.1",
"__meta_kubernetes_service_loadbalancer_ips": "1.2.3.4",
"__meta_kubernetes_service_loadbalancer_ip": "1.2.3.4",
},
},
Labels: model.LabelSet{
"__meta_kubernetes_service_name": "svc-metallb-v4",
"__meta_kubernetes_namespace": "default",
},
Source: "svc/default/svc-metallb-v4",
},
"svc/default/svc-metallb-dual": {
Targets: []model.LabelSet{
{
"__meta_kubernetes_service_port_protocol": "TCP",
"__address__": "svc-metallb-dual.default.svc:32001",
"__meta_kubernetes_service_type": "LoadBalancer",
"__meta_kubernetes_service_port_name": "testport",
"__meta_kubernetes_service_port_number": "32001",
"__meta_kubernetes_service_cluster_ip": "10.0.0.1",
"__meta_kubernetes_service_loadbalancer_ips": "2001:1:2:3:4::,1.2.3.4",
},
},
Labels: model.LabelSet{
"__meta_kubernetes_service_name": "svc-metallb-dual",
"__meta_kubernetes_namespace": "default",
},
Source: "svc/default/svc-metallb-dual",
},
"svc/default/svc-eks": {
Targets: []model.LabelSet{
{
"__meta_kubernetes_service_port_protocol": "TCP",
"__address__": "svc-eks.default.svc:32002",
"__meta_kubernetes_service_type": "LoadBalancer",
"__meta_kubernetes_service_port_name": "testport",
"__meta_kubernetes_service_port_number": "32002",
"__meta_kubernetes_service_cluster_ip": "10.0.0.1",
"__meta_kubernetes_service_loadbalancer_hostnames": "example-lb-name-abc.elb.eu-central-1.test.com",
},
},
Labels: model.LabelSet{
"__meta_kubernetes_service_name": "svc-eks",
"__meta_kubernetes_namespace": "default",
},
Source: "svc/default/svc-eks",
},
},
}.Run(t)
}
func TestServiceDiscoveryDelete(t *testing.T) {
t.Parallel()
n, c := makeDiscovery(RoleService, NamespaceDiscovery{}, makeService("default"))