Cilium 1.7发布:Hubble UI、全集群网络策略、基于eBPF的Direct Server Return、TLS可见性、新的eBPF Go库以及更多……


在这里,我们要向大家高兴地宣布,Cilium 1.7版本正式发布了!在本轮更新周期当中,由141位开发者组成的项目社区共完成了1551项提交,而且很多朋友是第一次为Cilium项目提交贡献。
  • Hubble:自功能发布以来,很多朋友对于Hubble给出了积极的反馈。为了进一步简化集群连接的可视化与调试方式,我们以开源形式公布了新的Hubble UI,允许大家根据需求对其出调整及扩展!我们还一直在努力对Hubble的核心实现做出一系列改进,包括将网络流量数据同Kubernetes资源更好地关联起来。
  • Cilium全集群网络策略:1.7版本带来备有期待的集群内CNP功能。这意味着无论当前Pod处于哪个命名空间内,用户都可以使用面向整个集群中全部Pod的基准性网络策略。
  • 利用Direct Server Return替代kube-proxy:正如我们在Kubecon US 2019与FSDEM 2020大会上所提到,此次最新版本完善了Direct Server Return(DSR)作为kube-proxy继任者的服务功能集,同时为前者带来更多支持选项。这将进一步改进DSR在Cilium中的延迟与性能表现。此外,我们的DSR也已经结束了beta测试阶段,将在具有较新内核版本的环境中自动启用。
  • 通过TLS自省拓展L7策略:我们已经为Cilium添加了支持,可通过Kubernets资源或者本地文件配置Envoy TLS证书。这基功能使Cilium能够更透明地观察HTTP调用,同时在TLS加密会话上强制执行API感知策略。
  • 各Pod的L7可见性注释:在之前的版本中,如果要在集群内实现对流量的L7可见性,用户需要编写网络策略以保证Pod处于默认拒绝的状态。现在,新的可见性注释功能允许用户首先实现L7网络流量可见性,再根据这些观察结论制定完整的网络策略。
  • 纯Go eBPF库:此次发布的1.7版本,也是第一个使用由Cilium社区与CloudFlare联合编写的纯Go eBPF库的版本。这套简化库使Cilium得以摆脱CGo,在提高性能的同时降低二进制文件大小。
  • 通过Kubernetes EndpointSlice支持与Cilium代理改进改善可扩展性,进一步发展上游Linux,在托管Kubernetes上运行我们的测试环境,通过Helm分发Cilium等等!


Cilium是什么?

Cilium是一款开源软件,负责以透明方式提供并保护由Linux容器管理平台(例如Kubernetes)部署完成的各应用程序服务间的网络与API连接。
Cilium的基础,是一种被称为eBPF的新型linux内核技术。该技术能够在Linux内部动态插入功能强大的安全性、可见性与网络控制逻辑机制。eBPF能够实现多种功能,包括多集群路由、负载均衡(用以替代kube-proxy的部分),透明加密以及网络与服务安全性等。除了提供传统的网络级安全性外,eBPF的出色灵活性也使其能够在应用程序协议以及DNS请求/响应等情境下为安全增添助力。Cilium与Envoy紧密集成,同时提供基于Go语言的扩展框架。由于eBPF运行在Linux内核当中,因此可以在应用全部Cilium功能的同时,避免对应用程序代码或者窗口配置产生任何干扰。

新的USERS.md文件:谁在使用Cilium?

* N: Adobe, Inc.
D: Adobe's Project Ethos uses Cilium for multi-tenant, multi-cloud clusters
U: L3/L4/L7 policies
L: https://youtu.be/39FLsSc2P-Y
* N: CENGN - Centre of Excellence in Next Generation Networks
D: CENGN is using Cilium in multiple clusters including production and development clusters (self-hosted k8s, On-premises)
U: L3/L4/L7 network policies, Monitoring via Prometheus metrics & Hubble
L: https://www.youtube.com/watch?v=yXm7yZE2rk4
Q: @rmaika @mohahmed13
* N: Datadog
D: Datadog is using Cilium in AWS (self-hosted k8s)
U: ENI Networking, Service load-balancing, Encryption
Q: @lbernail, @roboll
[...] 

查看完整USERS.md文件

要提高项目水准,交流体验并向用户学习当然是不可或缺的一环。我们非常关注是哪些用户在就Cilium中的特定功能与其他用户开展讨论,也一直在跟进其中的经验与最佳实践。从结果来看,Cilium Slack社区非常活跃,而用户们抱怨的主要问题是很难快速在Cilium中找到特定功能。

如果您正在使用Cilium,可以将自己添加为用户、创建一条pull request、描述您如何使用Cilium,同时简要说明自己的使用场景。如果您希望在Slack上与其他Cilium用户联系,也可以在其中添加您自己的Slack昵称。

Hubble

作者:Sebastian Wicki与Sergey Generalov
01.png

Cilium 1.7的开发周期与Hubble的第一个预览版基本一致。Hubble是专门为Cilium设计的查看工具。通过使用Cilium的eBPF数据路径,Hubble能够深入了解Kubernetes应用与服务的网络流量。以此为基础,您可通过Hubble CLI及UI查询相关信息,并据此对DNS问题进行交互式故障排除。在监控过程中,Hubble将为您提供可扩展的指标框架,这套框架已经被良好集成至Prometheus与Grafana当中。关于更多相关信息,请参阅关于在Grafana中设置Hubble指标的教程资料

Cilium 1.7版本也针对Hubble推出多项新功能:首先是L7 Pod可见性注释,允许Hubble从DNS及HTTP流量中提取应用层信息。新版本还扩展了Cilium API,允许Hubble利用其他元数据标观察到的网络数据流,例如将Kubernetes ClusterIP与其对应的服务名称映射起来。

Hubble UI

02.png

Hubble UI能够全自动发现L3/L4甚至是L7中的Kubernetes集群服务依赖关系图,轻松帮助用户实现可视化,并将这些数据流以服务映射的形式加以过滤。在Hubble刚刚亮相时,我们就开始为用户提供包含其预览版的Docker镜像,确保每个人都能在Minikube中体验Hubble Service Map的功能,同时不会对原有源代码产生任何影响。

在这里我们高兴地宣布,Hubble UI代码现已开源,您可以通过以下链接从Cilium的GitHub项目中获取:https://github.com/cilium/hubble-ui

在Cilium 1.7的开发过程中,我们还对Hubble UI做出了多项性能改进,希望它能够在小规模多节点集群中更好地运作。当然,目前的Hubble UI仍处于预览阶段,我们建议大家通过Hubble GitHub页面或者Cilium Slack的#hubble频道上提供反馈。

Cilium全集群网络策略

作者:Deepesh Pathak与André Martins
03.png

新版本带来Cilium全集群网络策略(CCNP)。在1.7版本之前,所有Cilium网络策略都包含对应的命名空间,因此用户无法以简单易行的方式配置适用于整个集群的基准性策略。集群范围内的策略允许集群维护者应用面向全部命名空间内各个Pod的策略要求,借此简化默认状态下的标准应用方式,而不必受限于特定命名空间内的现有策略。在各类使用场景下,全集群策略都显得非常重要,例如:
  • 在创建任意命名空间时,自动应用默认拒绝策略以保障安全;
  • 允许调用一组特定的基准性允许目标,例如kube-dns,确保所有应用程序都使用相同的DNS目标或者已知IP范围;
  • 减少大规模环境中由网络策略带来的管理开销。


CiliumClusterwideNetworkPolicy资源规范与现有CiliumNetworkPolicy CRD规范相同,只是在适用范围方面有所区别,具体由YAML中的“kind”字段负责界定。大家可以为CCNP分别定义基于资源的访问控制(RBAC)机制,确保对特定命名空间内策略做出修改的用户,不会影响到覆盖全集群的基准性策略。以下策略示例将向整个集群内带有my-app标签组的所有Pod授权通过kube-dns执行DNS请求的权限:

策略示例

apiVersion: "cilium.io/v2"
kind: CiliumClusterwideNetworkPolicy
description: "Default deny and allow egress to kube-dns pod."
metadata:
name: "clusterwide-policy-example"
spec:
endpointSelector:
matchLabels:
  group: my-app
egress:
- toEndpoints:
    - matchLabels:
        "k8s:io.kubernetes.pod.namespace": kube-system
        k8s-app: kube-dns
  toPorts:
    - ports:
        - port: "53"

1.7版本中针对全集群范围引入的这项新功能,将帮助大家更轻松地创建出适用于整个集群的网络策略。

Direct Server Return取代原有kube-proxy

作者: Martynas Pumputis、Daniel Borkmann、Sebastian Wicki以及André Martins
04.png

1.7版本还带来其他多项新的改进,并为Cilium v1.6中首次引入的CiBula eBPF中的kube-proxy提供替代性功能。基于eBPF的kue-proxy作为替代性方案,能够实现对ClusterIP、NodePort、ExternalIP以及LoadBalancer等Kubernetes服务的处理能力。

与Kubernetes中的原始kube-proxy相比,eBPF中的kuber-proxy替代方案具有一系列重要优势,例如更出色的性能、可靠性以及可调试性等等。关于快速入门指南以及高级配置选项,请参阅无kube-proxy Kubernetes。此外,也推荐大家参阅Kubecon US 2019FOSDEM 2020上发布的实施细节与性能基准信息。

在新版本中,这套替代性方案已经趋于稳定,因此从beta版本升级至通用版本。只要底层Linux内核提供支持,通过Helm部署的新Cilium会在默认情况下透明启用kube-proxy替代组件。换句话说,即使继续配合kube-proxy环境,用户也仍将从基于eBPF的数据路径优化效果中获得收益。
感兴趣的朋友可以观看下面这段时长为2分钟的Cilium演示,了解如何在无需kube-proxy及内核外netfilter/iptables编译的情况下运行Kubernetes:

视频

Direct Server Return

当大家通过NodePort、ExternalIP或者LoadBalancer从外部访问Kubernetes服务时,Kubernetes的工作节点可能会将某条请求重新定向至另一节点。当服务端点与请求发送目标处于不同节点时,这样的情况就会发生。在重新定向之前,该请求已经进行过SNAT处理,因此后端将看不到客户端的源IP地址。同样的,答复将通过初始节点发送回客户端,并带来额外的延迟。

为了避免这个问题,Kubernetes提供externalTrafficPolicy = Local,因此如果接收节点上未运行任何服务端点,则通过向服务发送请求以保留客户端的源IP地址。但这种作法会提高负载均衡器的实现复杂度,并可能影响到负载均衡效果。

考虑到这一点,我们以eBPF为基础给Kubernetes服务带来了Direct Server Return。这不仅保留了客户端的源IP地址,同时也避免在向客户端发送回复时带来额外的跃点,具体如下图所示:
05.png

06.png

利用External IP支持Kubernetes服务

现在,用户可以使用External IP为公开服务提供外部IP。如果用户将目标IP设置为externalIP列表中的一项,则对应流量将被重新定向至该服务支持的某个Pod上。
apiVersion: v1
kind: Service
metadata:
name: external-service
namespace: kube-system
spec:
ports:
- name: service-port
  protocol: TCP
  port: 8080
externalIPs:
- 10.0.0.1
- 10.0.0.2
- 10.0.0.3

优化服务端点选择

通过ClusterIP、NodePort、ExternalIP或者LoadBalancer从Cilium管理的节点访问某项Kubernetes服务时,整个过程会在eBPF内经由基于嵌套的负载均衡机制进行处理。具体来讲,在TCP connect (2)系统调用期间,内核会直接接入服务的后端地址;如此一来,我们只需要做出一次后端选择,而不必对处于堆栈内较低层中的数据包本身执行速度缓慢的DNAT。

面对各类NodePort与ExternalIP服务,我们引入了一项优化机制,即直接在本地节点上选择后端,以供主机命名空间或Cilium管理的Kubernetes Pod进行通信。这种方式与常规kube-proxy有所区别:后者需要在网络中搭建额外的跃点,才能首先到达服务的对应节点地址;在最糟糕的情况下,其甚至会将请求转发至远程后端。
07.png

08.png

为每个数据包节省额外跳数带来的等待时间,相当于以透明方式改进了应用程序的整体性能。因为由Cilium管理的各个节点都拥有Kubernetes服务及其后端的全局视图,同时了解由Cilium管理的各远程节点的内部安全身份,所以这套新设计才能切实起效。

其他改进

  • 添加对LoadBalancer类服务的支持,而且我们已经成功测试了利用MetalLB替代kuber-proxy的可能性。
  • 在Cilium中,kube-proxy的替代方案现在全面支持之前提到的,面向NodePort与LoadBalancer服务的externalTrafficPolicy设置。对于包含Local流量策略的服务,如果其请求中的节点不含任何本地服务端点,则服务本身会被直接丢弃,从而避免产生不必要的额外跃点。
  • 外部负载均衡器必须了解各独立节点上的服务端点可用性,为此Cilium 1.7版本开始支持Kubernetes的healthCheckNodePort字段。现在,Cilium用户空间代理将通过一项服务状态检查,对包含externalTrafficPolicy=Local的所有LoadBalacner类Kubernetes服务执行检查。
  • 对于每项NodePort服务,kube-proxy会在主机命名空间内开启一个嵌套,并将NodePort端口与该嵌套绑定起来,以防止被其他应用程序重用。如果服务数量庞大,这种作法会增加内核的资源开销总量,例如分配并绑定成千上万个嵌套。Cilium的kube-proxy替代方案彻底避免了这个问题——新方案不再分配单一嵌套,而是以基于嵌套的负载均衡机制明智eBPF bind (2) hook查询其eBPF服务映射,并拒绝那些指向含错误代码的端口的应用程序bind (2)请求。
  • Cilium提供的eBPF内基于嵌套负载均衡机制现在可支持IPv4-in-IPv6服务地址翻译。这意味着用户能够从纯IPv6应用中的connect(20/Sendmsg(2) hook中选择IPv4服务后端。这项功能通常在语言运行时(例如Java)内默认开启。
  • 我们还开发出广泛的kube-proxy兼容性测试套件,其中包含超过350项测试用例(现已作为Cilium CI基础设施的组成部分运行),以确保eBPF kube-proxy替代方案不致造成语义兼容影响。


用于L7策略的TLS可见性(beta版)

作者:Jarno Rajahalme

Cilium网络策略(CNP)规范中包含两项新的实验性扩展(可能在今后版本中做出调整),用以对受TLS保护的HTTP连接执行策略。两项都属于端口级策略规则,其一用于定义TLS上下文中如何终止Cilium主机代理内由客户端启动的TLS连接;其二则用于为上游代理连接发起TLS。为了实现代理TLS拦截功能,用户需要使用本地CA证书配置客户端容器,也可利用该本地CA证书根据端口规划创建TLS secret。关于更多细节介绍,请点击此处参阅入门指南
09.png

其次,HTTP规则层级迎来新的标头匹配,可对不匹配的标头执行正常标头操作。用户可以从Kubernetes Secret中获取匹配的标头值,这就避免了在CNP之内直接指定任何保密信息。目前支持的不匹配操作包括LOG、ADD、DELETE以及REPLACE。以此为基础,用户策略能够检查并记录正确的标头值,或者将不正确的值替换为正确的标头值。在得到客户端授权的标头上应用REPLACE不匹配操作,即可保证您的secret令牌永远不会被公开给应用程序容器。

将这些新功能与toFQDN规则配合起来,不仅能够将TLS流量限制为特定域名上的外部服务,同时也能强制执行并访问包含HTTP元数据(包括路径、方法及标头等)的记录,从而防止数据泄露事故的发生。

通过Pod注释实现L7协议可见性

作者:Ian Vernon与Joe Stringer

当用户将Cilium作为CNI运行时,如果单一数据包通过Cilium eBPF数据路径进行传递,那么Hubble或Cilium monitor等工具默认只能查看L2、L3及L4的信息。用户当然可以通过L7策略为集群中的网络流添加更强的API可见性与强制性,但在以往版本当中,要想既保证可见性又不丢失任何其他流量,用户必须为选定的端点构建完整策略、以确保各端点间的预期流量都能正常通过。

为了帮助用户对正在进行的API调用进行自省,且不必为端点构建完整策略,我们增加了对代理可见性注释的支持机制。用户可以在Pod上添加注释、指示方向、选择端口之间的活动协议,而后Cilium会收集当前API调用的相关信息并将其分发给Hubble等其他工具。下图中,tiefighter正将API请求发布至v1/request-landing上的deathstar。
010.png

感兴趣的朋友可以点击此处,了解关于Pod注释的更多细节信息。

纯Go eBPF库

作者:Joe Stringer

Linux Plumbers 2019 eBPF会议期间,Cilium核心开发者与Cloudflare的工程师们共同发布一项纯Go eBPF库提案,希望借此解决基于Cilium或Cloudflare的L4负载均衡器等由Go语言编写的长期守护进程与eBPF内核间的交互问题。解决方案的一项基本要求,就是避免引入CGo

目前,这项工作正在有序推进。在Cilium 1.7中,负责从eBPF数据路径向用户空间cilium-agent进程发送消息的ring-buffer迎来升级,从以往的CGo实现方案转化为速度更快、效率更高的新库。

目前已经存在多种eBPF外部库选项,包括libbpf或者libbcc。虽然前者已经成为新的规范,能够在Linux内核中支持基于C/C++语言的应用程序,但却还无法在纯Go环境下使用。后者的情况也差不多,能够很好地跟踪、打包libbpf甚至LLVM的eBPF后端,但同样不兼容Go环境。具有类似功能的其他Go库则依赖于CGo,虽然能够正常起效但却难以构建,而且在C与Go环境之间往往会带来高昂的上下文切换成本。

我们希望通过一套纯Go eBPF库解决Cilium与Cloudflare对于eBPF编排的生产级需求,也希望帮助整体Go社区更轻松地与我们内核中的eBPF子系统实现交互。这套新库主要面向网络用例,用于尽可能减少外部依赖性、解决常见问题,并在纯Go环境下提供一套经过测试及实证、足以支撑生产环境要求的eBPF库。

除了最初的eBPF映射、程序与ring-buffer之外,这套库还在开发过程中不断实现新的扩展,包括支持BPF类型格式(BTF),以及利用静态数据替代原始方案以支持模板化eBPF程序的想法(一次编译即可随处使用)。

要了解更多关于eBPF库的细节信息,请参阅Cilium GitHub项目下的: https://github.com/cilium/ebpf

支持Kubernetes EndpointSlice

作者:André Martins

为了给单一服务中的大量端点提供更好的可扩展性,Kubernetes 1.16版本引入了EndpointSlice。自Kubernetes 1.17版本以来,该API正式进入beta阶段并开始默认启用。遗憾的是,其中负责管理Endpoint Slices的控制器不会默认启用,因此用户需要参考指南启动控制器,才能真正享受到这项改进。

Cilium 1.7引入了enable-k8s-endpoint-slice这一全新标记,该标记默认处于启用状态,能够自动检测集群当中是否存在Endpoint Slice,并利用它们在eBPF中执行全服务转换。关闭也非常简单:用户只需要将该标记设置为false,即可继续使用之前版本提供的v1/Endpoints类型。

可扩展性

作者: Ian Vernon与André Martins

CNP节点状态

作为CiliumNetworkPolicy(CNP)可扩展性改进中的组成部分,Cilium引入了另一项新标记: enable-k8s-event-handover。

当大家在集群内创建新的CNP时,所有Cilium代理都会收到来自Kubernetes的通知事件;一旦新策略在数据路径内得到强制执行,各节点都将在CNP状态字段中更新自身状态。在拥有大量节点的情况下,这项机制可能快速提升kube-apiserver中的CPU使用率,因为每一个Cilium代理在收到更新时,都需要将其以Kubernetes新事件的形式发送给其余全部节点。在之前的版本中,我们支持使用--disable-cnp-status-updates标记彻底禁用这项功能,但这太过粗暴,会导致用户无法了解CNP的执行状态。

当启用enable-k8s-event-handover时,整个实现过程将略有不同:不同于在CNP中更新状态字段的方式,现在每个Cilium代理都会将自身状态更新至KVstore当中。接下来,Cilium Operator会在KVstore中为各个CNP监控更新,对各CNP中的所有Cilium代理状态执行增量更新。最后,CNP状态还是会被体现在Kubernetes当中,但整个填充方式明显更加高效。

Cilium代理

由于Cilium不再依赖于容器运行时,因此所有容器运行时层面的依赖关系都不必保存在Cilium之内。如此一来,cilium-agent二进制文件的大小能够从97 M下降至74 M。

Golang 1.13

Cilium 1.7使用Golang 1.13编译而成,能够在运行时内进行大量内存优化,从而减少Cilium的内存占用量。

Linux内核变更

作者:Daniel Borkmann

在Cilium 1.7开发周期当中,我们还对参与维护的Linux内核eBPF子系统做出一系列改进。接下来要提到的几项重要变更,将为全体eBPF用户带来助益,不过具体效果视Cilium与Hubble的eBPF实施方式而定。所有变更,都已被纳入新近发布的Linux 5.5内核当中。

eBPF程序的实时补丁机制

考虑到Cilium的数据路径需要支持多种Linux内核,从4.9版本到最新版本,因此大部分eBPF数据路径功能被拆分为eBPF尾调用。这种处理方式在启用Cilium的eBPF kube-proxy替代方案的情况下体现得尤其明显。除了降低较旧内核的验证程序复杂性之外,这种eBPF尾调用方式还能够以原子方式替换特定Pod中的eBPF功能,同时保证不对实时系统上的服务产生影响。

内核中的x86-64 eBPF JIT编译器会将eBPF尾调用映射为间接跳转,意味着从BPF尾调用映射中加载的当前eBPF程序地址会被提交至jmpq *%rax中的%rax寄存器内。由于现代CPU上存在多种推测性执行缺陷,因此我们后来决定将eBPF JIT转为emit retpolines形式,借此避免对性能造成严重影响。另外,考虑到所有主流编译器都采用到这项技术,因此Linux内核社区一直在努力避免在快速路径代码中执行间接调用。例如,将eBPF映射相关帮助程序转换为直接调用,能够立刻将性能提升14%。

在现在的5.5内核当中,我们对验证程序内跟踪了所有eBPF尾调用映射索引。如果验证程序最终确定所有程序路径中的特定索引都保持恒定不变,那么如同处理Cilium中的eBPF程序一样,我们也可以发出直接跳转指令。在尾调用程序更新完成后,eBPF JIT镜像将会直接跳转至新的位置。

为了演示该技术,以下示例eBPF程序将实现一项指向常量映射索引0的eBPF尾调用跳转:
0: (b7) r3 = 0
1: (18) r2 = map[id:526]
3: (85) call bpf_tail_call#12
4: (b7) r0 = 1
5: (95) exit

这个x86-64 eBPF JIT程序会在较旧的内核版本上发出retpoline(以粗体显示):
0xffffffffc076e55c:
[...]                                  _
19:   xor    %edx,%edx                |_ index (r3 = 0)
1b:   movabs $0xffff88d95cc82600,%rsi |_ map (r2 = map[id:526])
25:   mov    %edx,%edx                |  index >= array->map.max_entries check
27:   cmp    %edx,0x24(%rsi)          |
2a:   jbe    0x0000000000000066       |_
2c:   mov    -0x224(%rbp),%eax        |  tail call limit check
32:   cmp    $0x20,%eax               |
35:   ja     0x0000000000000066       |
37:   add    $0x1,%eax                |
3a:   mov    %eax,-0x224(%rbp)        |_
40:   mov    0xd0(%rsi,%rdx,8),%rax   |_ prog = array->ptrs[index]
48:   test   %rax,%rax                |  prog == NULL check
4b:   je     0x0000000000000066       |_
4d:   mov    0x30(%rax),%rax          |  goto *(prog->bpf_func + prologue_size)
51:   add    $0x19,%rax               |
55:   callq  0x0000000000000061       |  retpoline for indirect jump
5a:   pause                           |
5c:   lfence                          |
5f:   jmp    0x000000000000005a       |
61:   mov    %rax,(%rsp)              |
65:   retq                            |_
66:   mov    $0x1,%eax                (next instruction, r0 = 1)
[...]

对于5.5以及更新内核,此程序则会被优化为直接跳转(以粗体标记),且无需对代码做出任何修改:
0xffffffffc08e8930:
[...]                                  _
19:   xor    %edx,%edx                |_ index (r3 = 0)
1b:   movabs $0xffff9d8afd74c000,%rsi |_ map (r2 = map[id:526])
25:   mov    -0x224(%rbp),%eax        |  tail call limit check
2b:   cmp    $0x20,%eax               |
2e:   ja     0x000000000000003e       |
30:   add    $0x1,%eax                |
33:   mov    %eax,-0x224(%rbp)        |_
39:   jmpq   0xfffffffffffd1785       |_ [direct] goto *(prog->bpf_func + prologue_size)
3e:   mov    $0x1,%eax                (next instruction, r0 = 1)
[...]

程序更新之后,地址39上的jmpq 0xfffffffffffd1785指令将根据新的目标eBPF程序上的地址进行实时更新。同样的,如果目标eBPF程序被从尾调用映射中删除,那么该jmp也会被更新至同样大小的nop指令中,转化为可接受的失败形式:
0xffffffffc08e8930:
[...]                                  _
19:   xor    %edx,%edx                |_ index (r3 = 0)
1b:   movabs $0xffff9d8afd74c000,%rsi |_ map (r2 = map[id:526])
25:   mov    -0x224(%rbp),%eax        |
2b:   cmp    $0x20,%eax               .
2e:   ja     0x000000000000003e       .
30:   add    $0x1,%eax                .
33:   mov    %eax,-0x224(%rbp)        |_
39:   nopl   0x0(%rax,%rax,1)         |_ fall-through nop
3e:   mov    $0x1,%eax                (next instruction, r0 = 1)
[...]

如此一来,内核不必将推测重新定向到pause/lfence循环当中,也不必为给定的直接地址跳转执行任何推测,这将使eBPF代码的执行效率快速迈上一个台阶。

您可以点击此处了解关于合并补丁集的更多细节信息。

为eBPF探针帮助程序提供安全的多架构支持机制

Cilium的数据路径能够通过高性能、可定制的ring-buffer向用户空间代理导出各种聚合性跟踪信息。以Cilium为基础的Hubble,则借此成为一套高可见、全分布式网络与安全平台,帮助用户对服务及网络基础设施中的通信与行为建立起深入了解。此外,Hubbler还通过基于eBPF的内核跟踪机制进一步丰富收集到的信息。

由于多架构支持目前正在开发当中,计划通过Cilium 1.8版本正式发布,因此我们只能对这项新机制做出简要描述:我们在内核中构建起一组新的eBPF帮助程序,希望立足多种架构、更安全地对基于eBPF的内存进行探测。

目前的probe_kernel_read()与 bpf_probe_read_str()eBPF帮助程序集存在一系列缺点:虽然在大多数情况下,用户可以安全地禁用页面错误提示,但在x86-64上发生用户访问违规地址时,直接禁用很可能引发严重后果。这是因为非规范地址的范围,通常与应用程序用于标记指针的用户空间存在重合。

另一大严重缺陷,在于之前提到的两种eBPF帮助程序无法兼容非x86类架构,因为二者会假定自己需要探测的是内核空间地址与用户空间地址。很明显如果是在KERNEL_DS下执行访问,那么这两种尝试最终都只会指向内核空间地址空间。另外,x86的地址空间不重叠,但其他某些架构则允许地址重叠,意味着内核指针与用户指针可能具有相同的地址值。

因此,当我们把of bpf_probe_read_user()、bpf_probe_read_kernel() 、bpf_probe_read_user_str()以及bpf_probe_read_kernel_str() eBPF帮助程序集添加到USER_DS或者KERNEL_DS等具有严格访问限制的内核中时,将无法触发本应被激活的访问警告。

大家可以点击此处了解更多关于合并补丁集的细节信息。

在托管Kubernetes方案上支持Cilium测试

作者:Maciej Kwiek与Ray Bejjani

由于我们的测试框架与运行测试的集群之间存在着紧密的假设关联,因此Cilium的端到端测试一直比较令人头痛。在新自带,我们付出了大量努力,希望帮助开发人员缓解由此带来的压力。

Cilium 1.7为开发人员敞开大门,允许各位使用GKE等服务商提供的Kubernetes集群测试套件。各位能够在我们的CI GKE集群上运行多种可选测试,显著缓解本地集群的管理负担;此外,由于集群配置速度更快,因此您可以尝试进行更多测试驱动型开发工作。

Helm 3与Helm库

作者: Arthur Evstifeev与Joe Stringer

Helm3之前刚刚发布,其简化了Helm图表库的使用方式,而且不再需要配合Tiller即可实现集群安装。从1.7版本开始,我们将扩展1.6版本引入的Helm模板支持机制,允许用户将来自https://helm.cilium.io的Helm库与Cilium匹配起来。所有Cilium指南均已更新为Helm3语法版本,下面来看Helm3库的具体安装方式:

示例:为GKE配置Cilium
helm repo add cilium https://helm.cilium.io/
helm install cilium cilium/cilium \
--namespace cilium \
--set global.cni.binPath=/home/kubernetes/bin \
--set global.nodeinit.enabled=true \
--set nodeinit.reconfigureKubelet=true \
--set nodeinit.removeCbrBridge=true

1.7版本发布要点

对eBPF中的kube-proxy替代方案做出多项增强

  • 新的Direct Server Return(DSR)模式,可带来更低延迟与更好的客户端源IP保存效果
  • 支持Kubernetes ExternalIPs与LoadBalancer服务
  • 添加对NodePort健康状态检查服务的支持
  • 添加externalTrafficPolicy=Local处理机制
  • 在基于嵌套的负载均衡中实现对IPv4-in-IPv6支持能力
  • 为基于嵌套的负载均衡机制带来端点选择优化
  • 多项SNAT优化与更好的端口冲突处理能力
  • 通过绑定hook有效检测NodePort与ExternalIPs端口重用情况
  • 以默认方式为新的部署场景提供全新功能探测模式
  • 用于Cilium CI的kube-proxy全面兼容性测试套件


策略

  • TLS可见性策略(beta版)
  • 通过Pod注释实现L7可见性
  • 支持将远程节点作为单独的身份进行处理
  • 通过FQDN策略改进DNS超时处理机制


Kubernetes

  • 得到Kubernetes 1.17验证通过
  • 支持双栈模式
  • 支持EndpointSlices
  • 为Cilium资源提供更好的CRD验证


数据路径

  • eBPF与cillium-agent间的ring-buffer通信效率得到提升
  • 支持更灵活的连接事件聚合功能
  • 更好地限制大型映射转储
  • 改进了对大型CIDR策略的处理方式
  • 利用bpftool检测功能支持效果
  • 支持通过代理选项向ICMP片段转发消息
  • 支持指向NodePorts的绑定


可扩展性与资源消费

  • 将CiliumNetworkPolicy状态报告移交给KVstore与cilium-operator
  • 优化Go 1.13代码体积
  • 消除容器运行(CRI)中的依赖关系


CLI

  • 改进cilium status命令中的信息内容
  • zsh命令补全功能


说明文档

  • 使用Helm 3执行部署指令
  • 添加用于Cilium helm图的专用库
  • 对Kubernetes指南中的链接与内容进行多项修正


Istio

  • 支持1.4.3版本


内核变更

  • eBPF程序实时补丁
  • 多架构支持能力提升


Hubble

  • Hubble图形用户界面
  • 将其他元数据与网络流关联起来


持续集成/测试

  • 支持在GKE与eKS托管集群内运行Cilium CI


感兴趣的朋友可以点击此处,查看Cilium 1.7开发周期内的完整变更说明。

快速入门

您第一次接触Cilium?请参阅我们的《入门指南》获取更多帮助。

升级说明

与以往版本一样,请点击此处根据我们的升级指南升级您的Cilium部署方案。另外,您也可以点击此处通过Slack与我们联系。

发布

  • 发布说明与二进制文件:1.7.0
  • 容器镜像:docker.io/cilium/cilium:v1.7.0


原文链接:Cilium 1.7: Hubble UI, Cluster-wide Network Policies, eBPF-based Direct Server Return, TLS visibility, New eBPF Go Library, ...

0 个评论

要回复文章请先登录注册