CNI 网络流量 5.4 为什么 Cilium 不再需要 IPVlan 了?

前言

在 Cilium 1.11 版本,Cilium 彻底移除了 IPVlan 的代码,代表着 IPVlan 不再是 Cilium 默认支持的组网方式。那么 Cilium 为什么不再需要 IPVlan 了呢?

传统 CNI 模式

在如 Flannel,Calico 等 CNI 实现过程中,会为每一个 Pod 创建一对 veth 设备,一端在 Host ns 内,另一端在 Pod ns 内,在宿主机上有到 pod IP 的路由指向对应的 Host ns 的 veth 设备。当两个 Pod 通信时,流量流程如下图所示(calico bgp 模式):
暂时无法在飞书文档外展示此内容

流量从 pod1 到 pod2,依次经过 pod1 ns 内部网络栈,Host 网络栈和 pod2 ns 内部网络栈。

Cilium Veth 模式

Cilium Veth 模式下没有结构变化,不过没有指向 pod IP 的路由;而是在 pod1 的 lxcxxx1 加上 tc ingress ebpf 应用,将目的 IP 是 Pod2 IP 的流量重定向到 lxcxxx2。
暂时无法在飞书文档外展示此内容

流量从 pod1 到 pod2,依次经过 pod1 ns 内部网络栈,pod2 ns 内部网络栈。ns 之间执行了两次从出口到入口的切换。

Cilium IPVlan 模式

IPVlan 模式下内部转发逻辑直接是 pod 到 pod,不通过 BPF 程序执行到设备的转发,该种模式下,网络命名空间切换更高效,堆栈不需要像外部数据包基于 veth 的数据路径那样被重新遍历。
暂时无法在飞书文档外展示此内容

流量从 pod1 到 pod2,ns 之间只执行了一次从出口到入口的切换。

// Linux v6.0   drivers/net/ipvlan/ipvlan_core.c L564
static int ipvlan_xmit_mode_l3(struct sk_buff *skb, struct net_device *dev)
{
......
    if (!ipvlan_is_vepa(ipvlan->port)) {
        // 根据目的 IP 查看是否是该网卡和所有 ipvlan 子接口的 IP.
        addr = ipvlan_addr_lookup(ipvlan->port, lyr3h, addr_type, true);
        if (addr) {
            if (ipvlan_is_private(ipvlan->port)) {
                consume_skb(skb);
                return NET_XMIT_DROP;
            }
            // 如果是该网卡或子接口的 IP,且 linkup,修改 skb->dev = 接口 dev,由该接口处理。
            return ipvlan_rcv_frame(addr, &skb, true);
        }
    }
......
}

Cilium IPVlan 与 Veth 相比 堆栈需要更少的资源来将数据包推送到另一个网络命名空间,拥有更好的延迟;但是 IPVlan 也有自己的不足,不支持 NAT64,不支持 L7 Policy,Pod 不能拥有 CAP_NET_ADMIN 和 CAP_NET_RAW 特权。

形式逆转

在 linux 内核到 5.10 版本后,bpf Helper 提供了一个新的方法 bpf_redirect_peer;它支持 ebpf 可以直接将流量 redirect 到接口的 veth-pair 对端。
Cilium 在 lxcxxx1 tc ingress ebpf 程序

|- cil_from_container
  |- tail_handle_ipv4
    |- __tail_handle_ipv4
      |- tail_handle_ipv4_cont
        |- handle_ipv4_from_lxc
          |- ipv4_local_delivery   // 判断目的 IP 是本 node pod 上的
            |- redirect_ep         // 查找该 IP 在 host ns 上的索引
              |- ctx_redirect_peer

设置 redirect 的 iface 和 peer flag,转发。

// Linux v6.0   net/core/filter.c L2501

BPF_CALL_2(bpf_redirect_peer, u32, ifindex, u64, flags)
{
    struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);

    if (unlikely(flags))
        return TC_ACT_SHOT;
    // redirect 时,加上 flag 是 peer。
    ri->flags = BPF_F_PEER;
    ri->tgt_index = ifindex;

    return TC_ACT_REDIRECT;
}

基于以上,Cilium Veth 模式变化如下
在这里插入图片描述

流量从 pod1 到 pod2,ns 之间只执行了一次从出口到入口的切换,即 pod1 ns 到 host ns。

结论

在引入 bpf_redirect_peer 后,利用 veth 即可为 Kubernetes 提供同样的性能优势,鉴于 ipvlan 自身的部分限制;所以,默认支持 ipvlan 已经不是那么重要了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值