最近一直没有更新 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
2
3
4
$ ping pod-1
PING pod-1 (10.105.44.235): 56 data bytes
64 bytes from 10.105.44.235: seq=0 ttl=64 time=0.187 ms
64 bytes from 10.105.44.235: seq=1 ttl=64 time=0.056 ms

可以看到解析到了对应 pod 的 ip。ping 还不够清楚,我们用 traceroute 来看看。

1
2
3
$ traceroute pod-1
traceroute to pod-1 (10.105.44.235), 30 hops max, 46 byte packets
1 pod-1.pod1-namepsace.svc.cluster.local (10.105.44.235) 0.018 ms 0.024 ms 0.014 ms

可以非常清楚的看到,先被解析到了 pod-1.pod1-namepsace.svc.cluster.local 这样一个地址。你这个地址是哪里来的呢?那就要问问 DNS 了。

1
2
3
4
$ cat /etc/resolv.conf
nameserver 10.96.0.10
search pod1-namepsace.svc.cluster.local svc.cluster.local cluster.local
options ndots:5

可以看到我们的域名服务 nameserver 10.96.0.10 并且会尝试搜索下面 search 的名字,举例来说:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ nslookup pod-1
Server: 10.96.0.10
Address: 10.96.0.10:53

** server can't find pod-1.cluster.local: NXDOMAIN

** server can't find pod-1.cluster.local: NXDOMAIN

** server can't find pod-1.svc.cluster.local: NXDOMAIN


** server can't find pod-1.svc.cluster.local: NXDOMAIN

Name: pod-1.pod1-namespace.svc.cluster.local
Address: 10.105.44.235

关键来了 10.96.0.10 是个什么服务呢?

CoreDNS

然后我们就可以去 kube-system 的 namespace 下找找这样的 service ,于是乎你就会发现有一个 kube-dns 的 service 它的 clusterIP 就是 10.96.0.10 我们在 resolv.conf 里面看到的这个。那么它对应的 pod 服务也就是我们的 coreDNS 了。通过

1
2
labels:
k8s-app: kube-dns

关联上了。

总结

其实总的链路并不复杂:

  1. 域名
  2. 查看 /etc/resolv.conf 找到了 DNS 服务器
  3. 访问服务器也就是 CoreDNS 服务
  4. 服务返回了对应 DNS 的 ip 记录
  5. 最终通过 ip 访问到服务

这就是 k8s pod 之间是通过 DNS 访问的链路了。理解了它,无论是使用还是排查相信都能帮助到你。