本文将基于Dockerd运行时来进行展开描述。
Docker容器内的resolv.conf
(这里以一个docker container为例来描述)
在节点上运行一个nginx container。
代码语言:txt复制$ docker run -d nginx:latest
da30536de35915abe1214a25e1c6278f95e5c8af157517ddefc5eaa1d3b36d93
在容器内执行findmnt。
代码语言:txt复制$ docker exec da30536de35915abe1214a25e1c6278f95e5c8af157517ddefc5eaa1d3b36d93 findmnt
...
|-/etc/resolv.conf /dev/vda1[/var/lib/docker/containers/da30536de35915abe1214a25e1c6278f95e5c8af157517ddefc5eaa1d3b36d93/resolv.conf] ext4 rw,noatime
|-/etc/hostname /dev/vda1[/var/lib/docker/containers/da30536de35915abe1214a25e1c6278f95e5c8af157517ddefc5eaa1d3b36d93/hostname] ext4 rw,noatime
`-/etc/hosts /dev/vda1[/var/lib/docker/containers/da30536de35915abe1214a25e1c6278f95e5c8af157517ddefc5eaa1d3b36d93/hosts] ext4 rw,noatime
...
可以看到,容器内的/etc/resolv.conf 是挂载到了宿主机文件上(/var/lib/docker/containers/da30536de35915abe1214a25e1c6278f95e5c8af157517ddefc5eaa1d3b36d93/resolv.conf)。
(进一步看下文件内容,会发现同节点上的/etc/resolv.conf 内容一致)
在Docker Container创建时,Docker会基于节点上的/etc/resolv.conf文件来生成容器所需的resolv.conf,生成的resolv.conf被放到了container的配置目录下(/var/lib/docker/contaienrs/...)。
另外,也可以通过如下命令查看某个Docker Container resolv.conf的真实源。
代码语言:txt复制$ docker inspect da30536de35915abe1214a25e1c6278f95e5c8af157517ddefc5eaa1d3b36d93 -f {{.ResolvConfPath}}
Pod内的resolv.conf
pod支持以下4种dnsPolicy:
- "Default": Pod 从运行所在的节点继承域名解析配置。
- "ClusterFirst": 默认的配置,所有请求会优先在集群所在域(比如cluster.local)查询,如果没有才会转发到上游DNS。
- "ClusterFirstWithHostNet":对于以 hostNetwork 方式运行的 Pod,应显式设置其 DNS 策略 "ClusterFirstWithHostNet";否则将从运行所在的节点上继承域名解析配置。
- "None": 允许用户单独给 Pod 配置DNS。
当pod调度到节点上之后,kubelet会来给pod配置具体的resolv.conf内容:
1 kubelet会先创建并运行pod的sandbox,然后获取到sandbox的ResolvConfPath(/var/lib/docker/containers/xxxxxxx/resolv.conf),接下来,把dns policy的具体内容写到sandbox的ResolvConfPath(直接覆盖写)。
2 kubelet继续创建同一个pod中的其他container,并且使用相同的ResolvConfPath(同一个pod的所有容器的ResolvConfPath在宿主机上的真实源是同一个)。
所以,可以看到,pod内的resolv.conf是pod在创建的时候就确定下来的。
DNS不通的案例
问题描述:
客户创建好集群之后,手动改了节点上的/etc/resolv.conf文件,将nameserver配置成自建的域名解析,导致在pod内(dnsPolicy是ClusterFirst)无法正常解析内部域名。
问题根因:
业务pod(dnsPolicy是ClusterFirst)会将DNS请求发送给集群中的Coredns,由于是内部域名,Coredns会转发请求到/etc/resolv.conf(coredns pod内部的resolv.conf),而不是Coredns pod实例所在节点上的resolv.conf,导致客户无法解析内部域名。
修复方案:
重建Coredns pod实例。