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--(网络原理)