Kubernets解析-pod网络实现

35 阅读2分钟

Kubernets解析-pod网络实现

虽然k8s借助于docker实现虚拟化技术,但是pod的网络实现还是和docker的网络实现有些差距。dockers中基础单位就是单个容器,而k8s中以相关联的一组容器,也就是pod作为最小单位。以一个nginx容器为例

# kubectl run nginx --image=nginx --replicas=2 --port=8080 --hostport=80

查询所有容器可以看到一个pause状态的容器

$ docker ps
CONTAINER ID        IMAGE                                  COMMAND                CREATED             STATUS              PORTS               NAMES
f1a27680e401        busybox:latest                         "/bin/sh -c 'while t   6 seconds ago       Up 5 seconds                            k8s_log-truncator.72cfff7a_nginx-kx_default_419bc51e985b6bb5e53ea305e2c1e737_401a4c94   
c5e357fc981a        nginx:latest                           "nginx -g 'daemon of   6 seconds ago       Up 6 seconds                            k8s_nginx.515d0778_nginx-kx_default_419bc51e985b6bb5e53ea305e2c1e737_cd02602b           
b2692643c372        gcr.io/google_containers/pause:0.8.0   "/pause"               6 seconds ago       Up 6 seconds                            k8s_POD.ef28e851_nginx-kx_default_419bc51e985b6bb5e53ea305e2c1e737_836cadc7   

相信用过k8s的同学都不会陌生,每一个pod都会有这样一个pause状态的容器。进一步查询pause容器的详细信息可以发现,这个pause容器和nginx容器共享网络,相同容器之间的访问只需要用localhost+端口的形式。

$ docker inspect --format '{{ .NetworkSettings.IPAddress  }}' f1a27680e401

$ docker inspect --format '{{ .NetworkSettings.IPAddress  }}' c5e357fc981a

$ docker inspect --format '{{ .NetworkSettings.IPAddress  }}' b2692643c372
172.17.0.2

$ docker inspect --format '{{ .HostConfig.NetworkMode  }}' c5e357fc981a
container:b2692643c37216c3f1650b4a5b96254270e0489b96c022c9873ad63c4809ce93
$ docker inspect --format '{{ .HostConfig.NetworkMode  }}' f1a27680e401
container:b2692643c37216c3f1650b4a5b96254270e0489b96c022c9873ad63c4809ce93

现在再来看docker的网络实现。docker为每个容器分配一个ip,但是k8s中多个容器共享一个ip,如果仍然采用docker的网络实现则无法区分pod中不不同容器,所以k8s中pod有自己的网络实现,采用了一套Pod实现透明通信(without NAT)的机制。

flannel网络

flannel隧道网络实现,使得组网信息对pod间通信时透明,最终效果让所有pod认为自己在同一个局域网中。

假设有消息从k8s分配的虚拟ip 172.30.76.7发往172.30.9.2。首先通过route命令查看路由表

172.30.0.0      0.0.0.0         255.255.0.0     U     0      0        0 flanne

在路由表中172.30.0.0/16交由flannel处理。然后再查询ARP表

172.30.9.2 lladdr 96:8f:2d:49:c5:31 REACHABLE

再查询转发表(Forwarding Database entry), 转发表是 Linux 网桥维护的一个二层转发表,用于保存远端虚拟机/容器的 MAC地址,远端 VTEP IP,以及 VNI 的映射关系

# bridge fdb show flannel.1 |grep 96:8f:2d:49:c5:31
96:8f:2d:49:c5:31 dev flannel.1 dst 192.168.0.22 self permanent

linux主机将包发往物理ip 192.168.0.22 的主机。这里物理ip也就是k8s中node ip,而这里192.168.0.22这台主机也就是k8s中ip为172.30.9.2的container的宿主机B。查询B中路由表

172.30.9.0     0.0.0.0         255.255.255.0   U     0      0        0 docker0

可以看到发往172.30.9.0/8的包交由docker0网桥处理,通过docker0网桥将包转发给docker局域网中的具体container


参考文献

[1]: kubernetes从入门到放弃3--(网络原理)

[2]: 理解Kubernetes网络之Flannel网络

[3]: 《跟唐老师学习云网络》 - 什么是VLAN和VXLAN

[4]: What even is a kubelet?