k8s DNS的研究与实践

背景

一直对于k8s的dns机制不甚了解, 借此机会彻底搞懂.
主要参照文章 KubeDNS 和 CoreDNS 进行个人消化.

总结

容器内部DNS配置

明白了容器内部/etc/resolv.conf的含义:

$ cat /etc/resolv.conf
search default.svc.cluster.local svc.cluster.local cluster.local
nameserver 192.168.0.10
options ndots:5

本质上会:

  1. 根据传入的域名
  2. 当查询的域名中包含的 . 的数量少于 options.ndots 的值时,会依次拼接search列表中的每个值
  3. 逐个尝试拼接后缀
  4. 向nameserver发送解析请求
  5. 如果 search 走完了都没有找到, 那么就会使用原域名进行查找

例如

  1. 同个namesapce下:
-- 在host上执行, 看到有如下svc
[root@iZ2ze8h8q419hf1fze66dkZ ~]$ k get svc
NAME            TYPE        CLUSTER-IP        EXTERNAL-IP   PORT(S)             AGE
nginx-service   ClusterIP   192.168.198.117   <none>        80/TCP              19d
-- 登录default namespace上某个pod内部执行如下命令, 
-- 1. 直接通过clusterIP访问, 则不经过DNS, 可以访问通
$ curl 192.168.198.117:80
<!DOCTYPE html>
<html>
</html>

-- 2. 通过svc name访问, 则经过DNS, 可以访问通, 底层其实经过一次拼接, 完整域名是: nginx-service.default.svc.cluster.local
$ curl nginx-service:80
<!DOCTYPE html>
<html>
</html>

-- 3. 通过svc 完整访问, 则经过DNS, 可以访问通, 底层不经过拼接, 完整域名是: nginx-service.default.svc.cluster.local
$ curl nginx-service.default.svc.cluster.local:80
  1. 跨namesapce:
-- 在host上执行, 查看 kube-system namespace下的svc
[root@iZ2ze8h8q419hf1fze66dkZ ~]$ k get svc -n kube-system
NAME                                 TYPE           CLUSTER-IP        EXTERNAL-IP     PORT(S)                      AGE
heapster                             ClusterIP      192.168.32.77     <none>          80/TCP                       272d
-- 登录default namespace上某个pod内部执行如下命令, 
-- 1. 直接通过clusterIP访问, 则不经过DNS, 可以访问通
$ curl 192.168.32.77:80
404 page not found

-- 2. 通过svc不带namespace的name访问, 则经过DNS, 访问不通, 底层其实经过一次拼接, 完整域名是: heapster.default.svc.cluster.local 访问不通
$ curl heapster:80
curl: (6) Could not resolve host: heapster

-- 3. 通过svc带namespace的name访问, 则经过DNS, 访问通, 底层其实经过2次拼接, heapster.kube-system.default.svc.cluster.local 访问不通, heapster.kube-system.svc.cluster.local 访问通了
$ curl heapster.kube-system:80
404 page not found

-- 4. 通过svc带namespace的完整域名访问, 则经过DNS, 访问通, 底层不经过拼接
$ curl heapster.kube-system.svc.cluster.local:80
404 page not found

容器内部DNS配置的生成

容器内部/etc/resolv.conf:

$ cat /etc/resolv.conf
search default.svc.cluster.local svc.cluster.local cluster.local
nameserver 192.168.0.10
options ndots:5
  • nameserver 192.168.0.10 记录是如何生成的?
  • 本质上 192.168.0.10 是dnssvc的clusterIp:
[root@iZ2ze8h8q419hf1fze66dkZ ~]$ k get svc -n kube-system
NAME                                 TYPE           CLUSTER-IP        EXTERNAL-IP     PORT(S)                      AGE
kube-dns                             ClusterIP      192.168.0.10      <none>          53/UDP,53/TCP,9153/TCP       272d
  • nameserver 192.168.0.10 记录是何时生成的?
  • 是在创建pod时, 由kubelet注入pod内部

// TODO: 是如何注入pod内部的?
// TODO: pod内部访问公网, 是如何实现的? 如何禁止pod内部访问公网?