diff --git a/cmd/kube-dns/app/server.go b/cmd/kube-dns/app/server.go index 9141d90d4..98b4a11d7 100644 --- a/cmd/kube-dns/app/server.go +++ b/cmd/kube-dns/app/server.go @@ -187,6 +187,6 @@ func (d *KubeDNSServer) startSkyDNSServer() { glog.V(0).Infof("Skydns metrics not enabled") } - d.kd.BondSkydnsConfig(skydnsConfig) + d.kd.SkyDNSConfig = skydnsConfig go s.Run() } diff --git a/pkg/dns/config/config.go b/pkg/dns/config/config.go index ee213d213..85706de6a 100644 --- a/pkg/dns/config/config.go +++ b/pkg/dns/config/config.go @@ -133,3 +133,37 @@ func (config *Config) validateUpstreamNameserver() error { return nil } + +func (config *Config) ValidateHostAndPort(hostAndPort string) error { + host, port, err := net.SplitHostPort(hostAndPort) + if err != nil { + return err + } + if ip := net.ParseIP(host); ip == nil { + return fmt.Errorf("bad IP address: %s", host) + } + + if p, _ := strconv.Atoi(port); p < 1 || p > 65535 { + return fmt.Errorf("bad port number %s", port) + } + return nil +} + +// validateNameServer validates a configured name server and +// appends a ":53" if a :port is not included. IPv6 addresses are also +// enclosed in square brackets if not already so enclosed. +func (config *Config) ValidateNameServer(nameServer string) (string, error) { + if ip := net.ParseIP(nameServer); ip != nil { + if ip.To4() != nil { + // IPv4 without port + nameServer = nameServer + ":53" + } else { + // IPv6 without port + nameServer = "[" + nameServer + "]:53" + } + return nameServer, nil + } + // Assume it's IP:port + err := ValidateHostAndPort(nameServer) + return nameServer, err +} diff --git a/pkg/dns/dns.go b/pkg/dns/dns.go index 84e2f7051..f54327525 100644 --- a/pkg/dns/dns.go +++ b/pkg/dns/dns.go @@ -59,7 +59,7 @@ type KubeDNS struct { kubeClient clientset.Interface // skydns points to the skydns server instance for configuration syncing. - skydnsConfig *server.Config + SkyDNSConfig *server.Config // domain for which this DNS Server is authoritative. domain string @@ -139,21 +139,16 @@ func NewKubeDNS(client clientset.Interface, clusterDomain string, timeout time.D return kd } -// BondSkydnsConfig bonds the configuration of skydns for config sync. The -// function encapsulates skydnsConfig inside KubeDNS struct. -func (kd *KubeDNS) BondSkydnsConfig(config *server.Config) { - kd.skydnsConfig = config -} - func (kd *KubeDNS) updateConfig(nextConfig *config.Config) { kd.configLock.Lock() + defer kd.configLock.Unlock() kd.config = nextConfig if kd.skydnsConfig != nil { var nameservers []string for _, nameserver := range kd.config.UpstreamNameservers { if nameserverIpPort, err := util.ValidateNameServer(nameserver); err != nil { - glog.V(1).Infof("Invalid nameserver in configuration %s: %v", nameserver, err) + glog.V(1).Errorf("Invalid nameserver in configuration %s: %v", nameserver, err) } else { nameservers = append(nameservers, nameserverIpPort) } @@ -162,7 +157,6 @@ func (kd *KubeDNS) updateConfig(nextConfig *config.Config) { } glog.V(2).Infof("Configuration updated: %+v", *kd.config) - kd.configLock.Unlock() } func (kd *KubeDNS) Start() { diff --git a/pkg/dns/util/util.go b/pkg/dns/util/util.go index 24d84db34..ee106b4e1 100644 --- a/pkg/dns/util/util.go +++ b/pkg/dns/util/util.go @@ -89,37 +89,3 @@ func HashServiceRecord(msg *msg.Service) string { h.Write([]byte(s)) return fmt.Sprintf("%x", h.Sum32()) } - -func ValidateHostAndPort(hostAndPort string) error { - host, port, err := net.SplitHostPort(hostAndPort) - if err != nil { - return err - } - if ip := net.ParseIP(host); ip == nil { - return fmt.Errorf("bad IP address: %s", host) - } - - if p, _ := strconv.Atoi(port); p < 1 || p > 65535 { - return fmt.Errorf("bad port number %s", port) - } - return nil -} - -// validateNameServer validates a configured name server and -// appends a ":53" if a :port is not included. IPv6 addresses are also -// enclosed in square brackets if not already so enclosed. -func ValidateNameServer(nameServer string) (string, error) { - if ip := net.ParseIP(nameServer); ip != nil { - if ip.To4() != nil { - // IPv4 without port - nameServer = nameServer + ":53" - } else { - // IPv6 without port - nameServer = "[" + nameServer + "]:53" - } - return nameServer, nil - } - // Assume it's IP:port - err := ValidateHostAndPort(nameServer) - return nameServer, err -} diff --git a/pkg/e2e/options.go b/pkg/e2e/options.go index 96ebe7165..388100459 100644 --- a/pkg/e2e/options.go +++ b/pkg/e2e/options.go @@ -17,9 +17,9 @@ limitations under the License. package e2e const ( - etcdImage = "quay.io/coreos/etcd:v3.0.14" - hyperkubeImage = "k8s.gcr.io/hyperkube:v1.5.1" - dnsmasqPtrImage = "gcr.io/kubernetes-e2e-test-images/dnsmasq-ptr:1.0" + etcdImage = "quay.io/coreos/etcd:v3.0.14" + hyperkubeImage = "k8s.gcr.io/hyperkube:v1.5.1" + dnsmasqImage = "k8s.gcr.io/k8s-dns-dnsmasq-amd64:1.14.5" ) type Options struct { @@ -30,10 +30,10 @@ type Options struct { BaseDir string WorkDir string - EtcdImage string - HyperkubeImage string - ClusterIpRange string - DnsmasqPtrImage string + EtcdImage string + HyperkubeImage string + ClusterIpRange string + DnsmasqImage string } // DefaultOptions to use to run the e2e test. @@ -45,11 +45,11 @@ func DefaultOptions(baseDir string, workDir string) Options { BaseDir: baseDir, WorkDir: workDir, - Docker: "docker", - EtcdImage: etcdImage, - HyperkubeImage: hyperkubeImage, - DnsmasqPtrImage: dnsmasqPtrImage, - ClusterIpRange: "10.0.0.0/24", + Docker: "docker", + EtcdImage: etcdImage, + HyperkubeImage: hyperkubeImage, + DnsmasqImage: dnsmasqImage, + ClusterIpRange: "10.0.0.0/24", } return ret diff --git a/test/e2e/kubedns/kubedns.go b/test/e2e/kubedns/kubedns.go index 9592e6755..a273caac9 100644 --- a/test/e2e/kubedns/kubedns.go +++ b/test/e2e/kubedns/kubedns.go @@ -60,60 +60,87 @@ var _ = Describe("kube-dns", func() { }) }) - It("should forward missed ptr lookup to upstream server", func() { + It("should forward PTR queries to the upstream server", func() { By("Setting up environment without upstream server") kubeDNS := &e2edns.KubeDNS{} fr := e2e.GetFramework() - configDir := fr.Options.WorkDir + "/kube-dns-config" + workDir := fr.Options.WorkDir + "/ptr_forwarding" - if _, err := os.Stat(configDir); err == nil { - os.RemoveAll(configDir) + if _, err := os.Stat(workDir); err == nil { + os.RemoveAll(workDir) } + defer func() { + if _, err := os.Stat(workDir); err == nil { + os.RemoveAll(workDir) + } + }() + + configDir := workDir + "/kube-dns-config" if err := os.MkdirAll(configDir, 0744); err != nil { panic(err) } + if err := ioutil.WriteFile(configDir+"/upstreamNameservers", []byte("[\"127.0.0.1:10054\"]"), 0744); err != nil { + panic(err) + } + dnsmasqConfigDir := workDir + "/dnsmasq-config" + if err := os.MkdirAll(dnsmasqConfigDir, 0744); err != nil { + panic(err) + } + if err := ioutil.WriteFile(dnsmasqConfigDir+"/dnsmasq.conf", []byte("user=root\naddn-hosts=/etc/dnsmasq-hosts"), 0744); err != nil { + panic(err) + } + if err := ioutil.WriteFile(dnsmasqConfigDir+"/dnsmasq-hosts", []byte("192.0.2.123 my.test"), 0744); err != nil { + panic(err) + } + fr.Docker.Pull(fr.Options.DnsmasqImage) - fr.Docker.Pull(fr.Options.DnsmasqPtrImage) - dnsmasq := fr.Docker.Run( + By("Getting answer without numb upstream server") + dnsmasq_numb := fr.Docker.Run( "-d", "-p=10054:53/tcp", "-p=10054:53/udp", "--cap-add=NET_ADMIN", - fr.Options.DnsmasqPtrImage) + fr.Options.DnsmasqImage) + defer func() { + fr.Docker.Kill(dnsmasq_numb) + }() kubeDNS.Start("kube-dns-ptrfwd", "-v=4", "--config-dir="+configDir) + defer func() { + kubeDNS.Stop() + }() - By("Get answer without upstream server") om.Eventually(func() error { return doPtrQuery(kubeDNS) }, 1*time.Minute).ShouldNot(om.Succeed()) - By("Config upstream nameserver") - if err := ioutil.WriteFile(configDir+"/upstreamNameservers", []byte("[\"127.0.0.1:10054\"]"), 0744); err != nil { + By("Getting answer from upstream server") + dnsmasq := fr.Docker.Run( + "-d", + "-p=10055:53/tcp", + "-p=10055:53/udp", + "-v="+dnsmasqConfigDir+"/dnsmasq.conf:/etc/dnsmasq.conf", + "-v="+dnsmasqConfigDir+"/dnsmasq-hosts:/etc/dnsmasq-hosts", + "--cap-add=NET_ADMIN", + fr.Options.DnsmasqImage) + defer func() { + fr.Docker.Kill(dnsmasq) + }() + By("Configuring upstream nameserver") + if err := ioutil.WriteFile(configDir+"/upstreamNameservers", []byte("[\"127.0.0.1:10055\"]"), 0744); err != nil { panic(err) } - By("Get answer from upstream server") om.Eventually(func() error { return doPtrQuery(kubeDNS) }, 1*time.Minute).Should(om.Succeed()) - - By("Clean up test environment") - kubeDNS.Stop() - if dnsmasq != "" { - fr.Docker.Kill(dnsmasq) - } - - if _, err := os.Stat(configDir); err == nil { - os.RemoveAll(configDir) - } }) }) func doPtrQuery(kubeDNS *e2edns.KubeDNS) error { time.Sleep(1 * time.Second) - names, err := kubeDNS.Query("4.3.2.1.in-addr.arpa.", dns.TypePTR) - expected := "4.3.2.1.in-addr.arpa.\t0\tIN\tPTR\tmy.test." + names, err := kubeDNS.Query("123.2.0.192.in-addr.arpa.", dns.TypePTR) + expected := "123.2.0.192.in-addr.arpa.\t0\tIN\tPTR\tmy.test." if err != nil { return err }