diff --git a/middleware/kubernetes/kubernetes.go b/middleware/kubernetes/kubernetes.go index c22afb5ba..dea4a812d 100644 --- a/middleware/kubernetes/kubernetes.go +++ b/middleware/kubernetes/kubernetes.go @@ -366,6 +366,7 @@ func (k *Kubernetes) Records(r recordRequest) ([]msg.Service, error) { } records := k.getRecordsForK8sItems(services, pods, r) + return records, nil } @@ -386,8 +387,8 @@ func (k *Kubernetes) getRecordsForK8sItems(services []service, pods []pod, r rec zonePath := msg.Path(r.zone, "coredns") for _, svc := range services { - if svc.addr == api.ClusterIPNone { - // This is a headless service, create records for each endpoint + if svc.addr == api.ClusterIPNone || len(svc.endpoints) > 0 { + // This is a headless service or endpoints are present, create records for each endpoint for _, ep := range svc.endpoints { s := msg.Service{ Host: ep.addr.IP, @@ -522,47 +523,52 @@ func (k *Kubernetes) findServices(r recordRequest) ([]service, error) { continue } s := service{name: svc.Name, namespace: svc.Namespace} - // External Service + + // Endpoint query or headless service + if svc.Spec.ClusterIP == api.ClusterIPNone || r.endpoint != "" { + s.addr = svc.Spec.ClusterIP + endpointsList := k.APIConn.EndpointsList() + for _, ep := range endpointsList.Items { + if ep.ObjectMeta.Name != svc.Name || ep.ObjectMeta.Namespace != svc.Namespace { + continue + } + for _, eps := range ep.Subsets { + for _, addr := range eps.Addresses { + for _, p := range eps.Ports { + ephostname := endpointHostname(addr) + if r.endpoint != "" && r.endpoint != ephostname { + continue + } + if !(symbolMatches(r.port, strings.ToLower(p.Name), portWildcard) && symbolMatches(r.protocol, strings.ToLower(string(p.Protocol)), protocolWildcard)) { + continue + } + s.endpoints = append(s.endpoints, endpoint{addr: addr, port: p}) + } + } + } + } + if len(s.endpoints) > 0 { + resultItems = append(resultItems, s) + } + continue + } + + // External service if svc.Spec.ExternalName != "" { s.addr = svc.Spec.ExternalName resultItems = append(resultItems, s) continue } - // ClusterIP service - if svc.Spec.ClusterIP != api.ClusterIPNone { - s.addr = svc.Spec.ClusterIP - for _, p := range svc.Spec.Ports { - if !(symbolMatches(r.port, strings.ToLower(p.Name), portWildcard) && symbolMatches(r.protocol, strings.ToLower(string(p.Protocol)), protocolWildcard)) { - continue - } - s.ports = append(s.ports, p) - } - resultItems = append(resultItems, s) - continue - } - // Headless service - s.addr = svc.Spec.ClusterIP - endpointsList := k.APIConn.EndpointsList() - for _, ep := range endpointsList.Items { - if ep.ObjectMeta.Name != svc.Name || ep.ObjectMeta.Namespace != svc.Namespace { + // ClusterIP service + s.addr = svc.Spec.ClusterIP + for _, p := range svc.Spec.Ports { + if !(symbolMatches(r.port, strings.ToLower(p.Name), portWildcard) && symbolMatches(r.protocol, strings.ToLower(string(p.Protocol)), protocolWildcard)) { continue } - for _, eps := range ep.Subsets { - for _, addr := range eps.Addresses { - for _, p := range eps.Ports { - ephostname := endpointHostname(addr) - if r.endpoint != "" && r.endpoint != ephostname { - continue - } - if !(symbolMatches(r.port, strings.ToLower(p.Name), portWildcard) && symbolMatches(r.protocol, strings.ToLower(string(p.Protocol)), protocolWildcard)) { - continue - } - s.endpoints = append(s.endpoints, endpoint{addr: addr, port: p}) - } - } - } + s.ports = append(s.ports, p) } + resultItems = append(resultItems, s) } return resultItems, nil diff --git a/middleware/kubernetes/kubernetes_test.go b/middleware/kubernetes/kubernetes_test.go index d0b3dd219..2bfff0c78 100644 --- a/middleware/kubernetes/kubernetes_test.go +++ b/middleware/kubernetes/kubernetes_test.go @@ -348,7 +348,8 @@ func (APIConnServiceTest) EndpointsList() api.EndpointsList { { Addresses: []api.EndpointAddress{ { - IP: "172.0.0.1", + IP: "172.0.0.1", + Hostname: "ep1a", }, }, Ports: []api.EndpointPort{ @@ -455,6 +456,7 @@ func TestServices(t *testing.T) { // Cluster IP Services {qname: "svc1.testns.svc.interwebs.test.", qtype: dns.TypeA, answer: svcAns{host: "10.0.0.1", key: "/coredns/test/interwebs/svc/testns/svc1"}}, {qname: "_http._tcp.svc1.testns.svc.interwebs.test.", qtype: dns.TypeSRV, answer: svcAns{host: "10.0.0.1", key: "/coredns/test/interwebs/svc/testns/svc1"}}, + {qname: "ep1a.svc1.testns.svc.interwebs.test.", qtype: dns.TypeA, answer: svcAns{host: "172.0.0.1", key: "/coredns/test/interwebs/svc/testns/svc1/ep1a"}}, // External Services {qname: "external.testns.svc.interwebs.test.", qtype: dns.TypeCNAME, answer: svcAns{host: "coredns.io", key: "/coredns/test/interwebs/svc/testns/external"}}, diff --git a/test/kubernetes_test.go b/test/kubernetes_test.go index 22b2f7857..c0c836911 100644 --- a/test/kubernetes_test.go +++ b/test/kubernetes_test.go @@ -29,6 +29,16 @@ var dnsTestCases = []test.Case{ Rcode: dns.RcodeNameError, Answer: []dns.RR{}, }, + { + Qname: "bogusendpoint.svc-1-a.test-1.svc.cluster.local.", Qtype: dns.TypeA, + Rcode: dns.RcodeNameError, + Answer: []dns.RR{}, + }, + { + Qname: "bogusendpoint.headless-svc.test-1.svc.cluster.local.", Qtype: dns.TypeA, + Rcode: dns.RcodeNameError, + Answer: []dns.RR{}, + }, { Qname: "svc-1-a.*.svc.cluster.local.", Qtype: dns.TypeA, Rcode: dns.RcodeSuccess,