共计 14153 个字符,预计需要花费 36 分钟才能阅读完成。
作者:若禾
CNStack 是阿里云推出的一款凋谢的一站式企业级云原生技术中台。在异构的混合云基础设施上,对资源进行对立纳管和优化调度,以凋谢的、云原生的形式为平台及业务零碎提供生产可用的产品及组件,帮忙用户打造满足大规模、高性能、合规性和业务连续性等要求的分布式应用零碎,晋升企业数字化转型的整体效力。hybridnet 是 CNStack 应用的容器网络实现,同时也是阿里云推出的唯二开源通用 K8s 网络插件实现之一。
开源仓库地址:https://github.com/alibaba/hybridnet
解释下“通用”俩字,阿里云目前存在两种开源 K8s 网络插件实现:terway、hybridnet。与 hybridnet 网络插件不同,terway 网络插件是与阿里云基础设施紧密结合的,并不思考在非阿里云私有云基础设施环境部署的状况,而 hybridnet 更像是相似 flannel、calico 的社区解决方案,反对在任意环境拉起和部署。本文会详细描述 hybridnet 网络插件的设计与实现。
背景
从诞生到当初,在阿里外部 hybridnet 始终承载的是“私有化交付基石”的角色,即为以 K8s 为交付媒介的 PaaS/SaaS 产品提供在客户线下机房的网络部署、运维能力,其性质看起来也就和“为所有人提供 K8s 网络”更加相似,咱们对 hybridnet 的冀望有几点:
- 架构简略、性能稳固。对于要交付到客户线下机房的产品,一旦呈现问题,排查老本是十分高的,稳定性是重中之重。
- “On Anywhere”部署。这的确是一开始的冀望,听起来不堪设想,但某种程度上的确实现了。
- 灵便。可能满足不同客户性能需要以及就宽泛通用场景进行性能扩大。
- 运维简略。负责交付施行的同学可能疾速上手。
当然,社区也存在泛滥优良的网络插件实现,咱们也对其进行了理解和调研,总结下最终没有采纳的起因:
- 社区网络插件的网络模式是绝对简略的,不是 overlay 就是 underlay,看下来没法既实现“On Anywhere”部署,又满足客户对于 underlay 网络场景的需要(性能或者网络买通)。
- 对于 underlay 网络场景需要,社区提供的支流解决形式始终是“只提供通过 bgp 宣告路由”的形式,这种形式对没有进行 bgp 组网的公司并不是很敌对,咱们仍须要没有 bgp 条件环境下的容器网络实现(也就是 vlan 形式),这方面社区并没有十分成熟的计划。
- 大部分社区网络插件的 ip 调配是“为节点调配网段”的模型,仿佛并没有思考处于“传统运维”过渡到“云原生运维”阶段用户可能存在的“须要容器固定 ip 被拜访”的场景,也难以扩大实现。
- 局部社区网络插件的技术体系(ovs、ebpf)在运维、二次开发方面的门槛和老本比拟高。
设计与实现
如何“On Anywhere”
在设计之初,须要想明确的一个问题是:如何既实现“On Anywhere”部署又满足客户对于 underlay 网络场景的需要?首先咱们要了解 overlay、underlay 在交付场景下的不同意义。
“overlay”的网络计划作为在根底网络之上构建的形象网络,自身其实就是屏蔽了底层基础设施依赖的,以 vxlan 容器网络为例,容器网络的 ip 流量被封装成宿主机的 udp 数据包,依赖的只是比较简单的“底层网络环境放行 udp 流量”能力,其实曾经具备了“On Anywhere”部署的条件。
而在“underlay”容器网络计划中,容器网络的报文被“一成不变”地通过宿主机网卡转发到根底网络环境里,借助底层网络实现后续的通信,底层网络环境须要具备买通以及放行所有容器网络流量的能力,这就在不同场景下带来了交付上的重重挑战,交付一个 underlay K8s 集群时,在 K8s 集群能失常工作之前,咱们须要客户帮助进行的工作包含然而不限于“申请 / 布局网段”、“配置交换机端口”、“配置交换机路由”、“批改防火墙”等等,整个过程因为门槛因素往往须要网络专家直接参与,极大减少了交付老本。
随着交付教训的积攒,咱们发现,大部分须要私有化交付的产品是不依赖 underlay 网络能力的,即使是产品须要依赖 underlay 能力,这部分 pod 的数量在整个集群中的占比也通常比拟小,大部分产品的治理组件 pod 并没有非凡的网络要求。也就是说,对于大部分产品,如果可能保障治理组件在任何环境中能失常拉起,那产品的应用是不成问题的,其余配置甚至能够在交付后的阶段增量进行,晋升交付效率。
进而咱们得出了论断:“咱们须要一个 overlay 和 underlay 网络可能同时存在的集群,其中 underlay 网络是否失常不影响 overlay 网络,underlay 网络能够增量配置,并且集群内 overlay 网络能和 underlay 网络不依赖基础设施互通”,这仿佛就是目前私有化场景“On Anywhere”部署的正确答案。
通过 CRD 配置管理集群网络
为了便于管理,咱们须要一个形式对立形容 overlay、underlay 容器网络资源,思考到 underlay 容器网络依赖是对底层基础设施敏感的,并且往往呈现出“节点分组”的景象(比方同一交换机下的节点可能应用雷同网段),咱们提出了“网络域”的概念。
网络域中蕴含了一组具备雷同网络性质(比方,处于雷同 VLAN 环境、属于同一网关、属于雷同二层网络)的节点,作为创立 ip 的底层资源。一个网络域具备这样的性质:“一个带有特定地址的 Pod 如果能被部署到网络域内的某一节点,那么带有雷同地址的 Pod 应该能被调度到同一网络域内的其余任意节点”。对应了 Network CR 对象。在集群中能够通过 kubectl get network 命令查看,比方:
[root@iZf8z4x1svumpy31kcrltaZ ~]# kubectl get network init -oyaml
apiVersion: networking.alibaba.com/v1
kind: Network
metadata:
annotations:
meta.helm.sh/release-name: hybridnet
meta.helm.sh/release-namespace: kube-system
creationTimestamp: "2023-02-10T05:52:11Z"
generation: 1
labels:
app.kubernetes.io/managed-by: Helm
webhook.hybridnet.io/ignore: "true"
name: init
resourceVersion: "40647"
uid: cc889b11-9ede-4711-93b3-910f0e59335e
spec:
netID: 4
type: Overlay
status:
dualStackStatistics:
available: 65526
total: 0
used: 0
ipv6Statistics:
available: 65534
total: 65535
used: 1
lastAllocatedIPv6Subnet: init-2
lastAllocatedSubnet: init
nodeList:
- izf8z4x1svumpy31kcrltaz
- izf8zatm3b8zaaks5gqk0tz
statistics:
available: 65526
total: 65534
used: 8
subnetList:
- init
- init-2
Network 对象通过 nodeSelector 抉择带有特定 label 的节点作为网络域中的节点,借助网络域的概念,咱们实现了依赖特定网络资源 pod 的主动调度。
后面咱们说到,overlay 网络是不依赖底层网络资源的,所以创立 overlay 的 Network 对象时,nodeSelector 肯定只能为空,并且每个集群只能创立一个 overlay 的网络域,这网络域对应了集群内的所有节点
通过“网络域”概念解决了“基于网络资源的可用节点范畴对 pod 进行自动化调度”问题之后,咱们还须要引入一个 Subnet 对象形容 ip 地址调配信息。
Subnet 对象是依附于 Network 对象的,每个 Subnet 必须且只能属于一个 Network,同一个 Network 中能够有多个 Subnet。每个 Subnet 对象形容了该网络域内一个可用的容器网段的地址信息,比方:
[root@iZf8z4x1svumpy31kcrltaZ ~]# kubectl get subnet init -oyaml
apiVersion: networking.alibaba.com/v1
kind: Subnet
metadata:
annotations:
meta.helm.sh/release-name: hybridnet
meta.helm.sh/release-namespace: kube-system
creationTimestamp: "2023-02-10T05:52:11Z"
generation: 1
labels:
app.kubernetes.io/managed-by: Helm
webhook.hybridnet.io/ignore: "true"
name: init
resourceVersion: "40646"
uid: ca73b837-b28f-4727-949d-d06f152202ed
spec:
config:
autoNatOutgoing: true
network: init
range:
cidr: 172.24.0.0/16
version: "4"
status:
available: 65526
lastAllocatedIP: 172.24.0.23
total: 65534
used: 8
每个 hybridnet 集群要失常工作,至多须要存在一个 Network 和 Subnet。能够说 Network 和 Subnet 对象就是 hybridnet 对用户提供的配置入口。对于每个 pod 的 ip,hybridnet 会主动创立一个 IPInstance 对象,该 CRD 是 namespace scope 的,与 pod 处于雷同 namespace。IPInstance 对象次要的性能是用来长久化 hybridnet 地址调配信息,当然也能够用来提供给用户查问和审计,对于用户来讲,通常是只读的。
基于策略路由的 overlay/underlay 混合数据链路
策略路由
Linux 内核的路由能力其实十分弱小,绝大部分场景下咱们只用到了其中的一小部分,比方在一台 Linux 机器上运行 ip route 命令,咱们会失去上面的输入:
[root@iZf8z4x1svumpy31kcrltaZ ~]# ip route
default via 172.16.255.253 dev eth0
169.254.0.0/16 dev eth0 scope link metric 1002
172.16.0.0/16 dev eth0 proto kernel scope link src 172.16.69.139
这就是咱们所常常看见的“路由表”,但这其实只是内核的其中一张名字叫做“main”的路由表,也是个别状况下,咱们“增加路由”、“删除路由”的操作对象。
Linux 内核从 2.2 版本开始就反对了 策略路由(Policy Route)能力,通过执行 ip rule 命令咱们能够看到策略路由规定,默认状况下 Linux 操作系统中默认会存在“local”、“main”、“default”三张路由表,其中最后面的数字代表了优先级,数字越小,优先级越高,优先级从高到低第一张可能匹配流量的路由表会失效:
[root@iZf8z4x1svumpy31kcrltaZ ~]# ip rule
0: from all lookup local
32766: from all lookup main
32767: from all lookup default
其中“default”个别为空,“local”表中比拟要害的是存在了带有 local 关键字的路由条目,对应了每个节点的本地 ip 地址,示意发送到本机的哪些流量应该不进行转发间接进入下层协定栈解决:
[root@iZf8z4x1svumpy31kcrltaZ ~]# ip route show table default
[root@iZf8z4x1svumpy31kcrltaZ ~]# ip route show table local
broadcast 127.0.0.0 dev lo proto kernel scope link src 127.0.0.1
local 127.0.0.0/8 dev lo proto kernel scope host src 127.0.0.1
local 127.0.0.1 dev lo proto kernel scope host src 127.0.0.1
broadcast 127.255.255.255 dev lo proto kernel scope link src 127.0.0.1
broadcast 172.16.0.0 dev eth0 proto kernel scope link src 172.16.69.139
local 172.16.69.139 dev eth0 proto kernel scope host src 172.16.69.139
broadcast 172.16.255.255 dev eth0 proto kernel scope link src 172.16.69.139
数据链路概述
在一个 hybridnet 集群内,流量的行为总体形容如下:
- 同一节点上的 pod 之间通信的流量只在节点外部转发
- overlay pod 与其余 pod(包含 underlay pod)相互拜访的流量都是隧道流量
- underlay pod 拜访非 overlay pod 的流量(包含节点、集群外 ip 地址)为非隧道流量
- 集群内节点拜访 overlay pod 的流量为隧道流量(不通过 NAT)
- overlay pod 拜访集群内节点以及集群内部 ip 的流量为 NAT 流量(SNAT 成对应节点 ip)
数据链路齐全基于策略路由实现,这让 hybridnet 跟 kube-proxy、felix 的 iptables/ipvs 规定以及其余相似的 service/networkpolicy 实现可能良好地适配,其流量门路如图:
在一个只有 overlay 网段的环境(这里有两个网段,咱们认为环境中只有 ipv4 的 172.24.0.0/16,ipv6 的策略路由要应用 ip -6 rule 查看,逻辑一样),能够看到节点策略路由规定如下:
[root@iZf8z4x1svumpy31kcrltaZ ~]# kubectl get subnet
NAME VERSION CIDR START END GATEWAY TOTAL USED AVAILABLE NETID NETWORK
init 4 172.24.0.0/16 65534 8 65526 init
init-2 6 5408:4003:10bb:6a01:83b9:6360:c66d:0000/112 65535 1 65534 init
[root@iZf8z4x1svumpy31kcrltaZ ~]#
[root@iZf8z4x1svumpy31kcrltaZ ~]#
[root@iZf8z4x1svumpy31kcrltaZ ~]#
[root@iZf8z4x1svumpy31kcrltaZ ~]#
[root@iZf8z4x1svumpy31kcrltaZ ~]# ip rule
0: from all lookup local
1: from all lookup 39999
2: from all lookup 40000
3: from all fwmark 0x20/0x20 lookup 40001
4: from 172.24.0.0/16 fwmark 0x0/0x4040 lookup 10000
32766: from all lookup main
32767: from all lookup default
[root@iZf8z4x1svumpy31kcrltaZ ~]#
咱们能够看到 hybridnet 在策略路由中增加了四条规定,别离对应了 39999、40000、40001、10000 的路由表,表中的路由条目别离如下:
[root@iZf8z4x1svumpy31kcrltaZ ~]# ip route show table 39999
172.24.0.1 dev hybr6b3adcd7e1e
172.24.0.4 dev hybr1b7a9ed1883
172.24.0.7 dev hybr6809d4b1e0e
172.24.0.9 dev hybr56df5339e20
172.24.0.11 dev hybr3c237dc2041
[root@iZf8z4x1svumpy31kcrltaZ ~]# ip route show table 40000
172.24.0.0/16 dev eth0.vxlan4
[root@iZf8z4x1svumpy31kcrltaZ ~]# ip route show table 40001
default dev eth0.vxlan4
[root@iZf8z4x1svumpy31kcrltaZ ~]# ip route show table 10000
[root@iZf8z4x1svumpy31kcrltaZ ~]#
用起码的策略路由规定数量,咱们实现了 hybridnet 的数据链路:
- 对于 39999 路由表中的每个条目,其指标网段为本节点上 pod 的 ip 地址、进口设施为 pod 对应的 veth 设施。这个路由表的会解决所有指标地址为本机上 Pod 的流量,将其间接发送给本机 pod 的 netns 解决。咱们能够看到 39999 表的优先级是最高的
- 对于 40000 路由表中的每个条目,其指标网段为集群内的 overlay 网段、进口设施为 vxlan 设施。这个路由表解决了所有指标地址为 overlay 容器网段的流量,保障所有发往 overlay pod 的流量会通过 vxlan 设施进行隧道封装(这里没有配置 nexthop,示意下一跳 ip 就为数据包的指标 ip)
- 40001 路由表中目前只有一条 default 路由,它的作用是让“其余节点拜访本节点上 overlay pod”的反向流量通过 overlay 设施,达到“集群内节点拜访 overlay pod 的流量为隧道流量(不通过 NAT)”的成果
- 10000 路由表其实比拟非凡,咱们能够看到它对应的策略路由规定是 from 172.24.0.0/16 fwmark 0x0/0x4040 lookup 10000,以这条规定为例,它示意“只有源 ip 在 172.24.0.0/16 网段中并且没有相干 mark 的流量才会进入 10000 表处理”。对于集群内每个容器网段都会有这样一条策略路由规定,对应路由表中的条目形容了“从本节点上对应该容器网段 pod 中收回的流量”应该如何解决,不同网络模式的网段会有不同的规定:
-
- 对于 overlay 的网段(overlay 只有 vxlan [ 1] 模式),路由表内每个路由条目代表发送到某个 underlay 网段的流量。比方咱们在集群内通过 增量进行 underlay 网络配置 [ 2] ,增加了两个 192.168.56.0/24 和 192.168.57.0/24 的 Subnet(以及对应的 Network),一个为 vlan [ 3] 模式,一个为 bgp [4 ] 模式,10000 路由表会变成这样(因为 192.168.56.1 是 vlan 网段的网关,用 throw 类型的条目疏忽):
[root@iZf8z4x1svumpy31kcrltaZ ~]# ip route show table 10000
192.168.56.0/24 dev eth0.vxlan4
throw 192.168.56.1
192.168.57.0/24 dev eth0.vxlan4
-
- 对于 vlan 模式的网段,路由表的内容是固定的,一条指标地址为本网段 CIDR 的间接路由,一条下一跳为网段网关 ip(对应 Subnet 对象的 spec.range.gateway 字段)的默认路由,指标是让同网段的流量间接走物理网卡发送进来,跨网段的流量走内部网关路由进行转发,在对应 vlan 网络域中的节点上查看路由规定:
[root@iZf8z4x1svumpy31kcrltaZ ~]# ip rule
0: from all lookup local
1: from all lookup 39999
2: from all lookup 40000
3: from all fwmark 0x20/0x20 lookup 40001
4: from 172.24.0.0/16 fwmark 0x0/0x4040 lookup 10000
5: from 192.168.56.0/24 fwmark 0x0/0x4040 lookup 10001
32766: from all lookup main
32767: from all lookup default
[root@iZf8z4x1svumpy31kcrltaZ ~]#
[root@iZf8z4x1svumpy31kcrltaZ ~]#
[root@iZf8z4x1svumpy31kcrltaZ ~]#
[root@iZf8z4x1svumpy31kcrltaZ ~]#
[root@iZf8z4x1svumpy31kcrltaZ ~]# ip route show table 10001
default via 192.168.56.1 dev eth0
192.168.56.0/24 dev eth0 scope link
[root@iZf8z4x1svumpy31kcrltaZ ~]#
-
- 对于 bgp 模式的网段,路由表的内容是固定的,一条下一跳为 BGP 网关 ip(对应 Network 对象的 spec.config.bgpPeers[0].address 字段,这个地址须要是以后节点路由可达的)的默认路由,指标是让所有流量走内部网关路由进行转发,在对应 bgp 网络域中的节点上查看路由规定:
[root@iZf8zatm3b8zaaks5gqk0tZ ~]# ip rule
0: from all lookup local
1: from all lookup 39999
2: from all lookup 40000
3: from all fwmark 0x20/0x20 lookup 40001
4: from 172.24.0.0/16 fwmark 0x0/0x4040 lookup 10000
5: from 192.168.57.0/24 fwmark 0x0/0x4040 lookup 10001
32766: from all lookup main
32767: from all lookup default
[root@iZf8zatm3b8zaaks5gqk0tZ ~]# ip route show table 10001
default via 172.16.255.253 dev eth0
[root@iZf8zatm3b8zaaks5gqk0tZ ~]#
链路实现细节
如何让宿主机成为路由器
要应用策略路由构建容器网络,咱们须要宿主机来“路由”节点上所有 pod 的流量,也就是成为本节点所有 pod 的路由器。这一点其实和 calico 是一样的,咱们沿用了雷同的设计。
进入 pod 能够看到,pod netns 外部(main 表)只存在一条 default 路由条目,并且该路由条目标下一条 ip 为一个固定的不存在的 ip 地址(hybridnet 应用的是和 calico 雷同的 169.254.1.1、fe80::ecee:eeff:feee:eeee);在 pod netns 内部,host 侧会在 pod 对应的 veth 设施上配置 proxy_arp/proxy_ndp,保障所有从 pod 中收回的、“下一跳地址为上述不存在地址”的流量都能被 host netns 解决。
虚构大二层的 vxlan 网络
对于 calico、flannel 而言,“节点绑定网段”是容器网络 ip 调配的根本模型。在 hybridnet 中,因为存在“固定 ip”的诉求,如果节点固定某一个或者某几个容器网段的话,固定了 ip 的 pod 也会被迫与节点生命周期绑定,极大地影响了 pod 的可用性。咱们心愿每个 overlay 网段都是整个集群节点范畴内可用的,固定了 ip 的 pod 能够漂移到集群的其余节点上,同时也具备更加简略灵便的 ip 扩容能力(不须要思考节点上容器网段大小)。
在 overlay 的计划上(只有 vxlan 模式),咱们参考了 flannel 的实现。大同小异,对于如何应用 linux 内核的 vxlan 虚构设施进行组网,须要思考两个问题:
- 咱们须要 vxlan 设施可能像“外接了交换机的物理网卡”一样工作,也就是说,数据包在由 vxlan 设施收回时,vxlan 设施须要可能解决该数据包的指标 mac 地址,这部分配置是须要咱们去组织 vxlan 设施 fdb 表的,它决定了“哪个 mac 要发往哪个 VTEP ip”
- 当 vxlan 设施变成一张可用网卡后,咱们须要配置这张网卡相干的路由表,并且在跟 vxlan 设施相干的条目中须要给出一个可用的(可能被街坊解析的)下一跳 ip,让流量可能被正确从 vxlan 设施收回
在 flannel 历史上,存在三个版本的数据链路实现(能够在 flannel 代码 正文 [ 5] 里看到):
- 第一个版本,flannel 会在用户态监听 vxlan 设施的 L2/L3 miss 事件,这次要指两个阶段:
-
-
当容器数据包在实现路由查问后要从 vxlan 设施收回之前,须要依据路由表的下一跳 ip 进行街坊解析,以填充容器数据包的指标 mac 地址。因为此时没有对应的街坊缓存,这会收回一个 L2 miss 事件,flannel 用户态过程在监听到 L2 miss 事件之后会通过事后在 etcd 中记录的信息返回后果,提供对应该下一跳 ip 的正确 mac 地址
- 当容器数据包被填充结束后,会进入 vxlan 设施外部的发送逻辑。此时 vxlan 设施须要晓得对应容器数据包 mac 地址的 VTEP 网关 ip 是什么,以结构对应的 udp 数据包,这个时候会产生一个 L3 miss 事件,flannel 用户态过程在监听到之后会通过事后在 etcd 中记录的信息返回后果,提供对应容器网段 ip 所在节点上的宿主机 ip 地址
-
- 第二个版本,flannel 移除了 L3 miss 事件的用户态解决。因为宿主机被退出集群之后 ip 根本不会再发生变化,所以 flannel 会在发现节点的时候,间接更新每个节点上的 vxlan fdb 表项,将宿主机的 ip 地址写入。
- 第三个版本也就是当初的版本,为了晋升 flannel 的可靠性(如果数据链路依赖用户态过程,在 flannel 更新或者临时 Crash 的时候,节点上的容器网络通信会断开,也就是数据链路连通性和治理组件生命周期是紧耦合的),flannel 移除了 L2 miss 事件的用户态解决,采纳“发现节点之后间接为节点调配网段”的形式,为每个节点增加一条动态街坊缓存,并且为每个其余节点上的网段增加一条固定的路由规定
通过学习 flannel 的历史,不难发现,对于“vxlan 设施上街坊解析过程”(L2 miss 事件)的解决,是是否去掉“节点绑定网段”限度的要害。基于这一点,hybridnet 做出了和 flannel 不同的抉择,咱们在放弃数据链路连通性与组件生命周期松耦合的同时,实现了“容器网段跨节点”的 ip 调配模型。
在 hybridnet 中,vxlan 网络的配置具备以下特点:
- 进口设施为 vxlan 设施的路由都是没有指定“下一跳”的,也就是当数据包从 vxlan 设施上收回时,街坊解析的指标 ip 与数据包的指标 ip 统一
- 每个节点上,hybridnet 会为本节点上的所有 pod ip 配置 vxlan 设施上的 proxy 类型街坊缓存条目,这意味着宿主机会主动解决从 vxlan 设施上收到的街坊申请,并且将 vxlan 设施的 mac 地址作为后果响应,这样,所有的 pod 之间通过 vxlan 网络通信实际上应用的是 pod 所在节点的 vxlan 设施 mac 地址
- hybridnet 会在 vxlan 设施中为每个节点的 VTEP ip 配置 00:00:00:00:00:00 dev dst self permanent 的 fdb 条目,这种指标 mac 全零的条目标 VTEP ip 造成了一个组,当数据包的指标 mac 地址没有匹配到任何 fdb 条目时,内核会将数据包封装成 udp 隧道包并且别离拷贝一份发向该组中所有 VTEP ip
- hybridnet 会在 vxlan 设施中为每个节点的 VTEP ip 和 VTEP mac(节点 vxlan 设施的 mac 地址)配置 dev dst self permanent 的 fdb 条目,当数据包的指标 mac 地址匹配到 VTEP mac 时,内核会将数据包封装成 udp 隧道包发向对应 VTEP ip
- hybridnet 会有用户态过程监听 vxlan 设施的 L2 miss 事件,当呈现这种事件时,hybridnet 会查问 IPInstance 对象以及节点信息(通过 k8s informer 的本地缓存,通常比拟快),如果查问到了,会间接返回对应街坊解析的后果,跳过内核态街坊解析的播送报文发送过程
总体来讲,因为 pod 通过 vxlan 网络通信的 mac 地址都是其所在节点的 vxlan 设施 mac 地址,所以 vxlan 设施的 fdb 表规模是可控的,通过“每个节点的 VTEP ip 和 VTEP mac(节点 vxlan 设施的 mac 地址)fdb 表配置”,所有单播的报文都可能被失常解决。对于可能发送播送报文的街坊解析申请,咱们应用“手动保护播送组”和“用户态监听 L2 miss 代理街坊解析”的形式,前者会保障组件异样时不影响网络通信,后者会在组件失常工作时升高甚至打消因为播送产生的流量开销。
更多对于如何配置 vxlan 网络能够查看 wiki 中“vxlan 网络”局部。
路由实现的 vlan 网络
对于 vlan 模式的网络,hybridnet 次要逻辑为:
- 为 netID 不为 0 的网段,创立 vlan 虚构设施;如果 netID 为 0,间接应用宿主机网卡自身进行通信
- 在容器网络流量进口设施(如下面所说,可能是 vlan 虚构设施也可能不是)上为节点上所有 vlan 模式的 pod ip 创立 proxy 类型街坊缓存
联合“数据链路概述”中形容的 vlan 网段路由规定,大抵梳理规定之后咱们会发现,此时实践上网络曾经能通了,内部流量看起来会和二层桥接的流量统一,容器会应用宿主机网卡的 mac 地址进行通信。然而其实依然存在问题,问题次要在于内核发送 arp 申请的 sender ip 抉择过程。
在咱们的设计中,当 vlan 的 pod 要对外进行通信时,pod 对于同网段或者网关地址的 arp 申请永远是由宿主机收回的,又因为 underlay 网络的 ip 地址比拟贵重,咱们不心愿节约地址在节点上,所以并没有为节点调配任何容器网段的地址(overlay 网络也是一样);这就造成了,宿主机在替 pod 发送 arp 申请时只能将本人的 ip 填充到申请的 sender ip 字段。对于某些交换机,这类流量是非法的,因为看起来是“跨网段的街坊解析申请”。
通过考察相干内核逻辑咱们发现,在这种状况,内核决定 arp 申请 sender ip 时的逻辑次要为“优先选择网卡上第一个跟 target ip 在同一网段,并且 scope 为 link 或者 global 的地址”,同时又因为须要防止 scope 为 global 的地址可能被内核子系统“源地址抉择”过程选中,所以咱们须要的是一个同网段中,scope 为 link 的 ip 地址。
为了解决这个问题,咱们引入了“enhanced address”配置。大抵思路是,对于节点所在 vlan 网络域中的所有网段,当进口设施没有容器网段对应的 ip 地址时,随机抉择本节点上一个 pod ip 地址配置到进口设施上,这个地址的配置有以下特点:
- 开启了 noprefixroute 的 flag
- 地址的 scope 是 link 的
- 删除了 local 路由表中对应该地址主动生成的 local 路由条目
通过这样的配置,咱们胜利地让宿主机上的所有“enhanced address”只为 arp 解析过程服务,不影响其余过程。
更多对于如何配置 vlan 网络能够查看 wiki 中“vlan 网络”局部。
反对固定 ip 的 bgp 网络
通过后面的规定形容咱们能够发现,在 hybridnet 中对于 bgp 模式的数据链路设计非常简单:“始终通过内部网关交换机”。比较复杂的局部在于 bgp 协定的治理。具体设计能够参考 wiki 中“bgp 网络”局部。
CNStack 如何应用 hybridnet
CNStack 通过 hybridnet 实现了“On Anywhere”部署。
在创立集群时,CNStack 集群会初始化 overlay 网络资源的创立,并且始终应用 overlay 作为默认网络类型,绝大部分集群内的 pod 会通过 overlay 网络拉起,包含 CNStack 平台的治理 pod,这样就保障了 CNStack 的白屏平台治理逻辑能够在任意网络环境的正确工作。
同时,CNStack 中集成了对 hybridnet 网络配置的白屏治理能力,用户能够在 CNStack 平台实现交付后,在白屏管制台上自助增加 underlay 网络配置,并且通过在公布 pod 时带上固定 annotation 的形式应用 underlay 网络资源(因为集群默认网络类型是 overlay 的,应用 underlay 网络须要非凡指定)。
通过这样的形式,传统意义上在交付 underlay K8s 集群之前须要实现的网络布局、配置工作变成了与交付过程解藕的、用户可选自助配置的逻辑,并且 underlay 的配置并不影响产品的可用性和稳定性,极大地晋升了交付效率。
相干链接:
[1] vxlan
https://github.com/alibaba/hybridnet/wiki/VXLAN-%E7%BD%91%E7%BB%9C
[2] 增量进行 underlay 网络配置
https://github.com/alibaba/hybridnet/wiki/%E7%BD%91%E7%BB%9C%E9%85%8D%E7%BD%AE
[3] vlan
https://github.com/alibaba/hybridnet/wiki/VLAN-%E7%BD%91%E7%BB%9C
[4] bgp
https://github.com/alibaba/hybridnet/wiki/BGP-%E7%BD%91%E7%BB%9C
[5] 正文
https://github.com/flannel-io/flannel/blob/master/pkg/backend/vxlan/vxlan.go#L19
参考链接:
hybridnet github 仓库
https://github.com/alibaba/hybridnet
hybridnet 开源 wiki
https://github.com/alibaba/hybridnet/wiki
与容器服务 ACK 发行版的深度对话第二弹:如何借助 hybridnet 构建混合云对立网络立体
https://mp.weixin.qq.com/s/O095yS5xPtawkh55rvitTg
阿里云 CNStack 产品
https://www.aliyun.com/product/aliware/cnstack
CNStack 社区版
https://github.com/alibaba/CNStackCommunityEdition
阿里云 ACK 发型版
https://github.com/AliyunContainerService/ackdistro