Cilium 1.7发布:Hubble UI、全集群网络策略、基于eBPF的Direct Server Return以及更多

Cilium 1.7发布:Hubble UI、全集群网络策略、基于eBPF的Direct Server Return以及更多_第1张图片

在这里,我们要向大家高兴地宣布,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文件[1]。

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

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

Hubble

作者:Sebastian Wicki与Sergey Generalov

Cilium 1.7发布:Hubble UI、全集群网络策略、基于eBPF的Direct Server Return以及更多_第2张图片


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

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

Hubble UI

Cilium 1.7发布:Hubble UI、全集群网络策略、基于eBPF的Direct Server Return以及更多_第3张图片


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[3]页面或者Cilium Slack的#hubble频道[4]上提供反馈。

Cilium全集群网络策略

作者:Deepesh Pathak与André Martins

Cilium 1.7发布:Hubble UI、全集群网络策略、基于eBPF的Direct Server Return以及更多_第4张图片


新版本带来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

Cilium 1.7发布:Hubble UI、全集群网络策略、基于eBPF的Direct Server Return以及更多_第5张图片


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[5]。此外,也推荐大家参阅Kubecon US 2019[6]与FOSDEM 2020[7]上发布的实施细节与性能基准信息。

在新版本中,这套替代性方案已经趋于稳定,因此从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地址,同时也避免在向客户端发送回复时带来额外的跃点,具体如下图所示:

Cilium 1.7发布:Hubble UI、全集群网络策略、基于eBPF的Direct Server Return以及更多_第6张图片

Cilium 1.7发布:Hubble UI、全集群网络策略、基于eBPF的Direct Server Return以及更多_第7张图片

利用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有所区别:后者需要在网络中搭建额外的跃点,才能首先到达服务的对应节点地址;在最糟糕的情况下,其甚至会将请求转发至远程后端。

Cilium 1.7发布:Hubble UI、全集群网络策略、基于eBPF的Direct Server Return以及更多_第8张图片

Cilium 1.7发布:Hubble UI、全集群网络策略、基于eBPF的Direct Server Return以及更多_第9张图片


为每个数据包节省额外跳数带来的等待时间,相当于以透明方式改进了应用程序的整体性能。因为由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。关于更多细节介绍,请点击此处参阅入门指南[8]。

Cilium 1.7发布:Hubble UI、全集群网络策略、基于eBPF的Direct Server Return以及更多_第10张图片


其次,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。

Cilium 1.7发布:Hubble UI、全集群网络策略、基于eBPF的Direct Server Return以及更多_第11张图片


感兴趣的朋友可以点击此处[9],了解关于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的控制器不会默认启用,因此用户需要参考指南[10]启动控制器,才能真正享受到这项改进。

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代码的执行效率快速迈上一个台阶。

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

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

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

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

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

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

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

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

在托管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

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

快速入门

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

升级说明

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

发布

  • 发布说明与二进制文件:1.7.0,https://github.com/cilium/cilium/releases/tag/v1.7.0

  • 容器镜像:docker.io/cilium/cilium:v1.7.0

相关链接:

  1. https://github.com/cilium/cilium/blob/master/USERS.md

  2. https://github.com/cilium/hubble/tree/master/tutorials/deploy-hubble-and-grafana

  3. https://github.com/cilium/hubble/issues

  4. https://cilium.herokuapp.com/

  5. https://docs.cilium.io/en/stable/gettingstarted/kubeproxy-free/

  6. https://www.youtube.com/watch?v=bIRwSIwNHC0

  7. https://fosdem.org/2020/schedule/event/containers_bpf/

  8. https://docs.cilium.io/en/v1.7/gettingstarted/tls-visibility

  9. http://docs.cilium.io/en/stable/policy/visibility/

  10. https://kubernetes.io/docs/tasks/administer-cluster/enabling-endpointslices/#enabling-endpointslices

  11. https://lore.kernel.org/bpf/[email protected]/

  12. https://lore.kernel.org/bpf/[email protected]/

  13. https://github.com/cilium/cilium/blob/v1.7/CHANGELOG.md

  14. https://docs.cilium.io/en/v1.7/gettingstarted/

  15. https://cilium.readthedocs.io/en/v1.7/install/upgrade/#upgrading-minor-versions

  16. https://cilium.herokuapp.com/

原文链接:https://cilium.io/blog/2020/02/18/cilium-17/

你可能感兴趣的:(Cilium 1.7发布:Hubble UI、全集群网络策略、基于eBPF的Direct Server Return以及更多)