• 采坑指南——k8s域名解析coredns问题排查过程


    采坑指南——k8s域名解析coredns问题排查过程

     

    正文

    前几天,在ucloud上搭建的k8s集群(搭建教程后续会发出)。今天发现域名解析不了。

    组件版本:k8s 1.15.0,coredns:1.3.1

    过程是这样的:

    首先用以下yaml文件创建了一个nginx服务

    apiVersion: v1
    kind: Service
    metadata:
      name: nginx-svc-old
      labels:
        app: nginx-svc
    spec:
      selector:
        app: nginx
      ports:
      - protocol: TCP
        port: 80
        targetPort: 80
    ---
    apiVersion: apps/v1beta1
    kind: Deployment
    metadata:
      name: nginx-old
    spec:
      replicas: 1
      template:
        metadata:
          labels:
            app: nginx
        spec:
          containers:
          - name: nginx
            image: nginx
            ports:
            - containerPort: 80
    

    创建好之后:
    image.png
    因只部署了一个master节点。在master宿主机上直接执行以下命令:

    nslookup nginx-svc-old.default.svc
    

    image.png
    发现不能解析域名。事先也在宿主机上/etc/resolv.conf里配置了nameserver {coredns的podIP}
    image.png
    这样一来,就以为可能是coredns有问题。。

    然后用以下yaml创建了一个busybox作为调试工具:

    apiVersion: extensions/v1beta1
    kind: Deployment
    metadata:
      name: busybox-deployment
    spec:
      replicas: 1
      template:
        metadata:
          labels:
            app: busybox
        spec:
          restartPolicy: Always
          containers:
          - name: busybox
            command:
            - sleep
            - "3600"
            image: busybox
    

    这里用的是截止2019/07/20,busybox的最新镜像。创建好之后,exec进入容器,执行测试命令
    image.png
    发现解析不了:

    / # nslookup nginx-svc-old.default.svc
    Server:    10.96.0.10
    Address:  10.96.0.10:53
    
    ** server can't find nginx-svc-old.default.svc: NXDOMAIN
    
    *** Can't find nginx-svc-old.default.svc: No answer
    

    根据coredns解析集群内域名原理可知:

    服务 a 访问服务 b,对于同一个 Namespace下,可以直接在 pod 中,通过 curl b 来访问。对于跨 Namespace 的情况,服务名后边对应 Namespace即可,比如 curl b.default。DNS 如何解析,依赖容器内 resolv 文件的配置。

    查看busybox容器内的resolve.conf文件:

    
    [root@liabio nginx]# kubectl exec -ti busybox-deployment-59755c8c6d-rmrfq sh
    / # nslookup nginx-svc-old.default.svc
    Server:    10.96.0.10
    Address:  10.96.0.10:53
    
    ** server can't find nginx-svc-old.default.svc: NXDOMAIN
    
    *** Can't find nginx-svc-old.default.svc: No answer
    
    / # cat /etc/resolv.conf 
    nameserver 10.96.0.10
    search default.svc.cluster.local svc.cluster.local cluster.local
    options ndots:5
    / #
    

    这个文件中,配置的 DNS Server,一般就是 K8S 中,kubedns 的 Service 的 ClusterIP,这个IP是虚拟IP,无法ping,但可以访问。
    image.png
    在容器内发请求时,会根据 /etc/resolv.conf 进行解析流程。选择 nameserver 10.96.0.10 进行解析,然后用nginx-svc-old ,依次带入 /etc/resolve.conf 中的 search 域,进行DNS查找,分别是:

    search 内容类似如下(不同的pod,第一个域会有所不同)

    search default.svc.cluster.local svc.cluster.local cluster.local
    
    nginx-svc-old.default.svc.cluster.local -> nginx-svc-old.svc.cluster.local -> nginx-svc-old.cluster.local 
    

    直到找到为止。所以,我们执行 ping nginx-svc-old,或者执行 ping nginx-svc-old.default,都可以完成DNS请求,这2个不同的操作,会分别进行不同的DNS查找步骤。

    根据以上原理,查看到busybox内的域名/etc/resolv.conf没有问题,nameserver指向正确的kube-dns的service clusterIP。

    这下更加怀疑core-dns有问题了。

    但查看coredns日志,可以看到并没有报错:
    image.png
    那就说明不是coredns问题了。。

    把busybox里报的错误,进行搜索google

    *** Can't find nginx-svc-old.default.svc: No answer
    

    image.png

    查到了以下两个issue:

    issues1:

    https://github.com/kubernetes/kubernetes/issues/66924
    image.png

    issues2:

    https://github.com/easzlab/kubeasz/issues/260
    image.png
    发现都说是busybox镜像的问题,从1.28.4以后的镜像都存在这问题。把镜像换成1.28.4试试?修改yaml版本号:

    apiVersion: extensions/v1beta1
    kind: Deployment
    metadata:
      name: busybox-deployment
    spec:
      replicas: 1
      template:
        metadata:
          labels:
            app: busybox
        spec:
          restartPolicy: Always
          containers:
          - name: busybox
            command:
            - sleep
            - "3600"
            image: busybox:1.28.4
    

    重新apply后,进入容器:
    image.png

    确实可以成功解析域名了。

    那为什么宿主机上直接执行测试命令,域名不能解析呢?
    image.png

    继续google,知道resolver域名解析器:

    nameserver关键字,如果没指定nameserver就找不到DNS服务器,其它关键字是可选的。nameserver表示解析域名时使用该地址指定的主机为域名服务器。其中域名服务器是按照文件中出现的顺序来查询的,且只有当第一个nameserver没有反应时才查询下面的nameserver,一般不要指定超过3个服务器。
    而我在宿主上/etc/resolv.conf中nameserver如下:
    image.png
    且前三个域名解析服务器后可以通。

    现在试着把coredns的其中一个podIP:192.168.155.73放到第一个nameserver:
    image.png
    可以看到现在可以解析了。

    其实最好把kube-dns service的clusterIP放到/etc/resolv.conf中,这样pod重启后也可以解析。
    image.png

    参考

    Linux中/etc/resolv.conf文件简析
    https://blog.csdn.net/lcr_happy/article/details/54867510

    CoreDNS系列1:Kubernetes内部域名解析原理、弊端及优化方式

    https://hansedong.github.io/2018/11/20/9/

  • 相关阅读:
    第07组 Beta冲刺(2/5)
    第07组 Beta冲刺(1/5)
    第07组 Alpha事后诸葛亮
    第07组 Alpha冲刺(6/6)
    【Beta】软件使用说明——致社长
    【Beta】“北航社团帮”发布声明——小程序v2.0与网页端v1.0
    【Beta】“北航社团帮”测试报告——小程序v2.0与网页端v1.0
    [技术博客] 小程序扫码登录网页端原理
    [技术博客] 用户验证码验证机制---redis缓存数据库的使用
    [技术博客] 如何避免在代码中多重render
  • 原文地址:https://www.cnblogs.com/Python-K8S/p/14302745.html
Copyright © 2020-2023  润新知