目录
1、K8S网络要求
2、网络链路
(1)Internet与Service之间的网络
1)node到internet的网络
2)Internet到node的网络
(2)Service与Pod之间的网络
2)service到pod包的流转
(3)Pod与Pod之间的网络
1)同一台node节点上pod和pod通信
2)不同node节点上pod和pod通信
(4)容器和容器之间的网络
1、K8S网络要求
(1)Pods与Pods之间、Nodes与Nodes之间可以在不使用NAT网络地址转换的情况下相互通信。
(2)每个Pod都拥有一个独立的 IP地址,且每个Pod自己看到的自己的ip和其他Pod看到的一致,即Pod内部的应用程序看到的自己的IP地址和端口与集群内其他Pod看到的一样。
(3)不论Pod是否运行在同一个Node中,他们都可以同归对方IP进行访问。
2、网络链路
(1)Internet与Service之间的网络
(2)Service与Pod之间的网络
(3)Pod与Pod之间的网络
(4)容器和容器之间的网络
(1)Internet与Service之间的网络
1)node到internet的网络
数据包源自pod1网络命名空间,通过veth对连接到root网络命名空间,紧接着,转发表里没有IP对应的mac,会发送到默认路由,到达root网络命名空间的eth0那么在到达root网络明明空间之前,iptables会修改数据包,现在数据包源ip是pod1的,继续传输会被Internet网关拒绝掉,因为网关NAT仅转发node的ip,解决方案:使iptables执行源NAT更改数据包源ip,让数据包看起来是来自于node而不是pod,iptables修改完源ip之后,数据包离开node,根据转发规则发给Internet网关,Internet网关执行另一个NAT,内网ip转为公网ip,在Internet上传输。
流程见下图:
2)Internet到node的网络
让Internet流量进入k8s集群,这特定于配置的网络,可以在网络堆栈的不同层来实现:NodePort、Service LoadBalancer、Ingress控制器。
客户端现针对www.1234.com执行dns解析,DNS服务器返回ingress控制器的ip,客户端拿到ip后,向ingress控制器发送http的get请求,将域名加在host头部发送。控制器接收到请求后,从host头部就知道了该访问哪一个服务,通过与该service关联的endpoint对象查询podIP地址,将请求进行转发。
(2)Service与Pod之间的网络
分析:
当集群中pod的规模缩减或者pod故障或者node故障重启后,新的pod的ip就可能与之前的不一样的,所以k8s中用Service来解决这个问题。Service管理了多个Pods,每个Service有一个虚拟的ip,要访问service管理的Pod上的服务只需要访问你这个虚拟ip就可以了,这个虚拟ip是固定的,当service下的pod规模改变、故障重启、node重启时候,对使用service的用户来说是无感知的,因为他们使用的service的ip没有变。原理:
当数据包到达Service虚拟ip后,数据包会通过k8s给servcie自动创建的负载均衡器路由到背后的pod容器。在k8s里,iptables规则是由kube-proxy配置,kube-proxy监视APIserver的更改,因为集群中所有service(iptables)更改都会发送到APIserver上,所以每台kubelet-proxy监视APIserver,当对service或pod虚拟IP进行修改时,kube-proxy就会在本地更新,以便正确发送给后端pod
1)pod到service包的流转
数据包从pod1所在eth0离开,通过veth对的另一端veth0传给网桥cbr0,网桥找不到service的ip对应的mac,交给了默认路由,到达了root命名空间的eth0。 root命名空间的eth0接受数据包之前会经过iptables进行过滤,iptables接受数据包后使用kube-proxy在node上配置的规则响应service, 然后数据包的目的ip重写为service后端指定的pod的ip。
流程如下图:
2)service到pod包的流转
收到包的pod会回应数据包到源pod,源ip是发送方ip,目标IP是接收方,数据包进行回复时经过iptables,iptables使用内核机制conntrack记住它之前做的选择,又将数据包源ip重新为service的ip,目标ip不变,然后原路返回至pod1的eth0
(3)Pod与Pod之间的网络
pod自身拥有一个IP地址,不同pod之间直接使用IP地址进行通信。
1)同一台node节点上pod和pod通信
同一台node节点上,不同pod(不同网络命名空间)之间如何通信?veth对是一个成对的端口,所有从这对端口一端进入的数据包,都将从另一端出来。为了让多个Pod的网络命名空间链接起来,我们可以让veth对的一端链接到root网络命名空间(宿主机的),另一端链接到Pod的网络命名空间。
另外,需要用到一个Linux以太网桥,它是一个虚拟的二层网络设备,目的就是把多个以太网段连接起来,它维护一个转发表,通过查看每个设备mac地址决定转发,还是丢弃数据。
流程如下图:
描述:pod1-->pod2(同一台node上),pod1通过自身eth0网卡发送数据,eth0连接着veth0,网桥把veth0和veth1组成了一个以太网,然后数据到达veth0之后,网桥通过转发表,发送给veth1,veth1直接把数据传给pod2的eth0。
2)不同node节点上pod和pod通信
k8s集群中,每个node节点都会被分配一个CIDR块(把网络前缀都相同的连续地址组成地址组称为CIDR地址块)用来给node上的pod分配IP地址,另外还需要把pod的ip和所在nodeip进行关联。
流程如下图:
描述:比如node1上pod1和node2上的pod4进行通信。首先,pod1上网卡eth0将数据发送给已经管理到root命名空间的veth0上,被虚拟网桥收到,查看自己转发表之后,并没有pod4的mac地址。然后,把包转发到默认路由,root命名空间的eth0上,也就是已经到了node节点的往卡上,通过eth0发送到网络中。最后,寻址转发后包来到了node2,先被root命名空间的eth0设备接受,查看目标地址是发往pod4的,交给虚拟网桥路由到veth1,最终传给pod4的eth0上。
(4)容器和容器之间的网络
pod有多个容器,它们之间怎么通信?pod中每个docker容器和pod在一个网络命名空间内,所以ip和端口等等网络配置都和pod一样。通过docker的一种网络模式使新创建的Docker容器不会创建自己的网卡和IP,而是和一个指定的容器共享IP、端口等配置。