k8s pod 之间是如何通过 DNS 访问的
最近一直没有更新 k8s 源码的部分是因为看到这部分的时候发现对于 service 的一些细节还并不是非常的清晰,所以从原理的角度上来看有的地方不是特别好解释清楚。所以需要先补充一些小细节以帮助消化。嗯,这是一个非常让人同情的拖更理由了。
我之前有写过 K8S 之跨主机通信 是深入到了 ip 包内部的路由,但是回过头发现好像没有记录从应用层的流转是如何做的。也就是说,在 k8s 内部,pod1 访问 pod2 可以如何进行访问呢?这里面的链路是怎么走的呢?其实非常简单,让我们今天一起来看看。
如何访问
首先,k8s 官方文档中给出了访问的方式。
相同的 namespace 下
在相同的 namespace 下,我们可以很容易的通过对应 pod 的 service 的 name 来访问,比如 pod1 的 service 的 name 是 pod1-service。我们就可以通过
1 | $ curl http://pod1-service:port/ |
来访问,其中端口就是 service 申明的 port
不同的 namespace 下
而如果两个 pod 在不同的 namespace 下,也简单,只需要加上 namespace 的名称就可以了。
1 | $ curl http://pod1-service.pod1-namespace:port/ |
其中 pod1-namespace 就是 pod1 所在的 namespace
为什么可以访问?
那么为什么通过一个简单的名字就可以访问了呢?
寻找路由
首先我们来看看路由,对于我们访问的整个 url 地址,那么端口前面的一定是域名了,也就是说在 k8s 内部可以对这样的域名做解析。
1 | $ ping pod-1 |
可以看到解析到了对应 pod 的 ip。ping
还不够清楚,我们用 traceroute
来看看。
1 | $ traceroute pod-1 |
可以非常清楚的看到,先被解析到了 pod-1.pod1-namepsace.svc.cluster.local
这样一个地址。你这个地址是哪里来的呢?那就要问问 DNS 了。
1 | $ cat /etc/resolv.conf |
可以看到我们的域名服务 nameserver 10.96.0.10
并且会尝试搜索下面 search
的名字,举例来说:
1 | $ nslookup pod-1 |
关键来了 10.96.0.10
是个什么服务呢?
CoreDNS
然后我们就可以去 kube-system 的 namespace 下找找这样的 service ,于是乎你就会发现有一个 kube-dns
的 service 它的 clusterIP 就是 10.96.0.10
我们在 resolv.conf 里面看到的这个。那么它对应的 pod 服务也就是我们的 coreDNS
了。通过
1 | labels: |
关联上了。
总结
其实总的链路并不复杂:
- 域名
- 查看
/etc/resolv.conf
找到了 DNS 服务器 - 访问服务器也就是 CoreDNS 服务
- 服务返回了对应 DNS 的 ip 记录
- 最终通过 ip 访问到服务
这就是 k8s pod 之间是通过 DNS 访问的链路了。理解了它,无论是使用还是排查相信都能帮助到你。