1 典型的数据传输流程图
• 一个外部的business-manager请求,首先进入集群的入口(ingress),ingress反向代理后负载到business-manager的service。Service层再负载到某个node下的具体的business-manager pod
• Business-manager pod再将请求发往data-product的service,同理,service层继续随机选择一个data-product的Pod来接收请求
• 上面这个请求,涉及到容器的网络-docker0、跨主机通讯-flannel网络方案、ingress和service组件,以及DNS等,下面我会挨个介绍它们的基本原理。
2 3种ip说明
写这个文档的同时,我在虚拟机上搭建了一个K8S环境,集群内包含2台主机,ip分别为192.168.0.21和192.168.0.22,主要组件为ingress->nginx、service->kube-proxy、网络->flannel,我们以这个集群为例进行分析。
在深入之前,我们先科普一下K8S集群内常见IP的含义:
# kubectl get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE
business-manager-666f454f7f-bg2bt 1/1 Running 0 153m 172.30.76.4 192.168.0.21
business-manager-666f454f7f-kvn5z 1/1 Running 0 153m 172.30.76.5 192.168.0.21
business-manager-666f454f7f-ncjp7 1/1 Running 0 153m 172.30.9.4 192.168.0.22
data-product-6664c6dcb9-7sxnz 1/1 Running 0 160m 172.30.76.2 192.168.0.21
data-product-6664c6dcb9-j2f48 1/1 Running 0 160m 172.30.76.3 192.168.0.21
data-product-6664c6dcb9-p5xkw 1/1 Running 0 160m 172.30.9.3 192.168.0.22
Node ip:宿主机的ip,由路由器分配。上图最右边的NODE列代表的就是容器所在的宿主机的物理ip,可以看到现在集群内2台主机都有分配容器。
Pod ip:被docker0网桥隔离的pod子网的ip。K8s在每个Node里虚拟出的局域网。上图的IP列,就是每个pod ip,可以看到同一宿主机下Pod在同网段(后面我会介绍不同的node下的Pod,是如何借助flannel来实现跨主机通讯的)
# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
business-manager ClusterIP 10.254.80.22 <none> 80/TCP 156m
data-product ClusterIP 10.254.116.224 <none> 50051/TCP 159m
kubernetes ClusterIP 10.254.0.1 <none> 443/TCP 5h8m
Cluster ip:k8s分配给每个service的全局唯一的虚拟ip,也可以叫VIP。VIP没有挂接到网络设备,不能直接访问。(后面会介绍这个ip的用处)
除了上面的3个主要ip,集群里还有其他的一些特定的ip和网段:
• DNS服务器:这里配置的是10.254.0.2:53
• 10.254.0.0/16网段,是可配置的当前集群的网段,DNS和service的虚拟Ip正是处在这个网段里。
3 Docker0网桥和flannel网络方案
在介绍Ingress和service这两个组件之前,我们先简单了解一下k8s节点之间的底层网络原理及典型的flannel-VXLAN方案。后面的章节,默认在节点之间的传输,都会有docker0网桥和flannel插件的功劳。(有资料提到K8S采用cni0网桥替代了docker0网桥,两者的原理是一样的,我搭建的环境里只有docker0网桥,所以我们按docker0来分析)
# kubectl get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE
business-manager-666f454f7f-7l86b 1/1 Running 1 11m 172.30.76.7 192.168.0.21
business-manager-666f454f7f-h5tvw 1/1 Running 1 11m 172.30.76.6 192.168.0.21
business-manager-666f454f7f-zxmsx 1/1 Running 0 8s 172.30.9.3 192.168.0.22
data-product-6664c6dcb9-4zk27 1/1 Running 1 11m 172.30.76.5 192.168.0.21
data-product-6664c6dcb9-7bn7p 1/1 Running 1 11m 172.30.76.3 192.168.0.21
data-product-6664c6dcb9-tkmms 1/1 Running 0 5m39s 172.30.9.2 192.168.0.22
大家注意到没有,每个pod具备不同的Ip(这里指k8s集群内可访问的虚拟ip),不同node下的pod甚至在不同的网段。那么问题来了,集群内不同IP、不同网段的节点是怎么实现通讯的呢?这样归功于docker0和flannel.1这两个虚拟网络设备,我们先ifconfig查看一下:
# ifconfig
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1450
inet 172.30.76.1 netmask 255.255.255.0 broadcast 172.30.76.255
inet6 fe80::42:67ff:fe05:b530 prefixlen 64 scopeid 0x20<link>
ether 02:42:67:05:b5:30 txqueuelen 0