-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
feat: Node-local DNS cache support #550
feat: Node-local DNS cache support #550
Conversation
5eeb11d
to
cd9341f
Compare
Add a new field named `clusterDNS` that accepts the IP address to the DNS server used for all the internal/external DNS lookups a.k.a the `--cluster-dns` flag of `kubelet`. ```yaml nodeGroups: - name: nodegroup1 clusterDNS: 169.254.20.10 # snip ``` This, in combination with `k8s-dns-node-cache` deployed as a daemonset on your cluster, allows all the DNS lookups from your pods to firstly routed to the node-local DNS server, which adds more reliability. The configuration key `clusterDNS` is intentionally made per-nodegroup, not per-cluster, so that you can selectively use the node-local DNS. It, in combination with the proper use of node labels/taints, allows you to test the node-local DNS in only a subet of your workload. It would also be nice to add `clusterDNS` as a cluster-level config key later. But I believe it isn't a must-have in this change. See the [cluster/addons/dns/nodelocaldns](https://github.com/kubernetes/kubernetes/tree/master/cluster/addons/dns/nodelocaldns) in the upstream repository for more details. A concrete steps to enable node-local DNS would look like the below: - Decide the which IP addr to be used for binding the node-local DNS. Typically this is `169.254.20.10` - Add `clusterDNS: 169.254.20.10` to your nodegroup in the cluster config - Deploy [nodelocaldns.yaml](https://github.com/kubernetes/kubernetes/blob/master/cluster/addons/dns/nodelocaldns/nodelocaldns.yaml), replacing: `__PILLAR__LOCAL__DNS__` with `169.254.169.254`, `__PILLAR__DNS__DOMAIN__` with `cluster.local`, `__PILLAR__DNS__SERVER__` with [`10.100.0.10` or `172.20.0.10`](https://github.com/weaveworks/eksctl/blob/master/pkg/nodebootstrap/userdata.go#L87-L94) according to your VPC CIDR Resolves eksctl-io#542
cd9341f
to
58c4446
Compare
For anyone interested, this is how I've verified this to work.
nodeGroups:
- name: nodegroup1
clusterDNS: "169.254.20.10"
instanceType: m4.large
# and whatever you like
This should fail, as kubelet points cluster DNS to
|
Thanks @mumoshu, also thanks for keeping this small. |
func clusterDNS(spec *api.ClusterConfig, ng *api.NodeGroup) string { | ||
if ng.ClusterDNS != "" { | ||
return ng.ClusterDNS | ||
} | ||
// Default service network is 10.100.0.0, but it gets set 172.20.0.0 automatically when pod network | ||
// is anywhere within 10.0.0.0/8 | ||
if spec.VPC.CIDR != nil && spec.VPC.CIDR.IP[0] == 10 { |
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.
As a future improvement, we should probably move this into struct defaulting code path, and set the field to the default value. That is so the struct fully represents what's going on.
Just in case anyone else is implementing DNS caching using instructions here, there is a typo in mumoshu's instructions. Replace |
@rsyvarth Oh! Good catch! Seems like I was too used to type 169.254.169.254. |
For anyone interested in this feature - an alternative way to use the node local DNS would be to specify For example, this: dnsConfig:
nameservers:
- 169.254.20.10
searches:
- default.svc.cluster.local
- svc.cluster.local
- cluster.local
- ap-northeast-1.compute.internal
- us-west-2.compute.internal
options:
- name: attempts
value: "3"
- name: timeout
value: "1"
- name: rotate
dnsPolicy: None would result in pods having
whereas the default one used when I omit
The benefit of You can even add the default cluster DNS as the secondary DNS server:
This way, even while the node-local dns is down due to a rolling update or a transient failure you'll be unlikely to notice the down time because your DNS client(from e.g. glibc) is likely to handle the failure with retries and/or parallel query(I believe it depends on the DNS client you rely on). |
Is it possible to add the default cluster DNS as the secondary DNS server for the node this way:
Since kubelet options are:
|
Seems like it works! Hurrah! |
The KEP warns against this for some reason:
If musl queries nodelocal cache via tcp and kube-dns via udp in parallel, and one responds quickly and the other times out, why is that a problem? |
@StevenACoffman I guess you'll be interested on this line in the updated KEP https://github.com/kubernetes/enhancements/pull/1005/files#diff-a43ddcc01ee886cc9ca7c60a0900e436R166 The problem:
The updated KEP also note:
But when I experimented I saw on recent distros the resolver worked parallely. So my best bet that would work TODAY is that you have two nodelocal-dns daemonset, each listens on different virtual IP. All the application pods that wants to leverage the H/A nodelocal-dns-cache, the pod spec must be updated to include a |
I have one more alternative: Just try running two nodelocaldns, both listening on the same virtual IP address and the port. Surveying github issues and the codedns code, it turned out that coredns sets SO_REUSEPORT whereas available. So two or more nodelocal dns pods with the same IP:Port should just work. This allows you to use H/A nodelocaldns behind a single IP address for your cluster dns(set via a kubelet option), which is automatically used when |
Thank you! That last alternative is very interesting.
If the nodegroups are created before nodelocaldns is applied, they will not come up successfully. |
…error Clarify error message when unsupported volume capabilities are provided
TL;DR; This is the smallest change to allow enabling node-local DNS cache on eksctl-created nodes.
What
Add a new field named
clusterDNS
that accepts the IP address to the DNS server used for all the internal/external DNS lookups a.k.a the--cluster-dns
flag ofkubelet
.This, in combination with
k8s-dns-node-cache
deployed as a daemonset on your cluster, allows all the DNS lookups from your pods to firstly routed to the node-local DNS server, which adds more reliability.Notes
The configuration key
clusterDNS
is intentionally made per-nodegroup, not per-cluster, so that you can selectively use the node-local DNS. It, in combination with the proper use of node labels/taints, allows you to test the node-local DNS in only a subet of your workload.It would also be nice to add
clusterDNS
as a cluster-level config key later. But I believe it isn't a must-have in this change.Usage
See the cluster/addons/dns/nodelocaldns in the upstream repository for more details.
A concrete steps to enable node-local DNS would look like the below:
169.254.20.10
clusterDNS: 169.254.20.10
to your nodegroup in the cluster config__PILLAR__LOCAL__DNS__
with169.254.169.254
,__PILLAR__DNS__DOMAIN__
withcluster.local
,__PILLAR__DNS__SERVER__
with10.100.0.10
or172.20.0.10
according to your VPC CIDRResolves #542