最近我司业务扩展在机房新开了一个区域,折腾了一段时间的 Calico BGP,为了能将整个过程梳理得更简单明了,我还是决定将这个过程记录下来。不管是对当下的总结还是未来重新审视方案都是值得的。大家都知道,云原生下的网络架构在 Kubernetes 里可以算是百花齐放,各有所长,这无形中也导致网络始终是横在广大 K8S 爱好者面前迈向高阶管理的几座大山之一。通常大家在公有云上使用厂家提供的 CNI 组件可能还感受不到其复杂,但一旦要在 IDC 自建集群时,就会面临 Kubernetes 网络架构选型的问题。 Calico 作为目前 Kubernetes 上用途最广的 Kubernetes CNI 之一,自然也有很多追随者。而本篇便是在自建机房内 BGP 组网下的一次总结。

关于 CNI 选型

云原生 CNI 组件这么多,诸如老牌的 Flannel、Calico、WeaveNet、Kube-Router 以及近两年兴起的 Antrea、 Kube-OVN 和 Cilium。它们都在各自的场景下各有所长,在选择前我们可以先对其做一个简单的功能性的比较:

Flannel Calico Cilium WeaveNet Antrea Kube-OVN
部署模式 DaemonSet DaemonSet DaemonSet DaemonSet DaemonSet DaemonSet
包封装与路由 VxLAN IPinIP,BGP,eBPF VxLAN,eBPF VxLAN Vxlan Vlan/Geneve/BGP
网络策略 No Yes Yes Yes Yes Yes
存储引擎 Etcd Etcd Etcd No Etcd Etcd
传输加密 Yes Yes Yes Yes Yes No
运营模式 社区 Tigera 社区 WeaveWorks VMware 灵雀云

说明:传输加密主要以支持 WireGuard 或 IPSec 来评估

此外关于CNI 性能部分,我们也可以透过一份 2020 年的 CNI 性能测试报告《Benchmark results of Kubernetes network plugins (CNI) over 10Gbit/s network》 来选择。

上述性能测试原始数据:https://docs.google.com/spreadsheets/d/12dQqSGI0ZcmuEy48nA0P_bPl7Yp17fNg7De47CYWzaM/edit?ouid=118246426051561359914&usp=sheets_home&ths=true

为什么选择 Calico

在对我司机房新区域的网络选型上,我们最终选择了 Calico 作为云端网络解决方案,在这里我们简单阐述下为什么选择 Calico 的几点原因:

  • 支持 BGP 广播,Calico 通过 BGP 协议广播路由信息,且架构非常简单。在 kubernetes 可以很容易的实现 mesh to mesh 或者 RR 模式,在后期如果要实现容器跨集群网络通信时,实现也很容易。
  • Calico配置简单,且配置都是通过 Kubernetes 中的 CRD 来进行集中式的管理,通过操作 CR 资源,我们可以直接对集群内的容器进行组网和配置的实时变更
  • 丰富的功能及其兼容性,考虑到集群内需要与三方应用兼容,例如配置多租户网络、固定容器 IP 、网络策略等功能又或者与 Istio、MetalLB、Cilium 等组件的兼容,Calico 的的表现都非常不错
  • 高性能, Calico 的数据面采用 HostGW 的方式,由于是一个纯三方的数据通信,所以在实际使用下性能和主机资源占用方面不会太差,至少也能排在第一梯队

结合我司机房新区域采购的是 H3C S9 系列的交换机,支持直接在接入层的交换机侧开启路由反射器。所以最终我们选择Calico 并以 BGP RR 的模式作为 Kubernetes 的 CNI 组件便水到渠成。

关于 MetalLB

在讲 MetalLB 之前,先回顾下应用部署在 Kubernetes 中,它的下游服务是如何访问的吧。通常有如下几种情况

集群内请求:

直接通过 Kubernetes 的 Service 访问应用。

集群外请求:

  1. 通过 NodePort 在主机上以 nat 方式将流量转发给容器,优点配置简单且能提供简单的负载均衡功能, 缺点也很明显下游应用只能通过主机地址+端口来做寻址
  2. 通过 Ingress-nginx 做应用层的 7 层转发,优点是路由规则灵活,且流量只经过一层代理便直达容器,效率较高。缺点是 ingress-nginx 本身的服务还是需要通过 NodePort 或者 HostNetwork 来支持

可以看到在没有外部负载均衡器的引入之前,应用部署在 kubernetes 集群内,它对南北向流量的地址寻址仍然不太友好。也许有的同学就说了,我在公有云上使用 Kubernetes 时,将 Service 类型设置成 LoadBalancer,集群就能自动为我的应用创建一条带负载均衡器地址的 IP供外部服务调用,那我们自己部署的 Kubernetes 集群有没有类似的东西来实现呢?

当然有!MetalLB 就是在裸金属服务器下为 Kubernetes 集群诞生的一个负载均衡器项目。

事实上当然不止 MetalLB,开源界里面还有其他诸如PureLB、OpenELB等负载均衡产品。不过本文旨在采用 BGP 协议来实现负载均衡,所以重点会偏向 MetelLB

简单来说,MetalLB包含了两个组件,Controler用于操作 æ Service 资源的变更以及IPAM。Speaker用于外广播地址以及 BGP 的连接。它支持两种流模式模式即:layer2BGP

  • Layer2 模式

又叫ARP/NDP模式,在此模式下,Kubenretes集群中运行 Speaker 的一台机器通过 leader 选举,获取 Service 的 LoadBalancer IP 的所有权,并使用 ARP 协议将其 IP 和 MAC 广播出去,以使这些 IP 能够在本地网络上可访问。由此可见,使用 Layer2 的模式对现有网络并没有太多的要求,甚至不需要路由器的支持。不过缺点也显而易见,LoadBalancer IP 所在的 Node 节点承载了所有的流量,会产生一定的网络瓶颈。

此外,我们可以简单的将 Layer2 模式理解为与 Keepalived 原理相似,区别仅为 Layer2 的lead 选举并不是使用 VRRP 组播来通信的

  • BGP 模式

MabelLB 在 BGP 模式下,集群中的所有运行 Speaker 的主机都将与上层交换机建立一条BGP 连接,并广播其 LoadBalancer 的IP 地址。优点是真正的实现了网络负载均衡,缺点就是配置相对而言要复杂许多,且需上层路由器支持BGP。

MetalLB with Calico

通过上述的介绍,你可能发现了一个问题:在 BGP 模式的场景下,Calico 和 MetalLB 都需要运行一个 DaemonSet 的bgp 客户端在主机上与上层路由器建立 bgp peer,在 Calico 中是 Bird ,MetalLB 中是 Speaker。这就会引出来它们使用上的一些问题。

BGP 只允许每个节点建立一个会话,如果使用 Calico 并建立了 BGP 路由器会话,MetalLB 无法建立自己的会话.因为这条 BGP会话会被路由器认为是相冲突而拒绝连接

事实上我们传统的 Fabric 网络在运用上述方案也遇到此问题,MetalLB 社区也给了 3 个方案来解决:

  • BGP 与 Tor 交换机连接

    此方案即 MetalLB 放弃在 Node 节点上部署 Speaker 服务,关于主机上 BGP 路由的广播统一交给 Calico Bird 处理。这也是 Calico 社区建议采取的方案。

  • BGP 与 Spine 交换机连接

    此方案让 MetalLB Speaker 的 BGP Peer 绕过 Tor 路由,直达上层核心路由器。虽然解决了 BGP 连接问题,但是额外带来了配置的复杂性,以及损失了BGP 连接的扩展性,这大型的数据中心是不被认可的!

  • 开启 VRF-虚拟路由转发

    如果你的网络硬件支持 VRF(虚拟路由转发),那就可以将通过虚拟化的方式分别为 Calico Bird 和 MetalLB Speaker 创建独立的路由表,并建立 BGP 连接。然后再在两个 VRF 内部之间进行路由

此方案理论上可行,但笔者的数据中心并没有支持 VRF 功能的路由器,且受限于不同网络设备厂家的实现方式不同而带来的操作差异也不可控。所以具体的实现还需每个用户自行决定。

具体操作

前面谈了大段话关于 Calico 和 MetalLB 的使用,本节我们就简单的部署与配置来完成前面的所说的内容。

网络上面的一些基本信息:

规划CIDR 用途 关联服务
10.52.1.0/24 Kubernetes 主机物理网络,同时也是 IBGP 连接的承载网络 Kubernetes,Calico
10.59.0.0/16 Kubernetes 容器默认使用的 IP 地址池 Calico
10.96.0.0/12 Kubenretes Service 内部地址池,即 ClusterIP 区域 Kubernetes
10.60.0.0/21 Kubenretes Service 负载均衡器地址池,即 LoadBalancer IP 区域 Calico, MetalLB

IDC 中心的 BGP 信息

BGP 信息
AS 域 65001
BGP peer 10.52.1.253,10.52.1.254

Calico 部分

  • 下载并部署 Calico Manifest 文件,并将文件内容中关于 POD CIDR修改为自己环境下的配置
curl https://projectcalico.docs.tigera.io/manifests/calico.yaml -O----
containers:
- image: harbor.cloudminds.com/kubegems/calico-node:v3.22.1name: calico-nodeenv:- name: CALICO_IPV4POOL_CIDRvalue: 10.59.0.0/16
  • 配置 BGP Peering,可根据机房规模选择 Global BGP PeerPer-Node Peer。它们之间区别为Global BGP Peer的连接拓扑呈星状,所有的节点都在一个 AS 域内。Per-Node Peer则可以利用主机标签进行灵活的接入。

​ 这里由于我们服务器规模不大(<50)可直接采用全局 BGP 连接模式。

apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:name:  tor-router-253
spec:peerIP: 10.52.1.253asNumber: 65001
---
apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:name:  tor-router-254
spec:peerIP: 10.52.1.254asNumber: 65001

考虑到 BGP 连接的冗余,实际在使用上,我们可以创建两个 BGPPeer,防止路由器单点故障。

如果你需要按照机架来划分 AS 域的话,可以采用 Per-Node Peer 模式,通过 nodeSelector 来实现个性化的连接配置。

apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:name: rack1-tor
spec:peerIP: 192.20.30.40asNumber: 64567nodeSelector: rack == 'rack-1'
  • 禁用 Calico NodeToNodeMesh
calicoctl patch bgpconfiguration default -p '{"spec": {"nodeToNodeMeshEnabled": false}}'
  • 禁用 ipipMode 和vxlan Mode
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:name: default-ipv4-ippool
spec:allowedUses:- WorkloadblockSize: 26cidr: 10.59.0.0/16ipipMode: NevernatOutgoing: truenodeSelector: all()vxlanMode: Never

此时,我们使用calicoctl 来查看 BGP 状态,如果 STATE 为 up,就代表集群内主机的 BGP 连接正常。

MetalLB 部分

  • Kube-Proxy 采用 IPVS 的话,需开启严格的 ARP 学习设置。
kubectl edit configmap -n kube-system kube-proxy----
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: "ipvs"
ipvs:strictARP: true

如果多台用户主机同时向设备发送大量ARP报文,或者攻击者向设备发送伪造的ARP报文,会出现以下问题:

  • 处理 ARP 报文会消耗大量 CPU 资源。设备学习到很多无效的ARP表项,耗尽了ARP表项资源,导致设备无法学习到来自授权用户的ARP报文的ARP表项,造成用户的通信被中断。
  • 设备收到伪造的ARP报文后,错误地修改了ARP表项。造成用户无法相互通信。

为避免上述问题,开启 strictARP 后,设备对发送的ARP请求报文只学习ARP回复报文的ARP表项。这样,设备就可以防御大部分的ARP攻击。

  • 下载并安装 MetalLB
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.12.1/manifests/namespace.yaml
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.12.1/manifests/metallb.yaml

注意,由于我们不需要 MetalLB 的 Speaker 服务,所以当 MetalLB Controller 运行成功后,可以将 speaker 服务删除。

kubectl delete daemonset speaker -n metallb-system
  • 配置 MetalLB 中需要广播的 BGP 地址范围,也就是后面 Kubernetes Service 中 LoadBalancer 的地址。
apiVersion: v1
kind: ConfigMap
metadata:namespace: metallb-systemname: config
data:config: |address-pools:- name: defaultprotocol: bgpaddresses:- 10.60.0.0/21

Calico 广播 Kubernetes 服务地址(包含 MetalLB 地址)

得益于 BGP 的使用,Calico 可以很容易的将 Kubernetes 集中的 Service IP 地址像 Pod IP一样发布到内网。通过使用ECMP(等价多路径路由)来实现真正的负载均衡。

通常Kubenretes中 Service 中的地址涉及到 3 种类型,即 ClusterIPExternalIPLoadBalancerIP

考虑到我们仅需要将有限的服务通过LoadBalancerIP方式暴露出来。(虽然直接发布 ClusterIP 很酷,但它在某些网络限制严格的场景下是不被接受的)。所以对 Calico 的 BGP 仅需如下配置。

apiVersion: projectcalico.org/v3
kind: BGPConfiguration
metadata:name: default
spec:logSeverityScreen: InfonodeToNodeMeshEnabled: falseasNumber: 65001serviceLoadBalancerIPs:- cidr: 10.60.8.0/21

如果我们需要将 Kubernetes 的控制节点从广播中排除开来,那么仅需要为控制平面的主机添加如下标签即可:

kubectl label node control-plane-01 node.kubernetes.io/exclude-from-external-load-balancers=true

路由器

原则上说,在路由器上开启 BGP 协议是上述所有操作中最先应该开始的工作。但由于每位读者所在环境中支持BGP 的交换机厂家不尽相同,所以我将此部分挪到最后来说明。我并不是网络上的专家,这里我只对我们 Calico BGP 网络的架构做一个简单说明,读者在规划自己的 BGP 网络时,可与网络工程师一起合作完成。

最终当交换机上的路由反射器和 BGP 邻居创建完成后,Calico 的 Bird 服务便能与反射器建立对等连接,此时连接的状态如下


路由表信息如下

可以看到此时,容器的子网路由都明确了下一跳的主机地址,以及公布的LoadBalancer CIRD下一跳地址。

关于 EMCP

等价多路径路由ECMP(Equal-Cost Multi-Path routing)实现了等价多路径负载均衡和链路备份的目的。多用于 Layer 3 的负载均衡,用于解决“负载均衡服务器”的单点和扩缩容的问题。既然我们在内部采用了 BGP 网络,当然也可以在路由器上启用此功能。

当启用此功能后,我们在路由表中便可以看到对访问目标地址是LoadBalancer CIRD网段的路由,下一跳地址可以是多个 Calico 的 Node 主机。

不过在决定启用 ECMP 之前,你需了解它的背后仍然面临一些应用上的限制。

当我们使用 BGP 做Layer 3层的负载均衡时,当某一台主机出现故障后,交换机上通过连接三元组/五元组作为 hash key 进行负载均衡的数据包会被重新发到新的主机上去,由于目的地址变化,当数据包到达新主机时会被直接丢弃,导致连接断开。这是反应在应用层上的现象就是“Connection reset by peer”

当然我们可以使用一些其他方法来规避和缩小上述现象的影响范围,例如:

  1. 路由器上调整更稳定的等价多路径路由 ECMP(Equal-Cost Multi-Path routing)算法。当后端集群发生变化时而受到影响较少的连接数。

    • 逐流负载分担能保证包的顺序,保证了同一数据流的帧在同一条下一跳路由转发,而不同数据流在不同的下一跳路由上转发。

    • 逐包负载分担可以提高ECMP的带宽利用率,使等价多路径路由分担更均匀,但存在数据包乱序的问题,需要确保流量接收的设备或终端支持报文乱序组包的功能,实际使用场景很少。

  2. 服务部署调度时,尽量选择固定到更小的范围、或者更稳定的主机组。

  3. 上层应用需支持网络连接断开重试逻辑

  4. 在 MeltalLB和应用之间再加一层流量控制器(如 ingress-nginx),以此来维护连接状态的一致性。这样只有当 ingress-nginx 的规模产生变换时,才会出现上述问题。

总结

本文主要讲述在传统的自建数据中心,利用 Calico 和 MetalLB 来组件内部的 BGP 网络。并以此来为 Kubernetes 提供 Pod - PodNode - PodNode - Loadbalancer网络互访的能力。


面向云原生的通用型容器云平台

GitHub 搜索【KubeGems】或直接访问 https://kubegems.io/ 了解更多.

BGP 模式下 Calico 与 MetalLB 的组合相关推荐

  1. Kubernetes CNI Calico:BGP 模式 / Route Reflector 模式(RR)

    Ipip模式是通过宿主机的网络去传输的,这个模式和flannel的vxlan工作模式差不多是一样的,都是一种复杂的网络方案,IPIP和vxlan模式的性能基本上接近,所以在性能方面要相对于路由方面损失 ...

  2. 《信息与电脑》流通业在SaaS模式下的在线应用

    2008年,探寻适合中国企业SaaS国产软件企业逐渐转型,SaaS服务水平大幅提升.2009年伴随着后经济危机,国内SaaS市场可谓风生水起,传统电子商务(E-Commerce)和企业管理软件(ERP ...

  3. SAS vs SSD各种模式下MySQL TPCC OLTP对比测试结果

    在各种测试组合方案中,组合10(组合10:SSD * 2, RAID 0, XFS,WB,nobarrier,noop)的综合性能最高,因此以它为基准,其他方案与其对比,下表是各组合和组合10的对比: ...

  4. (转)检测到在集成的托管管道模式下不适用的ASP.NET 设置

    我们将ASP.NET程序从IIS6移植到IIS7,可能运行提示以下错误: HTTP 错误 500.23 - Internal Server Error 检测到在集成的托管管道模式下不适用的 ASP.N ...

  5. 技术分享 | 微服务模式下如何高效进行API测试

    导读:微服务架构下,API 测试的最大挑战来自于庞大的测试用例数量,以及微服务之间的相互耦合.基于这种挑战,如何进行高效的API测试,选择什么样的方式就比较重要,此文主要是采用契约测试的方法来对微服务 ...

  6. 前后端分离开发模式下后端质量的保证 —— 单元测试

    概述 在今天, 前后端分离已经是首选的一个开发模式.这对于后端团队来说其实是一个好消息,减轻任务并且更专注.在测试方面,就更加依赖于单元测试对于API以及后端业务逻辑的较验.当然单元测试并非在前后端分 ...

  7. IntelliJ IDEA for Mac在MacOS模式下的搜索/查询/查找快捷键(Search Shortcut)

    文章目录 根据内容查找文件 根据名称查找类文件(源代码文件) 根据名称查找任何类型文件 查找字段名称.方法名.类名声明的地方 查找所有的内容 查找任何动作 快捷键 快捷键符号 英文名称 功能说明 Do ...

  8. vim 底行命令模式下的全局命令 g(global)

    文章目录 命令格式介绍 常用的 ex 指令 关于 range 参考示例 结合替换指令 s 使用 将包含 pattern 的行追加到指定的寄存器中 插入空行 打印符合要求的行 删除匹配的行 删除不匹配的 ...

  9. 自由口通信模式下计算机读写PLC存储区的程序

    自由口通信模式下计算机读写PLC存储区的程序 2008-8-20 8:51:00 来源: 摘 要:本文介绍了在自由口通信模式下,用计算机读写S7-200 PLC存储区内相邻的多个字节数据的通信程序设计 ...

  10. 【OS学习笔记】二十三 保护模式七:保护模式下任务的隔离与任务的特权级概念

    上一篇文章学习了保护模式下操作系统内核如何加载程序并运行:点击链接查看上一篇文章 本篇文章接着上一篇文章学习保护模式下任务的隔离. 包括以下学习内容: 任务的全局空间和局部空间 任务的TSS 任务的L ...

最新文章

  1. python使用pickle保存和加载机器学模型
  2. Cloudify — 部署 OpenStack 基础设施
  3. 【约束布局】ConstraintLayout 约束布局 ( 简介 | 引入依赖 | 基本操作 | 垂直定位约束 | 角度定位约束 | 基线约束 )
  4. halcon select_shape_xld按区域大小描绘xld
  5. 浅谈sql中的in与not in,exists与not exists的区别
  6. 不同林间域账号密码迁移
  7. 元年·潮湃 首届搜狐5G峰会倒计时 参会大咖揭晓
  8. Jmeter中的变量(三)
  9. 大数据技术常用的工具有哪些
  10. URAL 1031 Railway Tickets
  11. linux系统可以玩星际争霸吧,在Linux下可用Wine安装和运行星际争霸2、水煮三国
  12. sql基本语句返回值类型
  13. 数据归档方案(带流程图)
  14. 华为小程序怎么弄出来_华为手机添加桌面小程序 华为手机小程序怎么弄出来...
  15. ado控件 怎么链接mysql_使用ADO或ADO控件访问数据库
  16. c语言一些算法解题技巧,c语言常见小算法的解题思路.doc
  17. 关于graphql快速入门
  18. Sigmoid 与 Softmax 的区别
  19. 太年轻,原来订阅号发红包也可以这么灵活
  20. 谨慎使用rm -rf

热门文章

  1. u盘iso安装服务器系统怎么安装win7系统安装方法,win7系统iso镜像文件通过U盘安装的操作方法...
  2. 论文标题管理----WPS自定义多级自动编号列表
  3. oracle数据库还原指令,oracle中备份和还原数据库的命令汇总
  4. SRE 到底是什么?
  5. 2019上半年个人成长复盘
  6. html5显示用户已读取文章,如何查看公众号文章是谁阅读
  7. 常用 ajax js 表单 下拉加载
  8. c语言SPF算法代码,SPF 算法具体过程
  9. 神书《笛卡儿几何》读后感
  10. echarts散列图示例