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
This commit is contained in:
parent
84988ce2c2
commit
338d148c78
6 changed files with 180 additions and 70 deletions
|
@ -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."
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue