From 77f42642ef7917cffd74360b5f51ab8c0f191ccc Mon Sep 17 00:00:00 2001 From: Aaron Henshaw Date: Mon, 24 Jun 2019 12:21:59 -0400 Subject: [PATCH] Add use-external-host-ip as annotation to use ExternalIP of Node for headless services --- source/service.go | 26 +++++++++++++++++++++++--- source/source.go | 7 +++++++ 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/source/service.go b/source/service.go index 1fba3d624b..85a7ca0225 100644 --- a/source/service.go +++ b/source/service.go @@ -211,7 +211,7 @@ func (sc *serviceSource) Endpoints() ([]*endpoint.Endpoint, error) { return endpoints, nil } -func (sc *serviceSource) extractHeadlessEndpoints(svc *v1.Service, hostname string, ttl endpoint.TTL) []*endpoint.Endpoint { +func (sc *serviceSource) extractHeadlessEndpoints(svc *v1.Service, hostname string, ttl endpoint.TTL, externalIp bool) []*endpoint.Endpoint { var endpoints []*endpoint.Endpoint labelSelector, err := metav1.ParseToLabelSelector(labels.Set(svc.Spec.Selector).AsSelectorPreValidated().String()) @@ -237,7 +237,22 @@ func (sc *serviceSource) extractHeadlessEndpoints(svc *v1.Service, hostname stri headlessDomains = append(headlessDomains, fmt.Sprintf("%s.%s", v.Spec.Hostname, hostname)) } for _, headlessDomain := range headlessDomains { - if sc.publishHostIP == true { + if sc.publishHostIP && externalIp { + node, err := sc.nodeInformer.Lister().Get(v.Spec.NodeName) + if err != nil { + return nil + } + if v.Status.Phase == v1.PodRunning { + for _, x := range node.Status.Addresses { + if x.Type == v1.NodeExternalIP { + log.Debugf("Generating matching endpoint %s with External %s", headlessDomain, v.Status.HostIP) + targetsByHeadlessDomain[headlessDomain] = append(targetsByHeadlessDomain[headlessDomain], x.Address) + } + } + } else { + log.Debugf("Pod %s is not in running phase", v.Spec.Hostname) + } + } else if sc.publishHostIP == true { log.Debugf("Generating matching endpoint %s with HostIP %s", headlessDomain, v.Status.HostIP) // To reduce traffice on the DNS API only add record for running Pods. Good Idea? if v.Status.Phase == v1.PodRunning { @@ -365,6 +380,11 @@ func (sc *serviceSource) generateEndpoints(svc *v1.Service, hostname string, pro log.Warn(err) } + externalIp := getExternalIpFromAnnotations(svc.Annotations) + if err != nil { + log.Warn(err) + } + epA := &endpoint.Endpoint{ RecordTTL: ttl, RecordType: endpoint.RecordTypeA, @@ -394,7 +414,7 @@ func (sc *serviceSource) generateEndpoints(svc *v1.Service, hostname string, pro targets = append(targets, extractServiceIps(svc)...) } if svc.Spec.ClusterIP == v1.ClusterIPNone { - endpoints = append(endpoints, sc.extractHeadlessEndpoints(svc, hostname, ttl)...) + endpoints = append(endpoints, sc.extractHeadlessEndpoints(svc, hostname, ttl, externalIp)...) } case v1.ServiceTypeNodePort: // add the nodeTargets and extract an SRV endpoint diff --git a/source/source.go b/source/source.go index 83fc846917..e45e464f29 100644 --- a/source/source.go +++ b/source/source.go @@ -37,6 +37,8 @@ const ( ttlAnnotationKey = "external-dns.alpha.kubernetes.io/ttl" // The annotation used for switching to the alias record types e. g. AWS Alias records instead of a normal CNAME aliasAnnotationKey = "external-dns.alpha.kubernetes.io/alias" + // The annotation used for having publishHostIP use the ExternalIP of the Host Node + externalIPAnnotationKey = "external-dns.alpha.kubernetes.io/use-external-host-ip" // The value of the controller annotation so that we feel responsible controllerAnnotationValue = "dns-controller" ) @@ -86,6 +88,11 @@ func getAliasFromAnnotations(annotations map[string]string) bool { return exists && aliasAnnotation == "true" } +func getExternalIpFromAnnotations(annotations map[string]string) bool { + aliasAnnotation, exists := annotations[externalIPAnnotationKey] + return exists && aliasAnnotation == "true" +} + func getProviderSpecificAnnotations(annotations map[string]string) endpoint.ProviderSpecific { providerSpecificAnnotations := endpoint.ProviderSpecific{}