k8s网络
一、同一宿主机的两个容器间通信
通过 Veth Pair 设备 + 宿主机网桥的方式,实现了跟同一宿主机上其他容器通信。
访问流程:当容器1想要跟容器2通信时,IP包会被转发到容器1的eth0这个网卡上,通过二层网络直接发往目的地,但是二层交换设备需要MAC地址进行转发(这个 eth0 网卡,是一个 Veth Pair,一段在容器内一段在docker0网桥上,此时该虚拟网卡是docker0的一个从设备)。因此发送ARP数据包,docker0把 ARP 广播转发到其他被“插”在 docker0 上的虚拟网卡上,找到容器2的mac地址,然后docker0将mac地址返回给容器1,docker0根据mac地址,在它的 CAM 表(即交换机通过 MAC 地址学习维护的端口和 MAC 地址的对应表)里查到对应的端口(Port),然后将数据包转发到该端口上,此时数据包流入容器2的eth0上(容器2的网卡也是Veth Pair)
二、跟其他宿主机通信
当跟容器外的宿主机通信时,首先经过 docker0 网桥出现在宿主机上(类似上面的分析)。然后根据宿主机的路由表里的直连路由规则,对 10.168.0.3 的访问请求就会交给宿主机的 eth0去处理,然后将这个数据包转发到10.168.0.3宿主机的eth0上。
三、容器跨主机通信
Overlay Network(覆盖网络):通过软件的方式,创建一个整个集群公用的网桥,将所有容器连在这个网桥上。每个宿主机上都有一个特殊的网桥,能将数据包发到正确的宿主机上。
Flannel
目前,Flannel 支持三种后端实现,分别是:
1、VXLAN;
2、host-gw;
3、UDP。
3.1 flannel UDP模式
当容器1和容器2通信时。容器1发起ip包,源地址为容器1的ip地址,目的地址为容器2的ip地址。而容器2的地址并不在docker0的网桥上,因此由默认路由规则处理,然后出现在宿主机
上。宿主机跟剧路由规则,将IP包转发到flannel0上,flannel0将这个ip包交给flannel进程也就是flanneld(flannel0是一个tunnel设备,这里内核态变为用户态)。flanneld将这个ip包封装成一个UDP包,UDP包的源地址为Node1的ip地址,目的地址为Node2的ip地址,每台宿主机上的 flanneld,都监听着一个 8285 端口,所以 flanneld 只要把 UDP 包发往 Node 2的8235端口即可。Node2的flanneld从UDP包里解析出容器1发给容器2的IP包,flanneld 会直接把这个 IP 包发送给它所管理的TUN 设备,即 flannel0 设备。Linux 内核网络栈就会负责处理这个 IP 包,具体的处理方法,就是通过本机的路由表来寻找这个 IP 包的下一步流向。Linux 内核就会按照这条路由规则,把这个 IP 包转发给docker0网桥,docker0 网桥会扮演二层交换机的角色,将数据包发送给正确的端口,进而通过 Veth Pair设备进入到容器2 的 Network Namespace 里。
这里如何知道UDP包的目的IP地址呢?
在flannel管理的网络里面,每个宿主机上的容器都属于分配给这个宿主机的子网。而这些子网和宿主机的对应关系存放在etcd数据库里面,所以,flanneld 进程在处理由 flannel0 传入ip包时,可以根据目的地址找到对应的子网,从而找到对应的宿主机,在etcd中找到对应宿主机的ip地址。
UDP 模式有严重的性能问题:
相比于两台主机直接通信,flannel UDP多了一个步骤,flanneld的处理过程。由于使用了flannel0这个tunnel设备,仅在发送IP包的过程,就经历了三次内核态和用户态的数据拷贝。如下图:
3.2 flannel VXLAN模式
(解决flannel UDP内核态用户态互相转换效率问题)
VXLAN 可以完全在内核态实现上述封装和解封装的工作,从而通过与前面相似的“隧道”机制,构建出覆盖网络(Overlay Network)。
而为了能够在二层网络上打通“隧道”,XLAN 会在宿主机上设置一个特殊的网络设备作为“隧道”的两端。这个设备就叫作 VTEP,即:VXLAN Tunnel End Point。
而 VTEP 设备的作用,其实跟前面的 flanneld 进程非常相似。只不过,它进行封装和解封装的对象,是二层数据帧(Ethernet frame);而且这个工作的执行流程,全部是在内核里完成的(因为 VXLAN 本身就是 Linux 内核中的一个模块)。
与前面UDP模式类似,当容器1发出请求后,这个目的地址是容器2的ip地址,首先会出现在docker0网桥上,然后被路由到本机flannel.1设备进行处理,也就是来到了隧道的入口,我们把这个ip称为“原始ip包”。
为了能将原始ip包封装并发送到正确的宿主机,VXLAN就需要找到这条隧道的出口,即目的宿主机的VTEP设备。这个设备就是每台宿主机上的flanneld进程负责维护的。
比如,当 Node 2 启动并加入 Flannel 网络之后,在 Node 1(以及所有其他节点)上,flanneld 就会添加一条如下所示的路由规则:凡是发往 10.1.16.0/24 网段的 IP 包,都需要经过 flannel.1 设备发出,并且,它最后被发往的网关地址是:10.1.16.0。
然后根据ARP表(flanneld进程在Node2节点启动时,自动加在Node1上的),找到目的VTEP设备的ip地址对应的MAC地址。
有了目的VTEP设备的MAC地址,Linux内核将原始ip包封装成“内部数据帧”,二层帧格式如下:
然后,Linux 内核会把这个数据帧封装进一个UDP 包里发出去。
此时,flannel.1扮演一个网桥的角色,在二层网络进行UDP包的转发。而在 Linux 内核里面,“网桥”设备进行转发的依据,来自于一个叫作 FDB(ForwardingDatabase)的转发数据库。这个 flannel.1“网桥”对应的 FDB 信息,也是 flanneld 进程负责维护的。它的内容可以通过 bridge fdb 命令查看到发往我们前面提到的“目的 VTEP 设备”的二层数据帧,应该通过 flannel.1 设备,发往 IP 地址为 10.168.0.3 的主机。显然,这台主机正是 Node 2,UDP 包要发往的目的地(目的宿主机ip)就找到了。
所以接下来的流程,就是一个正常的、宿主机网络上的封包工作。
Node2接收到数据帧后,内核网会发现这个数据帧有络栈里面有VXLAN Header,并且VNI=1.所以Linux内核会对它进行拆包,拿到内部数据帧,然后根据VIN的值,把它交给Node2上的flannel.1设备。flannel.1会进一步拆包,取出原始ip包。接下来回到上面讲的单机容器网络处理流程,最终ip包到容器2的network namespace中。
3.3 Flannel host-gw 模式
当你设置 Flannel 使用 host-gw 模式之后,flanneld 会在宿主机上创建这样一条规则,以Node 1 为例:目的 IP 地址属于 10.244.1.0/24 网段的IP 包,应该经过本机的 eth0 设备发出去(即:dev eth0);并且,它下一跳地址(next-hop)是 10.168.0.3(即:via 10.168.0.3)
当容器1要跟容器2通信的时候,IP包会从网络层传到链路层,在数据帧上封装Node2的MAC地址,因此,该ip可以通过Node1的eth0发到Node2,然后再发送到容器2
flannel host-gw 模式必须要求集群宿主机之间是二层联通的。
3.4 Calico
Calico 项目提供的网络解决方案,与 Flannel 的 host-gw 模式,几乎是完全一样的。Calico 也会在每台宿主机上,添加一个格式如下所示的路由规则:
Calico 项目使用BGP(边界网关协议)来自动地在整个集群中分发路由信息。BGP是一个 Linux 内核原生就支持的、专门用在大规模数据中心里维护不同的“自治系统”之间路由信息的、无中心的路由协议。AS 1 里面的主机 10.10.0.2,要访问AS 2 里面的主机 172.17.0.3 的话。它发出的ip包,就会先到达自治系统 AS 1 上的路由器 Router1。Router 1 的路由表里,有这样一条规则,即:目的地址是172.17.0.2 包,应该经过 Router 1 的的 C 接口,发往网关 Router 2(即:自治系统 AS 2 上的路由器)。
负责把自治系统连接在一起的路由器,我们就把它形象地称为:边界网关。
假如我们的网络拓扑结果非常复杂,可能是由多个自治系统组成的复合自治系统。这时就可以用BGP协议。使用BGP之后,可以认为在每个边界网关上都运行着一个小程序,他们会将各自的路由表信息,通过TCP传输给其他边界网关。而其他边界网关上的这个小程序会收到这些数据进行分析,然后将需要的信息添加到自己的路由表里。所谓 BGP,就是在大规模网络中实现节点路由信息共享的一种协议。
Calico 项目的架构就非常容易理解了。它由三个部分组成(它不会在宿主机上创建任何网桥设备。):
1、Calico 的 CNI 插件。这是 Calico 与 Kubernetes 对接的部分。
2、Felix。它是一个 DaemonSet,负责在宿主机上插入路由规则(即:写入 Linux 内核的 FIB 转发信息库),以及维护 Calico 所需的网络设备等工作。
3、BIRD。它就是 BGP 的客户端,专门负责在集群里分发路由规则信息。
Calico 的 CNI 插件会为每个容器设置一个 Veth Pair 设备,然后把其中的一端放置在宿主机上(它的名字以 cali 前缀开头)。此外,由于 Calico 没有使用 CNI 的网桥模式,Calico 的 CNI 插件还需要在宿主机上为每个容器的 Veth Pair 设备配置一条路由规则,用于接收传入的 IP 包。比如,宿主机 Node 2 上的 Container 4 对应的路由规则,如下所示:
即:发往 10.233.2.3 的 IP 包,应该进入 cali5863f3 设备。
有了这样的 Veth Pair 设备之后,容器发出的 IP 包就会经过 Veth Pair 设备出现在宿主机上。然后,宿主机网络栈就会根据路由规则的下一跳 IP 地址,把它们转发给正确的网关。接下来的流程就跟 Flannel host-gw 模式完全一致了。其中,这里最核心的“下一跳”路由规则,就是由 Calico 的 Felix 进程负责维护的。这些路由规则信息,则是通过 BGP Client 也就是 BIRD 组件,使用 BGP 协议传输而来的。
当Node1和Node2不在一个子网时,就需要为 Calico 打开 IPIP 模式。
当容器1要访问容器3时,路由规则的下一跳地址仍然是 Node 2 的 IP 地址,但这一次,要负责将 IP 包发出去的设备,变成了 tunl0。注意,是 T-U-N-L-0,而不是 Flannel UDP 模式使用的 T-U-N-0(tun0),这两种设备的功能是完全不一样的。Calico 使用的这个 tunl0 设备,是一个 IP 隧道(IP tunnel)设备。IP 包进入 IP 隧道设备之后,就会被 Linux 内核的 IPIP 驱动接管。IPIP 驱动会将这个 IP 包直接封装在一个宿主机网络的 IP 包中,如下所示:
其中,经过封装后的新的 IP 包的目的地址(图 5 中的 Outer IP Header 部分),正是原 IP 包的下一跳地址,即 Node 2 的 IP 地址:192.168.2.2。这样,
原先从容器到 Node 2 的 IP 包,就被伪装成了一个从 Node 1 到 Node 2 的 IP 包。由于宿主机之间已经使用路由器配置了三层转发,也就是设置了宿主机之间的“下一跳”。所以这个 IP 包在离开 Node 1 之后,就可以经过路由器,最终“跳”到 Node 2 上。
这时,Node 2 的网络内核栈会使用 IPIP 驱动进行解包,从而拿到原始的 IP 包。然后,原始 IP 包就会经过路由规则和 Veth Pair 设备到达目的容器内部。
小结:
三层和隧道的异同:
相同之处是都实现了跨主机容器的三层互通,而且都是通过对目的 MAC 地址的操作来实现的;不同之处是三层通过配置下一条主机的路由规则来实现互通,隧道则是通过通过在 IP 包外再封装一层 MAC 包头来实现。
三层的优点:少了封包和解包的过程,性能肯定是更高的。
三层的缺点:需要自己想办法维护路由规则。
隧道的优点:简单,原因是大部分工作都是由 Linux 内核的模块实现了,应用层面工作量较少。
隧道的缺点:主要的问题就是性能低。
k8s网络的更多相关文章
- 【Kubernetes】K8S网络方案--最近在看的
K8S网络-最近在看的 Create a Minikube cluster - Kubernetes Kubernetes Documentation - Kubernetes Kubernetes ...
- 【Kubernetes】K8S 网络隔离 方案
参考资料: K8S-网络隔离参考 OpenContrail is an open source network virtualization platform for the cloud. – Kub ...
- k8s网络之Flannel网络
k8s网络主题系列: 一.k8s网络之设计与实现 二.k8s网络之Flannel网络 三.k8s网络之Calico网络 简介 Flannel是CoreOS团队针对Kubernetes设计的一个网络规划 ...
- k8s网络之Calico网络
k8s网络主题系列: 一.k8s网络之设计与实现 二.k8s网络之Flannel网络 三.k8s网络之Calico网络 简介 Calico 是一种容器之间互通的网络方案.在虚拟化平台中,比如 Open ...
- k8s网络之设计与实现
k8s网络主题系列: 一.k8s网络之设计与实现 二.k8s网络之Flannel网络 三.k8s网络之Calico网络 K8s网络设计与实现是在学习k8s网络过程中总结的内容.在学习k8s网络各种插件 ...
- ASP.NET Core on K8S深入学习(11)K8S网络知多少
本篇已加入<.NET Core on K8S学习实践系列文章索引>,可以点击查看更多容器化技术相关系列文章. 一.Kubernetes网络模型 我们都知道Kubernetes作为容器编排引 ...
- k8s网络配置管理
docker容器的四种网络类型 1.桥接 2.联盟 3.主机 4.无 docker跨节点的容器通信必须通过NAT机制 宿主机上的容器一般都是私网地址 它可以通过宿主机 ...
- 一次客户需求引发的K8S网络探究
前言 在本次案例中,我们的中台技术工程师遇到了来自客户提出的打破k8s产品功能限制的特殊需求,面对这个极具挑战的任务,攻城狮最终是否克服了重重困难,帮助客户完美实现了需求?且看本期K8S技术案例分享! ...
- k8s网络原理
https://blog.csdn.net/watermelonbig/article/details/80646988 k8s中,每个 Pod 都有一个独立的 IP 地址,所有 Pod 在一个网络空 ...
- 办公环境下k8s网络互通方案
在 kubernetes 的网络模型中,基于官方默认的 CNI 网络插件 Flannel,这种 Overlay Network(覆盖网络)可以轻松的实现 pod 间网络的互通.当我们把基于 sprin ...
随机推荐
- pycharm的快捷键
一.编辑(Editing) Ctrl+Space 基本的代码完成(类.方法.属性) Ctrl+Alt+Space 快速导入任意类 Ctrl+Shift+Enter 语句完成 Ctrl+P 参数信息(在 ...
- Linux 的基本命令
Linux 的基本命令 1. 文件操作 a) Windows 是多根的文件系统,物理上是 1 到多块硬盘,逻辑上分为 C.D.E……盘, 每个盘都是一棵树.Linux 是单根的文件系统,不分 CDE ...
- centos7 yum安装nginx
1.添加源,centos7默认可能没有nginx源 sudo rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release ...
- Introducing Outflux: a smart way out of InfluxDB
转自:https://blog.timescale.com/migrate-outflux-a-smart-way-out-of-influxdb/ Migrate your workload fro ...
- js/php判断移动端还是PC端
if ((navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobi ...
- Java小代码
1. public class test1 {public static void main(String[] args) { Person P = new Person("gdsgds&q ...
- SQL :“传入的表格格式数据流(TDS)远程过程调用(RPC)协议流不正确” 错误
其中在DAL层调用存储过程来插入数据的参数 SqlParameter[] parameters = { new S ...
- Windows 数字化器类输入设备--笔设备分析(1)(原创)
一.前言: 参考microsoft公司的链接:https://developer.microsoft.com/zh-cn/windows/hardware 将对Windows数字化器类输入设备--笔设 ...
- vs2010直接调用av_register_all crash问题
需要做一个视频导出的功能,通过ffmpeg来实现,vs2010里面引用ffmpeg库的 dll 和 lib 文件 第一步av_register_all就直接crash了, 查了近半天的时间,都快崩溃了 ...
- 语音识别传统方法(GMM+HMM+NGRAM)概述
春节后到现在近两个月了,没有更新博客,主要是因为工作的关注点正从传统语音(语音通信)转向智能语音(语音识别).部门起了个新项目,要用到语音识别(准备基于Kaldi来做).我们之前做的传统音频已基本成熟 ...