k8s容器网络(一) -- 网络模型

k8s容器网络(一)-- 网络模型

  • k8s网络模型
    • k8s网络设计与要求
    • k8s容器网络接口
      • 网络配置
      • runtime配置
      • k8s调用cni插件流程
    • k8s网络通信实现方案
      • 隧道
      • 路由
      • underlay
  • 如何选择合适的网络插件
    • 环境
    • 功能
    • 性能
    • 参考文档

k8s网络模型

在k8s网络模型中,每台服务器上的容器都有自己独立的IP段,各个服务器之间的的容器可以根据目标容器的ip地址进行直接访问,各个容器可以跟服务器进行直接访问。
k8s容器网络(一) -- 网络模型_第1张图片

k8s网络设计与要求

为了实现这一目标,k8s设计了单pod单ip模型,其特点如下:

  1. 每个pod都有一个独立的ip,pod内的所有容器共享网络命名空间;
  2. 集群内所有Pod都在一个直接连通的扁平网络中,可通过IP直接访问,容器与容器之间、容器与节点之间能够直接通信,无需NAT和地址伪装

因此我们在设计k8s网络时主要考虑两点:

  1. 要能够为每一个Node上的Pod分配互相不冲突的IP地址;
  2. 要所有Pod之间能够互相访问

k8s容器网络接口

CNI(Container Network Interface)是一个标准的、通用的网络接口,是由CoreOS提出的一个容器网络规范。用于配置或销毁容器时动态配置适当的网络配置和资源。
k8s容器网络(一) -- 网络模型_第2张图片
CNI是k8s与底层网络插件之间的一个抽象层,为k8s屏蔽了底层网络实现的复杂度,同时解耦了k8s的具体网络插件实现。

CNI主要定义了两个接口:

  1. 创建容器时调用的配置网络接口
  2. 删除容器时调用的清理网络接口

这两个接口的入参都是两个:网络配置runtime配置

网络配置

CNI通过json文件来描述一个网络配置

runtime配置

由于k8s与容器运行时是解耦的,支持多种容器运行时,各个容器运行时对于网络空间的隔离和使用可能是不一样的,因此CNI为了与CRI解耦,所以需要传入runtime配置,主要是容器运行时传入的网络namespace信息。

k8s调用cni插件流程

k8s容器网络(一) -- 网络模型_第3张图片

  1. k8s调用CRI创建pause网络,生成对应的network namespace
  2. 调用网络驱动,如果是配置的CNI就要调用CNI的相关代码
  3. CNI调用添加网络接口(AddNetwork),解析cni插件配置,调用具体CNI插件
  4. CNI插件给pause容器配置正确的网络

k8s网络通信实现方案

为了实现容器与容器之间、容器与节点之间能够直接通信,目前大致有三种方案:

  1. 隧道(overlay)
  2. 路由
  3. underlay

隧道

隧道可以看做是一个虚拟通道,通信双方都认为自己在直接通信,是建立在现有网络之上的虚拟逻辑网络。
不依赖底层网络,一般要求底层三层可达。
通常是把某一协议的数据包封装在另一种网络协议中,然后通过底层网络进行路由转发。
目前常见的使用隧道的插件有:flannel(udp,vxlan),calico(ipip)

路由

跨主机的通信是通过路由打通,无需再不同主机之间做一个隧道封包。
部分插件使用路由方式通信需要依赖底层网络(二层可达)
常见支持路由方式的cni插件有:flannel(host-gateway),calico(bgp)

underlay

容器与宿主机位于同一层网络,两者拥有相同的地位,容器之间的网络打通主要依靠于底层网络

如何选择合适的网络插件

社区现在有很多网络插件,需要如何选择呢?通常需要根据自己环境、所需网络功能以及性能等方面去考虑

环境

不同环境中支持的底层能力是不同的。

  1. 虚拟化环境
    虚拟化环境下的网络限制比较多,比如不允许机器之间直接通过二层协议进行访问,必须要带有ip地址这种三层的才能进行转发,限制某一个机器是使用某些ip。在这种对网络有强限制的环境中,只能选择overlay的插件
  2. 物理机环境
    物理机环境底层网络限制比较少,比如说我们在同一个交换机下面直接做一个二层的通信。对于这种集群环境,我们可以选择 Underlay 或者路由模式的插件。Underlay 意味着我们可以直接在一个物理机上插多个网卡或者是在一些网卡上做硬件虚拟化;路由模式就是依赖于 Linux 的路由协议做一个打通。这样就避免了像 vxlan 的封包方式导致的性能降低。
  3. 公有云环境
    公有云环境也是虚拟化,因此底层限制也会较多。但每个公有云都会考虑适配容器,提升容器的性能,因此每家公有云可能都提供了一些 API 去配置一些额外的网卡或者路由这种能力。在公有云上,我们要尽量选择公有云厂商提供的 CNI 插件以达到兼容性和性能上的最优。

环境限制因素会对网络插件做一个筛选,在这个基础上,我们就可以去考虑功能上的需求。

功能

不同的k8s集群所需的网络功能不同。

  1. 安全需求
    k8s支持networkPolicy,这样我们就可以设定networkPolicy的规程去支持pod之间的访问策略。但是不是每个cni插件都支持networkPolicy的声明,这时我们需要选择支持networkPolicy的插件,比如:calico,weave
  2. 集群外的资源和集群内的资源互联互通
    大家的应用最初都是在虚拟机或者物理机上,容器化之后,应用无法一下就完成迁移,因此就需要传统的虚拟机或者物理机能跟容器的 IP 地址互通。为了实现这种互通,就需要两者之间有一些打通的方式或者直接位于同一层。此时可以选择 Underlay 的网络,比如 sriov 这种就是 Pod 和以前的虚拟机或者物理机在同一层。我们也可以使用 calico-bgp,此时它们虽然不在同一网段,但可以通过它去跟原有的路由器做一些 BGP 路由的一个发布,这样也可以打通虚拟机与容器。
  3. k8s服务发现与负载均衡
    K8s 的服务发现与负载均衡就是我们前面所介绍的 K8s 的 Service,但并不是所有的 CNI 插件都能实现这两种能力。比如很多 Underlay 模式的插件,在 Pod 中的网卡是直接用的 Underlay 的硬件,或者通过硬件虚拟化插到容器中的,这个时候它的流量无法走到宿主机所在的命名空间,因此也无法应用 kube-proxy 在宿主机配置的规则。
    这种情况下,插件就无法访问到 K8s 的服务发现。因此大家如果需要服务发现与负载均衡,在选择 Underlay 的插件时就需要注意它们是否支持这两种能力。

性能

  1. pod网络创建性能
    当业务高峰时,需要紧急扩容,这时可能短时间创建大量pod,就需要CNI插件短时间创建并配置大量pod的网络。这时我们可以选择overlay和路由模式的CNI插件,这类插件创建速度比较快,他只需要调用一些内核接口创建虚拟化网络即可。但对于 Underlay 模式,由于需要创建一些底层的网络资源,所以整个 Pod 的创建速度相对会慢一些。
  2. pod网络性能
    主要表现在两个 Pod 之间的网络转发、网络带宽、PPS 延迟等这些性能指标上。Overlay 模式的性能较差,因为它在节点上又做了一层虚拟化,还需要去封包,封包又会带来一些包头的损失、CPU 的消耗等,如果大家对网络性能的要求比较高,比如说机器学习、大数据这些场景就不适合使用 Overlay 模式。这种情形下我们通常选择 Underlay 或者路由模式的 CNI 插件。

参考文档

  1. k8s网络之设计与实现:https://www.cnblogs.com/goldsunshine/p/10740090.html
  2. 从零开始入门 K8s | 理解 CNI 和 CNI 插件:https://mp.weixin.qq.com/s/sGTEp9m8PC2zhlEgcnqtZA?spm=a2c6h.12873639.0.0.6ec05225vbXGLi

你可能感兴趣的:(kubernetes,kubernetes)