日期: July 22, 2022

K8s网络可按以下分类集群内部通信pod与pod通信(跨节点与非跨节点)pod内容器间的通信pod到service的通信集群内与集群外通信nodeport形式ingress形式loadblance形式


集群内部通信

1.pod与pod通信(非跨节点)

同一个node上的pod可以直接通过彼此的ip进行通信,它们通过veth(虚拟网络接口)连接到一个docker0网桥上,它们和docker0是同一个网段,并且在该node上的pod默认路由都是docker0的地址,发起通信时会默认发送到docker0网桥上,由网桥进行中转,完成通信

这里veth虚拟接口对的作用就是一端链接到宿主机的root网络命名空间,一端链接到pod内的网络空间,允许流量在两侧进行流动,相当于把pod内的ens网卡和宿主机上的veth虚拟网卡进行绑定

docker0网桥则维护一个转发表,实现veth0——>veth1数据的转发

所以同一个Node上pod间通信的流转情况为:

pod1上的eth0网卡——>宿主机veth1网卡(pod默认路由)——>docker0网桥(根据转发表)——>宿主机veth2网卡——>pod2上的eth0网卡

2.pod与pod通信(跨节点)

K8s本身没有实现网络规划的功能,它默认你已经把网络都规划好了,不过它提供了一套CNI接口规范,可以让大家开发网络插件,常见就是Flannel,Calico,这里就说下Flannel

借助Flannel,就可以使不同节点上的容器能够获得“同属一个内网”且”不重复的”IP地址,并让属于不同节点上的容器能够直接通过内网IP通信

具体是怎样实现的呢

在部署flannel的时候我们通过Network指定一个大网段,比如说10.244.0.0/16,然后每个节点上会分配一个子网段,就是flannel.1网卡的IP,比如说10.244.1.0,之后分配到这个节点上的pod的IP就会从这个子网段里分配,像10.244.1.10这样

Docker 0(网桥设备)

Docker 0获得的IP是分配的flannel.1子网段的第一个地址

node上每创建一个pod都会创建一对 veth pair。其中一端是pod中的eth0,另一端是docker 0网桥中的端口(网卡)。Pod从网卡eth0发出的流量都会发送到docker 0网桥设备的端口(网卡)上,这里和node内pod通信互相时是一样的

Flannel.1

overlay网络的设备,作用是进行 vxlan 报文的处理(封包和解包)。不同node之间的pod数据流量都从flannel.1以隧道的形式发送到对端

所以pod与pod跨节点通信的过程为

pod1(产生数据)——【根据pod的路由表】——docker 0——【根据node1的转发表】——flannel.1——【封装数据包】——node1的eth0—(读取ETCD,获得pod和所在节点的地址找到node2)—node2的eth0——node2的flannel.1——【解封数据包并根据路由表】——docker 0——pod2(收到)

image.png

pod与pod跨节点与非跨节点的通信,差别在于,非跨节点时直接使用的是docker0网桥,没有经过flannel.1网卡,因为两个pod都关联在同一个docker0网桥上

如何查看docker 0维护的转发表

brctl showmacs docker0

关于为何docker 0可以分配到flannel网卡网段的第一个IP

mk-docker-opts.sh

该脚本将分配给 flanneld 的 Pod 子网段信息写入 /run/flannel/docker 文件,后续 docker 启动时使用这个文件中的环境变量配置 docker0 网桥

默认在docker启动时自动调用这个脚本

我们可以手动生成docker启动要加载的环境变量文件

mk-docker-opts.sh -k DOCKER_NETWORK_OPTIONS -d /run/flannel/docker

3.pod内容器间的通信

見“关于kubernetes中的pause容器”

4.pod与service的clusterip通信

見“当在宿主机上访问pod的service的clusterIP时经历了什么”

集群外部与集群内部通信

1.nodeport形式

見“当外部访问nodeport时经历了什么”

2.ingress形式

3.loadblance形式