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