Cilium是一个开源的Linux容器网络和负载均衡解决方案,它为容器化应用提供高性能、可扩展的网络安全和网络连接。Cilium支持Encapsulation和NATive-routing两种组网方式。在Native-Routing方式中,Cilium会将PodCIDR中的跨节点流量委托给Linux内核的路由子系统。此时,Linux内核需要知道如何路由PodCIDR中的特定地址。当所有Node处于同一个L2网络时,我们可以设置参数autoDirectNodeRoutes=true,此时整个PodCIDR路由信息被插入到每个节点的内核路由表中,用户无需其他额外工作即可部署完成。
然而,在实际生产环境中,我们的Node往往分布在不同的L2网络中,不满足设置autoDirectNodeRoutes的条件。因此,我们需要借助设置BGP服务完成PodCIDR组网。在本文中,我们将使用FRR和Bird作为BGP服务,来展示如何配置Cilium和BGP协同工作。
首先,我们需要在路由器节点上部署软件路由器FRR。FRR是一个高性能的开源软件,它可以支持多种路由协议,包括BGP。在部署FRR后,我们需要修改配置文件,设置BGP的相关参数,包括本地ASN、router-id、邻居节点的ASN等。完成配置后,启动frr服务。
接下来,我们在NodE1和Node2上部署Cilium。在Cilium的配置中,我们需要设置k8sServiceHost、k8sServicePort、kubeProxyReplacement、devices等参数。此外,我们还需要配置ipam、loadBalancer、bpf、socketLB、nodePort、externalIPs、hostPort等参数。配置完成后,启动Cilium容器。
此时,Kubernetes集群中可以正常创建容器并分配容器IP,但是跨节点容器无法正常通信。为了解决这个问题,我们需要在Node1和Node2上部署Bird。Bird是一个高性能的开放源代码动态路由协议守护程序套件,它可以支持多种路由协议,包括BGP。在Bird的配置文件中,我们需要设置routerid、scan-time、disable、import、export、static、peer-address、peer-asn、my-asn、address-pools等参数。配置完成后,启动Bird服务。
最后,我们需要检查BGP连接是否正常。在router节点上执行以下命令:
#查看bgp peer连接 vtysh -c "show bgp summary" #查看注册到router的路由信息 vtysh -c "show bgp IPv4 all"
完成上述流程后,我们可以看到Node1和Node2上的容器网络打通,并且任意以router节点作为默认网关的服务器都可以直连PodIP。此时,我们可以通过查看router节点的路由信息,确认PodCIDR已经被注入。
总的来说,配置Cilium和BGP协同工作可以帮助我们实现跨节点的容器通信,并确保我们的服务能够高效稳定地运行。在实际生产环境中,我们可以根据实际情况选择使用FRR或Bird作为BGP服务。
背景
官方提供了多篇文档说明如何配置 Cilium 和 BGP 协同工作,本文主要对以下部分功能进行验证:
Using BIRD to run BGP[1]
Using kube-router to run BGP[2]
BGP[3]
Cilium BGP Control PLANE[4]
为了模拟支持 BGP 的网络环境,文中所有节点均是通过 vagrant 创建的 VM, 网络拓扑如下图。
注意:实际配置时使用 vagrant 创建的 VM 模拟网络环境并不便利。可以参考以下文章,使用 ContainerLab 和 Kind 进行验证。参考:HTTPS://mp.weixin.qq.com/s/k25e7gTIIJLnL_FLlgdHUw
上图中,Router 节点包含多张网卡并将作为其他两台主机的网关,对应的系统配置如下:
net.ipv4.ip_forward=1 net.IPv6.conf.all.disable_ipv6=1 net.ipv6.conf.default.disable_ipv6=1 net.ipv6.conf.lo.disable_ipv6=1 net.ipv6.conf.all.forwarding=1
node1、node2 节点均只包含一张网卡,其默认路由均指向 router 节点(node1 指向 10.0.1.2,node2 指向 10.0.2.2)。
node1、node2 上将部署 Kubernetes 和 Cilium。
基于 Bird 部署容器网络
Cilium 为 PodCIDR 提供了 Encapsulation 和 Native-Routing 两种组网方式。
Native-Routing 方案中,Cilium 会将 PodCIDR 中的跨节点流量委托给 Linux 内核的路由子系统,此时 Linux 内核需要知道如何路由 PodCIDR 中的特定地址。
当用户的所有 Node 处于同一个 L2 网络时,我们可以设置参数 autoDirectNodeRoutes=true ,此时整个 PodCIDR 路由信息被插入到每个节点的内核路由表中,用户无需其他额外工作即部署完成。
上述测试环境中,Node1 和 Node2 分别处于 10.0.1.0/24 和 10.0.2.0/24 ,并不满足设置 autoDirectNodeRoutes 的条件,因此我们需要借助设置 BGP 服务完成 PodCIDR 组网。
参考Using BIRD to run BGP[5]文档中的描述,并结合测试环境的网络拓扑,我们设定测试节点的 ASN 如下图:
1. FRR 设置
在 router 上部署软件路由器 FRR (参考:HTTPs://rpm.frrouting.org/), 如下:
FRRVER="frr-stable" curl-Ohttps://rpm.frrouting.org/repo/$FRRVER-repo-1-0.el7.noarch.rpm sudoyuminstall./$FRRVER* sudoyuminstallfrrfrr-Pythontools
修改 /etc/frr/daemons 文件,打开 bgpd 功能(设置配置文件中 bgpd=yes)。编辑 /etc/frr/frr.conf 文件,写入以下 BGP 相关的配置:
frrversion8.4.1 frrdefaultstraditional hostnamerouter#主机名 logsysloginformational ! routerbgp65100#router节点的本地ASN bgprouter-id192.168.121.16#router-id nobgpebgp-requires-policy neighbor10.0.1.10remote-as65010#配置Node1作为router的邻居,ASN为65010 neighbor10.0.2.10remote-as65020#配置Node2作为router的邻居,ASN为65020 exit !
完成上述配置后,启动 frr 服务systemctl restart frr!
2. 部署 Cilium
登录 Node1 或 Node2 部署 Cilium,配置如下:
k8sServiceHost:"10.0.1.10" k8sServicePort:6443 kubeProxyReplacement:strict devices:eth1 ipam: operator: clusterPoolIPv4PodCIDR:"172.31.254.0/23" clusterPoolIPv4PodCIDRList:[] clusterPoolIPv4MaskSize:26 loadBalancer: mode:dsr tunnel:disabLED autoDirectNodeRoutes:false bpf: masquerade:true ipv4NativeRoutingCIDR:"172.31.254.0/23" socketLB: enabled:true nodePort: enabled:true externalIPs: enabled:true hostPort: enabled:true
Cilium 容器就绪后,Kubernetes 集群中可以正常创建容器并分配容器IP,但是跨节点容器无法正常通信。
3. 部署 Bird
Cilium 官方文档中,给出了 Bird2 的配置示例。我们可以直接通过yum -y install bird2安装。
查看各个节点分配的 PodCIDR 网段,执行kubectl -n kube-system exec -it ds/cilium -- cilium node list:
参考以下配置 bird2 服务,配置文件 /etc/bird.conf
routerid10.0.1.10; protocoldevice{ scantime10;#Scaninterfacesevery10seconds } #Disableautomaticallygeneratingdirectroutestoallnetworkinterfaces. protocoldirect{ disabled;#Disablebydefault } #ForbidsynchronizingBIRDroutingtableswiththeOSkernel. protocolkernel{ ipv4{#ConnectprotocoltoIPv4tablebychannel importnone;#Importtotable,defaultisimportall exportnone;#Exporttoprotocol.defaultisexportnone }; } #StaticIPv4routes. protocolstatic{ ipv4; route172.31.254.0/26via"cilium_host";#将 PodCICR 通告到上游,PS:这里是 Node1 分配到的 PodCIDR } #BGPpeers protocolbgpuplink0{ description"BGPuplink0"; local10.0.1.10as65010;#设置当前节点的 ASN ,PS:这里示例的是 Node1 neighbor10.0.1.2as65100;#设置节点的Neighbor,这里是router节点 ipv4{ importfilter{reject;}; exportfilter{accept;}; }; }
在 Node1、Node2 按照上述方式配置完成 Bird2 后启动服务。执行以下命令检查 BGP 连接是否正常:
#在router执行以下命令 #查看bgppeer连接 vtysh-c"showbgpsummary" #查看注册到router的路由信息 vtysh-c"showbgpipv4all"
完成上述流程后,使得 Node1 和 Node2 上的容器网络打通,并且任意以 router 节点作为默认网关的服务器都可以直连 PodIP。
查看 router 接地的路由信息如下:
上图中,我们发现 router 节点被注入了 PodCIDR 。
本文测试环境的网络拓扑非常简单,实际上直接通过命令行直接在 router 节点上插入路由信息可以达到同样效果。在实际生产中,我们可以通过 BGP 动态发现简化配置流程。
内置 BGP
Cilium 1.10 之后的版本内置了 BGP Speaker 的功能,用户无需在节点上部署 Bird2 也可以向外广播节点的 PodCIDR 信息,并且 1.12 版本中 Cilium 参考 Metallb 实现支持基于 BGP + ECMP 的 LoadBalancer 功能。
参考文档[6]中的描述,启用内置的 BGP 能力需要额外创建以下 ConfigMap,Cilium-Agent 和 Cilium-Operator 启动时均会挂载该配置。
apiVersion:v1 kind:ConfigMap metadata: name:bgp-config namespace:kube-system data: config.yaml:| peers: -peer-address:192.168.121.16 peer-asn:65100 my-asn:65000 address-pools: -name:default protocol:bgp addresses: -192.0.2.0/24
上述配置中,Cilium 将使用 192.168.121.16 连接 router 节点的 bgpd 服务(PS:BGP 建立连接是基于 TCP 的),并且 Node1 和 Node2 将使用相同的 ASN 65000。
address-pools 指定的是 LoadBalaNACer 的 IP 地址池,当用户创建 LoadBalancer 类型的 Service 时,Cilium 将自动从该地址池中分配 ip 地址,并自动进行 BGP 宣告。
安装上述 Configmap 后,我们需要为 Cilium 为添加如下配置:
bgp: enabled:true announce: loadbalancerIP:true podCIDR:true loadBalancer: mode:snat#此处使用dsr模式时,存在问题
创建 service 如下:
apiVersion:v1 kind:Service metadata: name:whoami-lb spec: type:LoadBalancer ports: -port:80 targetPort:80 protocol:TCP name:http seLECtor: app:whoami
cilium 自动分配 192.0.2.0 作为 service 的 EXTERNAL-IP:
我们登录 router 节点通过 vtysh 查看 Cilium 是否 bgpd 服务建立了连接,并且查看其通告的路由信息如下:
需要注意,router 节点上我们需要添加 ECMP 的相关配置,并且依然静态指定 Node1 和 Node2 作为 neighbor 如下:
frrversion8.4.1 frrdefaultstraditional hostnamerouter logsysloginformational ! routerbgp65100 bgpbestpathas-pathmultipath-relax bgpbestpathbandwidthskip-missing bgprouter-id192.168.121.16 nobgpebgp-requires-policy neighbor10.0.1.10remote-as65000 neighbor10.0.2.10remote-as65000 exit !
执行vtysh -c "show bgp ipv4 unicast 192.0.2.0/32"我们可以查看当前,FRR 执行 ECMP 时的路径选择:
Cilium BGP Control Plane
BGP Controller 控制器是 Cilium 高版本推出的针对内置 BGP Speaker 更加细粒度的控制功能,其功能是上述 ConfigMap 的扩展。
责任编辑:彭菁