1. 博客/

Coredns 出现间断性无法正常解析域名问题

·1536 字·4 分钟· ·
k8s coredns dns
Johny
作者
Johny
熟练的 云原生搬砖师
Table of Contents

问题描述:
#

Kubernetes 节点中,有一台节点使用 coredns 进行解析某个域名时,出现间断性无法正常解析问题,而解析另外一个域名时不会出现解析问题。

再次重复一下问题重点: 且在集群中的某台节点中出现,且使用某个域名时出现

环境说明:
#

  • 操作系统: CentOS Linux release 7.9.2009
  • Kubernetes 集群: v1.17.4 (集群使用 rancher 自定义添加集群 一键部署)
  • Dashboard: Rancher-v2.3.5
  • Linux Kernel: 5.10.3-1.el7.elrepo.x86_64
  • Coredns : Coredns:1.6.5 + Node-local-dns

工具说明
#

  • 测试时使用的容器: praqma/network-multitool:latest

  • 测试时使用的dns 测试工具 : coredns-tools.go

    程序出自 Blog

    package main
    
    import (
    	"context"
    	"flag"
    	"fmt"
    	"net"
    	"sync/atomic"
    	"time"
    )
    
    var host string
    var connections int
    var duration int64
    var limit int64
    var timeoutCount int64
    
    func main() {
    	// os.Args = append(os.Args, "-host", "www.baidu.com", "-c", "200", "-d", "30", "-l", "5000")
    
    	flag.StringVar(&host, "host", "", "Resolve host")
    	flag.IntVar(&connections, "c", 100, "Connections")
    	flag.Int64Var(&duration, "d", 0, "Duration(s)")
    	flag.Int64Var(&limit, "l", 0, "Limit(ms)")
    	flag.Parse()
    
    	var count int64 = 0
    	var errCount int64 = 0
    	pool := make(chan interface{}, connections)
    	exit := make(chan bool)
    	var (
    		min int64 = 0
    		max int64 = 0
    		sum int64 = 0
    	)
    
    	go func() {
    		time.Sleep(time.Second * time.Duration(duration))
    		exit <- true
    	}()
    endD:
    	for {
    		select {
    		case pool <- nil:
    			go func() {
    				defer func() {
    					<-pool
    				}()
    				resolver := &net.Resolver{}
    				now := time.Now()
    				_, err := resolver.LookupIPAddr(context.Background(), host)
    				use := time.Since(now).Nanoseconds() / int64(time.Millisecond)
    				if min == 0 || use < min {
    					min = use
    				}
    				if use > max {
    					max = use
    				}
    				sum += use
    				if limit > 0 && use >= limit {
    					timeoutCount++
    				}
    				atomic.AddInt64(&count, 1)
    				if err != nil {
    					fmt.Println(err.Error())
    					atomic.AddInt64(&errCount, 1)
    				}
    			}()
    		case <-exit:
    			break endD
    		}
    	}
    
    	fmt.Printf("request count:%d\nerror count:%d\n", count, errCount)
    	fmt.Printf("request time:min(%dms) max(%dms) avg(%dms) timeout(%dn)\n", min, max, sum/count, timeoutCount)
    }
    

    工具编译

    export CGO_ENABLED=0
    export GOOS=linux
    export GOARCH=amd64
    go build coredns-tools.go
    
  • 使用文件分享工具: nginx

    配置文件如下所示:

cat /usr/local/etc/nginx/nginx.conf  # 且截取部分配置
server {
    listen 188;
    server_name _;
    charset utf-8;

    location / {
        root /Users/zun/Downloads;
        autoindex on;
        autoindex_exact_size off;
        autoindex_localtime on;
    }
}

nginx # 启动

问题表现
#

 ./coredns-tools-linux -host sim-gtw.dt.com -c 200 -d 30 -l 5000

image-20210107115048562

我们可以看到, 我们使用dns测试程序进行测试时,测试结果接近有 61% 的解析失败率,而解析其他域名时解析是正常的

image-20210107142038042

排查结果
#

排查到结果与 Coredns 使用到的上层DNS 有关; 如下如截图所示中,使用同一个域名解析出来的地址, 一个是外网地址一个是内网地址,由此推断出解析域名时分别使用了不同dns server进行解析的。

image-20210107111557846

为了验证我们刚才的推断,我们在coredns 的 configmap 中开启 hosts 插件,并将相关域名写入其中。类似于主机中的 hosts文件,hosts文件优先于dns server,当拿到地址解析后客户端将不再继续请求上层dns server。

排查步骤如下:
#

步骤一:
#

kubectl edit cm coredns -n kube-system  # 编辑 coredns configmap 添加 hosts插件配置 (配置如下)

     hosts {
         192.168.1.105   dt.com
         192.168.1.106   sim-gtw.dt.com
         fallthrough
     }

步骤二:
#

修改完成后 等待 coredns pod 重新读取配置或手动删除 coredns 与之相关的 pod 进行重载

kubectl get pod -n kube-system |grep coredns|awk '{print $1}'|xargs -I {} kubectl delete pod {} --force -n kube-system

修改后的结果展示:
#

image-20210107112810631

重载配置完成后 我们再测试一下结果
#

wget http://192.168.121.110:188/coredns-tools-linux \
&& chmod a+x  coredns-tools-linux \
&& ./coredns-tools-linux -host sim-gtw.dt.com -c 200 -d 30 -l 5000 

image-20210107114813398

可以看到, 此时我们再进行测试时,域名解析已不再提示报错了。但是最大延迟显示还是显示有5s左右,这个和我们正在使用的kube-proxy策略有关,默认策略使用的是 iptables 模式,如后期优化可进行更改为性能更高的 ipvs模式 及部署 node-local-dns 服务来减少解析延迟,我这里无法更改 kubelet的启动参数中 dns的地址,貌似 node-local-dns 没有太多效果 。

解决问题
#

我们通过上面的测试验证了间断性域名解析失效,是由于上层dns造成;解决方法也非常简单,只需要更改 coredns 使其使用正确的上层dns即可。

更改 coredns 配置
#

同样我们需要更改一下 coredns 的 configmap 文件

kubectl edit cm coredns -n kube-system

更改后的 配置展示

apiVersion: v1
data:
  Corefile: |-
    .:53 {
        errors
        health {
          lameduck 5s
        }
        ready
        kubernetes cluster.local in-addr.arpa ip6.arpa {
          pods insecure
          fallthrough in-addr.arpa ip6.arpa
          ttl 600
        }
        prometheus :9153
        forward . 192.168.1.112 192.168.121.112
        cache 600
        loop
        reload
        loadbalance
    }    
....
# 省略部分配置

适当的增减了 cache 时间与 ttl 时间

更改node-local-cahce 配置
#

kubectl edit cm  node-local-dns -n kube-system  # 编辑 node-local-dns 修改参数

更改后的配置展示:

    ip6.arpa:53 {
        errors
        cache 30
        reload
        reload
        loop
        bind 169.254.20.10 10.43.0.10
        forward . __PILLAR__CLUSTER__DNS__ {
                force_tcp
        }
        prometheus :9253
        }
    .:53 {
        errors
        cache 30
        reload
        loop
        bind 169.254.20.10 10.43.0.10
        forward . __PILLAR__CLUSTER__DNS__ {
            force_tcp
        }
        prometheus :9253
        }
....
# 省略部分配置

更改完成后,继续等待 coredns 相关pod重载配置。 或手动重载。

kubectl get pod -n kube-system |grep coredns|awk '{print $1}'|xargs -I {} kubectl delete pod {} --force -n kube-system

参考文档及博客:
#

Coredns Kubernetes 相关文档

CoreDNS 自定义域名失效

部署 Nodelocaldns 解决 Coredns 域名解析延迟

总结:
#

原生的coredns功能方面还是存在某些不完善及兼容性的问题,不过我们可以使用第三方扩展来进行解决。目前coredns主要出现问题的地方在于: 内核的版本、网络插件兼容、5s超时问题,而五秒超时问题我们可以通过升级内核版本及部署 node-local-dns 应用在每个节点中增加缓存解决。

相关文章

kubernetes 集群中 控制平面 组件频繁发生重启的问题排查记录
·688 字·2 分钟·
k8s coredns flannel fix
部署 Nginx-Ingress 并配置暴露 kubernetes dashboard
·661 字·2 分钟·
k8s ingress helm dashboard
Kubeadm 部署 kubernetes-v1.19.x 集群
·2153 字·5 分钟·
k8s kubeadm v1.19.x install
Kind 部署本地k8s集群的使用记录
·326 字·1 分钟·
k8s docker devops centos7 kind
使用 Docker 部署 Nexus3 私服的详细记录总结
·2798 字·6 分钟·
docker devops nexus3 install
部署 Devops 必备利器 OpenLdap
·953 字·2 分钟·
devops openldap centos7