查看原文
其他

云原生网络利器--Cilium 总览

熊中祥 道客船长 2022-12-29



01

背景

在云原生相对成熟的今天,对于 Kubernetes 本身的能力需求,逐渐变得不那么迫切,因为常见的能力都已经成熟稳定了。但是在周边领域还处于不断发展的过程,特别是容器的网络方案,存储方案,安全领域等。

重点是网络方案,举例来说,一个企业要想成功落地容器平台,首先要解决的问题就是网络方案的选型。选型的参考没有标准化。有根据易用性的;有根据规模的;有根据性能的;有根据应用亲和的 (固定 IP),有根据企业内部网络要求的,有根据网络安全要求的,有根据稳定性的 (相对而言) ,有根据可运维性的,等等。

在选型的时候选型的条件大多数是组合条件,这些条件对容器的网络方案就提出了很多的挑战。不同的厂商或者开源项目都在构建不同场景下的网络方案。

从容器的网络发展路线来看,包括以下几个阶段:
  • 基于 Linux bridge 以及基于 ovs 实现的 overlay 的网络。

  • 基于 bgp/hostgw 等基于路由能力的网络。

  • 基于 macvlan,ipvlan 等偏物理网络的 underlay 的网络。

  • 基于 Kernel 的 eBPF 的技术实现的网络。

  • 基于 dpdk/sriov/vpp/virtio-user/offload/af-xdp 实现的用户态的网络。

第一/二/三种网络的方案有一个共同的特性就是完全使用内核成熟的技术,以及对于 netfilter,也就是 iptables 的能力,就是拿来用就可以,不会考虑 bypass 它。

第四种的网络方案中也会用到 iptables,但是它的设计思想是尽量的 bypass netfilter/iptables,以及基于内核的 eBPF 技术实现网络设备之间 redirect 的方式 bypass netfilte,让网络数据处理的路径尽量的短,进而达到高性能的目的,不是说 eBPF 不稳定,而是想要实现更好的性能,对内核的 uapi 的依赖性比较高,往往要开发 feature,并合并到内核去,然后再使用,前三种方案使用的内核技术都是非常成熟的,不会有太多的功能会依赖开发新的内核特性。

第五种网络的方案的主要场景就是希望最快的网络,不同的实现方案,会有硬件的依赖,会有用户态协议栈的技术,内存网络加速的技术,有的方案还会对应用本身有侵入性,而且此方案也是相对最复杂的。

从技术路线来看,不难看出的是,对容器的网络方案的基本诉求就是要越来越快。

从功能的角度看和使用的角度看,基本是类似的,原因是使用的接口都是标准的 CNI 标准接口。

从发展的阶段看,理论上用户态的网络能力是最快的,因为 bypass 了 Kernel,但是也意味着对硬件和应用是有一定的要求的,技术的通用性稍微显得有点不太兼容。

其余 4 种方案都是基于内核技术,通用性比较好。方案没有好坏之分,适合自己的才是好的。那接下来就要看看谁的性能是比较好的。

本文不对所有的网络方案做分析,主要针对最近比较热门的基于 eBPF 实现的 Cilium 网络技术,做一些相关的技术分享。

 

02

技术术语

为了更好的理解 Cilium 实现的能力,首先需要对一些常见的内核技术和网络技术的相关概念有一个初步的认识之后,会更好的帮助理解原理。以下整理一些技术术语,不是包含所有的,主要列出来一些主要的点。

  • CNIKubernetes 网络插件的接口规范的定义,主要能力是对 Kubelet 成容器网卡的创建,申请和设 ip 址,路由设置,网关设置。核心接口就 cmdAdd/cmdDel ,调用接口期间,会传 Pod 关的信息,特别是容器网卡 name,以 Pod network namespace 信息。 

  • IPAM  容器的网卡对应 ip 分配就是 IPAM 成,从全称可以看出来,IP Address Management这个组件是 CNI 用来完成 Pod 申请 ip 址。

  • Vxlan用于在实 overlay 络中,跨主机通信的能力,基于封包和隧道的能力,实 2 虚拟网络。不同主机互相维护对端的隧道地址,通过主机的内核路由,实现数据包跨机器组 overlay 络。

  • Network Policy用于定 Kubernetes ,容器访问控制,容器安全等能力的定义规范。可以实现能不能从容器出去,能不能访问某一个容器,能不能访问某一个服务 port 等,包 L3/L4/L7 及自定义扩展的协议的安全能力。

  • Linux VethLinux 供的一种虚拟网络技术,可以实现 network namespace 信能力。一端在主机网络空间,一端在容器的网络空间。

  • Netfilter/Iptables实现对网络数据包的处理能力。它也 Linux Kernel hook 制,可以理解成在数据包经过内核网络协议栈处理的过程中,需要经过很多的方法处理,在特定的方法中定义 hook,所以这 hook 在内核方法执行前/执行后被调用和执行。Linux 5 这样 hook,分别 pre-routinginputforwordoutputpost-routing处理数据包的能力主要包括修改跟踪打标签过滤等。

  • CT这里 ct 的是连接跟 conntrack,主要完成接受连接和发起连接的时候,记录连接的状态,主要用 nat/reverse nat (snat/dnat) iptables 接处理操作等,作为数据包处理依据。网络连接讲究的是,连接从哪来回哪去。

  • BGP是一种路由协议,用 3 网络的路由发布能力, Pod 地址可以在物理网络设备之间被识别,从而完成跨主机的可路由的能力。

  • NAT/Reverse NAT地址转换在网络连接的过程中是常见的操作。举例,在路由器上就会对地址进行转换,具体 snat (源地址转换) /dnat (目的地址转换) 就看处理连接的阶段,如果是数据包从外部进来,就会进 dnat 作,作用是将数据包的目的地址,转换成真正要访问的服务的地址,如通 NodePort 访问应用,那肯定会将目的地址转换成要访问 Pod ip 址;如果是数据包要从主机出去的时候,一般会进 snat 操作,因为要让数据包的源地址是路由可达的,而一般路由可达的地址应该是主机的物理网卡的地址,所以一般 snat 主机的物理网络地址。 NAT,就会有反 NAT,主要是完 reply 的处理。

  • Linux 路由子系统 / Neigh 系统用于根 ip 址, fib 寻找下一条的地址,以及 Neigh 系统来查找对应 mac 址。在基于二层交换机的场景下,src mac 可以不设置的,但 dst mac 一定要设置的,对于三层的网络通信是一定 src mac dst mac 要设置正确,才可以完成数据包的正确处理。

  • Linux Network Namespace  Linux 供的网络隔离的能力,每一 Network Namespace 独立的网络协议栈, Netfilter/Iptables

  • eBPF是一种可以不改 Kernel 前提下,开 Kernel 关能力的一种技术。 eBPF 程序要使 C 言,因 Kernel C 言开发的,eBPF 开发的过程中会依 Kernel uapi 以及 Linux Hepler 法来完成处理。Linux 基于事件模型的系统,也支持 eBPF 类型 hook,在一 hook 执行挂载 eBPF 序。

  • 一致 Hash一致 Hash 身是一种算法,这里的提到的作用是为了说明在 1.11 本实现的基 XDP LB ,解决访问过程中,运 Backend Pod 主机出现故障之后,为了保证正常的访问,引入了一致 Hash 方式选 Pod具体就是在客户端访问的时候,选择后端可 Pod 时候,使用一致 Hash 算法来决定由哪一 Pod 供服务,这样可以保证选择 Pod 固定的,以及当提供服务 Pod 器出现故障,不会出现接手 Pod 在机器无法处理本次客户端的连接的问题。

  • SNAT/DSR这两个概念是讲的是在完 LB 过程中,采用的地址处理策略,选择不同的策略会影响数据包的流向,以及网络的延迟。SNAT 方式在数据包被代理 Backend 后,reply 包还是会回到代理服务器的节点,然后再由代理服务器的节点再返回 Client DSR 直接 Backend 点直接返回 Client,性能更好。

  • Session Affinity在访 Backends 时候,当需要同一 Client 直保持和之前选择 Backend 接的时候,就会需 Session Affinity 特性,也就是常说的粘性会话。

  • Egress Gateway这个概念不 Cilium 有的,而是一个特定的场景问题。主要解决的是,一 K8s 群要和外部进行通信的时候,需要经过出口的代理网关,这样的好处是可以在被访问端开启特定的防火墙规则,来控 K8s 群中的什么样的出口地址是可以访问墙内的什么样的服务,一般会在网络安全要求比较高的场景下会使用到这个特性。

  • 东西 LB 指的是集群内部,通过内部负载均衡实现的跨主机的容器网络通信。 Pod 访问 ClusterIP Service

  • 南北 LB外部客户端通 Kubernetes 露的支持负载均衡且主机可达的服务,访 Kubernetes 务的方式。 Client 访问 NodePort Service

  • 直接路由模式 / 隧道模式在 Cilium 中, Pod 间的路由方式分为直接路由和隧道的模式。直接路由推荐使 BGP 议完 Pod 由能力,隧道模式使用基 vxlan 技术完 Pod 间的路由能力。

  • EndpointCilium 络的端点 (CiliumEndpoint) ,也可以理解 Cilium 络中的一个参与者,或者实体, K8s 里的 Endpoint 是一个概念。其中不仅仅 Pod 身是一 EndpointHost 是一 Endpoint overlay 络模式 cilium_vxlan 是一 Endpoint而对于外部网络这样的一个虚拟不存在的参与者也是一 Endpoint, 它叫 WORLD_ID

  • Identity用于标记参 Cilium 络的端点 (Endpoint) 的安全身份,用标签的方式来标记。有相 Identity Endpoints 具有相同安全身份的,在处理安全策略的时候,是同样的验证逻辑。这样有一个好处是,不会随 Pod 启导 Pod ip 化,而 policy 要重新生成或者配置的问题。Cilium 身不仅仅完成了容器的网络的数据包处理和传输,其中安全也 Cilium 重要能力,在设计和实现的时候都是统一考虑和实现的。不像其它的网络方案都是在外围来实现。

  • ServiceCilium 中的 Service K8s 里的 Service 是一个定义,但是也是类似的概念,也是用来表述一组服务的访问入口,也有对应 Backend只是这 Service 模型 Cilium 自己定义的。在完 ctnat/reverse-nat,粘性会话的时候,都会用 Service

  • Kube Proxy Replacement使用基 eBPF 数据平面去替 kube-proxy 现的功能,进一步提 K8s 网络相关的性能。

  • Socket LB eBPF 现的东西向 LB,可以 Socket 别完成数据包的发送和接受,而不 Per-Packet 处理方式。可以实现跨主机 Pod->Pod 直接连接,直接通信,而传统 Kube-Proxy 实现 Per-Packet ,且需要基 ipvs/iptables 方式实现 LB 转发能力。 Per-Packet 处理,需要对每一个需要出去的数据包都要进 DNAT 处理, Socket 的方案只需要设置一次,那就是在建立连接 Socket 时候,设置一次的四元组里的目的地址就可以,这样可以提升更好的网络传输速度。

  • Host Reachable Service传统 LB 具,都会在代理请求的时候,进行 NAT 关的操作,但 Host Reachable Service 够完成连 K8s service 时候,真正建立连接的时候是直接连 Backend Pod ip 能力,减少了每次数据包处理 NAT 销。这样网络性能就自然会有所提高。

  • Host Routing / Fast Path 看到名字就可以想到是快速的意思,这个就 Kernel 5.10 新增加的能力,主要包 ctx redirect peer ctx redirect neigh在没 Host Routing 力之前,所有数据包要想进入到容器都需 Kernel 路由能力和邻居子系统,以及需要经 cilium_host 虚拟网络设备才可能进入到容器。而在有 Host Routing 后,可以实现网络设备到网络设备之间的直 redirect,进一步缩短数据包的传输路径。 ctx_redirect_peer ctx_redirect 升级版本,当然 Kernel 版本要求也更高。

  • TProxy 透明代理可以完 LB 景下,模 Client→Backend 直接连接的能力,从连接状态看,和直接连接一样,但是其实中间是有一层代理在处理数据包,完 Client Backend 代理能力。

  • Envoy/Envoy FilterEnvoy 身就是一个可以完 L4/L7 能力的代理工具。 Envoy 很好的扩展性,可以 Envoy 能力进行扩展,完成业务的需要。这里的扩展能力,主要指的就 Envoy Filters,这里 Filters 要包含常见 Listener FiltersNetwork Filters,以 Http Connection Manager FiltersCilium 开源版本就是基 Envoy 能力完成 L7 Network Policy Visibility Policy,以及一些自定义 L4 Policy

  • Hubble / Relay / Hubble-OTEL 这里的三个组件都是为了完 Cilium 可观测能力。 Hubble Cilium Agent 置的能力,每一个节点都会有。Relay 可以完成对所有单机 Hubble 数据进行收集和整合成统一的数据视图,但是在早一点的版本中,这些观测数据都是没有持久化的,都是能查看最近的一些数据,就类似 cAdvisor 对容器数据的监控一样,都是保存在特定的内存中的,在新版本中,有一 Hubble-OTEL 组件,可以完 Hubble 数据对接 OpenTelemetry 去,由 OpenTelemetry 有很多后端持久化插件,这样就可以完成观测数据的历史分析能力。

  • OpenTelemetry:是 CNCF 的用于完成观测能力的项目,支持 Traces、Metrics、Logs 能力的观测技术。具体可以参见官方文档或参见 云原生观测性 - OpenTelemetry

03

架构介绍

Cilium Agent:以 DaemonSet 的方式运行在所有的节点上,并且提供 API。负责全局 eBPF 程序的编辑和挂载,以及为 Pod 编译和挂载 Pod 对应的 eBPF 程序,当有 Pod 被创建的时候,CNI 就会在完成容器本身网卡,地址等设置之后,调用 Cilium Agent 的 EndpointCreate 方法完成 eBPF/Identity 相关数据路径以及安全策略的创建;负责相关 iptables 的初始化和维护,因为在内核版本还不是足够高的情况下,还是需要 iptables 来完成一些工作,如在支持 Network Policy 的时候,使用到基于 iptables 的 tproxy,以及基于 Envoy 实现的 Network Policy 时,需要的 iptables chains 等;负责 eBPF 程序所需要的全局的 Maps 的初始化和维护以及 Pod 相关的 Maps 的创建和维护,因为有一些 Maps 是全局性的,所以需要启动的时候初始化和恢复,有一些是随着 Pod 的创建而创建的;内置 Hubble Server,提供 Metrics 和 Trace 的能力,并且提供 API。同时 Cilium Agent 也内置实现了基于透明代理的 DNS Network Policy 能力的 DNS Proxy Server。

Cilium Operator:负责部分的 IPAM 的工作,主要是给主机节点分配 CIDR,接下来给 Pod 分配 ip 地址由主机上的 Cilium Agent 来完成;负责对存储 Provider 进行健康检查,现在支持 Cilium 的存储 Provider 有 K8s CRD,还有外置的 etcd,当发现存储设施不健康会触发 Cilium Agent 重启;优化 K8s 的 Endpoint 的发现机制,在早期一点的版本,Cilium Agent 要处理的 Endpoint 不是使用的 EndpointSlice 的方式,会导致数据量很大,增加 Cilium Agent 的压力,现在基于 Operator 进行转换,让 Cilium Agent 只处理 Operator 转换出来的 EndpointSlice,极大的减小了数据量,这样支持的集群的节点规模就可以增大,这里的 EndpointSlice 是 K8s 的特性,所以需要开启该特性。

Cilium Cli:用于和本地的 Cilium Agent 通信,提供操作 Cilium 的能力。虽然只和本地的 Cilium Agent 通信,但是可以拿到完整的整个 Cilium 网络方案内的数据。因为每一个 Cilium Agent 是会和控制平面通信。

Cilium Proxy:用于完成 L7/Proxylib 类型的 Network Policy 的合法检查,检查通过就会继续处理数据包,不通过就返回。实现的方式是使用 C++扩展 Envoy 实现的一整套 filters,包括 Listener Filter, Network Filter,Http Filter。可以支持 K8s Network Policy,支持 Kafka 的 Policy 等都是在这里完成的。Cilium Agent 会负责处理 Proxy 相关的控制流,包括启动一个包括定制化配置的 Envoy。这里的 Proxy 是完全只是和 Envoy 相关的,为了支持 Policy 能力的部分。对于 L3/L4 层的 Network Policy 是在 eBPF 的程序中直接完成验证的。

Cilium DNS Proxy:拦截和验证访问的 DNS 是不是可以访问,这里的 DNS Proxy 不是独立的组件,而是 Cilium Agent 内置实现的一个独立的 Server,在这里单独提出来,只是为了强调能力的独立性。主要的实现方式是基于 tproxy 的能力将请求转发到 DNS Proxy Server,完成 DNS 请求的验证。

Cilium CNI: 这个比较熟悉了,就是实现了 CNI 接口的组件,由 Kubelet 调用在 Pod 的网络命名空间中完成容器网络的管理,包括容器网卡的创建,网关的设置,路由的设置等,因为依赖 eBPF 的网络能力,这里还会调用 Cilium Agent 的接口,完成 Pod 所需要的 eBPF 程序的编译,挂载,配置,以及和 Pod 相关的 eBPF Maps 的创建和管理。

Hubble Server:主要负责完成 Cilium 网络方案中的观测数据的服务。在 Cilium 运行的数据路径中,会对数据包的处理过程进行记录,最后统一由 Hubble Server 来完成输出,同时提供了 API 来访问这些观测数据。

Hubble Relay: 因为 Hubble Server 提供了 API 接口,而 Relay 就是调用所有集群节点的 Hubble Server 的 API 接口,对观测数据进行汇总,然后由 Hubble UI 统一展示。 

Hubble UI:用于展示 Hubble Server 收集的观测数据,这里会直接连接到 Relay 去查询数据。

Hubble OTEL:用于将 Hubble Server 的观测数据以 OTLP 的协议导出到 OpenTelemetry 框架中。由于 OpenTelemetry 有丰富的生态,可以很好地对 Cilium 的观测数据进行管理和分析。

eBPF 程序:使用 eBPF 可以开发出对应不同类型的 Linux 子系统的能力扩展。这里主要使用最多的是和网络相关的能力。主要包括如下几个场景:在 XDP 和 TC 的 hook 处,对数据包进行处理,完成对数据包的验证和转发,这里的转发主要依赖 Kernle 的 redirect (ifindex, flags)/redirect_peer (ifindex, flags) 能力;使用 cgroup 类型的 eBPF 程序完成 Socket LB 能力,提供更高网络性能的东西向通信;使用 sockmap 类型和 socket ops 类型的 eBPF 程序完成 Socket Redirect 能力,加速本地 Socket 之间的通信。

eBPF Maps:Linux 提供了很多种类型的 eBPF Maps 供 eBPF 程序使用,理论上传统开发语言中的 Map 只是一种数据结构,eBPF 也一样,只是 eBPF 的 Maps 的类型更偏向场景或是功能,举例来说,要想完成 socket redirect,这里常用就是 BPF_MAP_TYPE_SOCKHASH 类型的 Map,配合 msg_redirect_hash 方法,完成 socket 的数据包的 redirect。Maps 的类型有很多种,暂不列出具体的类型。

iptables:用于完成在内核版本不支持的某一些功能下的时候,还是需要 iptables 来支撑,举例在 Kernel 的版本低于 5.7 的时候,tproxy 还是要依赖于 iptables 来完成,但是在高的版本里就直接可以用基于 eBPF 实现的 tproxy 了。再比如,在使用 Envoy 实现 Network Policy 的能力,以及处理完成之后将数据包 reply 到 Cilium 的网络的过程中,依赖于 iptables 和 ip rule 将数据包定向传输到 cilium_host。

Grafana:用于展示 Cilium 暴露出来的 Prometheus 的 Metrics 数据。

Prometheus:用于收集 Cilium 暴露出来的 Prometheus 的 Metrics 数据。

OpenTelemetry:用于收集 Cilium 通过 OTLP 协议暴露出来的 Trace 的数据。

K8s api server:用于 Cilium 的 datastore,保存 Cilium 的数据。如 Identity 数据, Endpoint 数据。Cilium Agent 会与其通信,完成数据的发现。

etcd:另一种可用于 Cilium 的 datastore,保存 Cilium 的数据。如 Identity 数据,Endpoint 数据。Cilium Agent 会与其通信,完成数据的发现。

04

观测能力

Cilium 默认提供了一些观测的能力,支持基于 Cilium Agent 内置的 Prometheus 来获取 Metrics 数据,配合 Grafana 实现监控数据的展示;支持基于数据包访问路径的 Trace,包括 L4/L7 的观测。这里有一个点比较特别是 L7 的观测,默认是不打开的,在需要观测 L7 的 Pod 上打上 annotation 就可以拿到这个 Pod 的 L7 的观测数据,对于 L4 是默认就实现了观测,不需要额外配置。

  • L7 Trace 实现:
基于 Pod 的 annotation,annotation 的 name 是 “io.cilium.proxy-visibility”, value 是      “<{Traffic Direction}/{L4 Port}/{L4 Protocol}/{L7 Protocol}>”
举例:
kubectl annotate pod foo -n bar io.cilium.proxy-visibility="<Egress/53/UDP/DNS>,<Egress/80/TCP/HTTP>"。    

实现方式:

1. Cilium Agent 会 watch Pod 的一些 annotation 的变化,其中就是包括了 ProxyVisibility,也就是“io.cilium.proxy-visibility”这个 annotation。     
2. Cilium Agent 会为 Visibility Policy 创建 redirect 对象,在经过 proxy 处理之后,会记录下相关的 Trace 信息,最后通过 Hubble 组件暴露出来。
  • Trace:

  • Metrics:

05

性能

TCP Throughput  (TCP_STREAM)

Request/Response Rate  (TCP_RR)

Connection Rate  (TCP_CRR)

Test Configurations

06

社区发展

除了 Cilium 关键的容器网络能力之外,还包括在发展的:

  • Cilium Cluster Mesh 多集群的能力,主要包括跨集群的服务发现,负载均衡,网络策略,透明加密,Pod 由等。

  • Cilium Service Mesh 服务网格的能力,主要包括基 No Sidecar 式运行代理。 L7 服务,使用每台机器一 Envoy 机制完成微服务治理的相关能力。





 本文作者 


熊中祥

「DaoCloud 道客」技术合伙人

云原生技术专家






相关资料:

https://docs.cilium.io/en/stable/bpf/

https://docs.cilium.io/en/v1.11/operations/performance/benchmark/

https://grafana.com/grafana/dashboards/13539






DaoCloud 公司简介

「DaoCloud 道客」云原生领域的创新领导者,成立于 2014 年底,拥有自主知识产权的核心技术,致力于打造开放的云操作系统为企业数字化转型赋能。产品能力覆盖云原生应用的开发、交付、运维全生命周期,并提供公有云、私有云和混合云等多种交付方式。成立迄今,公司已在金融科技、先进制造、智能汽车、零售网点、城市大脑等多个领域深耕,标杆客户包括交通银行、浦发银行、上汽集团、东风汽车、海尔集团、屈臣氏、金拱门(麦当劳)等。目前,公司已完成了 D 轮超亿元融资,被誉为科技领域准独角兽企业。公司在北京、武汉、深圳、成都设立多家分公司及合资公司,总员工人数超过 400 人,是上海市高新技术企业、上海市“科技小巨人”企业和上海市“专精特新”企业,并入选了科创板培育企业名单。


网址:www.daocloud.io

邮件:info@daocloud.io

电话:400 002 6898




您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存