-
Notifications
You must be signed in to change notification settings - Fork 24
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
Magicdns #79
Conversation
cmd/kindnetd/dnsproxy.go
Outdated
} | ||
|
||
// create a connection with the upstream DNS server | ||
dnsTCPConn, err := dialer.Dial("tcp", net.JoinHostPort(d.nameServer, "53")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's great that this upstreams over TCP!
cmd/kindnetd/dnsproxy.go
Outdated
if len(questions) == 0 { | ||
return dnsErrorMessage(hdr.ID, dnsmessage.RCodeFormatError, dnsmessage.Question{}) | ||
} | ||
// it is supported but not wildly implemented, at least not in golang stdlib |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: s/wildly/widely
cmd/kindnetd/dnsproxy.go
Outdated
} | ||
switch q.Type { | ||
case dnsmessage.TypeA: | ||
klog.V(7).Infof("DNS A request for %s", q.Name.String()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd be really interested to see what DNS requests come from your average pod. If we could "fix" the ndots situation, that would be great. That's got me thinking that we might want to (somehow?) warn about namespaces that collide with TLDs; I quickly scanned through B - both .blog and .build are TLDs and not-unlikely namespace-names!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this was reported recently in sig-network, I think you want something like https://coredns.io/plugins/kubernetes/#autopath , but once we have tcp pipelining working with a pool of connections I'm curious about if that will be relevant ... from 5 requests 4 will be nxdomains
cmd/kindnetd/dnsproxy.go
Outdated
switch q.Type { | ||
case dnsmessage.TypeA: | ||
klog.V(7).Infof("DNS A request for %s", q.Name.String()) | ||
addrs, err := d.lookupIP(context.Background(), "ip4", q.Name.String()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Idea for the future: I do think that sometimes DNS returns additional records, to avoid a round-trip. Maybe lookupIP
should return a set of DNS answers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, I think what I'm doing have some limitations, and I just should work with the dns records directly instead of perform the translation
cmd/kindnetd/dnsproxy.go
Outdated
PreferGo: true, | ||
Dial: func(ctx context.Context, network, address string) (net.Conn, error) { | ||
select { | ||
case conn, ok := <-d.connCh: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: I do wonder if we should put the dial logic in this function, so we can recover if we drop a TCP connection? I assume we don't because we want to reuse it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This turns out to be more involved https://datatracker.ietf.org/doc/html/rfc7766#ref-edns-tcp-keepalive , we want to keep a pool of connections and we need to work on keep them open, then we can implement pipelining
cmd/kindnetd/dnsproxy.go
Outdated
LocalAddr: &net.UDPAddr{IP: net.ParseIP(d.nameServer), Port: 53}, | ||
Control: func(network, address string, c syscall.RawConn) error { | ||
return c.Control(func(fd uintptr) { | ||
// Mark connections so thet are not processed by the netfilter TPROXY rules |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: "... so that they are not processed ... " ?
cmd/kindnetd/dnsproxy.go
Outdated
klog.V(7).Info("starting parsing packet") | ||
hdr, err := p.Start(b) | ||
if err != nil { | ||
return dnsErrorMessage(hdr.ID, dnsmessage.RCodeFormatError, dnsmessage.Question{}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: maybe logging for the error cases here?
|
@justinsb I have this fundamental question? should we cache or should we serve the DNS directly from each Nodes ... imaging we embed kube-proxy and coredns, both reuse the same information for EndpointSlices and Services and you save 2 components ... and kindnet becomes the only networking component needed in the cluster ... my point is that I don't see much value in caching if you can serve directly from the nodes ... the later completely removes the problem meanwhile the former just mitigates it but introduces a complexity that can be hard to support ... transparent proxies are complicated if they start misbehaving |
This is next , I just settled on the algorithm, the main problem of kubernetes DNS is p99 latency and conntrack exhaustion, to solve that kindnet will
|
4e5d358
to
7cc54d6
Compare
enable dns cache by default, it has the proper guardrails to avoid to break clusters, if anything fails processing the packet it falls back to the dataplane.
@justinsb Quick test with https://github.com/guessi/dnsperf-bench
With cache enabled, the min latency is faster without the cache, it seems I need to Independently, now each DNS request does NOT generate any UDP conntrack entry, a TCP connection is created and reused in a pool, with a maximum of 3 TCP connections per Node. TODO:
|
No description provided.