From de28274a6f80a9e448ad13ea3f55f421068d0bfd Mon Sep 17 00:00:00 2001 From: Alfred Krohmer Date: Sun, 28 Apr 2019 10:04:39 +0200 Subject: [PATCH 1/5] Headless service: retrieve endpoints via Endpoints resource; evaluate spec.publishNotReadyAddresses Currently, the endpoints of headless services are retrieved by querying pods using the pod selector of the service. Instead, we now query for an Endpoints resource with the same name as the Service object to get the endpoints for the service. This is needed in order to support the spec.publishNotReadyPods attribute of a service. --- source/service.go | 71 ++++++++++++----- source/service_test.go | 174 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 205 insertions(+), 40 deletions(-) diff --git a/source/service.go b/source/service.go index 11323eae3e..cf15a7581c 100644 --- a/source/service.go +++ b/source/service.go @@ -59,6 +59,7 @@ type serviceSource struct { publishInternal bool publishHostIP bool serviceInformer coreinformers.ServiceInformer + endpointsInformer coreinformers.EndpointsInformer podInformer coreinformers.PodInformer nodeInformer coreinformers.NodeInformer serviceTypeFilter map[string]struct{} @@ -84,6 +85,7 @@ func NewServiceSource(kubeClient kubernetes.Interface, namespace, annotationFilt // Set resync period to 0, to prevent processing when nothing has changed informerFactory := kubeinformers.NewSharedInformerFactoryWithOptions(kubeClient, 0, kubeinformers.WithNamespace(namespace)) serviceInformer := informerFactory.Core().V1().Services() + endpointsInformer := informerFactory.Core().V1().Endpoints() podInformer := informerFactory.Core().V1().Pods() nodeInformer := informerFactory.Core().V1().Nodes() @@ -94,6 +96,13 @@ func NewServiceSource(kubeClient kubernetes.Interface, namespace, annotationFilt }, }, ) + endpointsInformer.Informer().AddEventHandler( + cache.ResourceEventHandlerFuncs{ + AddFunc: func(obj interface{}) { + log.Debug("endpoints added") + }, + }, + ) podInformer.Informer().AddEventHandler( cache.ResourceEventHandlerFuncs{ AddFunc: func(obj interface{}) { @@ -136,6 +145,7 @@ func NewServiceSource(kubeClient kubernetes.Interface, namespace, annotationFilt publishInternal: publishInternal, publishHostIP: publishHostIP, serviceInformer: serviceInformer, + endpointsInformer: endpointsInformer, podInformer: podInformer, nodeInformer: nodeInformer, serviceTypeFilter: serviceTypes, @@ -219,6 +229,12 @@ func (sc *serviceSource) extractHeadlessEndpoints(svc *v1.Service, hostname stri return nil } + endpointsObject, err := sc.endpointsInformer.Lister().Endpoints(svc.Namespace).Get(svc.GetName()) + if err != nil { + log.Errorf("Get endpoints of service[%s] error:%v", svc.GetName(), err) + return endpoints + } + pods, err := sc.podInformer.Lister().Pods(svc.Namespace).List(selector) if err != nil { log.Errorf("List Pods of service[%s] error:%v", svc.GetName(), err) @@ -226,32 +242,47 @@ func (sc *serviceSource) extractHeadlessEndpoints(svc *v1.Service, hostname stri } targetsByHeadlessDomain := make(map[string][]string) - for _, v := range pods { - headlessDomains := []string{hostname} - - if v.Spec.Hostname != "" { - headlessDomains = append(headlessDomains, fmt.Sprintf("%s.%s", v.Spec.Hostname, hostname)) + for _, subset := range endpointsObject.Subsets { + addresses := subset.Addresses + if svc.Spec.PublishNotReadyAddresses { + addresses = append(addresses, subset.NotReadyAddresses...) } - for _, headlessDomain := range headlessDomains { - if sc.publishHostIP { - log.Debugf("Generating matching endpoint %s with HostIP %s", headlessDomain, v.Status.HostIP) - // To reduce traffic on the DNS API only add record for running Pods. Good Idea? - if v.Status.Phase == v1.PodRunning { - targetsByHeadlessDomain[headlessDomain] = append(targetsByHeadlessDomain[headlessDomain], v.Status.HostIP) - } else { - log.Debugf("Pod %s is not in running phase", v.Spec.Hostname) + + for _, address := range addresses { + // find pod for this address + if address.TargetRef.APIVersion != "" || address.TargetRef.Kind != "Pod" { + log.Debugf("Skipping address because its target is not a pod: %v", address) + continue + } + var pod *v1.Pod + for _, v := range pods { + if v.Name == address.TargetRef.Name { + pod = v + break } - } else { - log.Debugf("Generating matching endpoint %s with PodIP %s", headlessDomain, v.Status.PodIP) - // To reduce traffice on the DNS API only add record for running Pods. Good Idea? - if v.Status.Phase == v1.PodRunning { - targetsByHeadlessDomain[headlessDomain] = append(targetsByHeadlessDomain[headlessDomain], v.Status.PodIP) + } + if pod == nil { + log.Errorf("Pod %s not found for address %v", address.TargetRef.Name, address) + continue + } + + headlessDomains := []string{hostname} + if pod.Spec.Hostname != "" { + headlessDomains = append(headlessDomains, fmt.Sprintf("%s.%s", pod.Spec.Hostname, hostname)) + } + + for _, headlessDomain := range headlessDomains { + var ep string + if sc.publishHostIP { + ep = pod.Status.HostIP + log.Debugf("Generating matching endpoint %s with HostIP %s", headlessDomain, ep) } else { - log.Debugf("Pod %s is not in running phase", v.Spec.Hostname) + ep = address.IP + log.Debugf("Generating matching endpoint %s with EndpointAddress IP %s", headlessDomain, ep) } + targetsByHeadlessDomain[headlessDomain] = append(targetsByHeadlessDomain[headlessDomain], ep) } } - } headlessDomains := []string{} diff --git a/source/service_test.go b/source/service_test.go index 7acdbbc604..ca7e74955c 100644 --- a/source/service_test.go +++ b/source/service_test.go @@ -1645,7 +1645,8 @@ func TestHeadlessServices(t *testing.T) { lbs []string podnames []string hostnames []string - phases []v1.PodPhase + podsReady []bool + publishNotReadyAddresses bool expected []*endpoint.Endpoint expectError bool }{ @@ -1670,7 +1671,8 @@ func TestHeadlessServices(t *testing.T) { []string{}, []string{"foo-0", "foo-1"}, []string{"foo-0", "foo-1"}, - []v1.PodPhase{v1.PodRunning, v1.PodRunning}, + []bool{true, true}, + false, []*endpoint.Endpoint{ {DNSName: "foo-0.service.example.org", Targets: endpoint.Targets{"1.1.1.1"}}, {DNSName: "foo-1.service.example.org", Targets: endpoint.Targets{"1.1.1.2"}}, @@ -1699,7 +1701,8 @@ func TestHeadlessServices(t *testing.T) { []string{}, []string{"foo-0", "foo-1"}, []string{"foo-0", "foo-1"}, - []v1.PodPhase{v1.PodRunning, v1.PodRunning}, + []bool{true, true}, + false, []*endpoint.Endpoint{}, false, }, @@ -1725,7 +1728,8 @@ func TestHeadlessServices(t *testing.T) { []string{}, []string{"foo-0", "foo-1"}, []string{"foo-0", "foo-1"}, - []v1.PodPhase{v1.PodRunning, v1.PodRunning}, + []bool{true, true}, + false, []*endpoint.Endpoint{ {DNSName: "foo-0.service.example.org", Targets: endpoint.Targets{"1.1.1.1"}, RecordTTL: endpoint.TTL(1)}, {DNSName: "foo-1.service.example.org", Targets: endpoint.Targets{"1.1.1.2"}, RecordTTL: endpoint.TTL(1)}, @@ -1754,13 +1758,44 @@ func TestHeadlessServices(t *testing.T) { []string{}, []string{"foo-0", "foo-1"}, []string{"foo-0", "foo-1"}, - []v1.PodPhase{v1.PodRunning, v1.PodFailed}, + []bool{true, false}, + false, []*endpoint.Endpoint{ {DNSName: "foo-0.service.example.org", Targets: endpoint.Targets{"1.1.1.1"}}, {DNSName: "service.example.org", Targets: endpoint.Targets{"1.1.1.1"}}, }, false, }, + { + "annotated Headless services return endpoints for all Pod if publishNotReadyAddresses is set", + "", + "testing", + "foo", + v1.ServiceTypeClusterIP, + "", + "", + false, + map[string]string{"component": "foo"}, + map[string]string{ + hostnameAnnotationKey: "service.example.org", + }, + v1.ClusterIPNone, + []string{"1.1.1.1", "1.1.1.2"}, + map[string]string{ + "component": "foo", + }, + []string{}, + []string{"foo-0", "foo-1"}, + []string{"foo-0", "foo-1"}, + []bool{true, false}, + true, + []*endpoint.Endpoint{ + {DNSName: "foo-0.service.example.org", Targets: endpoint.Targets{"1.1.1.1"}}, + {DNSName: "foo-1.service.example.org", Targets: endpoint.Targets{"1.1.1.2"}}, + {DNSName: "service.example.org", Targets: endpoint.Targets{"1.1.1.1", "1.1.1.2"}}, + }, + false, + }, { "annotated Headless services return endpoints for pods missing hostname", "", @@ -1782,7 +1817,8 @@ func TestHeadlessServices(t *testing.T) { []string{}, []string{"foo-0", "foo-1"}, []string{"", ""}, - []v1.PodPhase{v1.PodRunning, v1.PodRunning}, + []bool{true, true}, + false, []*endpoint.Endpoint{ {DNSName: "service.example.org", Targets: endpoint.Targets{"1.1.1.1", "1.1.1.2"}}, }, @@ -1795,9 +1831,10 @@ func TestHeadlessServices(t *testing.T) { service := &v1.Service{ Spec: v1.ServiceSpec{ - Type: tc.svcType, - ClusterIP: tc.clusterIP, - Selector: tc.selector, + Type: tc.svcType, + ClusterIP: tc.clusterIP, + Selector: tc.selector, + PublishNotReadyAddresses: tc.publishNotReadyAddresses, }, ObjectMeta: metav1.ObjectMeta{ Namespace: tc.svcNamespace, @@ -1810,6 +1847,8 @@ func TestHeadlessServices(t *testing.T) { _, err := kubernetes.CoreV1().Services(service.Namespace).Create(service) require.NoError(t, err) + var addresses []v1.EndpointAddress + var notReadyAddresses []v1.EndpointAddress for i, podname := range tc.podnames { pod := &v1.Pod{ Spec: v1.PodSpec{ @@ -1824,13 +1863,41 @@ func TestHeadlessServices(t *testing.T) { }, Status: v1.PodStatus{ PodIP: tc.podIPs[i], - Phase: tc.phases[i], }, } _, err = kubernetes.CoreV1().Pods(tc.svcNamespace).Create(pod) require.NoError(t, err) + + address := v1.EndpointAddress{ + IP: tc.podIPs[i], + TargetRef: &v1.ObjectReference{ + APIVersion: "", + Kind: "Pod", + Name: podname, + }, + } + if tc.podsReady[i] { + addresses = append(addresses, address) + } else { + notReadyAddresses = append(notReadyAddresses, address) + } } + endpointsObject := &v1.Endpoints{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: tc.svcNamespace, + Name: tc.svcName, + Labels: tc.labels, + }, + Subsets: []v1.EndpointSubset{ + { + Addresses: addresses, + NotReadyAddresses: notReadyAddresses, + }, + }, + } + _, err = kubernetes.CoreV1().Endpoints(tc.svcNamespace).Create(endpointsObject) + require.NoError(t, err) // Create our object under test and get the endpoints. client, _ := NewServiceSource( @@ -1879,7 +1946,8 @@ func TestHeadlessServicesHostIP(t *testing.T) { lbs []string podnames []string hostnames []string - phases []v1.PodPhase + podsReady []bool + publishNotReadyAddresses bool expected []*endpoint.Endpoint expectError bool }{ @@ -1904,7 +1972,8 @@ func TestHeadlessServicesHostIP(t *testing.T) { []string{}, []string{"foo-0", "foo-1"}, []string{"foo-0", "foo-1"}, - []v1.PodPhase{v1.PodRunning, v1.PodRunning}, + []bool{true, true}, + false, []*endpoint.Endpoint{ {DNSName: "foo-0.service.example.org", Targets: endpoint.Targets{"1.1.1.1"}}, {DNSName: "foo-1.service.example.org", Targets: endpoint.Targets{"1.1.1.2"}}, @@ -1933,7 +2002,8 @@ func TestHeadlessServicesHostIP(t *testing.T) { []string{}, []string{"foo-0", "foo-1"}, []string{"foo-0", "foo-1"}, - []v1.PodPhase{v1.PodRunning, v1.PodRunning}, + []bool{true, true}, + false, []*endpoint.Endpoint{}, false, }, @@ -1959,7 +2029,8 @@ func TestHeadlessServicesHostIP(t *testing.T) { []string{}, []string{"foo-0", "foo-1"}, []string{"foo-0", "foo-1"}, - []v1.PodPhase{v1.PodRunning, v1.PodRunning}, + []bool{true, true}, + false, []*endpoint.Endpoint{ {DNSName: "foo-0.service.example.org", Targets: endpoint.Targets{"1.1.1.1"}, RecordTTL: endpoint.TTL(1)}, {DNSName: "foo-1.service.example.org", Targets: endpoint.Targets{"1.1.1.2"}, RecordTTL: endpoint.TTL(1)}, @@ -1988,13 +2059,44 @@ func TestHeadlessServicesHostIP(t *testing.T) { []string{}, []string{"foo-0", "foo-1"}, []string{"foo-0", "foo-1"}, - []v1.PodPhase{v1.PodRunning, v1.PodFailed}, + []bool{true, false}, + false, []*endpoint.Endpoint{ {DNSName: "foo-0.service.example.org", Targets: endpoint.Targets{"1.1.1.1"}}, {DNSName: "service.example.org", Targets: endpoint.Targets{"1.1.1.1"}}, }, false, }, + { + "annotated Headless services return endpoints for all Pod if publishNotReadyAddresses is set", + "", + "testing", + "foo", + v1.ServiceTypeClusterIP, + "", + "", + false, + map[string]string{"component": "foo"}, + map[string]string{ + hostnameAnnotationKey: "service.example.org", + }, + v1.ClusterIPNone, + []string{"1.1.1.1", "1.1.1.2"}, + map[string]string{ + "component": "foo", + }, + []string{}, + []string{"foo-0", "foo-1"}, + []string{"foo-0", "foo-1"}, + []bool{true, false}, + true, + []*endpoint.Endpoint{ + {DNSName: "foo-0.service.example.org", Targets: endpoint.Targets{"1.1.1.1"}}, + {DNSName: "foo-1.service.example.org", Targets: endpoint.Targets{"1.1.1.2"}}, + {DNSName: "service.example.org", Targets: endpoint.Targets{"1.1.1.1", "1.1.1.2"}}, + }, + false, + }, { "annotated Headless services return endpoints for pods missing hostname", "", @@ -2016,7 +2118,8 @@ func TestHeadlessServicesHostIP(t *testing.T) { []string{}, []string{"foo-0", "foo-1"}, []string{"", ""}, - []v1.PodPhase{v1.PodRunning, v1.PodRunning}, + []bool{true, true}, + false, []*endpoint.Endpoint{ {DNSName: "service.example.org", Targets: endpoint.Targets{"1.1.1.1", "1.1.1.2"}}, }, @@ -2029,9 +2132,10 @@ func TestHeadlessServicesHostIP(t *testing.T) { service := &v1.Service{ Spec: v1.ServiceSpec{ - Type: tc.svcType, - ClusterIP: tc.clusterIP, - Selector: tc.selector, + Type: tc.svcType, + ClusterIP: tc.clusterIP, + Selector: tc.selector, + PublishNotReadyAddresses: tc.publishNotReadyAddresses, }, ObjectMeta: metav1.ObjectMeta{ Namespace: tc.svcNamespace, @@ -2044,6 +2148,8 @@ func TestHeadlessServicesHostIP(t *testing.T) { _, err := kubernetes.CoreV1().Services(service.Namespace).Create(service) require.NoError(t, err) + var addresses []v1.EndpointAddress + var notReadyAddresses []v1.EndpointAddress for i, podname := range tc.podnames { pod := &v1.Pod{ Spec: v1.PodSpec{ @@ -2058,13 +2164,41 @@ func TestHeadlessServicesHostIP(t *testing.T) { }, Status: v1.PodStatus{ HostIP: tc.hostIPs[i], - Phase: tc.phases[i], }, } _, err = kubernetes.CoreV1().Pods(tc.svcNamespace).Create(pod) require.NoError(t, err) + + address := v1.EndpointAddress{ + IP: "4.3.2.1", + TargetRef: &v1.ObjectReference{ + APIVersion: "", + Kind: "Pod", + Name: podname, + }, + } + if tc.podsReady[i] { + addresses = append(addresses, address) + } else { + notReadyAddresses = append(notReadyAddresses, address) + } } + endpointsObject := &v1.Endpoints{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: tc.svcNamespace, + Name: tc.svcName, + Labels: tc.labels, + }, + Subsets: []v1.EndpointSubset{ + { + Addresses: addresses, + NotReadyAddresses: notReadyAddresses, + }, + }, + } + _, err = kubernetes.CoreV1().Endpoints(tc.svcNamespace).Create(endpointsObject) + require.NoError(t, err) // Create our object under test and get the endpoints. client, _ := NewServiceSource( From 6cab35b4047471c8deb18bde17f7334036f09c01 Mon Sep 17 00:00:00 2001 From: Alfred Krohmer Date: Fri, 23 Aug 2019 13:05:13 +0200 Subject: [PATCH 2/5] Add CLI option to always publish not ready addresses of headless services --- main.go | 39 ++++++++++++----------- pkg/apis/externaldns/types.go | 2 ++ source/service.go | 60 +++++++++++++++++++---------------- source/service_test.go | 10 +++++- source/store.go | 41 ++++++++++++------------ 5 files changed, 84 insertions(+), 68 deletions(-) diff --git a/main.go b/main.go index db45b41b85..6e62380504 100644 --- a/main.go +++ b/main.go @@ -71,25 +71,26 @@ func main() { // Create a source.Config from the flags passed by the user. sourceCfg := &source.Config{ - Namespace: cfg.Namespace, - AnnotationFilter: cfg.AnnotationFilter, - FQDNTemplate: cfg.FQDNTemplate, - CombineFQDNAndAnnotation: cfg.CombineFQDNAndAnnotation, - IgnoreHostnameAnnotation: cfg.IgnoreHostnameAnnotation, - Compatibility: cfg.Compatibility, - PublishInternal: cfg.PublishInternal, - PublishHostIP: cfg.PublishHostIP, - ConnectorServer: cfg.ConnectorSourceServer, - CRDSourceAPIVersion: cfg.CRDSourceAPIVersion, - CRDSourceKind: cfg.CRDSourceKind, - KubeConfig: cfg.KubeConfig, - KubeMaster: cfg.Master, - ServiceTypeFilter: cfg.ServiceTypeFilter, - IstioIngressGatewayServices: cfg.IstioIngressGatewayServices, - CFAPIEndpoint: cfg.CFAPIEndpoint, - CFUsername: cfg.CFUsername, - CFPassword: cfg.CFPassword, - ContourLoadBalancerService: cfg.ContourLoadBalancerService, + Namespace: cfg.Namespace, + AnnotationFilter: cfg.AnnotationFilter, + FQDNTemplate: cfg.FQDNTemplate, + CombineFQDNAndAnnotation: cfg.CombineFQDNAndAnnotation, + IgnoreHostnameAnnotation: cfg.IgnoreHostnameAnnotation, + Compatibility: cfg.Compatibility, + PublishInternal: cfg.PublishInternal, + PublishHostIP: cfg.PublishHostIP, + AlwaysPublishNotReadyAddresses: cfg.AlwaysPublishNotReadyAddresses, + ConnectorServer: cfg.ConnectorSourceServer, + CRDSourceAPIVersion: cfg.CRDSourceAPIVersion, + CRDSourceKind: cfg.CRDSourceKind, + KubeConfig: cfg.KubeConfig, + KubeMaster: cfg.Master, + ServiceTypeFilter: cfg.ServiceTypeFilter, + IstioIngressGatewayServices: cfg.IstioIngressGatewayServices, + CFAPIEndpoint: cfg.CFAPIEndpoint, + CFUsername: cfg.CFUsername, + CFPassword: cfg.CFPassword, + ContourLoadBalancerService: cfg.ContourLoadBalancerService, } // Lookup all the selected sources by names and pass them the desired configuration. diff --git a/pkg/apis/externaldns/types.go b/pkg/apis/externaldns/types.go index c4136a429b..a4fbdcd225 100644 --- a/pkg/apis/externaldns/types.go +++ b/pkg/apis/externaldns/types.go @@ -51,6 +51,7 @@ type Config struct { Compatibility string PublishInternal bool PublishHostIP bool + AlwaysPublishNotReadyAddresses bool ConnectorSourceServer string Provider string GoogleProject string @@ -293,6 +294,7 @@ func (cfg *Config) ParseFlags(args []string) error { app.Flag("compatibility", "Process annotation semantics from legacy implementations (optional, options: mate, molecule)").Default(defaultConfig.Compatibility).EnumVar(&cfg.Compatibility, "", "mate", "molecule") app.Flag("publish-internal-services", "Allow external-dns to publish DNS records for ClusterIP services (optional)").BoolVar(&cfg.PublishInternal) app.Flag("publish-host-ip", "Allow external-dns to publish host-ip for headless services (optional)").BoolVar(&cfg.PublishHostIP) + app.Flag("always-publish-not-ready-address", "Always publish also not ready addresses for headless services (optional)").BoolVar(&cfg.AlwaysPublishNotReadyAddresses) app.Flag("connector-source-server", "The server to connect for connector source, valid only when using connector source").Default(defaultConfig.ConnectorSourceServer).StringVar(&cfg.ConnectorSourceServer) app.Flag("crd-source-apiversion", "API version of the CRD for crd source, e.g. `externaldns.k8s.io/v1alpha1`, valid only when using crd source").Default(defaultConfig.CRDSourceAPIVersion).StringVar(&cfg.CRDSourceAPIVersion) app.Flag("crd-source-kind", "Kind of the CRD for the crd source in API group and version specified by crd-source-apiversion").Default(defaultConfig.CRDSourceKind).StringVar(&cfg.CRDSourceKind) diff --git a/source/service.go b/source/service.go index cf15a7581c..db6c2c72f1 100644 --- a/source/service.go +++ b/source/service.go @@ -51,23 +51,25 @@ type serviceSource struct { client kubernetes.Interface namespace string annotationFilter string + // process Services with legacy annotations - compatibility string - fqdnTemplate *template.Template - combineFQDNAnnotation bool - ignoreHostnameAnnotation bool - publishInternal bool - publishHostIP bool - serviceInformer coreinformers.ServiceInformer - endpointsInformer coreinformers.EndpointsInformer - podInformer coreinformers.PodInformer - nodeInformer coreinformers.NodeInformer - serviceTypeFilter map[string]struct{} - runner *async.BoundedFrequencyRunner + compatibility string + fqdnTemplate *template.Template + combineFQDNAnnotation bool + ignoreHostnameAnnotation bool + publishInternal bool + publishHostIP bool + alwaysPublishNotReadyAddresses bool + serviceInformer coreinformers.ServiceInformer + endpointsInformer coreinformers.EndpointsInformer + podInformer coreinformers.PodInformer + nodeInformer coreinformers.NodeInformer + serviceTypeFilter map[string]struct{} + runner *async.BoundedFrequencyRunner } // NewServiceSource creates a new serviceSource with the given config. -func NewServiceSource(kubeClient kubernetes.Interface, namespace, annotationFilter string, fqdnTemplate string, combineFqdnAnnotation bool, compatibility string, publishInternal bool, publishHostIP bool, serviceTypeFilter []string, ignoreHostnameAnnotation bool) (Source, error) { +func NewServiceSource(kubeClient kubernetes.Interface, namespace, annotationFilter string, fqdnTemplate string, combineFqdnAnnotation bool, compatibility string, publishInternal bool, publishHostIP bool, alwaysPublishNotReadyAddresses bool, serviceTypeFilter []string, ignoreHostnameAnnotation bool) (Source, error) { var ( tmpl *template.Template err error @@ -135,20 +137,21 @@ func NewServiceSource(kubeClient kubernetes.Interface, namespace, annotationFilt } return &serviceSource{ - client: kubeClient, - namespace: namespace, - annotationFilter: annotationFilter, - compatibility: compatibility, - fqdnTemplate: tmpl, - combineFQDNAnnotation: combineFqdnAnnotation, - ignoreHostnameAnnotation: ignoreHostnameAnnotation, - publishInternal: publishInternal, - publishHostIP: publishHostIP, - serviceInformer: serviceInformer, - endpointsInformer: endpointsInformer, - podInformer: podInformer, - nodeInformer: nodeInformer, - serviceTypeFilter: serviceTypes, + client: kubeClient, + namespace: namespace, + annotationFilter: annotationFilter, + compatibility: compatibility, + fqdnTemplate: tmpl, + combineFQDNAnnotation: combineFqdnAnnotation, + ignoreHostnameAnnotation: ignoreHostnameAnnotation, + publishInternal: publishInternal, + publishHostIP: publishHostIP, + alwaysPublishNotReadyAddresses: alwaysPublishNotReadyAddresses, + serviceInformer: serviceInformer, + endpointsInformer: endpointsInformer, + podInformer: podInformer, + nodeInformer: nodeInformer, + serviceTypeFilter: serviceTypes, }, nil } @@ -217,6 +220,7 @@ func (sc *serviceSource) Endpoints() ([]*endpoint.Endpoint, error) { return endpoints, nil } +// extractHeadlessEndpoints extracts endpoints from a headless service using the "Endpoints" Kubernetes API resource func (sc *serviceSource) extractHeadlessEndpoints(svc *v1.Service, hostname string, ttl endpoint.TTL) []*endpoint.Endpoint { var endpoints []*endpoint.Endpoint @@ -244,7 +248,7 @@ func (sc *serviceSource) extractHeadlessEndpoints(svc *v1.Service, hostname stri targetsByHeadlessDomain := make(map[string][]string) for _, subset := range endpointsObject.Subsets { addresses := subset.Addresses - if svc.Spec.PublishNotReadyAddresses { + if svc.Spec.PublishNotReadyAddresses || sc.alwaysPublishNotReadyAddresses { addresses = append(addresses, subset.NotReadyAddresses...) } diff --git a/source/service_test.go b/source/service_test.go index ca7e74955c..3325bf3ae0 100644 --- a/source/service_test.go +++ b/source/service_test.go @@ -51,6 +51,7 @@ func (suite *ServiceSuite) SetupTest() { "", false, false, + false, []string{}, false, ) @@ -143,6 +144,7 @@ func testServiceSourceNewServiceSource(t *testing.T) { "", false, false, + false, ti.serviceTypesFilter, false, ) @@ -1107,6 +1109,7 @@ func testServiceSourceEndpoints(t *testing.T) { tc.compatibility, false, false, + false, tc.serviceTypesFilter, tc.ignoreHostnameAnnotation, ) @@ -1277,6 +1280,7 @@ func TestClusterIpServices(t *testing.T) { tc.compatibility, true, false, + false, []string{}, tc.ignoreHostnameAnnotation, ) @@ -1608,6 +1612,7 @@ func TestNodePortServices(t *testing.T) { tc.compatibility, true, false, + false, []string{}, tc.ignoreHostnameAnnotation, ) @@ -1909,6 +1914,7 @@ func TestHeadlessServices(t *testing.T) { tc.compatibility, true, false, + false, []string{}, tc.ignoreHostnameAnnotation, ) @@ -2210,6 +2216,7 @@ func TestHeadlessServicesHostIP(t *testing.T) { tc.compatibility, true, true, + false, []string{}, tc.ignoreHostnameAnnotation, ) @@ -2314,6 +2321,7 @@ func TestExternalServices(t *testing.T) { tc.compatibility, true, false, + false, []string{}, tc.ignoreHostnameAnnotation, ) @@ -2356,7 +2364,7 @@ func BenchmarkServiceEndpoints(b *testing.B) { _, err := kubernetes.CoreV1().Services(service.Namespace).Create(service) require.NoError(b, err) - client, err := NewServiceSource(kubernetes, v1.NamespaceAll, "", "", false, "", false, false, []string{}, false) + client, err := NewServiceSource(kubernetes, v1.NamespaceAll, "", "", false, "", false, false, false, []string{}, false) require.NoError(b, err) for i := 0; i < b.N; i++ { diff --git a/source/store.go b/source/store.go index 586068068e..02db492246 100644 --- a/source/store.go +++ b/source/store.go @@ -40,25 +40,26 @@ var ErrSourceNotFound = errors.New("source not found") // Config holds shared configuration options for all Sources. type Config struct { - Namespace string - AnnotationFilter string - FQDNTemplate string - CombineFQDNAndAnnotation bool - IgnoreHostnameAnnotation bool - Compatibility string - PublishInternal bool - PublishHostIP bool - ConnectorServer string - CRDSourceAPIVersion string - CRDSourceKind string - KubeConfig string - KubeMaster string - ServiceTypeFilter []string - IstioIngressGatewayServices []string - CFAPIEndpoint string - CFUsername string - CFPassword string - ContourLoadBalancerService string + Namespace string + AnnotationFilter string + FQDNTemplate string + CombineFQDNAndAnnotation bool + IgnoreHostnameAnnotation bool + Compatibility string + PublishInternal bool + PublishHostIP bool + AlwaysPublishNotReadyAddresses bool + ConnectorServer string + CRDSourceAPIVersion string + CRDSourceKind string + KubeConfig string + KubeMaster string + ServiceTypeFilter []string + IstioIngressGatewayServices []string + CFAPIEndpoint string + CFUsername string + CFPassword string + ContourLoadBalancerService string } // ClientGenerator provides clients @@ -164,7 +165,7 @@ func BuildWithConfig(source string, p ClientGenerator, cfg *Config) (Source, err if err != nil { return nil, err } - return NewServiceSource(client, cfg.Namespace, cfg.AnnotationFilter, cfg.FQDNTemplate, cfg.CombineFQDNAndAnnotation, cfg.Compatibility, cfg.PublishInternal, cfg.PublishHostIP, cfg.ServiceTypeFilter, cfg.IgnoreHostnameAnnotation) + return NewServiceSource(client, cfg.Namespace, cfg.AnnotationFilter, cfg.FQDNTemplate, cfg.CombineFQDNAndAnnotation, cfg.Compatibility, cfg.PublishInternal, cfg.PublishHostIP, cfg.AlwaysPublishNotReadyAddresses, cfg.ServiceTypeFilter, cfg.IgnoreHostnameAnnotation) case "ingress": client, err := p.KubeClient() if err != nil { From 9343fb261f5354ce29a8e63b5283b9b44c897fa0 Mon Sep 17 00:00:00 2001 From: Alfred Krohmer Date: Tue, 17 Sep 2019 10:57:50 +0200 Subject: [PATCH 3/5] Fix typo --- pkg/apis/externaldns/types.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/apis/externaldns/types.go b/pkg/apis/externaldns/types.go index a4fbdcd225..3c428c93f0 100644 --- a/pkg/apis/externaldns/types.go +++ b/pkg/apis/externaldns/types.go @@ -294,7 +294,7 @@ func (cfg *Config) ParseFlags(args []string) error { app.Flag("compatibility", "Process annotation semantics from legacy implementations (optional, options: mate, molecule)").Default(defaultConfig.Compatibility).EnumVar(&cfg.Compatibility, "", "mate", "molecule") app.Flag("publish-internal-services", "Allow external-dns to publish DNS records for ClusterIP services (optional)").BoolVar(&cfg.PublishInternal) app.Flag("publish-host-ip", "Allow external-dns to publish host-ip for headless services (optional)").BoolVar(&cfg.PublishHostIP) - app.Flag("always-publish-not-ready-address", "Always publish also not ready addresses for headless services (optional)").BoolVar(&cfg.AlwaysPublishNotReadyAddresses) + app.Flag("always-publish-not-ready-addresses", "Always publish also not ready addresses for headless services (optional)").BoolVar(&cfg.AlwaysPublishNotReadyAddresses) app.Flag("connector-source-server", "The server to connect for connector source, valid only when using connector source").Default(defaultConfig.ConnectorSourceServer).StringVar(&cfg.ConnectorSourceServer) app.Flag("crd-source-apiversion", "API version of the CRD for crd source, e.g. `externaldns.k8s.io/v1alpha1`, valid only when using crd source").Default(defaultConfig.CRDSourceAPIVersion).StringVar(&cfg.CRDSourceAPIVersion) app.Flag("crd-source-kind", "Kind of the CRD for the crd source in API group and version specified by crd-source-apiversion").Default(defaultConfig.CRDSourceKind).StringVar(&cfg.CRDSourceKind) From c91eae9d2f533ce093e0283406fb5cefa45a4db8 Mon Sep 17 00:00:00 2001 From: Alfred Krohmer Date: Sun, 24 Nov 2019 09:16:59 +0100 Subject: [PATCH 4/5] Update documentation to include RBAC permissions for endpoints resources --- docs/tutorials/alibabacloud.md | 2 +- docs/tutorials/aws-sd.md | 2 +- docs/tutorials/aws.md | 2 +- docs/tutorials/azure-private-dns.md | 4 ++-- docs/tutorials/azure.md | 4 ++-- docs/tutorials/cloudflare.md | 2 +- docs/tutorials/contour.md | 2 +- docs/tutorials/coredns.md | 2 +- docs/tutorials/designate.md | 2 +- docs/tutorials/digitalocean.md | 2 +- docs/tutorials/dnsimple.md | 2 +- docs/tutorials/exoscale.md | 2 +- docs/tutorials/gke.md | 2 +- docs/tutorials/hostport.md | 2 +- docs/tutorials/infoblox.md | 2 +- docs/tutorials/istio.md | 2 +- docs/tutorials/linode.md | 2 +- docs/tutorials/nginx-ingress.md | 2 +- docs/tutorials/ns1.md | 2 +- docs/tutorials/oracle.md | 2 +- docs/tutorials/pdns.md | 2 +- docs/tutorials/rcodezero.md | 2 +- docs/tutorials/rdns.md | 2 +- docs/tutorials/transip.md | 2 +- docs/tutorials/vinyldns.md | 2 +- 25 files changed, 27 insertions(+), 27 deletions(-) diff --git a/docs/tutorials/alibabacloud.md b/docs/tutorials/alibabacloud.md index fb15711acd..a470bd797e 100644 --- a/docs/tutorials/alibabacloud.md +++ b/docs/tutorials/alibabacloud.md @@ -147,7 +147,7 @@ metadata: name: external-dns rules: - apiGroups: [""] - resources: ["services"] + resources: ["services","endpoints"] verbs: ["get","watch","list"] - apiGroups: [""] resources: ["pods"] diff --git a/docs/tutorials/aws-sd.md b/docs/tutorials/aws-sd.md index 4343eff62b..c013bae61d 100644 --- a/docs/tutorials/aws-sd.md +++ b/docs/tutorials/aws-sd.md @@ -108,7 +108,7 @@ metadata: name: external-dns rules: - apiGroups: [""] - resources: ["services"] + resources: ["services","endpoints"] verbs: ["get","watch","list"] - apiGroups: [""] resources: ["pods"] diff --git a/docs/tutorials/aws.md b/docs/tutorials/aws.md index 23cd0c77b9..dedac41927 100644 --- a/docs/tutorials/aws.md +++ b/docs/tutorials/aws.md @@ -172,7 +172,7 @@ metadata: name: external-dns rules: - apiGroups: [""] - resources: ["services"] + resources: ["services","endpoints"] verbs: ["get","watch","list"] - apiGroups: [""] resources: ["pods"] diff --git a/docs/tutorials/azure-private-dns.md b/docs/tutorials/azure-private-dns.md index 2aefc0308a..81ff2b2c02 100644 --- a/docs/tutorials/azure-private-dns.md +++ b/docs/tutorials/azure-private-dns.md @@ -194,7 +194,7 @@ metadata: name: externaldns rules: - apiGroups: [""] - resources: ["services"] + resources: ["services","endpoints"] verbs: ["get","watch","list"] - apiGroups: [""] resources: ["pods"] @@ -268,7 +268,7 @@ metadata: name: externaldns rules: - apiGroups: [""] - resources: ["services"] + resources: ["services","endpoints"] verbs: ["get","watch","list"] - apiGroups: [""] resources: ["pods"] diff --git a/docs/tutorials/azure.md b/docs/tutorials/azure.md index 29fc9fccc3..02a5e43983 100644 --- a/docs/tutorials/azure.md +++ b/docs/tutorials/azure.md @@ -221,7 +221,7 @@ metadata: name: external-dns rules: - apiGroups: [""] - resources: ["services"] + resources: ["services","endpoints"] verbs: ["get","watch","list"] - apiGroups: [""] resources: ["pods"] @@ -298,7 +298,7 @@ metadata: name: external-dns rules: - apiGroups: [""] - resources: ["services"] + resources: ["services","endpoints"] verbs: ["get","watch","list"] - apiGroups: [""] resources: ["pods"] diff --git a/docs/tutorials/cloudflare.md b/docs/tutorials/cloudflare.md index 442e0513b5..def528fc8d 100644 --- a/docs/tutorials/cloudflare.md +++ b/docs/tutorials/cloudflare.md @@ -75,7 +75,7 @@ metadata: name: external-dns rules: - apiGroups: [""] - resources: ["services"] + resources: ["services","endpoints"] verbs: ["get","watch","list"] - apiGroups: [""] resources: ["pods"] diff --git a/docs/tutorials/contour.md b/docs/tutorials/contour.md index cd3923d597..202f3bbedb 100644 --- a/docs/tutorials/contour.md +++ b/docs/tutorials/contour.md @@ -48,7 +48,7 @@ metadata: name: external-dns rules: - apiGroups: [""] - resources: ["services"] + resources: ["services","endpoints"] verbs: ["get","watch","list"] - apiGroups: [""] resources: ["pods"] diff --git a/docs/tutorials/coredns.md b/docs/tutorials/coredns.md index 01cbd2476d..a7dd1e14cd 100644 --- a/docs/tutorials/coredns.md +++ b/docs/tutorials/coredns.md @@ -128,7 +128,7 @@ metadata: name: external-dns rules: - apiGroups: [""] - resources: ["services"] + resources: ["services","endpoints"] verbs: ["get","watch","list"] - apiGroups: [""] resources: ["pods"] diff --git a/docs/tutorials/designate.md b/docs/tutorials/designate.md index 24959447ba..40f5418f15 100644 --- a/docs/tutorials/designate.md +++ b/docs/tutorials/designate.md @@ -93,7 +93,7 @@ metadata: name: external-dns rules: - apiGroups: [""] - resources: ["services"] + resources: ["services","endpoints"] verbs: ["get","watch","list"] - apiGroups: [""] resources: ["pods"] diff --git a/docs/tutorials/digitalocean.md b/docs/tutorials/digitalocean.md index a7f34b7af7..d68a0bfa52 100644 --- a/docs/tutorials/digitalocean.md +++ b/docs/tutorials/digitalocean.md @@ -69,7 +69,7 @@ metadata: name: external-dns rules: - apiGroups: [""] - resources: ["services"] + resources: ["services","endpoints"] verbs: ["get","watch","list"] - apiGroups: [""] resources: ["pods"] diff --git a/docs/tutorials/dnsimple.md b/docs/tutorials/dnsimple.md index 2aca16a90f..98350c6343 100644 --- a/docs/tutorials/dnsimple.md +++ b/docs/tutorials/dnsimple.md @@ -60,7 +60,7 @@ metadata: name: external-dns rules: - apiGroups: [""] - resources: ["services"] + resources: ["services","endpoints"] verbs: ["get","watch","list"] - apiGroups: [""] resources: ["pods"] diff --git a/docs/tutorials/exoscale.md b/docs/tutorials/exoscale.md index 08c5905b3b..8674b1ac84 100644 --- a/docs/tutorials/exoscale.md +++ b/docs/tutorials/exoscale.md @@ -72,7 +72,7 @@ metadata: name: external-dns rules: - apiGroups: [""] - resources: ["services"] + resources: ["services","endpoints"] verbs: ["get","watch","list"] - apiGroups: [""] resources: ["pods"] diff --git a/docs/tutorials/gke.md b/docs/tutorials/gke.md index cf360944aa..de9a21602a 100644 --- a/docs/tutorials/gke.md +++ b/docs/tutorials/gke.md @@ -116,7 +116,7 @@ metadata: name: external-dns rules: - apiGroups: [""] - resources: ["services"] + resources: ["services","endpoints"] verbs: ["get","watch","list"] - apiGroups: [""] resources: ["pods"] diff --git a/docs/tutorials/hostport.md b/docs/tutorials/hostport.md index 2aae14f808..0441aec397 100644 --- a/docs/tutorials/hostport.md +++ b/docs/tutorials/hostport.md @@ -56,7 +56,7 @@ metadata: name: external-dns rules: - apiGroups: [""] - resources: ["services"] + resources: ["services","endpoints"] verbs: ["get","watch","list"] - apiGroups: [""] resources: ["pods"] diff --git a/docs/tutorials/infoblox.md b/docs/tutorials/infoblox.md index a9f51213be..9e13bc1e00 100644 --- a/docs/tutorials/infoblox.md +++ b/docs/tutorials/infoblox.md @@ -109,7 +109,7 @@ metadata: name: external-dns rules: - apiGroups: [""] - resources: ["services"] + resources: ["services","endpoints"] verbs: ["get","watch","list"] - apiGroups: [""] resources: ["pods"] diff --git a/docs/tutorials/istio.md b/docs/tutorials/istio.md index 5dfb32ffaa..74556c8086 100644 --- a/docs/tutorials/istio.md +++ b/docs/tutorials/istio.md @@ -54,7 +54,7 @@ metadata: name: external-dns rules: - apiGroups: [""] - resources: ["services"] + resources: ["services","endpoints"] verbs: ["get","watch","list"] - apiGroups: [""] resources: ["pods"] diff --git a/docs/tutorials/linode.md b/docs/tutorials/linode.md index a555b7ca64..cc594d200f 100644 --- a/docs/tutorials/linode.md +++ b/docs/tutorials/linode.md @@ -65,7 +65,7 @@ metadata: name: external-dns rules: - apiGroups: [""] - resources: ["services"] + resources: ["services","endpoints"] verbs: ["get","watch","list"] - apiGroups: [""] resources: ["pods"] diff --git a/docs/tutorials/nginx-ingress.md b/docs/tutorials/nginx-ingress.md index bd32af4c11..6a642bb2ec 100644 --- a/docs/tutorials/nginx-ingress.md +++ b/docs/tutorials/nginx-ingress.md @@ -222,7 +222,7 @@ metadata: name: external-dns rules: - apiGroups: [""] - resources: ["services"] + resources: ["services","endpoints"] verbs: ["get","watch","list"] - apiGroups: [""] resources: ["pods"] diff --git a/docs/tutorials/ns1.md b/docs/tutorials/ns1.md index 1511353b5c..7a0ce4713b 100644 --- a/docs/tutorials/ns1.md +++ b/docs/tutorials/ns1.md @@ -85,7 +85,7 @@ metadata: name: external-dns rules: - apiGroups: [""] - resources: ["services"] + resources: ["services","endpoints"] verbs: ["get","watch","list"] - apiGroups: [""] resources: ["pods"] diff --git a/docs/tutorials/oracle.md b/docs/tutorials/oracle.md index 70092d1874..246a8418ee 100644 --- a/docs/tutorials/oracle.md +++ b/docs/tutorials/oracle.md @@ -51,7 +51,7 @@ metadata: name: external-dns rules: - apiGroups: [""] - resources: ["services"] + resources: ["services","endpoints"] verbs: ["get","watch","list"] - apiGroups: [""] resources: ["pods"] diff --git a/docs/tutorials/pdns.md b/docs/tutorials/pdns.md index 7852fc6f73..de1e2c371c 100644 --- a/docs/tutorials/pdns.md +++ b/docs/tutorials/pdns.md @@ -76,7 +76,7 @@ metadata: name: external-dns rules: - apiGroups: [""] - resources: ["services"] + resources: ["services","endpoints"] verbs: ["get","watch","list"] - apiGroups: ["extensions"] resources: ["ingresses"] diff --git a/docs/tutorials/rcodezero.md b/docs/tutorials/rcodezero.md index deba0bc35e..ad79c211c2 100644 --- a/docs/tutorials/rcodezero.md +++ b/docs/tutorials/rcodezero.md @@ -80,7 +80,7 @@ metadata: name: external-dns rules: - apiGroups: [""] - resources: ["services"] + resources: ["services","endpoints"] verbs: ["get","watch","list"] - apiGroups: [""] resources: ["pods"] diff --git a/docs/tutorials/rdns.md b/docs/tutorials/rdns.md index a7e6a225a3..fda112a8e0 100644 --- a/docs/tutorials/rdns.md +++ b/docs/tutorials/rdns.md @@ -76,7 +76,7 @@ metadata: name: external-dns rules: - apiGroups: [""] - resources: ["services"] + resources: ["services","endpoints"] verbs: ["get","watch","list"] - apiGroups: [""] resources: ["pods"] diff --git a/docs/tutorials/transip.md b/docs/tutorials/transip.md index d93c903a2f..ddcbbd537a 100644 --- a/docs/tutorials/transip.md +++ b/docs/tutorials/transip.md @@ -67,7 +67,7 @@ metadata: name: external-dns rules: - apiGroups: [""] - resources: ["services"] + resources: ["services","endpoints"] verbs: ["get","watch","list"] - apiGroups: [""] resources: ["pods"] diff --git a/docs/tutorials/vinyldns.md b/docs/tutorials/vinyldns.md index 2b19a6ca48..2fbe025afa 100644 --- a/docs/tutorials/vinyldns.md +++ b/docs/tutorials/vinyldns.md @@ -97,7 +97,7 @@ metadata: name: external-dns rules: - apiGroups: [""] - resources: ["services"] + resources: ["services","endpoints"] verbs: ["get","watch","list"] - apiGroups: [""] resources: ["pods"] From 65208db6ec630b905c4c466388cf875e924ef481 Mon Sep 17 00:00:00 2001 From: Alfred Krohmer Date: Tue, 18 Feb 2020 19:58:56 +0100 Subject: [PATCH 5/5] Address review comments --- docs/tutorials/akamai-fastdns.md | 7 ++----- docs/tutorials/alibabacloud.md | 5 +---- docs/tutorials/aws-sd.md | 5 +---- docs/tutorials/aws.md | 5 +---- docs/tutorials/azure-private-dns.md | 12 +++--------- docs/tutorials/azure.md | 10 ++-------- docs/tutorials/cloudflare.md | 5 +---- docs/tutorials/contour.md | 5 +---- docs/tutorials/coredns.md | 5 +---- docs/tutorials/designate.md | 2 +- docs/tutorials/digitalocean.md | 5 +---- docs/tutorials/dnsimple.md | 5 +---- docs/tutorials/exoscale.md | 5 +---- docs/tutorials/gke.md | 5 +---- docs/tutorials/hostport.md | 5 +---- docs/tutorials/infoblox.md | 5 +---- docs/tutorials/istio.md | 5 +---- docs/tutorials/linode.md | 5 +---- docs/tutorials/nginx-ingress.md | 5 +---- docs/tutorials/ns1.md | 5 +---- docs/tutorials/oracle.md | 5 +---- docs/tutorials/pdns.md | 2 +- docs/tutorials/rcodezero.md | 5 +---- docs/tutorials/rdns.md | 5 +---- docs/tutorials/rfc2136.md | 2 ++ docs/tutorials/transip.md | 5 +---- docs/tutorials/vinyldns.md | 5 +---- source/service.go | 1 - source/service_test.go | 3 +-- 29 files changed, 33 insertions(+), 111 deletions(-) diff --git a/docs/tutorials/akamai-fastdns.md b/docs/tutorials/akamai-fastdns.md index 30d67287e0..6dfae56c2d 100644 --- a/docs/tutorials/akamai-fastdns.md +++ b/docs/tutorials/akamai-fastdns.md @@ -95,10 +95,7 @@ metadata: name: external-dns rules: - apiGroups: [""] - resources: ["services"] - verbs: ["get","watch","list"] -- apiGroups: [""] - resources: ["pods"] + resources: ["services","endpoints","pods"] verbs: ["get","watch","list"] - apiGroups: ["extensions"] resources: ["ingresses"] @@ -192,4 +189,4 @@ spec: **Important!**: Don't run dig, nslookup or similar immediately. You'll get hit by [negative DNS caching](https://tools.ietf.org/html/rfc2308), which is hard to flush. -Wait about 30s-1m (interval for external-dns to kick in) \ No newline at end of file +Wait about 30s-1m (interval for external-dns to kick in) diff --git a/docs/tutorials/alibabacloud.md b/docs/tutorials/alibabacloud.md index a470bd797e..73d6010840 100644 --- a/docs/tutorials/alibabacloud.md +++ b/docs/tutorials/alibabacloud.md @@ -147,10 +147,7 @@ metadata: name: external-dns rules: - apiGroups: [""] - resources: ["services","endpoints"] - verbs: ["get","watch","list"] -- apiGroups: [""] - resources: ["pods"] + resources: ["services","endpoints","pods"] verbs: ["get","watch","list"] - apiGroups: ["extensions"] resources: ["ingresses"] diff --git a/docs/tutorials/aws-sd.md b/docs/tutorials/aws-sd.md index c013bae61d..b0fa610bfa 100644 --- a/docs/tutorials/aws-sd.md +++ b/docs/tutorials/aws-sd.md @@ -108,10 +108,7 @@ metadata: name: external-dns rules: - apiGroups: [""] - resources: ["services","endpoints"] - verbs: ["get","watch","list"] -- apiGroups: [""] - resources: ["pods"] + resources: ["services","endpoints","pods"] verbs: ["get","watch","list"] - apiGroups: ["extensions"] resources: ["ingresses"] diff --git a/docs/tutorials/aws.md b/docs/tutorials/aws.md index dedac41927..d3b814fb21 100644 --- a/docs/tutorials/aws.md +++ b/docs/tutorials/aws.md @@ -172,10 +172,7 @@ metadata: name: external-dns rules: - apiGroups: [""] - resources: ["services","endpoints"] - verbs: ["get","watch","list"] -- apiGroups: [""] - resources: ["pods"] + resources: ["services","endpoints","pods"] verbs: ["get","watch","list"] - apiGroups: ["extensions"] resources: ["ingresses"] diff --git a/docs/tutorials/azure-private-dns.md b/docs/tutorials/azure-private-dns.md index 81ff2b2c02..a362457e18 100644 --- a/docs/tutorials/azure-private-dns.md +++ b/docs/tutorials/azure-private-dns.md @@ -194,10 +194,7 @@ metadata: name: externaldns rules: - apiGroups: [""] - resources: ["services","endpoints"] - verbs: ["get","watch","list"] -- apiGroups: [""] - resources: ["pods"] + resources: ["services","endpoints","pods"] verbs: ["get","watch","list"] - apiGroups: ["extensions"] resources: ["ingresses"] @@ -268,10 +265,7 @@ metadata: name: externaldns rules: - apiGroups: [""] - resources: ["services","endpoints"] - verbs: ["get","watch","list"] -- apiGroups: [""] - resources: ["pods"] + resources: ["services","endpoints","pods"] verbs: ["get","watch","list"] - apiGroups: ["extensions"] resources: ["ingresses"] @@ -399,4 +393,4 @@ $ az network private-dns record-set a list -g externaldns -z example.com Substitute the zone for the one created above if a different domain was used. -This should show the external IP address of the service as the A record for your domain ('@' indicates the record is for the zone itself). \ No newline at end of file +This should show the external IP address of the service as the A record for your domain ('@' indicates the record is for the zone itself). diff --git a/docs/tutorials/azure.md b/docs/tutorials/azure.md index 02a5e43983..0a62de70a7 100644 --- a/docs/tutorials/azure.md +++ b/docs/tutorials/azure.md @@ -221,10 +221,7 @@ metadata: name: external-dns rules: - apiGroups: [""] - resources: ["services","endpoints"] - verbs: ["get","watch","list"] -- apiGroups: [""] - resources: ["pods"] + resources: ["services","endpoints","pods"] verbs: ["get","watch","list"] - apiGroups: ["extensions"] resources: ["ingresses"] @@ -298,10 +295,7 @@ metadata: name: external-dns rules: - apiGroups: [""] - resources: ["services","endpoints"] - verbs: ["get","watch","list"] -- apiGroups: [""] - resources: ["pods"] + resources: ["services","endpoints","pods"] verbs: ["get","watch","list"] - apiGroups: ["extensions"] resources: ["ingresses"] diff --git a/docs/tutorials/cloudflare.md b/docs/tutorials/cloudflare.md index def528fc8d..3f2faf644a 100644 --- a/docs/tutorials/cloudflare.md +++ b/docs/tutorials/cloudflare.md @@ -75,10 +75,7 @@ metadata: name: external-dns rules: - apiGroups: [""] - resources: ["services","endpoints"] - verbs: ["get","watch","list"] -- apiGroups: [""] - resources: ["pods"] + resources: ["services","endpoints","pods"] verbs: ["get","watch","list"] - apiGroups: ["extensions"] resources: ["ingresses"] diff --git a/docs/tutorials/contour.md b/docs/tutorials/contour.md index 202f3bbedb..aa9448f3ad 100644 --- a/docs/tutorials/contour.md +++ b/docs/tutorials/contour.md @@ -48,10 +48,7 @@ metadata: name: external-dns rules: - apiGroups: [""] - resources: ["services","endpoints"] - verbs: ["get","watch","list"] -- apiGroups: [""] - resources: ["pods"] + resources: ["services","endpoints","pods"] verbs: ["get","watch","list"] - apiGroups: ["extensions"] resources: ["ingresses"] diff --git a/docs/tutorials/coredns.md b/docs/tutorials/coredns.md index a7dd1e14cd..1d3f640901 100644 --- a/docs/tutorials/coredns.md +++ b/docs/tutorials/coredns.md @@ -128,10 +128,7 @@ metadata: name: external-dns rules: - apiGroups: [""] - resources: ["services","endpoints"] - verbs: ["get","watch","list"] -- apiGroups: [""] - resources: ["pods"] + resources: ["services","endpoints","pods"] verbs: ["get","watch","list"] - apiGroups: ["extensions"] resources: ["ingresses"] diff --git a/docs/tutorials/designate.md b/docs/tutorials/designate.md index 40f5418f15..875eb14d9f 100644 --- a/docs/tutorials/designate.md +++ b/docs/tutorials/designate.md @@ -93,7 +93,7 @@ metadata: name: external-dns rules: - apiGroups: [""] - resources: ["services","endpoints"] + resources: ["services","endpoints","pods"] verbs: ["get","watch","list"] - apiGroups: [""] resources: ["pods"] diff --git a/docs/tutorials/digitalocean.md b/docs/tutorials/digitalocean.md index d68a0bfa52..c23fe98787 100644 --- a/docs/tutorials/digitalocean.md +++ b/docs/tutorials/digitalocean.md @@ -69,10 +69,7 @@ metadata: name: external-dns rules: - apiGroups: [""] - resources: ["services","endpoints"] - verbs: ["get","watch","list"] -- apiGroups: [""] - resources: ["pods"] + resources: ["services","endpoints","pods"] verbs: ["get","watch","list"] - apiGroups: ["extensions"] resources: ["ingresses"] diff --git a/docs/tutorials/dnsimple.md b/docs/tutorials/dnsimple.md index 98350c6343..586efe940e 100644 --- a/docs/tutorials/dnsimple.md +++ b/docs/tutorials/dnsimple.md @@ -60,10 +60,7 @@ metadata: name: external-dns rules: - apiGroups: [""] - resources: ["services","endpoints"] - verbs: ["get","watch","list"] -- apiGroups: [""] - resources: ["pods"] + resources: ["services","endpoints","pods"] verbs: ["get","watch","list"] - apiGroups: ["extensions"] resources: ["ingresses"] diff --git a/docs/tutorials/exoscale.md b/docs/tutorials/exoscale.md index 8674b1ac84..64f6efbe29 100644 --- a/docs/tutorials/exoscale.md +++ b/docs/tutorials/exoscale.md @@ -72,10 +72,7 @@ metadata: name: external-dns rules: - apiGroups: [""] - resources: ["services","endpoints"] - verbs: ["get","watch","list"] -- apiGroups: [""] - resources: ["pods"] + resources: ["services","endpoints","pods"] verbs: ["get","watch","list"] - apiGroups: ["extensions"] resources: ["ingresses"] diff --git a/docs/tutorials/gke.md b/docs/tutorials/gke.md index de9a21602a..d402ba7d56 100644 --- a/docs/tutorials/gke.md +++ b/docs/tutorials/gke.md @@ -116,10 +116,7 @@ metadata: name: external-dns rules: - apiGroups: [""] - resources: ["services","endpoints"] - verbs: ["get","watch","list"] -- apiGroups: [""] - resources: ["pods"] + resources: ["services","endpoints","pods"] verbs: ["get","watch","list"] - apiGroups: ["extensions"] resources: ["ingresses"] diff --git a/docs/tutorials/hostport.md b/docs/tutorials/hostport.md index 0441aec397..7568b36b4c 100644 --- a/docs/tutorials/hostport.md +++ b/docs/tutorials/hostport.md @@ -56,10 +56,7 @@ metadata: name: external-dns rules: - apiGroups: [""] - resources: ["services","endpoints"] - verbs: ["get","watch","list"] -- apiGroups: [""] - resources: ["pods"] + resources: ["services","endpoints","pods"] verbs: ["get","watch","list"] - apiGroups: ["extensions"] resources: ["ingresses"] diff --git a/docs/tutorials/infoblox.md b/docs/tutorials/infoblox.md index 9e13bc1e00..edf7b95199 100644 --- a/docs/tutorials/infoblox.md +++ b/docs/tutorials/infoblox.md @@ -109,10 +109,7 @@ metadata: name: external-dns rules: - apiGroups: [""] - resources: ["services","endpoints"] - verbs: ["get","watch","list"] -- apiGroups: [""] - resources: ["pods"] + resources: ["services","endpoints","pods"] verbs: ["get","watch","list"] - apiGroups: ["extensions"] resources: ["ingresses"] diff --git a/docs/tutorials/istio.md b/docs/tutorials/istio.md index 74556c8086..d397709afc 100644 --- a/docs/tutorials/istio.md +++ b/docs/tutorials/istio.md @@ -54,10 +54,7 @@ metadata: name: external-dns rules: - apiGroups: [""] - resources: ["services","endpoints"] - verbs: ["get","watch","list"] -- apiGroups: [""] - resources: ["pods"] + resources: ["services","endpoints","pods"] verbs: ["get","watch","list"] - apiGroups: ["extensions"] resources: ["ingresses"] diff --git a/docs/tutorials/linode.md b/docs/tutorials/linode.md index cc594d200f..859b87aa5b 100644 --- a/docs/tutorials/linode.md +++ b/docs/tutorials/linode.md @@ -65,10 +65,7 @@ metadata: name: external-dns rules: - apiGroups: [""] - resources: ["services","endpoints"] - verbs: ["get","watch","list"] -- apiGroups: [""] - resources: ["pods"] + resources: ["services","endpoints","pods"] verbs: ["get","watch","list"] - apiGroups: ["extensions"] resources: ["ingresses"] diff --git a/docs/tutorials/nginx-ingress.md b/docs/tutorials/nginx-ingress.md index 6a642bb2ec..fd19ff3246 100644 --- a/docs/tutorials/nginx-ingress.md +++ b/docs/tutorials/nginx-ingress.md @@ -222,10 +222,7 @@ metadata: name: external-dns rules: - apiGroups: [""] - resources: ["services","endpoints"] - verbs: ["get","watch","list"] -- apiGroups: [""] - resources: ["pods"] + resources: ["services","endpoints","pods"] verbs: ["get","watch","list"] - apiGroups: ["extensions"] resources: ["ingresses"] diff --git a/docs/tutorials/ns1.md b/docs/tutorials/ns1.md index 7a0ce4713b..014deacef3 100644 --- a/docs/tutorials/ns1.md +++ b/docs/tutorials/ns1.md @@ -85,10 +85,7 @@ metadata: name: external-dns rules: - apiGroups: [""] - resources: ["services","endpoints"] - verbs: ["get","watch","list"] -- apiGroups: [""] - resources: ["pods"] + resources: ["services","endpoints","pods"] verbs: ["get","watch","list"] - apiGroups: ["extensions"] resources: ["ingresses"] diff --git a/docs/tutorials/oracle.md b/docs/tutorials/oracle.md index 246a8418ee..98918816cf 100644 --- a/docs/tutorials/oracle.md +++ b/docs/tutorials/oracle.md @@ -51,10 +51,7 @@ metadata: name: external-dns rules: - apiGroups: [""] - resources: ["services","endpoints"] - verbs: ["get","watch","list"] -- apiGroups: [""] - resources: ["pods"] + resources: ["services","endpoints","pods"] verbs: ["get","watch","list"] - apiGroups: ["extensions"] resources: ["ingresses"] diff --git a/docs/tutorials/pdns.md b/docs/tutorials/pdns.md index de1e2c371c..5a555faa43 100644 --- a/docs/tutorials/pdns.md +++ b/docs/tutorials/pdns.md @@ -76,7 +76,7 @@ metadata: name: external-dns rules: - apiGroups: [""] - resources: ["services","endpoints"] + resources: ["services","endpoints","pods"] verbs: ["get","watch","list"] - apiGroups: ["extensions"] resources: ["ingresses"] diff --git a/docs/tutorials/rcodezero.md b/docs/tutorials/rcodezero.md index ad79c211c2..4338523bad 100644 --- a/docs/tutorials/rcodezero.md +++ b/docs/tutorials/rcodezero.md @@ -80,10 +80,7 @@ metadata: name: external-dns rules: - apiGroups: [""] - resources: ["services","endpoints"] - verbs: ["get","watch","list"] -- apiGroups: [""] - resources: ["pods"] + resources: ["services","endpoints","pods"] verbs: ["get","watch","list"] - apiGroups: ["extensions"] resources: ["ingresses"] diff --git a/docs/tutorials/rdns.md b/docs/tutorials/rdns.md index fda112a8e0..aa7635421a 100644 --- a/docs/tutorials/rdns.md +++ b/docs/tutorials/rdns.md @@ -76,10 +76,7 @@ metadata: name: external-dns rules: - apiGroups: [""] - resources: ["services","endpoints"] - verbs: ["get","watch","list"] -- apiGroups: [""] - resources: ["pods"] + resources: ["services","endpoints","pods"] verbs: ["get","watch","list"] - apiGroups: ["extensions"] resources: ["ingresses"] diff --git a/docs/tutorials/rfc2136.md b/docs/tutorials/rfc2136.md index d848a77a18..4c77f34fed 100644 --- a/docs/tutorials/rfc2136.md +++ b/docs/tutorials/rfc2136.md @@ -144,6 +144,8 @@ rules: - "" resources: - services + - endpoints + - pods verbs: - get - watch diff --git a/docs/tutorials/transip.md b/docs/tutorials/transip.md index ddcbbd537a..a416b1bc3f 100644 --- a/docs/tutorials/transip.md +++ b/docs/tutorials/transip.md @@ -67,10 +67,7 @@ metadata: name: external-dns rules: - apiGroups: [""] - resources: ["services","endpoints"] - verbs: ["get","watch","list"] -- apiGroups: [""] - resources: ["pods"] + resources: ["services","endpoints","pods"] verbs: ["get","watch","list"] - apiGroups: ["extensions"] resources: ["ingresses"] diff --git a/docs/tutorials/vinyldns.md b/docs/tutorials/vinyldns.md index 2fbe025afa..6c5b6fc5ab 100644 --- a/docs/tutorials/vinyldns.md +++ b/docs/tutorials/vinyldns.md @@ -97,10 +97,7 @@ metadata: name: external-dns rules: - apiGroups: [""] - resources: ["services","endpoints"] - verbs: ["get","watch","list"] -- apiGroups: [""] - resources: ["pods"] + resources: ["services","endpoints","pods"] verbs: ["get","watch","list"] - apiGroups: ["extensions"] resources: ["ingresses"] diff --git a/source/service.go b/source/service.go index db6c2c72f1..e32961aefd 100644 --- a/source/service.go +++ b/source/service.go @@ -101,7 +101,6 @@ func NewServiceSource(kubeClient kubernetes.Interface, namespace, annotationFilt endpointsInformer.Informer().AddEventHandler( cache.ResourceEventHandlerFuncs{ AddFunc: func(obj interface{}) { - log.Debug("endpoints added") }, }, ) diff --git a/source/service_test.go b/source/service_test.go index 3325bf3ae0..ee96335b28 100644 --- a/source/service_test.go +++ b/source/service_test.go @@ -1852,8 +1852,7 @@ func TestHeadlessServices(t *testing.T) { _, err := kubernetes.CoreV1().Services(service.Namespace).Create(service) require.NoError(t, err) - var addresses []v1.EndpointAddress - var notReadyAddresses []v1.EndpointAddress + var addresses, notReadyAddresses []v1.EndpointAddress for i, podname := range tc.podnames { pod := &v1.Pod{ Spec: v1.PodSpec{