Cilium

转载自Kubernetes 网络方案——炫酷的 Cilium - 知乎 (zhihu.com)

最近业界使用范围最广的K8S CNI网络方案 Calico 宣布支持 eBPF,而作为第一个通过 eBPF 实现了 kube-proxy 所有功能的 K8S 网络方案——Cilium,它的先见之名是否能转成优势,继而成为 CNI 新的头牌呢?今天我们一起来入门最 Cool Kubernetes 网络方案 Cilium。

介绍

当前趋势

现代数据中心的应用系统已经逐渐转向基于微服务架构的开发体系,一个微服务架构的应用系统是由多个小的独立的服务组成,它们之间通过轻量通信协议如 HTTP、gRPC、Kafka 等进行通信。微服务架构下的服务天然具有动态变化的特点,结合容器化部署,时常会引起大规模的容器实例启动或重启。要确保这种向高度动态化的微服务应用之间的安全可达,既是挑战,也是机遇。

现有问题

传统的Linux网络访问安全控制机制(如iptables)是基于静态环境的IP地址和端口配置网络转发、过滤等规则,但是IP地址在微服务架构下是不断变化的,非固定的;出于安全目的,协议端口(例如HTTP传输的TCP端口80)也不再固定用来区分应用系统。为了匹配大规模容器实例快速变化的生命周期,传统网络技术需要维护成千上万的负载均衡规则和访问控制规则,并且需要以不断增长的频率更新这些规则,而如果没有准确的可视化功能,要维护这些规则也是非常困难,这些对传统网络技术的可用性和性能都是极大的挑战。比如经常会有人对kube-proxy基于iptables的服务负载均衡功能,在大规模容器场景下具有严重的性能瓶颈,同时由于容器的创建和销毁非常频繁,基于IP做身份关联的故障排除和安全审计也很难实现。、

kube-proxy是Kubernetes中的一个组件,用于实现服务的负载均衡和网络代理。在默认情况下,kube-proxy使用iptables作为负载均衡的实现方式。

现在来解释一下iptables和Linux的iptables之间的区别:

  1. iptables:iptables是Linux系统上的一个工具,用于配置和管理防火墙规则和网络地址转换(NAT)。它是一个用户空间的命令行工具,用于设置和修改Linux内核中的防火墙规则。
  2. kube-proxy的iptables实现:kube-proxy使用iptables来实现服务的负载均衡。它在每个节点上创建一组iptables规则,根据服务的IP和端口将流量转发到后端Pod。这些规则可以通过iptables命令进行配置和管理。

总结起来,iptables是Linux系统上的一个工具,用于配置和管理防火墙规则和NAT。而kube-proxy使用iptables作为一种实现方式,通过在每个节点上创建和管理iptables规则来实现服务的负载均衡。

解决方案

Cilium作为一款Kubernetes CNI插件,从一开始就是为大规模和高度动态的容器环境而设计,并且带来了API级别感知的网络安全管理功能,通过使用基于Linux内核特性的新技术BPF,提供了基于server/pod、container作为标识,而非传统的ip地址,来定义和加强容器和pod之间网络层、应用层的安全策略。因此Cilium不仅将安全控制与寻址解耦来简化在高度动态环境中应用安全性策略,而且提供传统网络第3层、第4层隔离功能,以及基于http蹭上隔离控制,来提供更强的安全隔离性。另外,由于BPF可以动态地插入控制Linux系统的程序,实现了强大的安全可视化功能,而且这些变化是不需要更新应用代码活重启应用服务本身就可以生效,因为BPF是运行在系统内核中的。以上这些特性,使Cilium能够在大规模容器环境中也具有高度可伸缩性、可视化以及安全性。

部署 Cilium

部署 Cilium 非常简单,可以通过单独的 yaml 文件部署全部组件(目前我使用了这个方式部署了1.7.1 版本),也可以通过 helm chart 一键完成。重要的是部署环境和时机:

  1. 官方建议所有部署节点都使用 Linux 最新稳定内核版本,这样所有的功能都能启用,具体部署环境建议可以参照这里。
  2. 作为一个 Kubernetes 网络组件,它应该在部署 Kubernetes 其他基础组件之后,才进行部署。这里,我自己遇到的问题是,因为还没有 CNI 插件,coredns 组件的状态一直是 pending的,直到部署完 Cilium 后,coredns 完成了重置变成running状态。

下图是 Cilium 的整体部署组件图:

测试安装效果

官方提供了一个 connectivity 检查工具,以检测部署好的 Cilium 是否工作正常。如果你的网络环境有些限制,我作了一些简单修改,可以参照这里。部署起来很简单,请确保至少有两个可用的节点,否则有几个 deployment 会无法成功运行:

> kubectl apply -f connectivity-check.yaml

NAME                                    READY   UP-TO-DATE   AVAILABLE   AGE
echo-a                                  1/1     1            1           16d
echo-b                                  1/1     1            1           16d
host-to-b-multi-node-clusterip          1/1     1            1           16d
host-to-b-multi-node-headless           1/1     1            1           16d
pod-to-a                                1/1     1            1           16d
pod-to-a-allowed-cnp                    1/1     1            1           16d
pod-to-a-external-1111                  1/1     1            1           16d
pod-to-a-l3-denied-cnp                  1/1     1            1           16d
pod-to-b-intra-node                     1/1     1            1           16d
pod-to-b-multi-node-clusterip           1/1     1            1           16d
pod-to-b-multi-node-headless            1/1     1            1           16d
pod-to-external-fqdn-allow-google-cnp   1/1     1            1           16d

如果所有的 deployment 都能成功运行起来,说明 Cilium 已经成功部署并工作正常。

网络可视化神器 Hubble

上文提到了 Cilium 强大之处就是提供了简单高效的网络可视化功能,它是通过 Hubble组件完成的。Cilium在1.7版本后推出并开源了Hubble,它是专门为网络可视化设计,能够利用 Cilium 提供的 eBPF 数据路径,获得对 Kubernetes 应用和服务的网络流量的深度可见性。这些网络流量信息可以对接 Hubble CLI、UI 工具,可以通过交互式的方式快速诊断如与 DNS 相关的问题。除了 Hubble 自身的监控工具,还可以对接主流的云原生监控体系—— Prometheus 和 Grafana,实现可扩展的监控策略。

取代kube-proxy组件

Cilium 另外一个很大的宣传点是宣称已经全面实现kube-proxy的功能,包括 ClusterIP, NodePort, ExternalIPsLoadBalancer,可以完全取代它的位置,同时提供更好的性能、可靠性以及可调试性。当然,这些都要归功于 eBPF 的能力。官方文档中提到,如果你是在先有 kube-proxy 后部署的 Cilium,那么他们是一个 “共存” 状态,Cilium 会根据节点操作系统的内核版本来决定是否还需要依赖 kube-proxy 实现某些功能,可以通过以下手段验证是否能停止 kube-proxy 组件:

# 检查 Cilium 对于取代 kube-proxy 的状态
> kubectl exec -it -n kube-system [Cilium-agent-pod] -- cilium status | grep KubeProxyReplacement
# 默认是 Probe 状态
# 当 Cilium agent 启动并运行,它将探测节点内核版本,判断 BPF 内核特性的可用性,
# 如果不满足,则通过依赖 kube-proxy 来补充剩余的 Kubernetess,
# 并禁用 BPF 中的一部分功能
KubeProxyReplacement:   Probe   [NodePort (SNAT, 30000-32767), ExternalIPs, HostReachableServices (TCP, UDP)]
# 查看 Cilium 保存的应用服务访问列表
# 有了这些信息,就不需要 kube-proxy 进行中转了
> kubectl exec -it -n kube-system [Cilium-agent-pod] -- cilium service list
ID   Frontend              Service Type   Backend
1    10.96.0.10:53         ClusterIP      1 => 100.64.0.98:53
                                          2 => 100.64.3.65:53
2    10.96.0.10:9153       ClusterIP      1 => 100.64.0.98:9153
                                          2 => 100.64.3.65:9153
3    10.96.143.131:9090    ClusterIP      1 => 100.64.4.100:9090
4    10.96.90.39:9090      ClusterIP      1 => 100.64.4.100:9090
5    0.0.0.0:32447         NodePort       1 => 100.64.4.100:9090
6    10.1.1.179:32447      NodePort       1 => 100.64.4.100:9090
7    100.64.0.74:32447     NodePort       1 => 100.64.4.100:9090
8    10.96.190.1:80        ClusterIP
9    10.96.201.51:80       ClusterIP
10   10.96.0.1:443         ClusterIP      1 => 10.1.1.171:6443
                                          2 => 10.1.1.179:6443
                                          3 => 10.1.1.188:6443
11   10.96.129.193:12000   ClusterIP      1 => 100.64.4.221:12000
12   0.0.0.0:32321         NodePort       1 => 100.64.4.221:12000
13   10.1.1.179:32321      NodePort       1 => 100.64.4.221:12000
14   100.64.0.74:32321     NodePort       1 => 100.64.4.221:12000
15   10.96.0.30:3000       ClusterIP
16   10.96.156.253:3000    ClusterIP
17   100.64.0.74:31332     NodePort
18   0.0.0.0:31332         NodePort
19   10.1.1.179:31332      NodePort
20   10.96.131.215:12000   ClusterIP      1 => 100.64.4.221:12000
# 查看 iptables 是否有 kube-proxy 维护的规则
> iptables-save | grep KUBE-SVC
<Empty> # 说明 kube-proxy 没有维护任何应用服务跳转,即可以停止它了。
Last modification:December 11, 2023
如果觉得我的文章对你有用,请随意赞赏