Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Forward PTR record lookup from kubedns to upstream server. #220

Merged
merged 1 commit into from
Apr 5, 2018

Conversation

grayluck
Copy link
Contributor

@grayluck grayluck commented Mar 23, 2018

Fixes #198

Approach: Let kubedns sync config to skydns nameservers, allowing skydns to do the request forwarding.

@k8s-ci-robot k8s-ci-robot added do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. size/XS Denotes a PR that changes 0-9 lines, ignoring generated files. labels Mar 23, 2018
@k8s-ci-robot k8s-ci-robot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. and removed size/XS Denotes a PR that changes 0-9 lines, ignoring generated files. labels Mar 28, 2018
@grayluck grayluck changed the title [WIP] Forward external IP from kubedns to upstream server Forward external IP from kubedns to upstream server Mar 28, 2018
@k8s-ci-robot k8s-ci-robot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Mar 28, 2018
@grayluck
Copy link
Contributor Author

/assign @MrHohn

@MrHohn
Copy link
Member

MrHohn commented Mar 29, 2018

/ok-to-test

@k8s-ci-robot k8s-ci-robot removed the needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. label Mar 29, 2018
@MrHohn
Copy link
Member

MrHohn commented Mar 30, 2018

@grayluck Seems like travis failed on this:

--- FAIL: TestConfigSync (0.00s)
panic: runtime error: invalid memory address or nil pointer dereference [recovered]
	panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x68 pc=0x11963f6]
goroutine 38 [running]:
testing.tRunner.func1(0xc4204651d0)
	/usr/local/go/src/testing/testing.go:711 +0x2d2
panic(0x12e4380, 0x1cb8c40)
	/usr/local/go/src/runtime/panic.go:491 +0x283
k8s.io/dns/pkg/dns.(*KubeDNS).updateConfig(0xc42027f200, 0xc4201a5950)
	/go/src/k8s.io/dns/pkg/dns/dns.go:160 +0x346
k8s.io/dns/pkg/dns.(*KubeDNS).startConfigMapSync(0xc42027f200)
	/go/src/k8s.io/dns/pkg/dns/dns.go:214 +0x20a
k8s.io/dns/pkg/dns.TestConfigSync(0xc4204651d0)
	/go/src/k8s.io/dns/pkg/dns/dns_test.go:683 +0x164
testing.tRunner(0xc4204651d0, 0x14b7ff8)
	/usr/local/go/src/testing/testing.go:746 +0xd0
created by testing.(*T).Run
	/usr/local/go/src/testing/testing.go:789 +0x2de
FAIL	k8s.io/dns/pkg/dns	0.125s

@grayluck
Copy link
Contributor Author

/assign @bowei

Makefile Outdated
# dnsmasq-nanny \
# kube-dns \
# sidecar
CONTAINER_BINARIES := kube-dns
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reverted.

Makefile Outdated

# List of images to build (contained in images/)
IMAGES := dnsmasq
# Registry to push to.
REGISTRY ?= staging-k8s.gcr.io
# REGISTRY ?= gcr.io
REGISTRY ?= gcr.io/yankaiz-kube-test
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

revert

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reverted.

@@ -163,40 +162,6 @@ func setupSignalHandlers() {
}()
}

func validateHostAndPort(hostAndPort string) error {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should just go into config/ package instead of creating a new package util

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's now in config package.
I am making it public for now in testing purpose. Will change it to private method very soon on Monday.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two validation logic merged. Now skydns's nameserver is synced/guarded by kubedns.

pkg/dns/dns.go Outdated
@@ -57,6 +58,9 @@ type KubeDNS struct {
// to get Endpoints and Service objects.
kubeClient clientset.Interface

// skydns points to the skydns server instance for configuration syncing.
skydnsConfig *server.Config
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's just make this a Public field and call set directly

SkyDNSConfig *server.Config

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

pkg/dns/dns.go Outdated
@@ -135,6 +139,32 @@ 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) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

delete this...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@@ -87,3 +89,37 @@ func HashServiceRecord(msg *msg.Service) string {
h.Write([]byte(s))
return fmt.Sprintf("%x", h.Sum32())
}

func ValidateHostAndPort(hostAndPort string) error {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move unit tests as well. Are there any unit tests?

hyperkubeImage = "k8s.gcr.io/hyperkube:v1.5.1"
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"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now using k8s.gcr.io/k8s-dns-dnsmasq-amd64:1.14.5 instead.

@@ -55,4 +59,69 @@ var _ = Describe("kube-dns", func() {
kubeDNS.Stop()
})
})

It("should forward missed ptr lookup to upstream server", func() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should forward PTR queries to the upstream server

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.


kubeDNS.Start("kube-dns-ptrfwd", "-v=4", "--config-dir="+configDir)

By("Get answer without upstream server")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getting

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.


func doPtrQuery(kubeDNS *e2edns.KubeDNS) error {
time.Sleep(1 * time.Second)
names, err := kubeDNS.Query("4.3.2.1.in-addr.arpa.", dns.TypePTR)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use an IP from the testbed range to guarantee no one will reply. 1.2.3.4 may be someone's address.

192.0.2.0/24

https://en.wikipedia.org/wiki/Reserved_IP_addresses

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IP changed. Now using numb upstream server when test starts and then switch to a upstream server with the desired PTR record.

@grayluck grayluck force-pushed the fwdup branch 2 times, most recently from 33bbedf to a34f511 Compare April 2, 2018 00:13
return err
}
if ip := net.ParseIP(host); ip == nil {
return fmt.Errorf("bad IP address: %s", host)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use %q

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

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)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use %q

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

pkg/dns/dns.go Outdated

if kd.SkyDNSConfig != nil {
var nameServers []string
for _, nameServer := range kd.config.UpstreamNameservers {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there a reason why this isn't match the parsing routine in config.go?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

config.go only validates the address of nameservers. Here a default port is appended to the address if the address doesn't have a port.


configDir := workDir + "/kube-dns-config"
if err := os.MkdirAll(configDir, 0744); err != nil {
panic(err)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Expect("foo").To(Equal("foo"))

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

return "", "", err
}
if ip := net.ParseIP(host); ip == nil {
return "", "", fmt.Errorf("bad IP address: %s", host)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For invalid strings, you should use %q so the string is quoted.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

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)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For invalid strings, you should use %q so the string is quoted.

check err as well

if p, err := strconv.Atoi(port); err != nil || p < 1 || p > 65535 {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

import (
"testing"

"github.com/stretchr/testify/assert"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't use testify, we are trying to move away from it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

{false, "asdf", "", ""},
} {
ip, port, err := ValidateNameserverIpAndPort(tc.nameserver)
if tc.isValid {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gotErr := err != nil
if gotErr != tc.wantErr {
  t.Errorf("ValidateNameserverIpAndPort(%q) = %q, %q, %v; gotErr = %t, want %t", ip, port, err, gotErr, tc.wantErr)
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed.

} else {
assert.Error(t, err, "%s should not be valid nameserver", tc.nameserver)
}
assert.Equal(t, tc.expectedIp, ip, "Ip doesn't match.")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if ip != tc.ip || port != tc.port {
  t.Errorf("ValidateNameserverIpAndPort(%q) = %q, %q, nil; want %q, %q, nil", ip, port, tc.ip, tc.port)
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

{false, "1.1.1.1:abc", "", ""},
{false, "1.1.1.1:123456789", "", ""},
{false, "1.1.1.1:", "", ""},
{false, "asdf", "", ""},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add case `{wantErr: true, ns:"invalidip:80"},

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added.

cmd *exec.Cmd
isRunning bool
}

// Start kube DNS, passing in extra arguments
func (kd *KubeDNS) Start(args ...string) {
func (kd *KubeDNS) Start(name string, args ...string) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

document name

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doc updated.

@@ -0,0 +1,49 @@
/*
Copyright 2016 The Kubernetes Authors.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2018

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

pkg/dns/dns.go Outdated
}
kd.config = nextConfig
glog.V(2).Infof("Configuration updated: %+v", *kd.config)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extra line

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

func (d *KubeDNSServer) startSkyDNSServer() {
glog.V(0).Infof("Starting SkyDNS server (%v:%v)", d.dnsBindAddress, d.dnsPort)
skydnsConfig := &server.Config{
Domain: d.domain,
DnsAddr: fmt.Sprintf("%s:%d", d.dnsBindAddress, d.dnsPort),
}
if d.nameServers != "" {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where doe d.nameServers get initialized now?

Copy link
Contributor Author

@grayluck grayluck Apr 5, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will get initialized when kubeDNS initialize its configuration through Once.
Let's say the user provides nameservers as commandline parameters. In the case of using configMap or configDir, the nameserver from command line will be overwriten when kubedns initializes its config through sync once. As for no configmap or configdir, both kubedns and skydns will use the nameserver from commandline parameter after kubedns sync once.

https://github.com/grayluck/dns/blob/acd9f258a0a65dcc27ef03d6cf059969fb4f602f/cmd/kube-dns/app/server.go#L74

@bowei
Copy link
Member

bowei commented Apr 5, 2018

Ok, can you squash all of the commits and clean up the commit message?

git rebase -i upstream/master

then we can merge.

@grayluck grayluck changed the title Forward external IP from kubedns to upstream server Forward PTR record lookup from kubedns to upstream server. Apr 5, 2018
@grayluck
Copy link
Contributor Author

grayluck commented Apr 5, 2018

Squashed. Also changed the title of this PR.

Fixes issue kubernetes#198.

e2e test for PTR lookup forwarding also included.

Skydns syncs config with kubeDNS. Now Skydns will ignore nameservers
parameter from the commandline if either configmap or configdir is
given.

Merged hostname validation logic and moved them to util. Unittest is
added for this.
@bowei
Copy link
Member

bowei commented Apr 5, 2018

/lgtm

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Apr 5, 2018
@bowei
Copy link
Member

bowei commented Apr 5, 2018

/approved

@bowei bowei merged commit acd6b1e into kubernetes:master Apr 5, 2018
@grayluck grayluck deleted the fwdup branch April 9, 2018 18:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. lgtm "Looks good to me", indicates that a PR is ready to be merged. size/L Denotes a PR that changes 100-499 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants