Kubernetes-Kubernetes-深化了解-中的网络原理和最佳通常-网络模型综合指南 (kubernetes与docker的关系)
这篇详细的博文讨论了Kubees网络的复杂性,提供了关于如何在容器化环境中确保高效和安保通讯的见地。
译自NavigatingtheNetwork:AComprehensiveGuidetoKubernetesNetworkingModels。
引见
在Kubernetes的环球中,网络是一个基本方面,它编排着集群内外各种组件之间的通讯。了解Kubernetes网络模型关于任何经常使用这个编排工具的人来说都是至关关键的。
这篇详细的博文讨论了Kubernetes网络的复杂性,提供了关于如何在容器化环境中确保高效和安保通讯的见地。
Kubernetes网络被设计来满足四个关键要求,每个要求在Kubernetes集群的性能和操作中都表演着至关关键的角色。
容器与容器之间的通讯:这是Kubernetes网络的基本层。它成功了同一个Pod内容器之间的间接通讯。这些容器共享相反的网络命名空间,象征着它们可以经常使用localhost相互通讯。关于触及多容器Pod的运行程序而言,这种设置关于须要亲密高效地交互的容器至关关键。
Pod-to-Pod通讯:在Kubernetes中,每个Pod都被调配了一个惟一的IP地址。这种设计选用简化了启用Pod之间通讯的环节,无论它们位于哪个节点上。Pod之间可以间接通讯,无需启动网络地址转换(NAT),确保了间接且便捷的衔接。这种模型是创立散布式系统的基础,其中每个Pod都可以作为独立的微服务运转。
Pod-to-Service通讯:Kubernetes服务是一个关键的形象,为Pod访问其余Pod提供了一种分歧牢靠的形式。服求实质上是一组变动的Pod的稳固地址。它确保任何发送到服务的恳求都会智能智能地路由到正确的Pod,即使Pod被创立、销毁或更新。这种形象层关于保养一个具备弹性和可裁减性的系统至关关键。
External-to-Internal通讯:Kubernetes网络的这一方面触及治理来自集群外部到集群外部服务的入站流量。经过Ingress控制器和负载平衡器等机制来处置。这些工具准许外部用户和运行程序安保高效地访问运转在集群外部的服务。它们在将运行程序泄露给最终用户和其余外部系统方面施展着至关关键的作用。
服务和负载平衡
Kubernetes中的服务关于为一组或许随期间灵活变动的Pod提供稳固的地址至关关键。它们在治理访问运转在Pod上的运行程序方面起着至关关键的作用。让咱们深化了解不同类型的服务及其在负载平衡中的作用:
ClusterIP:这是Kubernetes的自动服务。ClusterIP服务调配一个惟一的外部IP地址,用于与服务启动通讯。这些服务只能在集群外部访问,关于集群中的Pod之间的外部通讯十分有用。这在不须要外部访问服务的场景中十分现实。
NodePort:NodePort服务裁减了ClusterIP的性能。除了外部IP外,NodePort服务还在一切集群节点上提供了一个特定的端口。外部流量可以访问这些泄露的端口上的服务,而后将流量路由到相应的外部IP。当您须要外部流量跨一切节点访问特定端口时,这尤其有用。
LoadBalancer:在NodePort的基础上,LoadBalancer服务与云服务提供商的负载平衡器集成。这种类型会智能创立一个外部负载平衡器,将外部流量疏导到整个集群节点上的NodePort,而后再路由到正确的Pod上。它简化了将服务泄露到互联网的环节,特意实用于散发传入的网络流量,从而提高了运行程序的可裁减性和牢靠性。
ExternalName:与其余类型不同,ExternalName服务不会将流量路由到Pod。相反,它们充任别名,经过前往一个CNAME记载到一个外部服务。当您想要经常使用将Kubernetes集群中的服务与外部服务集成时,这是十分有用的。
网络安保的网络战略
Kubernetes中的网络战略提供了一个关键的安保层,规则了Pod之间以及与其余网络端点之间的通讯形式。它们充任了Pod的防火墙,准许用户依据标签选用器和CIDR块指定入站和出站规则。
例如,思考这样一个情形:您有一个前端和一个后端服务。后端服务不应该从集群外部访问,但应该准许来自前端服务的流量。您可以经常使用相似以下内容的网络战略来成功:
apiVersion:networking.k8s.io/v1kind:NetworkPolicymetadata:name:backend-network-policynamespace:defaultspec:podSelector:matchLabels::backendpolicyTypes:-Ingressingress:-from:-podSelector:matchLabels:app:kubeops-frontendports:-protocol:TCPport:80
这个战略确保只要带有标签app:kubeops-frontend的Pod可以访问TCP端口80上的后端Pod。这种细粒度的控制有助于在Kubernetes中保养一个安保且受控的网络环境。
思考自动行为也是至关关键的。自动状况下,Kubernetes集群中的一切Pod都可以彼此通讯。运行网络战略可以扭转这种自动行为。例如,运行准许特定流量的战略象征着一切不合乎该战略的其余流量都将被拒绝。
Ingress和Egress控制器
图片
Kubernetes中的入口和进口控制器治理集群外部服务的外部访问,通常是HTTP。入口控制器促成将外部流量路由到正确的外部资源,而进口控制器则治理集群的出站流量。
入口控制器担任读取入口资源消息并适外地处置它。例如,当用户恳求URL时,入口控制器依据入口资源中定义的路由规则将恳求路由到适当的服务。这关于治理对微服务的访问和成功SSL/TLS中断特意有用。
另一方面,进口控制器处置出站流量。它们确保来自集群外部到外部环球的恳求被正确治理和路由。进口控制器可以强迫口头限制Pod可以建设衔接的目的地的战略,增强了集群的全体安保性。
成功这些控制器须要对网络架构和运行程序的流量形式有明晰的了解。例如,一特性能良好的入口控制器可以高效地处置流量突增,依据URL门路启动路由,并提供基于称号的虚构主机。
外围网络处置打算:关键性与作用
Calico用于网络战略口头:以其弱小的网络战略口头而知名,Calico在保养运行程序安保方面施展着关键作用。它对Pod通讯提供了精细的控制,仅准许授权的流量,从而口头安保战略并分段网络流量以防止未经授权的访问。其关键性在于增强了运行程序外部网络交互的全体安保性和完整性。
Flannel用于便捷的笼罩网络:Flannel以其在设置笼罩网络方面的便捷性和效率而至关关键,衔接跨节点的Pod。它的作用是经过智能治理子网调配来简化Kubernetes部署中的网络性能。这缩小了与网络治理关系的复杂性和经营开支,使其成为间接但有效的网络衔接的有价值工具。
Cilium用于API感知网络:Cilium关于将API感知的网络安保过滤引入Kubernetes至关关键。应用BPF,在内核级别过滤网络流量,了解Kubernetes标签和元数据。它的作用在于增强安保性,并为网络流量提供改良的可见性,特意是关于微服务,从而促成更安保、更透明的网络环境。
Canal作为Flannel和Calico的组合:Canal兼并了Flannel和Calico的好处,为Kubernetes提供了片面的网络处置打算。它的作用是提供易用性(来自Flannel)和弱小的安保性能(来自Calico)。这种组合使得Canal成为一个多性能的选用,满足了对高效网络笼罩和灵敏网络战略的需求。
Kube-router作为轻量级处置打算:Kube-router是规范网络处置打算的简化、更高效的代替打算。它的作用是经过单个守护程序处置路由、网络战略和服务代感性能。这使其成为较小或资源受限环境的现实选用,提供了轻量级但有效的网络处置打算。
图片
Kubernetes网络的最佳通常
论断
Kubernetes网络是支持容器化运口头态和散布式特性的关键要素。经过了解其模型,并有效地实施网络战略和服务,您可以确保为Kubernetes集群建设一个持重、安保和高效的环境。
k8s网络原理-ipvs
一、背景知识
本文主要介绍k8s网络中service 的两种模式(clusterIp、nodeport),数据是如何通过ipvs&iptables流转的。在学习上述知识的同时,还需要了解一下ipset、conntrack的相关知识。 往期回顾文章
ipset是什么?ipset其实是iptables的扩展,可以定义一些列地址的集合。拿黑名单来举例,我想让黑名单里面的ip拒绝访问网站(黑名单有很多个),按照传统iptables做法,需要在filter表添加很多规则匹配时一条一条匹配效率很低(严重影响性能),而有了ipset,则只用添加一条规则即可,使用hash结构效率很高。
而使用ipset命令如下
lvs是什么?全称是Linux Virtual Server,是由章文嵩博士主导的开源负载均衡项目,目前已经集成到linux内核中。lvs提供了丰富的负载均衡能力,接收到用户请求后根据具体的负载均衡算法在内核态把请求转发到后端的某个server上,也就是说lvs不需要监听具体的端口。接下来我们看一下lvs的一些基本概念。
ipvs的原理如下。ipvs工作在iptables 的 input链上,VIP一般定义在DS节点上的一个虚拟ip,拿nat模式举例如下。
① : 当请求数据包到DS上最先经过iptables 的PREROUTING链,判断目标ip (VIP) 是本机的ip,于是把请求转发到INPUT链上。 ② : 因为lvs工作在INPUT链上,数据到达INPUT链上后lvs会将用户请求和定义的后端服务做对比,如果是请求的后端服务,则使用某种负载均衡算法找到一个后端RIP,修改数据包的目的ip和端口为某个RIP的(DNAT转换)。 ③ : 此时数据到达POSTROUTING链(不会做SNAT),数据包的源ip 为CIP,目的ip为RIP,数据包发往RIP上。
lvs提供了三种包转发模式,如下所示
由于k8s使用的是NAT模式,接下来看下 NAT模式下的数据包流向 。如下图所示
①:请求数据包到达DS,数据包经过PREROUTING链,此时ip 包 src ip为CIP,dst ip 为VIP ②:由于请求的VIP是DS上的虚拟ip,数据包发往INPUT链。 ③:数据包到INPUT链上后,ipvs发现数据包请求是定义的集群服务,于是使用定义好的负载均衡算法找到一个具体的RS节点,做DNAT,修改数据包dst ip为RIP,数据包到达POSTROUTING链,发送给RS。 ④:RS收到数据包后对比dst ip 发现是自己,接收数据包做处理,处理完成后ip 数据包 src ip 为RIP,dst ip 为CIP,把数据包发给DS。 ⑤:DS 接收到RS的响应包,修改src ip 为自身的VIP,dst ip 为CIP,把数据包发送给client端。
三种模式对比&优缺点
接下来在简单聊一下ipvs的负载均衡策略,简单介绍下面四种。
上面介绍完了ipvs内核态的基本原理,接下来介绍一下如何使用 ipvsadm 用户态命令来操作ipvs。说明:此次试验是在四个虚拟机上,ipvs的模式使用的nat模式,RS的网关没有指向DS的ip(没办法做到)在DS节点上手动创建SNAT命令,下文有详细介绍。创建一个vip,在ip为192.168.113.101上
为vip添加RS
添加完成RS后,查看ipvs规则,如下图所示
client端的ip地址为192.168.113.102,client端要想直接访问vip的话,需要在client端添加静态路由,添加命令如下
添加完命令后,在client端curl 10.10.0.1:8410 发现不通,此时去某个RS上抓包如下
上图抓包显示,client 直接访问的vip,而数据包的目的ip 变为了rs的ip,因此可以看出ipvs做了DNAT转换。因为做了DNAT,RS发送响应数据直接发给client,client收到RS的数据包。client给vip发的包却收到了RS的响应包(client 想我从来没有给RS发过数据),因此client端会把此数据包丢弃。
因为ipvs没有做SNAT,接下来在DS上添加iptables规则自己实现SNAT的功能,添加完SNAT后, RS就看不到真实的CIP了 。
此时还是不通,查找资料后发现ipvs 的 conntrack没有开,手动打开,后续文章介绍conntrack是什么,设置完成后可以愉快的访问了。
总结:通过ipvs提供的DNAT功能和负载均衡功能,很容易实现外部用户访问内网的需求。但是还要考虑高可用层面,比如主DS宕机VIP要漂移到备DS上,后端RS重启或宕机,ipvs负载均衡列表中要及时把有问题的RS剔除,这样才能真正的实现高可用。
1.3、conntrack
大家在家上网时用到的都是192.168.x.x的ip地址,这是私网ip地址。那么大家是如何能够成功的访问外网的呢?答案是路由器帮我们做了SNAT的功能,使我们发出的数据包的src ip变为路由器的公网ip,这样数据包就能在互联网上愉快的转发了。从而实现了对内网的保护。
那么问题来了,既然做了SNAT转换,那响应数据包回来以后路由器怎么知道转到哪台PC上呢?路由器可能链接了很多PC,不可能都给每一个PC转发吧。。。答案就是conntrack实现的。
接下来我拿上面ipvs的例子举例,我们手动实现了在DS上SNAT转换,在client上curl vip:8410,这时候查看DS上和client上的conntrack表如下
先从client上的连接跟踪分析起:主要看 src、dst、sport、dport这几个字段。 client发送数据包
client端发出数据包的src ip 为192.168.113.102,dst ip 为10.10.0.1 (VIP), sport 为这个端口,dport为8410(VIP 定义端口)。
client端接收响应数据包
期望src ip 为vip(10.10.0.1),dst ip 为CIP(192.168.113.102),sport为8410,dport为
DS接收数据包
DS接收到src ip 为CIP(192.168.113.102),dst ip 为vip(10.10.0.1),sport为,dport为8410的数据包
DS接收响应数据包
由于在DS侧做了DNAT转换,根据负载均衡策略找到了一个RS(RIP 192.168.113.99),同时也做了SNAT转换(判断是否是VIP和端口),转换为DS的DIP。所以当DS收到src ip 为192.168.113.99(RIP),dst ip 为192.168.113.101(DIP),sport为8080,dport为,会根据连接跟踪表找到这个包是192.168.113.102这个client发过来的,因此把数据包在转发给192.168.113.102 上。
conntrack各个字段的含义
总结:
本文只是简单的说明了一下conntrack,并没有具体说明数据流经netfilter时何时创建记录,数据存储的数据结构啥样,底层比较复杂,感兴趣的大佬可以自行研究~
二、k8s网络通信
介绍完了ipset、ipvs、conntrack,接下来进入正题,看一下ipvs模式下k8s的网络通信。kube-proxy 的主要作用是watch apiserver,当监听到pod 或service变化时,修改本地的iptables规则或ipvs规则。
2.1、clusterIp模式
clusterIp模式为一个集群内部可访问的ip,集群外部没办法访问这个ip,试验环境如下:
创建完deployment和service后,查看一下service的ip如下。
接下来看下宿主机网卡、ipvs规则、ipset规则有什么变化
查看iptables 的nat表和filter表,看一下k8s创建了哪些规则以及经过哪些链
接下来分析一下curl 10.108.113.237 数据是如何走的,只讨论在nat表和filter表的流向,因为在mangle和raw都没有规则。
1、nat表PREROUTING链 ①:数据首先进入PREROUTING链,所有请求都会进入KUBE-SERVICES链。 ②:进入KUBE-SERVICES后,查看对应在此链上的规则,发现请求的目的ip和port在KUBE-CLUSTER-IP 对应的ipset里面(上面已有展示),匹配上了则跳往KUBE-MARK-MASQ链。
③:数据流向KUBE-MARK-MASQ链,主要做了mark 打标记的功能,iptables命令如下
④:之后走向KUBE-NODE-PORT链,因为没有定义nodepode 类型的service,此处先略过。 2、filter表的INPUT链 ⑤:首先进入INPUT链,所有数据转向KUBE-FIREWALL链。 ⑥:进入KUBE-FIREWALL链,如果发现数据包打了0x8000/0x8000,DROP掉。因为ipvs工作在INPUT链上,做完DNAT之后直接转发到POSTROUTING链上。 3、nat表POSTROUTING链 ⑦:进入POSTROUTING链,所有数据转向KUBE-POSTROUTING链 ⑧:进入KUBE-POSTROUTING链,对有0x4000/0x4000标记的数据包做SNAT转换,因为ipvs只有DNAT功能。
4、数据转发给flannel网卡,进行转发 ⑨:flannel 根据具体的backend模式,对数据做封包等操作,然后发出去。flannel的网络模式比较复杂,之后会专门文章进行说明。
2.2、nodeport模式
要想把集群内部的服务可以让集群外部访问,可以使用nodeport模式在物理机上开一个端口,这样外部就能访问集群内部的服务了。说明:还是使用上面创建的deployment。
查看创建service的信息,发现也创建了集群内部的一个ip。
iptables规则如下
接下来看下ipset规则有什么变化,发现KUBE-NODE-PORT-TCP下的一个成员是刚才我们指定的那个nodePort的值。
接下来看一下iptables规则,nat表和filter表 1、nat表PREROUTING链 ①:数据首先进入PREROUTING链,所有请求都会进入KUBE-SERVICES链。 ②:ip和port匹配不上KUBE-CLUSTER-IP 的ipset,判断是访问的本地地址,进入KUBE-NODE-PORT链。
![网络模型综合指南](https://tyye.cn/zb_users/theme/tpure/style/images/lazyload.png)
③:进入KUBE-NODE-PORT链后,判断访问端口在 KUBE-NODE-PORT-TCP ipset规则中,因此进入KUBE-MARK-MASQ链。
④:进入KUBE-MARK-MASQ链,对数据做mark标记
后续流程跟clusterIp一样,此处就不在阐述。 2.3、dns相关
k8s中的dns默认使用的是coredns,通过以下命令查看。k8s中定义的service是有域名的,访问域名要通过dns解析,此时coredns就发挥它的作用了。
上面的试验时我们创建了一个my-service 的nodePort的service,此时查看一下此域名对应的ip,如下图所示,域名解析出来的ip与service对应的ip相同,大功告成。
参考:
计算机网络-k8s网络
K8S网络模型设计:扁平的可连通的网络 K8S的网络是一个极其复杂的网络,如果想要用两个简单的词来描述K8S网络,那么我觉得扁平和可连通是K8S网络最大的特点(不懂隔离性)。 何为连通呢? 二层网络的连通:如果能够直接通过MAC帧直接通信的网络便是二层连通的网络,LAN就是这种网络 比如无限WIFI网络,比如以太网 三层网络的连通:如果能够通过IP报直接通信的网络便是三层连通的网络,便是三层连通 三层网络的连通分为两个部分,第一个部分是三层网络中的每一个LAN都是二层连通的,其次需要存在能够连通的路由来保证;这里可以简单回顾下三层网络通信的流程 通过路由表确定目标ip是否在链路上 如果在链路上,通过arp协议获取对应主机的mac地址,发送mac帧到链路上; 如果不在同一个链路上,通过本地路由表发送mac帧给下一跳,然后下一跳解析mac帧,分析ip报,继续路由直到最终跳到目标网络再次通过mac帧发送到目标主机或者到达ttl消失。 假如其中任何一个步骤不满足或者出问题,三层网络就无法连通 何为扁平呢? 就是希望可以在pod内直接通过IP进行互相通信而不需要在pod内部使用vpn之类的东西来连接其他pod(基础架构化),具体的可以看下k8s对网络的设计与要求。 k8s在设计其网络时,就希望网络对运行在其中的pod是透明的,因此提出了以下的一些要求与原则 k8s组网要求 所有的Pods之间可以在不使用 NAT网络地址转换 的情况下相互通信 所有的Nodes之间可以在不使用NAT网络地址转换的情况下相互通信 每个Pod自己看到的自己的ip和其他Pod看到的一致 k8s网络模型设计原则 每个Pod都拥有一个独立的 IP地址,而且 假定所有 Pod 都在一个可以直接连通的、扁平的网络空间中 。 不管它们是否运行在同 一 个 Node (宿主机)中,都要求它们可以直接通过对方的 IP 进行访问。 设计这个原则的原因 是,用户不需要额外考虑如何建立 Pod 之间的连接,也不需要考虑将容器端口映射到主机端口等问题。 而要想深入了解K8S的网络,就不得不去了解Linux操作系统中的网络以及计算机网络协议栈和一些网络技术 其中关于计算机网络协议栈道部分上次分享已经分享过了,所以本次的主题更多是Linux操作系统的网络以及一些网络技术 Linux操作系统中的网络 首先,我们来看下基本的linux网络,如下图所示 一个APP生成socket数据,然后经过网络协议栈包装IP报文,然后封装成MAC帧,在经过网络协议栈的过程中,会存在netfilters对数据进行一定的处理,同时也会存在路由的过程, 如果在同一个物理链路内,将直接通过ARP协议获取目标IP地址的MAC地址最终发送出去; 如果不在同一个物理链路则通过路由表确定下一跳的MAC地址,封装成MAC帧发送到目标地址。 在这个过程中,会根据路由表选择对应的端口,如果是lo端口,则会将帧原封不动的返回计算机网络协议栈,然后回到监听对应端口的SOCKET里。 如果是以太网端口则走以太网端口,如果是蓝牙或者无线网端口同理。 iptables与netfilters iptables是一个用户空间的应用程序,通过该程序可以修改一些配置文件,这些文件定义了防火墙的一些行为,netfilters是操作系统内核的一部分,netfilters里有5个回调钩子会触发iptables里的规则;iptables只是Linux防火墙的管理工具而已,位于/sbin/iptables。 真正实现防火墙功能的是netfilter,它是Linux内核中实现包过滤的内部结构。 这里不具体讲述其实现的原理,仅仅列出netfilters的一些功能: 1)filter表——三个链:INPUT、FORWARD、OUTPUT 作用:过滤数据包 内核模块:iptables_filter. 2)Nat表——三个链:PREROUTING、POSTROUTING、OUTPUT 作用:用于网络地址转换(IP、端口) 内核模块:iptable_nat 3)Mangle表——五个链:PREROUTING、POSTROUTING、INPUT、OUTPUT、FORWARD 作用:修改数据包的服务类型、TTL、并且可以配置路由实现QOS内核模块:iptable_mangle(别看这个表这么麻烦,咱们设置策略时几乎都不会用到它) 4)Raw表——两个链:OUTPUT、PREROUTING 作用:决定数据包是否被状态跟踪机制处理 内核模块:iptable_raw 虚拟网络设备 tap/tun TUN 和 TAP 设备是 Linux 内核虚拟网络设备,纯软件实现。 TUN(TUNnel)设备模拟网络层设备,处理三层报文如 IP 报文。 TAP 设备模拟链路层设备,处理二层报文,比如以太网帧。 TUN 用于路由,而 TAP 用于创建网桥。 OS 向连接到 TUN/TAP 设备的用户空间程序发送报文;用户空间程序可像往物理口发送报文那样向 TUN/TAP 口发送报文,在这种情况下,TUN/TAP 设备发送(或注入)报文到 OS 协议栈,就像报文是从物理口收到一样。 虚拟网络设备 veth-pairs 虚拟以太网电缆。 使用双向有名管道实现。 常用于不同 namespace 之间的通信,即 namespace 数据穿越或容器数据穿越。 虚拟网络设备 bridge bridge是linux自带的虚拟交换机(网桥),其可以连接多个以太网设备,拥有智能处理MAC帧的能力,流向交换机的MAC帧将智能的被传输到相应的二层链路 网络命名空间 在 Linux 中,网络名字空间可以被认为是隔离的拥有单独网络栈(网卡、路由转发表、iptables)的环境。 网络名字空间经常用来隔离网络设备和服务,只有拥有同样网络名字空间的设备,才能看到彼此。 从逻辑上说,网络命名空间是网络栈的副本,有自己的网络设备、路由选择表、邻接表、Netfilter表、网络套接字、网络procfs条目、网络sysfs条目和其他网络资源。 从系统的角度来看,当通过clone()系统调用创建新进程时,传递标志CLONE_NEWNET将在新进程中创建一个全新的网络命名空间。 从用户的角度来看,我们只需使用工具ip(package is iproute2)来创建一个新的持久网络命名空间。 从系统实现来说,就是原本一个数据结构是static公共的,后来变成进程私有的,在PCB里存在一个命名空间的结构,命名空间里有着网络命名空间,网络命名空间拥有着所有跟网络相关的配置数据 默认空的网络命名空间可能只有一个未启动的lo回环网卡。 两个网络命名空间可以通过以太网揽直接连着两个网络命名空间的网卡,也可以通过以太网网桥连接。 通过以太网网桥或者以太网揽连接的两个网络命名空间只能说是在二层连通的,如果希望在三层连通,还需要给每个网络命名空间配置相应的路由表规则以及分配IP地址。 如何使用虚拟网络设备联通网络命名空间 SingleHost容器网络 none模式 本质上就是创建一个网络命名空间,里面没有路由表,也没有通过veths-pair连接任何链路,外部无法访问这个容器,容器也无法访问外部 host模式 本质上就是使用宿主机的默认网络命名空间 container模式 本质上就是将当前容器部署在另一个容器所在的网络命名空间,这样发给本地的报文最终通过回环网卡回到了本机,这是同一个网络命名空间可以互通的原因 bridge模式 桥接模式就是在这些网络命名空间通过veth-pairs连接到同一个虚拟交换机上(二层连通),同时在对应的命名空间配置对应的路由表规则,但是从图片中可以看到交换机另一端连的上网络协议栈。 也就是那些MAC帧都会被宿主机接收,但是宿主机接收并不一定会处理,比如并没有开启ip转发功能(工作于路由器模式还是主机模式),那么不是本地ip的报文都会被丢弃;或者说netfilters拒绝处理 这些奇怪的报文。 理论上,这些容器发送给其他容器的mac报文是会被虚拟交换机智能转发到对应的容器的,这是同一主机不同容器互相连通的原因 假如宿主机配备了相应的路由规则和防火墙规则,那么容器的报文说能够通过路由最终转发出去的,这也是容器访问互联网的原理 但是这种模式是没法运用在多主机的情况下,因为宿主机不知道其他宿主机里的虚拟网络的路由,当相关ip报到达宿主机时,这些ip报将会被宿主机交给默认路由(下一跳:路由器) 最终路由器会把相关的ip报丢失或者到达ttl最终丢失 MultiHost容器网络 路由方案 回顾docker的单机网络模型,我们发现多主机不能通行的原因就在于你只能给当前主机配置路由规则和防火墙规则,而其他主机并不知道这些ip在你的虚拟网络中,假如能够将这些路由信息同步到其他 宿主机,那么网络便会打通。 比较直接的想法就是给每台宿主机配置路由规则。 而路由规则要求下一跳必须在当前网络,所以假如宿主机是二层互联的,那么通过给这些宿主机同步这些路由规则便能够 实现一个扁平的连通的网络。 其中布置在每一台宿主机可以通过k8s的daemonSet实现,而这种数据的管理可以交给etcd来实现。 这类方案便是基于路由,基于这个方案的实现有基于静态路由的flannel的host-gateway,以及基于动态路由的calico(使用边际路由协议以及一堆深奥的名词的实现)。 下面来看看Flannel的host-gateway原理(每一台宿主机都相当于本机容器网络的路由器): 通过路由方案构建的网络,宿主机也能访问这些虚拟网络里的Pod 询问基德大佬得知国际化sit环境的k8s网络接口实现就是Flannel的Host-gateway,而我们的办公网络和集群网络之间的路由是搭建好的,所以我们应该可以直接通过podId访问pod里的服务 下面是sit环境的两个服务 跟踪路由发现符合猜想 其中10.1.9.56和10.1.1.24就是宿主机的ip,这些宿主机在一个LAN里,这些宿主机相当于虚拟网络中的路由器; 猜测我们办公网和qunhe集群在一个VLAN里(二层可达) 隧道方案 隧道方案比较典型的就是UDP和XVLAN,两者都是使用Overlay网络(覆盖网络,所谓的大二层技术);其实用隧道技术最多的是VPN应用 其中UDP是XVLAN的替代品(早期Linux没有支持XVLAN协议,通过tun/tap技术将流量引到用户空间然后解包生成包再发,因为发生在用户空间而且多次copy导致性能较差,所以一般不推荐,除非你的linux版本比较低没法用xvlan) 下面就简单介绍下XVLAN技术的大概原理,下图是XVLAN的报文格式,可以发现就是在高层协议的报文里塞了二层报文 其中XVLAN头里有一个关键的字段,VNID这是个24位的字段,每个虚拟的网络主机都有一个自身的VNID作为标识,理论上支持2的24次方个虚拟网络。 在docker的桥接网络里,是使用docker0网桥,在Flannel的xvlan方案里则是使用cni0作为网桥(和docker0没啥区别),主要的不同是cni网桥后面连接的是flannel.1这个网络设备,应该是一个虚拟网卡 这个网卡将原始报文包装成XVLAN报文(linux高版本支持xvlan报文) 这时需要的信息有 源nodeId,目标nodeId,源vnid,源macId,目标macId,源podId,目标podId 其中目标nodeId,目标macId这两个信息是不存在的;因此需要有个方式根据目标podId获取目标nodeId以及目标macId 因此需要记录如何根据目标podId获取目标macId以及目标nodeId即可 这些数据是可以托管在某个地方的,Flannel就是将这些信息记录在etcd上 在每个node上的flannel.1网络设备通过etcd来通过对方的podId获取nodeId和macId 这样最终报文就变成了一个源ip是源nodeIp,目标ip是目标nodeIp的IP报文了(两台宿主机三层可达) 原本经过虚拟网桥是直接连接网络协议栈,但在xvlan模式下,则改为连接一个flannel1,在flannel1中将对原始报文封装成overlay报文转发 udp模式类似,只是udp转发报文说通过tap连通到用户空间,用户空间对报文进行处理然后发送(因为多次内核态用户态切换且数据copy问题,性能较差,仅在不支持xvlan的低版本linux中使用) 当然xvlan是一个技术,上面只是简单介绍最简单的形式 参考: 开发内功修炼之网络篇:K8S知识图谱:VXLAN协议原理简介:
免责声明:本文转载或采集自网络,版权归原作者所有。本网站刊发此文旨在传递更多信息,并不代表本网赞同其观点和对其真实性负责。如涉及版权、内容等问题,请联系本网,我们将在第一时间删除。同时,本网站不对所刊发内容的准确性、真实性、完整性、及时性、原创性等进行保证,请读者仅作参考,并请自行核实相关内容。对于因使用或依赖本文内容所产生的任何直接或间接损失,本网站不承担任何责任。