From 7044fdf040d5d0958762cfb770e87827f861d8ef Mon Sep 17 00:00:00 2001 From: John Gardiner Myers Date: Sat, 16 Sep 2023 17:32:28 -0700 Subject: [PATCH] Use ServiceIP for ClusterIP Services with internal-hostname annotation --- docs/annotations/annotations.md | 2 +- docs/sources/service.md | 3 ++- source/service.go | 2 +- source/service_test.go | 44 +++++++++++++++++++++++---------- 4 files changed, 35 insertions(+), 16 deletions(-) diff --git a/docs/annotations/annotations.md b/docs/annotations/annotations.md index a880674f8c..890b0bc323 100644 --- a/docs/annotations/annotations.md +++ b/docs/annotations/annotations.md @@ -25,7 +25,7 @@ The following table documents which sources support which annotations: | Traefik | | Yes | | Yes | Yes | Yes | [^1]: Unless the `--ignore-hostname-annotation` flag is specified. -[^2]: Only behaves differently than `hostname` for `Service`s of type `LoadBalancer`. +[^2]: Only behaves differently than `hostname` for `Service`s of type `ClusterIP` or `LoadBalancer`. [^3]: Also supported on `Pods` referenced from a headless `Service`'s `Endpoints`. [^4]: The annotation should be on the `Gateway` diff --git a/docs/sources/service.md b/docs/sources/service.md index 0eb439461d..9a1871c7b1 100644 --- a/docs/sources/service.md +++ b/docs/sources/service.md @@ -75,7 +75,8 @@ or the `--publish-host-ip` flag was specified, uses the Pod's `status.hostIP` fi ### ClusterIP (not headless) -1. If the `--publish-internal-services` flag is specified, uses the `spec.ServiceIP`. +1. If the hostname came from an `external-dns.alpha.kubernetes.io/internal-hostname` annotation +or the `--publish-internal-services` flag was specified, uses the `spec.ServiceIP`. 2. Otherwise, does not create any targets. diff --git a/source/service.go b/source/service.go index f1faf68c03..fd091d0f44 100644 --- a/source/service.go +++ b/source/service.go @@ -505,7 +505,7 @@ func (sc *serviceSource) generateEndpoints(svc *v1.Service, hostname string, pro case v1.ServiceTypeClusterIP: if svc.Spec.ClusterIP == v1.ClusterIPNone { endpoints = append(endpoints, sc.extractHeadlessEndpoints(svc, hostname, ttl)...) - } else if sc.publishInternal { + } else if useClusterIP || sc.publishInternal { targets = extractServiceIps(svc) } case v1.ServiceTypeNodePort: diff --git a/source/service_test.go b/source/service_test.go index 84d555cd8a..13c029d593 100644 --- a/source/service_test.go +++ b/source/service_test.go @@ -910,7 +910,25 @@ func testServiceSourceEndpoints(t *testing.T) { expected: []*endpoint.Endpoint{}, }, { - title: "internal-host annotated services return an endpoint with Cluster IP", + title: "internal-host annotated and host annotated clusterip services return an endpoint with Cluster IP", + svcNamespace: "testing", + svcName: "foo", + svcType: v1.ServiceTypeClusterIP, + labels: map[string]string{}, + annotations: map[string]string{ + hostnameAnnotationKey: "foo.example.org.", + internalHostnameAnnotationKey: "foo.internal.example.org.", + }, + clusterIP: "1.1.1.1", + externalIPs: []string{}, + lbs: []string{"1.2.3.4"}, + serviceTypesFilter: []string{}, + expected: []*endpoint.Endpoint{ + {DNSName: "foo.internal.example.org", RecordType: endpoint.RecordTypeA, Targets: endpoint.Targets{"1.1.1.1"}}, + }, + }, + { + title: "internal-host annotated loadbalancer services return an endpoint with Cluster IP", svcNamespace: "testing", svcName: "foo", svcType: v1.ServiceTypeLoadBalancer, @@ -927,7 +945,7 @@ func testServiceSourceEndpoints(t *testing.T) { }, }, { - title: "internal-host annotated and host annotated services return an endpoint with Cluster IP and an endpoint with lb IP", + title: "internal-host annotated and host annotated loadbalancer services return an endpoint with Cluster IP and an endpoint with lb IP", svcNamespace: "testing", svcName: "foo", svcType: v1.ServiceTypeLoadBalancer, @@ -1816,10 +1834,10 @@ func TestServiceSourceNodePortServices(t *testing.T) { }, }, }}, - podNames: []string{"pod-0"}, - nodeIndex: []int{1}, - phases: []v1.PodPhase{v1.PodRunning}, - conditions: []v1.PodCondition{{Type: v1.PodReady, Status: v1.ConditionFalse}}, + podNames: []string{"pod-0"}, + nodeIndex: []int{1}, + phases: []v1.PodPhase{v1.PodRunning}, + conditions: []v1.PodCondition{{Type: v1.PodReady, Status: v1.ConditionFalse}}, deletionTimestamp: []*metav1.Time{{}}, }, { @@ -1867,7 +1885,7 @@ func TestServiceSourceNodePortServices(t *testing.T) { {Type: v1.PodReady, Status: v1.ConditionFalse}, {Type: v1.PodReady, Status: v1.ConditionFalse}, }, - deletionTimestamp: []*metav1.Time{{},{}}, + deletionTimestamp: []*metav1.Time{{}, {}}, }, { title: "annotated NodePort services with ExternalTrafficPolicy=Local return pods in Ready & Running state", @@ -1911,7 +1929,7 @@ func TestServiceSourceNodePortServices(t *testing.T) { {Type: v1.PodReady, Status: v1.ConditionTrue}, {Type: v1.PodReady, Status: v1.ConditionFalse}, }, - deletionTimestamp: []*metav1.Time{{},{}}, + deletionTimestamp: []*metav1.Time{{}, {}}, }, { title: "annotated NodePort services with ExternalTrafficPolicy=Local return pods in Ready & Running state & not in Terminating", @@ -2254,14 +2272,14 @@ func TestServiceSourceNodePortServices(t *testing.T) { NodeName: tc.nodes[tc.nodeIndex[i]].Name, }, ObjectMeta: metav1.ObjectMeta{ - Namespace: tc.svcNamespace, - Name: podname, - Labels: tc.labels, - Annotations: tc.annotations, + Namespace: tc.svcNamespace, + Name: podname, + Labels: tc.labels, + Annotations: tc.annotations, DeletionTimestamp: tc.deletionTimestamp[i], }, Status: v1.PodStatus{ - Phase: tc.phases[i], + Phase: tc.phases[i], Conditions: []v1.PodCondition{tc.conditions[i]}, }, }