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 | 75 ++++++++++++------ source/service_test.go | 174 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 207 insertions(+), 42 deletions(-) diff --git a/source/service.go b/source/service.go index 11323eae3..cf15a7581 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) - } - } 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) - } 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 } } - } + 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 { + 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 7acdbbc60..ca7e74955 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 db45b41b8..6e6238050 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 c4136a429..a4fbdcd22 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 cf15a7581..db6c2c72f 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 ca7e74955..3325bf3ae 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 586068068..02db49224 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 a4fbdcd22..3c428c93f 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 fb15711ac..a470bd797 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 4343eff62..c013bae61 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 23cd0c77b..dedac4192 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 2aefc0308..81ff2b2c0 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 29fc9fccc..02a5e4398 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 442e0513b..def528fc8 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 cd3923d59..202f3bbed 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 01cbd2476..a7dd1e14c 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 24959447b..40f5418f1 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 a7f34b7af..d68a0bfa5 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 2aca16a90..98350c634 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 08c5905b3..8674b1ac8 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 cf360944a..de9a21602 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 2aae14f80..0441aec39 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 a9f51213b..9e13bc1e0 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 5dfb32ffa..74556c808 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 a555b7ca6..cc594d200 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 bd32af4c1..6a642bb2e 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 1511353b5..7a0ce4713 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 70092d187..246a8418e 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 7852fc6f7..de1e2c371 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 deba0bc35..ad79c211c 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 a7e6a225a..fda112a8e 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 d93c903a2..ddcbbd537 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 2b19a6ca4..2fbe025af 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 30d67287e..6dfae56c2 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 a470bd797..73d601084 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 c013bae61..b0fa610bf 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 dedac4192..d3b814fb2 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 81ff2b2c0..a362457e1 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 02a5e4398..0a62de70a 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 def528fc8..3f2faf644 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 202f3bbed..aa9448f3a 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 a7dd1e14c..1d3f64090 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 40f5418f1..875eb14d9 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 d68a0bfa5..c23fe9878 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 98350c634..586efe940 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 8674b1ac8..64f6efbe2 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 de9a21602..d402ba7d5 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 0441aec39..7568b36b4 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 9e13bc1e0..edf7b9519 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 74556c808..d397709af 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 cc594d200..859b87aa5 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 6a642bb2e..fd19ff324 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 7a0ce4713..014deacef 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 246a8418e..98918816c 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 de1e2c371..5a555faa4 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 ad79c211c..4338523ba 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 fda112a8e..aa7635421 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 d848a77a1..4c77f34fe 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 ddcbbd537..a416b1bc3 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 2fbe025af..6c5b6fc5a 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 db6c2c72f..e32961aef 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 3325bf3ae..ee96335b2 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{