DockOne微信分享(二一五):Kube-OVN 的设计思路和实现原理

大家好,我是灵雀云的工程师刘梦馨,今天主要来分享一下我们的开源Kubernetes网络方案 Kube-OVN 功能设计和背后的实现。希望能帮助大家更好的理解这个比较新的网络方案,给我们提供更多的反馈。

关于 OVN 和 OVS 的介绍可以参考之前在 dockone 的分享这里就不再重复了,大家感兴趣的可以看一下上次分享的记录 http://dockone.io/article/8718. 目前 Kube-OVN 已经在 github 开源 https://github.com/alauda/kube-ovn 也欢迎大家 star 做贡献。

先来看一下我们为什么要自起炉灶又做一个网络方案

像我们灵雀云这种小破公司,一般是能用现成的方案就绝对不自己动手,之所以要自己动手来做,还是有很多现实的原因。

  1. 首先最主要的是现有的开源方案很难满足我们客户的需求,例如子网划分,IP固定,QoS,vlan 隔离,流量镜像等等这种在传统网络里很常见的功能在绝大部分的开源网络方案里都是缺失的。造成的结果是真正落地的时候我们会发现没有一个开源网络方案能用,只能不断的和网络部、系统部、应用部各个部门扯皮,割舍掉原有的一些网络功能来上容器。我们希望能通过技术的手段丰富现有的容器网络能力,来帮助客户更顺利的落地容器。

    1. 就是从我们自身维护容器云的角度来看,容器平台网络相关的问题是最难排查的。一个网络不通的问题可能会涉及 pod 网络,cni,service,iptables,ipvs,ingress,dns,networkpolicy,loadbalancer 等等多个组件,流量的分散导致故障十分难以排查,并且需要运维人员掌握很多组件的原理。我们希望能够把网络流量的数据面进行统一,不要再分散到各个组件上,降低维护方面的复杂度。
    2. 经过调研我们认为 ovn/ovs 这套网络组件功能上比较齐全,毕竟能够实现 OpenStack 的所有网络功能,那么对k8s的网络来说能力其实是大幅溢出的,可以实现很多高级功能。此外 ovs 已经是经久考验的虚拟交换机,稳定性是很有保证的,性能方面也有各种 DPDK 和硬件加速方案来托底,真正到要性能的时候我们有应对的方案。此外我们了解到的一些公有容器云厂商内部其实也是用的 OVN 来做容器网络,我们也不算第一个烈士。

综合这些因素我们决定自己开发一个基于 OVN 的网络方案,也就是 Kube-OVN 。一方面能够很好满足客户和我们自己的需求,另一方面开源出来也能帮助社区一同进步。

下面来说一下我们在实现 Kube-OVN 的一些设计目标和思路

  1. 平移 OpenStack 网络的概念和功能到 k8s。OpenStack 的网络已经发展了很多年,很多设计和概念也基本成了 SDN 的标准。我们希望能通过 OVN 不仅仅是引入一些高级功能,还能引入一些比较成熟的网络概念,像 VPC,Subnet,多租户,FIP,SecurityGroup 等等,从整体上增强 k8s 网络的能力。
  2. 统一网络的数据平面,我们希望把 k8s 作为网络的控制平面,所有数据平面的功能都能通过 OVN 来实现,包括 Service,DNS,NetworkPolicy 都通过 OVN 来实现,简化之后的维护工作
  3. 尽可能覆盖其他开源网络方案的功能。对我们来说也不希望同时支持多个网络插件,每个客户都不一样,这样对我们成本也很高。我们自己希望有这么一个跟水桶机一样的网络方案要的功能都覆盖了,还能有些特色,这样是最好的
  4. 尽可能的易于安装使用。ovn、ovs这套东西本身的安装和使用都还是比较复杂,门槛比较高我们希望能进行简化,降低用户使用的门槛。方便交付,也方便更好的推广。

下面来看下我们的网络架构和具体实现的一些细节

先看一下组件的架构,Kube-OVN 自身的安装 yaml 里包含了 OVN 和 OVS 的安装和配置,Kube-OVN 自身的逻辑主要集中在图中蓝色的部分 kube-ovn-controller,kube-ovn-cni 和 kube-ovn-cniserver。其中最主要的逻辑在 kube-ovn-controller 可以看成是一个 k8s 资源的控制器,它会 watch k8s 内所有和网络相关的资源变化,例如 pod,node,namespace,service,endpoint 和 networkpolicy。每当资源发生变化 kube-ovn-controller 会计算预期的状态,并将网络对应的变化翻译成 OVN 北向数据库的资源对象。同时 kube-ovn-controller 会将配置具体网络的信息,例如分配的 ip,mac,网关等信息再以 annotation 的方式回写到 k8s 的资源里,方便后续的处理。

kube-ovn-cni 本身是很薄的一层,主要工作是适配 CNI 的协议和 Kubelet 对接,将标准的 cni add/del 命令发送到每台机器上的 kube-ovn-cniserver 进行后续处理。而 kube-ovn-cniserver 会根据传入的参数反查 k8s 中资源对应的 annotation,操作每台机器上的 ovs 以及容器网络。

举一个创建 pod 的栗子,pod 下发到 apiserver 后 kube-ovn-controller 会 watch 的新生成了一个 pod,然后调用 ovn-nb 的接口去创建一个虚拟交换机接口,成功后将ovn分配的 ip,mac,gw 等信息反写到这个 pod 的 annotation 中。接下来 kubelet 创建 pod 时会调用 kube-ovn-cni,kube-ovn-cni 将信息传递给 kube-ovn-cniserver。cniserver 会反查 pod 的 annotation 获得具体的 ip 和 mac 信息来配置本地的 ovs 和容器网卡,完成整个工作流。其他的service,networkpolicy 的流程也是和这个类似的。

下面来看一下 Kube-OVN 实现的网络模型。

Flannel 和很多网络的实现上都是一个 node 一个子网,我们发现这种子网模型很不灵活,而且也很难扩展。因此在 Kube-OVN 里我们采用了一个 namespace 一个子网的模型,子网是可以跨节点的这样比较符合用户的预期和管理。每个子网对应着 OVN 里的一个虚拟交换机,LB,DNS 和 ACL 等流量规则现在也是应用在虚拟交换机上,这样方便我们之后做更细粒度的权限控制,例如实现 vpc,多租户这样的功能。

所有的虚拟交换机目前会接在一个全局的虚拟路由器上,这样可以保证默认的容器网络互通,未来要做隔离也可以很方便的在路由层面进行控制。此外还有一个特殊的 node 子网,会在每个宿主机上添加一块 ovs 的网卡,这个网络主要是把 node 接入容器网络,使得主机和容器之间网络可以互通。需要注意的是这里的虚拟交换机和虚拟路由器都是逻辑上的,实现中是通过流表分布在所有的节点上的,因此并不存在单点的问题。

网关负责访问集群外部的网络,目前有两种实现,一种是分布式的,每台主机都可以作为运行在自己上面的 pod 的出网节点。另一种是集中式的,可以一个namespace配置一个网关节点,作为当前namespace里的 pod 出网所使用的网关,这种方式所有出网流量用的都是特定的 IP nat 出去的,方便外部的审计和防火墙控制。当然网关节点也可以不做 nat 这样就可以把容器 IP 直接暴露给外网,达到内外网络的直连。

下面来看一下具体的功能和背后的实现

  1. 首先是子网,子网是 Kube-OVN 中最为重要的一个概念,涉及到之后的 IP 分配,ACL 以及未来的 VPC 等功能。实现上每个子网对应 OVN 中的一个虚拟交换机,对应 Kubernetes 中的一个 namespace,我们可以通过给 namespace 加 annotation 的方式来配置一个虚拟交换机。子网里可以配置基础的 cidr,gateway,保留ip段,以及一些基本的 acl,这些都可以用 ovn 自身提供的能力。

  1. 然后是 IP 分配。Kube-OVN 现在支持随机分配和固定 IP 分配。随机分配比较简单,可以使用 OVN 提供的 dynamic addresses 能力,自动分配一个当前子网内不冲突的 IP/Mac。固定 IP 我们采用了一个额外的 annoation ip_pool,pod 在启动时 controller 会跳过 ovn 的自动分配根据 ip_pool 内的 ip 选择一个未被占用的地址分配给 pod。对于 deployment pod 启停会产生 ip 的释放和再分配的过程。表面上看deployment 下面的几个 pod 一直用固定的 ip,但实际上是一个动态变化,最中表现出来使用固定ip的过程。

  1. 之后是 QoS,通过 QoS 可以控制容器的 ingress 和 egress 带宽,我们可以通过 pod 的 annotation 来动态控制容器带宽。实现上我们最早计划使用 OVN 的 QoS 能力,但是实际使用时发现 OVN 的 QoS 这块存在问题,无法控制同主机内的流量,因此最终使用的是 ovs 自身的 ingress_policing_rate 和 port qos 来实现带宽控制。

  1. 网关这里 OVN 本身提供了网关的能力,但是对网络有额外的需求需要用到一块单独的网卡做overlay网络的offload,使用上有些限制因此我们并没有采用。我们最终的实现是使用了OVN中的策略路由,将访问外网的流量路由到特定节点,再通过 iptable 做 masq 自己实现了一套从网关出网的逻辑。这种方案的好处是对网络没有额外的需求,我们在公有云上都可以使用这种网关模式。当然在具体落地时也可以根据场景替换成性能较好的 ovn gateway 方式

  1. 流量镜像。对容器流量进行抓包是件很繁琐的事情,好在 ovs 本身又流量镜像的功能,Kube-OVN 会在每台主机上创建一块 mirror0 的网卡,并设置镜像规则,将该主机上所有的容器流量复制一份到 mirror0 网卡。这样我们只需要 tcpdump -i mirror0 就可以捕获到这台主机上所有的容器网络流量了。方便之后的应用层面的监控和审计。

  1. 还有一些其他的功能。例如用 ovn 的 lb 代替 kube-proxy,用 acl 来实现 networkpolicy 还有 ovn 的高可用等等,感兴趣的可以爬一下 Kube-OVN 的 release note 看看还有什么隐藏功能。

这些看上去功能都比较复杂,但实际使用还是比较简单的在对应的资源上打 annotation 就可以了。此外即使不做任何配置,Kube-OVN 会带一个默认的子网,默认的分布式网关,以及内置的 Service 和 NetworkPolicy 实现,完全可以当一个增强版本的 Flannel 来用。

最后说一下近期工作和未来的发展

  1. ipv6 的支持,这是我们客户方面比较急迫的一个需求,由于工信部的ipv6推广计划,对 ipv6 的需求也越来越多,同时借这个机会我们会对 kube-ovn 现有的子网进行重新的设计,可能会抽象出一个 crd 来做更复杂的控制
  2. 监控/tracing 工具的集成。传统网络工程有很多不错的网络检测工具例如 ipfix,sflow 和 netflow,我们未来会将这些工具加进来丰富网络的功能。此外借助流量镜像的能力我们也可以做一些应用层的流量分析和监控
  3. 性能优化和 DPDK 的支持,主要是为了消除客户对 ovs 性能的担心。我们和社区内的一些人进行过交流,在使用 dpdk 后即使是小包也可以打满万兆网卡,因此性能方面还是很有前途的。

现在项目已经开源在 https://github.com/alauda/kube-ovn 欢迎大家来 star 给作者打打气,也欢迎感兴趣的个人,公司或者友商都能参与进来,大家一块来完善这个项目。

Q1:能说说组件kube-ovn-cni具体是做什么的?ovn本身不是已经是ovs的控制面了么

A:其实做的是容器网卡和 ovs 的对接,ovn那边生成了port的信息,需要kube-ovn-cni把这个信息同步到ovs和容器网卡

Q2:能讲讲kube-onv负载均衡和会话保持是怎么做的吗?已经支持哪些策略?

A:目前的负载均衡用的是 OVN 的 L2 Loadbalancer,这一块的负载均衡还比较简单只支持ip hash

Q3:多租户/vpc模式下是否可以互相之间网段冲突, 如何实现livenessProbe?

A:这块暂时还不支持,主要是kubelet是在主机的network namespace进行probe,其实可以改 kubelete 代码进入到对应容器的 ns 再 probe 就可以了,但是这块需要upstream来进行支持,自己魔改现在倒也是个方案

Q4:讲解的很精彩,但是有一个问题,k8s的业务使用本身就是有局限的,这种无限制扩大虚拟网络的做法,基于业务风险和成本来讲,真的很勇敢,如果原有的k8s生态被改掉了,怎么保证开源的东西可以业务延续?

A:这个问题有点大,我们现在看到的趋势还是 k8s 不断的发展,各个业务都在往 k8s 走,我们做这个其实也希望能尽量和upstream同步,并且之后可以去影响upstream。还有很多复杂的功能,比如ipv4/ipv6的双栈,多租户我们暂时也还没开始,也是因为upstream现在对这块的支持还不好

Q5:和 https://github.com/ovn-org/ovn-kubernetes 的区别是什么?

A:ovn-kubernetes 我们之前调研主要问题在于他们是和 flannel类似的一个节点一个子网的模型,再就是看他们的代码过程中发现控制平面存在着丢消息的隐患。最后看到网络模型和控制平面都要改,工作量太大了我们就自己从头来了

Q6:容器内流量采集监控有没有什么实战和想法?

A:目前还是用的标准的采集网卡上 TX,RX 的一些指标的做法。不过Kube-OVN上现在有流量镜像的能力,未来其实可以做更详细的应用层数据包分析

Q7:使用flow负载均衡器的性能怎么样?是否适合上生产环境。

A:大部分的 flow 性能问题都可以用 dpdk 来解决,我们之前问过一些公有云的厂商性能方面是可以的,但是可能功能方面有些简单

Q8:请问网络相关的功能支持,目前是只针对以太网络吗?你们有对其它高速网络有支持不?

A:目前是只有以太网,但是其他形式的理论上只要 ovs 支持,适配起来应该都比较方便

Q9:使用ovs对host机器的性能压迫有多大?

A:我们目前看来还好,ovs本身带cache的机制,主要还是业务对性能用的比较多一些

Q10:tracing方面跟踪流表有没有想过做自动化

A:有过这个计划,打算结合 ovn-tracing,ovs-tracing 再加上宿主机的探针做一个端到端的数据包跟踪,来解决网络不通排查方面的问题

Q11:kube-ovn-controller如果来不及写入podip这些信息,cni插件获取不到分配的ip信息,会不会导致pod创建失败,还有ovn-cni是能过什么协议和ovn-cni-server进行协作的

A:来不及写入的情况下 cniserver 会重试等待annotation ready,如果超时的话会失败等 kubelet 下次调用 cni 的时候重新获取信息。cni 和 cniserver 现在是通过一个本机的 socket 走http协议进行通信

Q12:dpdk怎么满足需求?使用容器,可以用dpdk加速么?

A:dpdk主要做 ovs 的流表加速,社区由 ovs-dpdk 的 binding,容器相当于用的是 ovs 的网卡,这样dpdk就可以加速容器的网络

Q13:请问你们在使用网络相关的功能时,会在某些场景对特权模式有强需求吗?

A:需要使用特权模式,因为要对宿主机的网络进行一些操作

Q14:在没有硬件交换机的情况,这个网络插件怎么利用虚拟机模拟交换机呢

A:还是要有硬件交换机做物理上的网络连通的,虚拟交换机是在机器中用软件的方式来模拟交换机的行为,这样一台机器上的多个容器或者虚拟机就好像接在了一个物理交换机上

Q15:dpdk并不能加速容器,还会更慢,因为dpdk是用户态得,容器流量是内核态的。

A:dpdk 主要是用来加速流表的处理吧,这块可能得问一下熟悉dpdk的同学了

我来评几句
登录后评论

已发表评论数()

相关站点

+订阅
热门文章