k8s 集群中 nodelocaldns 造成 coredns hosts 插件失效
在实际环境中根据需求可能需要做些假域名映射到本地 ip, 查看 coredns 文档, 发现可以用如下方式来设置 hosts 到 ip 的映射
.:53 {
errors
health
ready
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
upstream /etc/resolv.conf
fallthrough in-addr.arpa ip6.arpa
}
hosts {
192.168.223.111 test.xxx.com
fallthrough
}
prometheus :9153
forward . /etc/resolv.conf {
prefer_udp
}
cache 30
loop
reload
loadbalance
}
但是如果集群中安装了 nodelocaldns 插件的话会不成功
nodelocaldns 简介
NodeLocal DNSCache 通过在集群上运行一个dnsCache daemonset来提高clusterDNS性能和可靠性。在ACK集群上的一些测试表明:相比于纯coredns方案,nodelocaldns + coredns方案能够大幅降低DNS查询timeout的频次,提升服务稳定性。
nodelocaldns通过添加iptables规则能够接收节点上所有发往169.254.20.10的dns查询请求,把针对集群内部域名查询请求路由到coredns;把集群外部域名请求直接通过host网络发往集群外部dns服务器。
原因分析
之所以 coredns 的 hosts 插件不起作用, 是因为集群 pod 使用的 dns 是 169.254.20.10, 也就是请求 nodelocaldns,而 nodelocaldns 配置的 forward 如下
Corefile: |
cluster.local:53 {
errors
cache {
success 9984 30
denial 9984 5
}
reload
loop
bind 169.254.25.10
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 . /etc/resolv.conf
prometheus :9253
}
10.233.0.3 为 coredns 的 service ip, 所以集群内部域名会转发给 coredns, 而非集群内部域名会转发给 /etc/resolv.conf, 根本就不会转发给 coredns, 所以 coredns 里面配置的 hosts 自然不会生效
直接在 nodelocaldns 中配置 rewrite 与 hosts ,结果发现 nodelocaldns 镜像集成的 coredns 版本不支持这 2 个插件(plugin)
解决方案
方法一
参考:https://github.com/coredns/coredns/issues/3298
修改 nodelocaldns 配置:kubectl edit configmap nodelocaldns -n kube-system # 这里的 configmap 名称不一定就是 nodelocaldns,要看你部署时的设置而定
从:
.:53 {
errors
cache 30
reload
loop
bind 169.254.25.10
forward . /etc/resolv.conf
prometheus :9253
}
变更为:
.:53 {
errors
cache 30
reload
loop
bind 169.254.25.10
forward . 10.233.0.3 {
force_tcp
}
prometheus :9253
}
- 10.233.0.3 为集群 coredns svc 地址
然后重启nodelocaldns(重启节点上的 docker 容器或者 kubectl 删除 pod)
方法二
手动搭建一个 dns 服务器, 在自己搭建的 dns 服务器里面配置映射, 参考:https://hub.docker.com/r/jpillora/dnsmasq
先创建 /opt/dnsmasq.conf 文件
#dnsmasq config, for a complete example, see:
# http://oss.segetech.com/intra/srv/dnsmasq.conf
#log all dns queries
log-queries
#dont use hosts nameservers
no-resolv
#use cloudflare as default nameservers, prefer 1^4
server=223.5.5.5
server=8.8.8.8
strict-order
#serve all .company queries using a specific nameserver
# server=/company/10.0.0.1
#explicitly define host-ip mappings
address=/myhost.company/10.0.0.2
address=/myhost1.company/10.0.0.3
启动容器
docker run --name dnsmasq -d -p 172.16.13.14:53:53/udp -p 5380:8080 -v /opt/dnsmasq.conf:/etc/dnsmasq.conf --log-opt "max-size=100m" -e "HTTP_USER=admin" -e "HTTP_PASS=admin" --restart always jpillora/dnsmasq
然后修改各节点上的 dns 配置为我们搭建的 dns 服务, 最后使用 kubectl 删除 nodelocaldns pod,让 k8s 重建 nodelocaldns