aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--plugin/backend_lookup.go9
-rw-r--r--plugin/kubernetes/kubernetes.go10
-rw-r--r--plugin/kubernetes/kubernetes_apex_test.go4
-rw-r--r--plugin/kubernetes/kubernetes_test.go40
-rw-r--r--plugin/kubernetes/local.go49
-rw-r--r--plugin/kubernetes/ns.go21
-rw-r--r--plugin/kubernetes/ns_test.go2
-rw-r--r--plugin/kubernetes/setup.go7
8 files changed, 91 insertions, 51 deletions
diff --git a/plugin/backend_lookup.go b/plugin/backend_lookup.go
index 096cf806b..9e5c9eeec 100644
--- a/plugin/backend_lookup.go
+++ b/plugin/backend_lookup.go
@@ -372,6 +372,8 @@ func NS(ctx context.Context, b ServiceBackend, zone string, state request.Reques
// ... and reset
state.Req.Question[0].Name = old
+ seen := map[string]bool{}
+
for _, serv := range services {
what, ip := serv.HostType()
switch what {
@@ -380,8 +382,13 @@ func NS(ctx context.Context, b ServiceBackend, zone string, state request.Reques
case dns.TypeA, dns.TypeAAAA:
serv.Host = msg.Domain(serv.Key)
- records = append(records, serv.NewNS(state.QName()))
extra = append(extra, newAddress(serv, serv.Host, ip, what))
+ ns := serv.NewNS(state.QName())
+ if _, ok := seen[ns.Ns]; ok {
+ continue
+ }
+ seen[ns.Ns] = true
+ records = append(records, ns)
}
}
return records, extra, nil
diff --git a/plugin/kubernetes/kubernetes.go b/plugin/kubernetes/kubernetes.go
index e7b36917e..68176d78c 100644
--- a/plugin/kubernetes/kubernetes.go
+++ b/plugin/kubernetes/kubernetes.go
@@ -43,11 +43,10 @@ type Kubernetes struct {
Fall fall.F
ttl uint32
opts dnsControlOpts
-
- primaryZoneIndex int
- interfaceAddrsFunc func() net.IP
- autoPathSearch []string // Local search path from /etc/resolv.conf. Needed for autopath.
- TransferTo []string
+ primaryZoneIndex int
+ localIPs []net.IP
+ autoPathSearch []string // Local search path from /etc/resolv.conf. Needed for autopath.
+ TransferTo []string
}
// New returns a initialized Kubernetes. It default interfaceAddrFunc to return 127.0.0.1. All other
@@ -56,7 +55,6 @@ func New(zones []string) *Kubernetes {
k := new(Kubernetes)
k.Zones = zones
k.Namespaces = make(map[string]struct{})
- k.interfaceAddrsFunc = func() net.IP { return net.ParseIP("127.0.0.1") }
k.podMode = podModeDisabled
k.ttl = defaultTTL
diff --git a/plugin/kubernetes/kubernetes_apex_test.go b/plugin/kubernetes/kubernetes_apex_test.go
index 9a91ea2e2..5d2f4079b 100644
--- a/plugin/kubernetes/kubernetes_apex_test.go
+++ b/plugin/kubernetes/kubernetes_apex_test.go
@@ -2,6 +2,7 @@ package kubernetes
import (
"context"
+ "net"
"testing"
"github.com/coredns/coredns/plugin/pkg/dnstest"
@@ -63,6 +64,7 @@ func TestServeDNSApex(t *testing.T) {
k := New([]string{"cluster.local."})
k.APIConn = &APIConnServeTest{}
k.Next = test.NextHandler(dns.RcodeSuccess, nil)
+ k.localIPs = []net.IP{net.ParseIP("127.0.0.1")}
ctx := context.TODO()
for i, tc := range kubeApexCases {
@@ -85,7 +87,7 @@ func TestServeDNSApex(t *testing.T) {
}
if err := test.SortAndCheck(resp, tc); err != nil {
- t.Error(err)
+ t.Errorf("Test %d: %v", i, err)
}
}
}
diff --git a/plugin/kubernetes/kubernetes_test.go b/plugin/kubernetes/kubernetes_test.go
index 4fd8e22a6..b259869a8 100644
--- a/plugin/kubernetes/kubernetes_test.go
+++ b/plugin/kubernetes/kubernetes_test.go
@@ -310,20 +310,28 @@ func TestServicesAuthority(t *testing.T) {
key string
}
type svcTest struct {
- interfaceAddrs func() net.IP
- qname string
- qtype uint16
- answer *svcAns
+ localIPs []net.IP
+ qname string
+ qtype uint16
+ answer []svcAns
}
tests := []svcTest{
- {interfaceAddrs: func() net.IP { return net.ParseIP("127.0.0.1") }, qname: "ns.dns.interwebs.test.", qtype: dns.TypeA, answer: &svcAns{host: "127.0.0.1", key: "/" + coredns + "/test/interwebs/dns/ns"}},
- {interfaceAddrs: func() net.IP { return net.ParseIP("127.0.0.1") }, qname: "ns.dns.interwebs.test.", qtype: dns.TypeAAAA},
- {interfaceAddrs: func() net.IP { return net.ParseIP("::1") }, qname: "ns.dns.interwebs.test.", qtype: dns.TypeA},
- {interfaceAddrs: func() net.IP { return net.ParseIP("::1") }, qname: "ns.dns.interwebs.test.", qtype: dns.TypeAAAA, answer: &svcAns{host: "::1", key: "/" + coredns + "/test/interwebs/dns/ns"}},
+ {localIPs: []net.IP{net.ParseIP("1.2.3.4")}, qname: "ns.dns.interwebs.test.", qtype: dns.TypeA, answer: []svcAns{{host: "1.2.3.4", key: "/" + coredns + "/test/interwebs/dns/ns"}}},
+ {localIPs: []net.IP{net.ParseIP("1.2.3.4")}, qname: "ns.dns.interwebs.test.", qtype: dns.TypeAAAA},
+ {localIPs: []net.IP{net.ParseIP("1:2::3:4")}, qname: "ns.dns.interwebs.test.", qtype: dns.TypeA},
+ {localIPs: []net.IP{net.ParseIP("1:2::3:4")}, qname: "ns.dns.interwebs.test.", qtype: dns.TypeAAAA, answer: []svcAns{{host: "1:2::3:4", key: "/" + coredns + "/test/interwebs/dns/ns"}}},
+ {
+ localIPs: []net.IP{net.ParseIP("1.2.3.4"), net.ParseIP("1:2::3:4")},
+ qname: "ns.dns.interwebs.test.",
+ qtype: dns.TypeNS, answer: []svcAns{
+ {host: "1.2.3.4", key: "/" + coredns + "/test/interwebs/dns/ns"},
+ {host: "1:2::3:4", key: "/" + coredns + "/test/interwebs/dns/ns"},
+ },
+ },
}
for i, test := range tests {
- k.interfaceAddrsFunc = test.interfaceAddrs
+ k.localIPs = test.localIPs
state := request.Request{
Req: &dns.Msg{Question: []dns.Question{{Name: test.qname, Qtype: test.qtype}}},
@@ -334,7 +342,7 @@ func TestServicesAuthority(t *testing.T) {
t.Errorf("Test %d: got error '%v'", i, e)
continue
}
- if test.answer != nil && len(svcs) != 1 {
+ if test.answer != nil && len(svcs) != len(test.answer) {
t.Errorf("Test %d, expected 1 answer, got %v", i, len(svcs))
continue
}
@@ -347,11 +355,13 @@ func TestServicesAuthority(t *testing.T) {
continue
}
- if test.answer.host != svcs[0].Host {
- t.Errorf("Test %d, expected host '%v', got '%v'", i, test.answer.host, svcs[0].Host)
- }
- if test.answer.key != svcs[0].Key {
- t.Errorf("Test %d, expected key '%v', got '%v'", i, test.answer.key, svcs[0].Key)
+ for i, answer := range test.answer {
+ if answer.host != svcs[i].Host {
+ t.Errorf("Test %d, expected host '%v', got '%v'", i, answer.host, svcs[i].Host)
+ }
+ if answer.key != svcs[i].Key {
+ t.Errorf("Test %d, expected key '%v', got '%v'", i, answer.key, svcs[i].Key)
+ }
}
}
}
diff --git a/plugin/kubernetes/local.go b/plugin/kubernetes/local.go
index 199af6f0d..d09255061 100644
--- a/plugin/kubernetes/local.go
+++ b/plugin/kubernetes/local.go
@@ -2,41 +2,54 @@ package kubernetes
import (
"net"
+
+ "github.com/caddyserver/caddy"
+ "github.com/coredns/coredns/core/dnsserver"
)
-func localPodIP() net.IP {
- addrs, err := net.InterfaceAddrs()
- if err != nil {
- return nil
+// boundIPs returns the list of non-loopback IPs that CoreDNS is bound to
+func boundIPs(c *caddy.Controller) (ips []net.IP) {
+ conf := dnsserver.GetConfig(c)
+ hosts := conf.ListenHosts
+ if hosts == nil || hosts[0] == "" {
+ hosts = nil
+ addrs, err := net.InterfaceAddrs()
+ if err != nil {
+ return nil
+ }
+ for _, addr := range addrs {
+ hosts = append(hosts, addr.String())
+ }
}
-
- for _, addr := range addrs {
- ip, _, _ := net.ParseCIDR(addr.String())
+ for _, host := range hosts {
+ ip, _, _ := net.ParseCIDR(host)
ip4 := ip.To4()
if ip4 != nil && !ip4.IsLoopback() {
- return ip4
+ ips = append(ips, ip4)
+ continue
}
ip6 := ip.To16()
if ip6 != nil && !ip6.IsLoopback() {
- return ip6
+ ips = append(ips, ip6)
}
}
- return nil
+ return ips
}
// LocalNodeName is exclusively used in federation plugin, will be deprecated later.
func (k *Kubernetes) LocalNodeName() string {
- localIP := k.interfaceAddrsFunc()
- if localIP == nil {
+ if len(k.localIPs) == 0 {
return ""
}
- // Find endpoint matching localIP
- 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)) {
- return addr.NodeName
+ // Find fist endpoint matching any localIP
+ for _, localIP := range k.localIPs {
+ 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)) {
+ return addr.NodeName
+ }
}
}
}
diff --git a/plugin/kubernetes/ns.go b/plugin/kubernetes/ns.go
index 4774e176f..f21890cc9 100644
--- a/plugin/kubernetes/ns.go
+++ b/plugin/kubernetes/ns.go
@@ -21,15 +21,10 @@ func (k *Kubernetes) nsAddrs(external bool, zone string) []dns.RR {
svcIPs []net.IP
)
- // Find the CoreDNS Endpoint
- localIP := k.interfaceAddrsFunc()
- endpoints := k.APIConn.EpIndexReverse(localIP.String())
+ // Find the CoreDNS Endpoints
+ for _, localIP := range k.localIPs {
+ endpoints := k.APIConn.EpIndexReverse(localIP.String())
- // 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))
@@ -59,6 +54,16 @@ func (k *Kubernetes) nsAddrs(external bool, zone string) []dns.RR {
}
}
+ // If no local IPs matched any endpoints, use the localIPs directly
+ if len(svcIPs) == 0 {
+ svcIPs = make([]net.IP, len(k.localIPs))
+ svcNames = make([]string, len(k.localIPs))
+ for i, localIP := range k.localIPs {
+ svcNames[i] = defaultNSName + zone
+ svcIPs[i] = localIP
+ }
+ }
+
// Create an RR slice of collected IPs
var rrs []dns.RR
rrs = make([]dns.RR, len(svcIPs))
diff --git a/plugin/kubernetes/ns_test.go b/plugin/kubernetes/ns_test.go
index af057c254..5f9786a74 100644
--- a/plugin/kubernetes/ns_test.go
+++ b/plugin/kubernetes/ns_test.go
@@ -111,7 +111,7 @@ func TestNsAddrs(t *testing.T) {
k := New([]string{"inter.webs.test."})
k.APIConn = &APIConnTest{}
- k.interfaceAddrsFunc = func() net.IP { return net.ParseIP("10.244.0.20") }
+ k.localIPs = []net.IP{net.ParseIP("10.244.0.20")}
cdrs := k.nsAddrs(false, k.Zones[0])
diff --git a/plugin/kubernetes/setup.go b/plugin/kubernetes/setup.go
index eb33936fa..1309139d7 100644
--- a/plugin/kubernetes/setup.go
+++ b/plugin/kubernetes/setup.go
@@ -61,6 +61,12 @@ func setup(c *caddy.Controller) error {
return k
})
+ // get locally bound addresses
+ c.OnStartup(func() error {
+ k.localIPs = boundIPs(c)
+ return nil
+ })
+
return nil
}
@@ -113,7 +119,6 @@ func kubernetesParse(c *caddy.Controller) (*Kubernetes, error) {
func ParseStanza(c *caddy.Controller) (*Kubernetes, error) {
k8s := New([]string{""})
- k8s.interfaceAddrsFunc = localPodIP
k8s.autoPathSearch = searchFromResolvConf()
opts := dnsControlOpts{