k8s-网络模型
容器网络发端于 Docker 的网络。Docker 使用的网络模型是内部的网桥加内部的保留 IP。当需要访问外部世界时,会采用 SNAT 这种方法来借用 Node 的 IP 去访问外面的服务。若容器需要对外提供服务的时候,所用的是 DNAT 技术,把流导入到容器的进程上。该模型的问题在于,外部网络无法区分哪些是容器的网络与流量、哪些是宿主机的网络与流量。
SNAT(Source NAT):作用:在数据包离开内部网络时,替换数据包中的源 IP 地址,通常是将内部私有地址转换为公共地址,以隐藏内部网络的真实结构。
DNAT(Destination NAT):作用:在数据包到达目标网络之前,替换数据包中的目标 IP 地址,通常是将公共地址转换为内部私有地址,以将流量导向内部网络中的特定主机。
kubernetes 提出了这样一种机制:即每一个 Pod,也就是一个组功能内聚的容器拥有一个 IP。对这个 Pod IP 的访问就是才是对它的服务的访问,中间拒绝任何的转换(NAT)。
网络架构
协议层次:它和 TCP 协议栈的概念是相同的,需要从两层、三层、四层一层层地摞上去,发包的时候从右往左,即先有应用数据,然后发到了 TCP 或者 UDP 的四层协议,继续向下传送,加上 IP 头,再加上 MAC 头就可以送出去了。收包的时候则按照相反的顺序,首先剥离 MAC 的头,再剥离 IP 的头,最后通过协议号在端口找到需要接收的进程。
网络拓扑:一个容器的包所要解决的问题分为两步:第一步,如何从容器的空间 (c1) 跳到宿主机的空间 (infra);第二步,如何从宿主机空间到达远端。
第一个是接入,就是说我们的容器和宿主机之间是使用哪一种机制做连接,比如 Veth + bridge、Veth + pair 这样的经典方式,也有利用高版本内核的新机制等其他方式(如 mac/IPvlan 等),来把包送入到宿主机空间;
第二个是流控,就是说我的这个方案要不要支持 Network Policy,如果支持的话又要用何种方式去实现。这里需要注意的是,我们的实现方式一定需要在数据路径必经的一个关节点上。如果数据路径不通过该 Hook 点,那就不会起作用;
第三个是通道,即两个主机之间通过什么方式完成包的传输。我们有很多种方式,比如以路由的方式,具体又可分为 BGP 路由或者直接路由。还有各种各样的隧道技术等等。最终我们实现的目的就是一个容器内的包通过容器,经过接入层传到宿主机,再穿越宿主机的流控模块(如果有)到达通道送到对端。
例子:Flannel-host-gw,限制:两个宿主机之间须是二层连接的(mac可互通)。
Service 的工作机制及实现
Service 其实是一种负载均衡 (Load Balance) 的机制,是一种用户侧(Client Side) 的负载均衡,也就是说 VIP 到 RIP 的转换在用户侧就已经完成了。
VIP(Virtual IP Address):虚拟 IP 地址是一种网络配置,其中一个 IP 地址被用于表示多个设备或服务的集合。这个 IP 地址并不是实际存在于网络中的某个设备,而是通过网络设备或负载均衡器管理的,用于将请求分配到后端的真实服务器。
RIP(Routing Information Protocol):路由信息协议是一种动态路由协议,用于在网络中交换路由信息。RIP 使用跳数作为衡量路径开销的度量标准,通过在路由器之间共享路由信息,使得网络可以自适应地调整路由表,以找到最短的路径。
Kube-proxy,拿到了一个 Service 的相关配置(Cluster IP,该 IP 上的端口是 9376,需要反馈到容器上的是 80 端口)
首先需要让内核相信它拥有这样的一个Cluster IP,这是 LVS 的工作机制所决定的,因为它工作在第四层,并不关心 IP 转发,只有它认为这个 IP 是自己的才会拆到 TCP 或 UDP 这一层。将该 IP 设到内核中,告诉内核它确实有这么一个 IP。实现的方法有很多,可以用 ip route 直接加 local 的方式,用 Dummy 哑设备上加 IP 的方式也是可以的。
告诉内核需要为这个 IP 进行负载均衡分发,后面的参数就是一些分发策略等等。
需要为 virtual server 配置相应的 real server,就是真正提供服务的后端是什么。只是Kube-proxy还需要去监控一些 Pod 的变化,比如 Pod 的数量变成 5 个了,那么规则就应变成 5 条。如果这里面某一个 Pod 死掉了或者被杀死了,那么就要相应地减掉一条。又或者整个 Service 被撤销了,那么这些规则就要全部删掉。所以它其实做的是一些管理层面的工作。

浙公网安备 33010602011771号