DNS

Linux上通过/etc/resolv.conf文件可以配置DNS相关信息,该文件是resovler类库所使用的配置文件,每当通过域名访问其他主机时,该类库会将域名转换为对应的IP,然后才可以进行访问。

resolv.conf 配置

nameserver 该选项用来配置DNS服务器地址,可以指定多个DNS

domain 该选项用来指定本地的域名,没有配置search的情况下,search默认使用的为domain的值

search 用来指定多个域名,用空格分隔。当访问的域名无法被DNS服务器解析时,resolver会将该域名后加上search指定的值,重新请求DNS,直到被正确解析或者列表循环结束。

nslookup

默认的超时时间为15s左右。

没有配置nameserver

在没有配置任何DNS的情况下,解析域名失败,返回如下错误:

$ nslookup baidu.com
;; connection timed out; no servers could be reached

配置nameserver

$ cat /etc/resolv.conf
nameserver 8.8.8.8
$ nslookup baidu.com
Server:         8.8.8.8
Address:        8.8.8.8#53

Non-authoritative answer:
Name:   baidu.com
Address: x.x.x.x
Name:   baidu.com
Address: y.y.y.y

如果没有解析域名成功会有如下信息:

$ nslookup aaa.bbb.ccc
Server:         8.8.8.8
Address:        8.8.8.8#53

** server can't find aaa.bbb.ccc: NXDOMAIN

DNS常见记录类型

  • A:指定域名对应的IP地址

  • AAAA:将域名解析到指定的IPv6的IP地址上

  • CNAME:别名解析。将注册的不同域名转到同一个域名记录上,由这个域名进行统一解析管理。

  • NS:域名服务器记录,用来指定该域名由哪个DNS服务器进行解析。

  • PTR:反向DNS,用于将IP地址映射到对应主机名。即通过IP查询对应的域名。

工作原理

dns工作原理

  1. 本地的DNS客户端向resolver发送域名(example.me)解析请求;
  2. resolver向根DNS服务器请求顶级域名DNS服务的地址;
  3. 拿到顶级域名me.的DNS服务地址后,向顶级DNS服务请求example.me域名解析的服务;
  4. 得到该域名的服务后,可以拿到该域名对应的IP地址,之后可以进行通信。

DNS resolver有两种DNS查询方式:

  • 迭代查询:每个DNS服务返回另外一台DNS服务的位置,客户端依次询问不同级别的DNS服务,直到查询到了想要的结果。

  • 递归查询:DNS服务收到客户端的请求之后,会直接返回准确的结果,如果当前DNS服务没有存储该结果,会自己访问其他的DNS服务,并将结果返回给客户端。

域名层级关系

域名层级

CoreDNS

Corefile

apiVersion: v1
data:
  Corefile: |
    .:53 {
        errors
        health
        kubernetes cluster.local in-addr.arpa ip6.arpa {
           pods insecure
           upstream
           fallthrough in-addr.arpa ip6.arpa
        }
        prometheus :9153
        proxy . /etc/resolv.conf
        cache 30
        reload
    }    
kind: ConfigMap
metadata:
  name: coredns
  namespace: kube-system

集群内部pod通过service来进行访问的时候,采用的是域名方式,会根据容器里的/etc/reslov.conf文件内容进行DNS解析。

alpine的容器进行DNS解析

设置CoreDNS所在宿主机的DNS nameserver为一个无法ping通的地址(192.168.100.200)。

使用下面的yaml创建一个用于测试的Pod,访问我们自己的一个在kube-system的命名空间下的服务k8s-keystone-auth

apiVersion: v1
kind: Pod
metadata:
  name: alpine
spec:
  containers:
  - name: alpine
    image: alpine:3.6
    command:
      - sleep
      - "3600"
    imagePullPolicy: IfNotPresent
  restartPolicy: Always
$ kubectl get pod
NAME              READY     STATUS    RESTARTS   AGE
alpine            1/1       Running   0          54m

查看该Pod的/etc/resolv.conf内容如下:

 $ kubectl exec alpine -- cat /etc/resolv.conf
nameserver 10.96.0.10
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5

在直接访问k8s-keystone-auth这个服务的时候,因为该服务和当前Pod不在同一个命名空间,因此会导致DNS解析失败,而且出现超时的情况。

$ kubectl exec busybox -- nslookup k8s-keystone-auth
nslookup: can't resolve 'k8s-keystone-auth': Try again

CoreDNS的日志信息:

2019/06/06 17:53:29 [ERROR] 2 k8s-keystone-auth. AAAA: unreachable backend: read udp 10.120.25.14:58391->192.168.100.200:53: i/o timeout
2019/06/06 17:53:29 [ERROR] 2 k8s-keystone-auth. A: unreachable backend: read udp 10.120.25.14:46773->192.168.100.200:53: i/o timeout
2019/06/06 17:53:31 [ERROR] 2 k8s-keystone-auth. A: unreachable backend: read udp 10.120.25.14:56768->192.168.100.200:53: i/o timeout
2019/06/06 17:53:31 [ERROR] 2 k8s-keystone-auth. AAAA: unreachable backend: read udp 10.120.25.14:33867->192.168.100.200:53: i/o timeout

在访问k8s-keystone-auth.kube-system的时候,因为指定了命名空间,因此会导致DNS解析成功,CoreDNS的日志无超时或错误信息。

$ kubectl exec busybox -- nslookup k8s-keystone-auth.kube-system
Name:      k8s-keystone-auth.kube-system
Address 1: 10.99.215.79 k8s-keystone-auth.kube-system.svc.cluster.local

nameserver不通,访问集群内部服务

如果在/etc/resolv.conf文件中配置了nameserver,并且nameserver无法连通,会导致集群内部所有域名解析超时,超时时间为15s。

$ kubectl exec -it busybox -- nslookup kubernetes.default
;; connection timed out; no servers could be reached
2019/06/06 09:34:56 [ERROR] 2 kubernetes.default. AAAA: unreachable backend: read udp 10.120.25.5:55430-><nameserver>:53: i/o timeout

如果nameserver不通,此时访问集群内部服务使用<my-svc>.<namespace>.svc.cluster.local的方式可以解析成功。如下示例:

$ kubectl exec -it busybox -- nslookup k8s-keystone-auth-service.kube-system.svc.cluster.local
Server:    10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local

Name:      k8s-keystone-auth-service.kube-system.svc.cluster.local
Address 1: 10.99.215.79 k8s-keystone-auth-service.kube-system.svc.cluster.local

注意事项

  • Linux限制DNS nameserver为3条记录,DNS search为6条记录,因为Kubernetes要使用1个nameserver和3个search记录,因此本地设置DNS的话需要注意

  • Alpine镜像小于3.3版本,对于DNS解析可能存在问题,因此建议使用更高级的版本

参考文档

https://kubernetes.io/docs/tasks/administer-cluster/dns-debugging-resolution/

https://kubernetes.io/docs/tasks/administer-cluster/dns-custom-nameservers/#coredns

https://blog.csdn.net/luanpeng825485697/article/details/84108166

https://github.com/coredns/coredns/issues/2287