CoreDNS
实现K8s所有的域名解析。集群CoreDNS镜像版本:[gcr.io/coredns/coredns:1.9.3]
NodeLocalDNS
节点本地域名解析。如果k8s集群pod数增加后,pod之间的相互访问,都需先通过域名解析,那么CoreDNS将不堪重负,所以通过Daemonset在每个节点都启动了一个NodeLocalDNS,缓解全局CoreDNS的域名解析压力,其本身k8s-dns镜像,但功能没有全局的CoreDNS镜像丰富。
集群NodeLocalDNS镜像版本:k8s.gcr.io/dns/k8s-dns-node-cache:1.22.18
Kubernetes的域名解析流程
k8s的pod域名解析配置和解析流程:
- pod首先检查自己的/etc/resolv.conf
nameserver 169.254.25.10
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5
发现DNS服务器的地址为169.254.25.10,这个IP是NodeLocalDNS侦听DNS请求的IP,所以pod会先将dns请求发给本地的NodeLocalDNS进行域名解析。
cluster.local:53 {
errors
cache {
success 9984 30
denial 9984 5
}
reload
loop
bind 169.254.25.10 # 绑定的IP
forward . 10.233.0.3 {
force_tcp
}
prometheus :9253
health 169.254.25.10:9254
}
in-addr.arpa:53 {
errors
cache 30
reload
loop
bind 169.254.25.10
forward . 10.233.0.3 {
force_tcp
}
prometheus :9253
}
ip6.arpa:53 {
errors
cache 30
reload
loop
bind 169.254.25.10
forward . 10.233.0.3 {
force_tcp
}
prometheus :9253
}
.:53 {
errors
cache 30
reload
loop
bind 169.254.25.10
forward . 10.233.0.3
prometheus :9253
}
2.NodeLocalDNS如果能够解析则直接返回解析结果,如果不能解析则转发给全局DNS服务器。
如有以下场景:
namespace1->service1->[pod1]
namespace2->service2->[pod2]
现在pod1要访问pod2,其实一般pod1通过service2访问pod2,直接pod访问比较少,因为pod IP重启会变化,而服务IP一般不会改变。
pod1根据service2.namespace2.svc.cluster.local向NodeLocalDNS请求域名解析,如果NodeLocalDNS有[解析缓存],能够解析,将结果直接返回,否则将此域名发送给全局CoreDNS,CoreDNS将解析的IP发送给pod1,pod1通过IP访问pod2,完成DNS解析过程。
问题
1.场景:有很多应用,原来开发的很多微服务的nacos配置不想修改,直接部署在另外一个环境,但是重新搭建的时候,依赖的Nacos域名发生了改变,这时需要在全局CoreDNS进行rewrite操作,但是发现域名到NodeLocalDNS之后就无法解析(可以用dig @目标DNS服务器 域名,检测指定DNS服务器的域名解析能力),现给出NodeLocalDNS配置和CoreDNS配置:
1.NodeLocalDNS容器的Corefile:
Corefile: |
cluster.local:53 {
errors
cache {
success 9984 30
denial 9984 5
}
reload
loop
bind 169.254.25.10
forward . 10.233.0.3 {
prefer_udp
}
prometheus :9253
health 169.254.25.10:9254
}
in-addr.arpa:53 {
errors
cache 30
reload
loop
bind 169.254.25.10
forward . 10.233.0.3 {
prefer_udp
}
prometheus :9253
}
ip6.arpa:53 {
errors
cache 30
reload
loop
bind 169.254.25.10
forward . 10.233.0.3 {
prefer_udp
}
prometheus :9253
}
.:53 {
errors
cache 30
reload
loop
bind 169.254.25.10
forward . /etc/resolv.conf
prometheus :9253
}
2.NodeLocalDNS容器的/etc/resolv.conf:
# cat /etc/resolv.conf
nameserver 10.233.0.3 # 全局CoreDNS服务的IP地址
nameserver 114.114.114.114 # 自定义的一个DNS服务IP地址
3.全局CoreDNS的配置
Corefile: |
.:53 {
errors
health
ready
rewrite name nacos.cc.in nacos-svc.default.svc.cluster.local
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
upstream /etc/resolv.conf
fallthrough in-addr.arpa ip6.arpa
}
prometheus :9153
forward . /etc/resolv.conf
cache 30
loop
reload
loadbalance
}
经过查询, forward . /etc/resolv.conf这种配置会随机选择一个nameserver去解析现在的配置,但是/etc/resolv.conf配置中有一个114.114.114.114的配置,当采用此nameserver时,将不能被正确解析,只有转发到10.233.0.3,全局DNS服务器,此域名才能被正确解析。
解决方案:
参考github issue的解决方案:https://github.com/coredns/coredns/issues/3147
,增加策略字段,策略为顺序采用nameserver,将强制选择第一个nameserver 10.233.0.3作为DNS首先服务器:
forward . /etc/resolv.conf{
policy sequential
}
测试没有用。。。
于是直接将forward . /etc/resolv.conf改为[forward]. 10.233.0.3
问题成功解决。
测试工具
有的容器登陆进去后,发现没有nslookup工具或dig工具,这里提供一个容器工具,里面有nslookup工具、等工具,方便用于DNS排错,yaml脚本如下:
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
deployment.kubernetes.io/revision: "1"
labels:
app: busybox
name: busybox
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: busybox
template:
metadata:
creationTimestamp: null
labels:
app: busybox
spec:
containers:
- command:
- sleep
- "3600"
image: busybox:1.28.3 # 注意镜像版本,1.28.4有问题,不能正常进行DNS解析
imagePullPolicy: IfNotPresent
name: busybox