diff options
author | 2019-08-23 12:54:06 -0400 | |
---|---|---|
committer | 2019-08-23 16:54:06 +0000 | |
commit | 338d148c7845ca4e3a44253ac8b6f040c394b8c4 (patch) | |
tree | 116d758e8a3ec7f8daccda847743e15240890750 /plugin/kubernetes/ns.go | |
parent | 84988ce2c20a33a6c37e8136aecb023bad3f17ef (diff) | |
download | coredns-338d148c7845ca4e3a44253ac8b6f040c394b8c4.tar.gz coredns-338d148c7845ca4e3a44253ac8b6f040c394b8c4.tar.zst coredns-338d148c7845ca4e3a44253ac8b6f040c394b8c4.zip |
plugin/k8s_external/kubernetes: handle NS records (#3160)
* fix external ns records
* use k8s service name for ns record
* update test, add func comment
* expand nsAddrs() test cases
* support local ipv6 ip
* use less confusing pod ip in test
Diffstat (limited to 'plugin/kubernetes/ns.go')
-rw-r--r-- | plugin/kubernetes/ns.go | 91 |
1 files changed, 56 insertions, 35 deletions
diff --git a/plugin/kubernetes/ns.go b/plugin/kubernetes/ns.go index f3d33ee22..6d18c0b77 100644 --- a/plugin/kubernetes/ns.go +++ b/plugin/kubernetes/ns.go @@ -4,6 +4,7 @@ import ( "net" "strings" + "github.com/coredns/coredns/plugin/kubernetes/object" "github.com/miekg/dns" api "k8s.io/api/core/v1" ) @@ -12,54 +13,74 @@ func isDefaultNS(name, zone string) bool { return strings.Index(name, defaultNSName) == 0 && strings.Index(name, zone) == len(defaultNSName) } -// nsAddr return the A record for the CoreDNS service in the cluster. If it fails that it fallsback -// on the local address of the machine we're running on. -// -// This function is rather expensive to run. -func (k *Kubernetes) nsAddr() *dns.A { +// nsAddrs returns the A or AAAA records for the CoreDNS service in the cluster. If the service cannot be found, +// it returns a record for the the local address of the machine we're running on. +func (k *Kubernetes) nsAddrs(external bool, zone string) []dns.RR { var ( - svcName string - svcNamespace string + svcNames []string + svcIPs []net.IP ) - rr := new(dns.A) + // Find the CoreDNS Endpoint localIP := k.interfaceAddrsFunc() - rr.A = localIP + endpoints := k.APIConn.EpIndexReverse(localIP.String()) -FindEndpoint: - for _, ep := range k.APIConn.EpIndexReverse(localIP.String()) { - for _, eps := range ep.Subsets { - for _, addr := range eps.Addresses { - if localIP.Equal(net.ParseIP(addr.IP)) { - svcNamespace = ep.Namespace - svcName = ep.Name - break FindEndpoint + // If the CoreDNS Endpoint is not found, use the locally bound IP address + if len(endpoints) == 0 { + svcNames = []string{defaultNSName + zone} + svcIPs = []net.IP{localIP} + } else { + // Collect IPs for all Services of the Endpoints + for _, endpoint := range endpoints { + svcs := k.APIConn.SvcIndex(object.ServiceKey(endpoint.Name, endpoint.Namespace)) + for _, svc := range svcs { + if external { + svcName := strings.Join([]string{svc.Name, svc.Namespace, zone}, ".") + for _, exIP := range svc.ExternalIPs { + svcNames = append(svcNames, svcName) + svcIPs = append(svcIPs, net.ParseIP(exIP)) + } + continue + } + svcName := strings.Join([]string{svc.Name, svc.Namespace, Svc, zone}, ".") + if svc.ClusterIP == api.ClusterIPNone { + // For a headless service, use the endpoints IPs + for _, s := range endpoint.Subsets { + for _, a := range s.Addresses { + svcNames = append(svcNames, endpointHostname(a, k.endpointNameMode)+"."+svcName) + svcIPs = append(svcIPs, net.ParseIP(a.IP)) + } + } + } else { + svcNames = append(svcNames, svcName) + svcIPs = append(svcIPs, net.ParseIP(svc.ClusterIP)) } } } } - if len(svcName) == 0 { - rr.Hdr.Name = defaultNSName - rr.A = localIP - return rr - } - -FindService: - for _, svc := range k.APIConn.ServiceList() { - if svcName == svc.Name && svcNamespace == svc.Namespace { - if svc.ClusterIP == api.ClusterIPNone { - rr.A = localIP - } else { - rr.A = net.ParseIP(svc.ClusterIP) - } - break FindService + // Create an RR slice of collected IPs + var rrs []dns.RR + rrs = make([]dns.RR, len(svcIPs)) + for i, ip := range svcIPs { + if ip.To4() == nil { + rr := new(dns.AAAA) + rr.Hdr.Class = dns.ClassINET + rr.Hdr.Rrtype = dns.TypeAAAA + rr.Hdr.Name = svcNames[i] + rr.AAAA = ip + rrs[i] = rr + continue } + rr := new(dns.A) + rr.Hdr.Class = dns.ClassINET + rr.Hdr.Rrtype = dns.TypeA + rr.Hdr.Name = svcNames[i] + rr.A = ip + rrs[i] = rr } - rr.Hdr.Name = strings.Join([]string{svcName, svcNamespace, "svc."}, ".") - - return rr + return rrs } const defaultNSName = "ns.dns." |