『黑马程序员』网络模型来龙去脉,Kubernetes( 二 )


『黑马程序员』网络模型来龙去脉,Kubernetes
文章图片
这个方案的精髓在于route表的设置 , 如上图所示 。 接下来为大家一一解读一下 。
第一条很简单 , 我们在设置网卡的时候都会加上这一行 。 就是指定我的默认路由是通过哪个IP走掉 , 默认设备又是什么;第二条是对Subnet的一个规则反馈 。 就是说我的这个网段是10.244.0.0 , 掩码是24位 , 它的网关地址就在网桥上 , 也就是10.244.0.1 。 这就是说这个网段的每一个包都发到这个网桥的IP上;第三条是对对端的一个反馈 。 如果你的网段是10.244.1.0(上图右边的Subnet) , 我们就把它的Host的网卡上的IP(10.168.0.3)作为网关 。 也就是说 , 如果数据包是往10.244.1.0这个网段发的 , 就请以10.168.0.3作为网关 。再来看一下这个数据包到底是如何跑起来的?
假设容器(10.244.0.2)想要发一个包给10.244.1.3 , 那么它在本地产生了TCP或者UDP包之后 , 再依次填好对端IP地址、本地以太网的MAC地址作为源MAC以及对端MAC 。 一般来说本地会设定一条默认路由 , 默认路由会把cni0上的IP作为它的默认网关 , 对端的MAC就是这个网关的MAC地址 。 然后这个包就可以发到桥上去了 。 如果网段在本桥上 , 那么通过MAC层的交换即可解决 。
这个例子中我们的IP并不属于本网段 , 因此网桥会将其上送到主机的协议栈去处理 。 主机协议栈恰好找到了对端的MAC地址 。 使用10.168.0.3作为它的网关 , 通过本地ARP探查后 , 我们得到了10.168.0.3的MAC地址 。 即通过协议栈层层组装 , 我们达到了目的 , 将Dst-MAC填为右图主机网卡的MAC地址 , 从而将包从主机的eth0发到对端的eth0上去 。
所以大家可以发现 , 这里有一个隐含的限制 , 上图中的MAC地址填好之后一定是能到达对端的 , 但如果这两个宿主机之间不是二层连接的 , 中间经过了一些网关、一些复杂的路由 , 那么这个MAC就不能直达 , 这种方案就是不能用的 。 当包到达了对端的MAC地址之后 , 发现这个包确实是给它的 , 但是IP又不是它自己的 , 就开始Forward流程 , 包上送到协议栈 , 之后再走一遍路由 , 刚好会发现10.244.1.0/24需要发到10.244.1.1这个网关上 , 从而到达了cni0网桥 , 它会找到10.244.1.3对应的MAC地址 , 再通过桥接机制 , 这个包就到达了对端容器 。
大家可以看到 , 整个过程总是二层、三层 , 发的时候又变成二层 , 再做路由 , 就是一个大环套小环 。 这是一个比较简单的方案 , 如果中间要走隧道 , 则可能会有一条vxlantunnel的设备 , 此时就不填直接的路由 , 而填成对端的隧道号 。
Service究竟如何工作
Service其实是一种负载均衡(LoadBalance)的机制 。
我们认为它是一种用户侧(ClientSide)的负载均衡 , 也就是说VIP到RIP的转换在用户侧就已经完成了 , 并不需要集中式地到达某一个NGINX或者是一个ELB这样的组件来进行决策 。
『黑马程序员』网络模型来龙去脉,Kubernetes
文章图片
它的实现是这样的:首先是由一群Pod组成一组功能后端 , 再在前端上定义一个虚IP作为访问入口 。 一般来说 , 由于IP不太好记 , 我们还会附赠一个DNS的域名 , Client先访问域名得到虚IP之后再转成实IP 。 Kube-proxy则是整个机制的实现核心 , 它隐藏了大量的复杂性 。 它的工作机制是通过apiserver监控Pod/Service的变化(比如是不是新增了Service、Pod)并将其反馈到本地的规则或者是用户态进程 。
一个LVS版的Service我们来实际做一个LVS版的Service 。 LVS是一个专门用于负载均衡的内核机制 。 它工作在第四层 , 性能会比用iptable实现好一些 。
假设我们是一个Kube-proxy , 拿到了一个Service的配置 , 如下图所示:它有一个ClusterIP , 在该IP上的端口是9376 , 需要反馈到容器上的是80端口 , 还有三个可工作的Pod , 它们的IP分别是10.1.2.3,10.1.14.5,10.1.3.8 。


推荐阅读