创建开放,可扩展且安全的无服务器平台的13个挑战

介绍

服务器是云计算的自然发展。从本质上讲,无服务器可归结为两个主要功能:(1)您为所有计算资源“按需付费”;(2)与较大的工作负载相比,您可以获得更细粒度的扩展。但是,要充分利用这种扩展的计算模型,开发人员需要将应用程序和服务重组为可以在不需要时缩减为零的组件。

微服务架构是朝正确方向迈出的一步。Kubernetes(K8s)作为运行微服务的平台,是用于管理用于运行微服务的容器的核心基础架构的有前途且广受欢迎的具体实现。但是,Kubernetes本身不足以满足无服务器工作负载的需求,并且不需要所有人重新改造基础平台之上的层。在2019年输入Knative作为K8之上的通用无服务器层。

背景

过去几年中出现了各种开放源代码的无服务器平台,例如OpenFaaSApache OpenWhisk。它们使用类似于K8的组件或在其上构建,但没有一个是为Kubernetes本身构建的。Knative于2019年从Google诞生,是一套自定义资源,可扩展K8以运行无服务器工作负载。Knative提供了服务和事件的两个关键核心组件。最初,Knative包含一个构建组件,但在第一年就将其拆分为自己的项目,现在称为Tekton

原始状态

自成立以来(截至撰写本文时),Knative经过21次迭代,完善了核心组件,添加了新组件,并提供了扩展流程。特别是,事件组件不断演变,以提供具有渠道,中间人和来源(代表事件提供者的抽象)的完整事件衬底。事件源是可插入的,现在有20多个源。

原始治理从Google所控制的一种发展到更加开放和包容的一种。尤其是通过解决所有参与方的意见,解决项目发展中棘手的问题,以及由Google拥有的Knative商标的许可法律问题。为了解决后一个问题,成立了一个新的商标委员会,其目的是定义Knative名称的含义以及何时可以使用或不能使用它。

动机

自从Knative于2019年发布以来,作为Knative的贡献者,我们看到了该项目的发展,我们可以重点介绍随着时间的推移遇到的“挑战”(或障碍)。我们希望记录并列出这些挑战将有助于后代和文档编制,但更重要的是,可以成为将来的开源项目和其他团队尝试类似工作时的源泉。我们将挑战分为三类:

  • 挑战本质上是纯技术性的,不是Knative项目本身的一部分,但与Knative所具有的依赖项有关(例如,K8和Istio)。我们称这些平台为挑战
  • Knative项目本身还包含其他技术挑战。我们称这些组件为挑战
  • 挑战不是技术性的,而是组织性或治理性的挑战。

平台挑战

Knative建立在K8之上。您可以将Knative视为K8之上的一组层,这些层一起增加了运行无服务器工作负载的能力。这些层被创建为自定义资源或自定义资源定义(CRD)。由于K8需要联网网格才能正确执行各种工作负载,因此Knative需要一个。但是,Knative开发人员使网格需求变得灵活,以允许插入不同的网格层,这很有用,因为并非Knative使用K8s网格的所有功能。

在与Knative合作期间,我们发现了两个与基础平台直接相关的挑战。这些是在我们开发和采用过程中进行的,随着我们开始大规模测试基于Knative,Kubernetes和Istio构建的云产品。它被命名为IBM Cloud Code Engine。让我们探索我们可以从经验中提取的两个挑战。

挑战1.可伸缩性

在测试中间件的可伸缩性时,您需要接近最终发布的版本以避免早期优化,并衡量是否满足可伸缩性要求。随着IBM Cloud Code Engine产品接近其第一个公开测试版,我们在斯图加特和北京的团队越来越多地运行各种基准测试,以验证嵌入式Knative的低端性能。经过数月的反复来确定已确定问题的根本原因,全球团队合作开始解决这些问题。

北京测试的第一个重要结果是,随着每个集群创建的服务数量的增加,Knative服务的启动时间受到了影响。此外,服务(甚至一个)的启动时间与我们之前的无服务器项目IBM Cloud Functions不相上下。

Knative发行版中缓慢的启动时间是一致的,并且该团队表明,随着服务数量接近数千,启动时间通常达到数十秒的峰值。此结果的推论是,当使用不同的网络入口(例如IstioContourKourier)时,启动时间缓慢会有所不同。特别是,使用Istio进行测试的安装受害最大。

注意到Istio持续的成果意味着我们必须让该社区参与寻求帮助。经过数轮复制并证明问题存在后,从事Istio项目的IBM团队能够确定问题的根本原因,并在Istio 1.7.x代码库中提供了有效的修复程序。该补丁现已发布,并且正在进行各种修订。

我们尚未实现现有的非Kubernetes本地解决方案(例如IBM Cloud Functions环境)的完整规模和完整性能。但是,我们在缩小这一差距方面继续取得进展。

挑战2.改进

在现有平台之上创建非平凡的层(例如Knative),尤其是像Kubernetes一样彻底而复杂的层,势必会揭示阻抗不匹配的情况。这些不匹配可能存在于您可能需要修改和改进较低组件以实现最上层组件的地方。令人惊讶的是,我们很少遇到在其下添加无服务器层(例如Knative暴露的问题)的地方。让我们探索两个领域。

首先,对于自动缩放,K8的有关正在运行的Pod的信息传递的越快,Knative组件就可以做出更快的决策。当前,Kubernetes会使用定期运行的探针来进行大部分数据收集。不幸的是,执行频率无法设置为亚秒。以更快的进度运行的能力可能使Knative对扩展决策做出更快的响应。我们正在努力提交Kubernetes增强提案,以解决这一确切问题。

挑战1所述,我们确定了可以改善Istio的地方,并且正在寻找更多的地方。例如,我们在最近的可伸缩性测试中发现,必须以特定的方式配置Istio,以避免当存在许多Knative服务时,Sidecars到Pilot的通信不堪重负。我们正在与Istio社区合作,以更好地了解合适的默认设置,并改善Istio组件的内部通信,同时提高可伸缩性。

组件(或Knative层)挑战

如前所述,Knative被实现为Kubernetes之上的层。主要是通过添加实现无服务器工作负载所需的位。这些层可以整齐地分解为三个部分,再加上一个最近的包罗万象的内容。这些组件包括:服务,事件,构建以及现在的扩展。Knative从头三个组件开始,然后迅速将建筑层拆分为自己的不同开源项目(Tekton)。随着时间的推移,出现了其他各种不能很好地融入其余组件的组件,它们形成了另一个组件,我们现在称之为扩展。

虽然核心Knative架构在过去的一年中一直保持稳定,但是却在不断发展。特别是,事件组件进行了完整的“重构”,以更好地描述事件源和事件接收器,并使这些关注点分离和可插入。随着参与Knative开发的不同公司尝试将更多自己(以及客户)深奥的无服务器工作负载进行测试,服务组件随着点的改进而不断发展。

在本节中,我们描述了在尝试使用Knative作为IBM Cloud Code Engine在线平台的基础时遇到的三个挑战。此外,我们讨论了扩展组件,它通过添加命令行界面(CLI)和直接来自于我们采用Knative本身的各种插件而帮助开拓了这一领域。

挑战3.自动缩放

各种挑战导致了Knative自动缩放子系统的设计。毕竟,可以将工作负载缩减至零,并在需求到达时迅速将其扩展回去,这无疑是无服务器架构最重要的特征。当Knative团队研究解决方案以通过监视其活动和传入流量来自动扩展已部署服务的Pod时,早先的简单设计决策就导致了与我们预期的无服务器架构的根本分歧。

简而言之,原始的Knative自动缩放组件设想已部署的服务将始终希望在服务部署上启动Pod。这意味着系统在尝试围绕其执行创建缩放约束之前,可以假设已部署的映像是可用且“可运行”的。从本质上讲,部署到Knative的服务始终会缩放到一个,然后由于缺乏传入请求流而会缩放到零,最大或更多。

尽管可以使用,但这种方法意味着部署的工作负载总是经历执行时间,无论是否需要执行时间(这意味着即使用户的服务未收到请求,也可能会“向用户收费”)。特别是,以前的IBM无服务器系统做出了相反的假设。部署的工作负载纯粹是按需扩展,而不是依靠部署。这开始了IBM团队的努力,以提交对Knative自动缩放的更改,以使“在部署时缩放为零”。经过各种尝试,甚至想出了改变Knative在Pod上收集指标的方式,该功能已被接受,现在已成为当前版本的组成部分。

Knative自动缩放器在许多方面与Horizo​​ntal Pod自动缩放器(HPA或默认的Kubernetes自动缩放器)不同。虽然HPA希望从Kubernetes系统接收诸如CPU和内存使用率之类的指标,但Knative Autoscaler与Knative系统本身紧密集成在一起。它针对基于请求的自动缩放以及对请求计数更改的快速响应进行了调整。

与传统的非无服务器系统不同,Knative Autoscaler必须针对突发性工作负载进行优化。例如,如果某个服务用于响应GitHub事件,则该服务长时间可能有零个请求,而在短时间内却有许多请求。传统的自动缩放系统和策略很难正确地应对此类工作负载。我们在Knative Autoscaler中添加了各种功能,以帮助其处理这些类型的随机用例。例如,一种ScaleDownDelay配置用于控制Autoscaler在看到减少的请求计数之后将等待多长时间,然后再执行副本的缩减。

挑战4:事件自动缩放

Knative Eventing在基于推式事件处理和基于拉式事件处理的两个领域都面临着自动扩展的挑战。

基于推送的事件处理是将事件“推送”到事件组件中的时间。通过HTTP推送事件(例如webhooks)时,可以使用Knative Serving自动缩放。例如,请参阅通过使用Knative Serving提供HTTP Webhook来接收事件而实现的Knative GitHub Source。但是,可能存在HTTP以外的协议,这是在通过非HTTP协议接收事件时如何自动缩放Knative Eventing组件的第一个挑战。

下图显示了一个事件源,该事件源使用HTTP连接将事件发送到事件组件。由于使用HTTP,因此可以通过使用Knative Serving Autoscaler监视HTTP连接来实现组件的缩放。

基于推送的事件处理图

基于拉式的事件处理是事件组件直接从事件系统中拉出事件时的处理。在这种情况下,自动缩放会更加复杂,因为事件组件必须基于事件产生者的指标(例如必须提取的事件数)进行缩放。

下图显示了一个事件源,该事件源正在使用非HTTP协议(例如Kafka)将事件发送到事件组件,这些事件组件通过使用监视事件源的非本地自动缩放器(例如KEDA)进行缩放。例如,Kafka主题中的消息数。

基于拉式事件处理的图

对于基于拉式的事件处理,Kubernetes事件驱动的自动缩放(KEDA)项目可能会提供自动缩放解决方案,因为它使我们能够基于事件系统指标定义触发器。KEDA触发器用于扩展事件组件。探索了这种方法,并且在Knative Eventing中提供了原型。

将来,Knative Serving可能会支持HTTP以外的协议,这可能会有助于基于推式的自动缩放。但是,在不支持其他协议之前,最直接的解决方案是对不支持HTTP推送的事件系统使用基于请求的方法。

自动缩放的另一个挑战与提高密度和跨命名空间共享事件组件有关。在这种情况下,它们共享每个系统规模的组件(例如通道或代理),而不是让每个命名空间都拥有所有事件数据平面组件,这些组件会自动缩放事件并将事件传递到不同的命名空间。

挑战5.异步请求

设计去耦的分布式系统时,有必要在组件之间创建松散的通信。当系统需要扩展时,这种方法变得越来越重要。

实现这些松散通信的几种方法包括事件总线或组件之间的异步调用。后者是一种常见的模式,其中从一个组件到另一个组件的请求不会阻止或等待服务器的响应,而是立即返回。调用的结果随后通过协商的策略(例如回调或共享数据库)确定。

在Knative Serving的初始版本中,服务请求在设计上是同步的。对Knative服务的任何请求都将被阻止,直到该服务完成请求为止。服务以阻塞或同步方式运行并非总是合理或期望的。如果该服务最多需要10或15分钟的时间进行计算或工作,该怎么办?如果用户不关心立即接收特定功能的结果该怎么办?如果函数最终写入共享数据库,以后可以检查该怎么办?

这种用户体验促使我们开始与Knative社区进行对话,讨论对异步服务请求的支持,将其作为所有服务的一流调用模型。我们与Knative社区合作,为该异步服务支持构建了提案和原型。

这个附加组件使服务调用可以通过包含HTTP标头来进行Prefer: respond-async。提供此标头后,服务202 Accepted将向用户返回响应,并且该请求不必等待服务请求完成处理。支持此功能的是一个新的控制器,该控制器查找异步入口类,然后使用适当的路由规则创建一个新的入口。如下图所示,异步请求存储在共享队列中,这触发队列使用者在随后的时间向服务发出同步请求。

异步请求图

我们计划支持始终异步的服务,在这种情况下,将不需要标头。您可以在github.com/knative-sandbox/async-component上关注我们的进度。

挑战六:事件来源

Knative Eventing是使事件的来源,转换和使用成为可能的组件。该系统足够灵活,可以将各种来源集成到已部署的Knative安装中。事件来源多种多样。示例是现有的云系统和服务,例如数据库和对象存储系统。但是事件源可以是Knative系统本身,例如在Knative运行的Kubernetes集群中,甚至在开发软件的开发环境中,例如GitHub和GitLab。

事件的挑战是为事件源集成提供一条简单的路径。首先,具有创建事件源并将其集成到Knative的能力。第二,要完成从源到接收的路径,我们需要具有创建代理和渠道以从源传递这些事件的能力。

Knative社区擅长创建各种各样的事件源,这些事件源可以用作类似事件类型的示例。但是,使这些事件源更易于创建的工作是正在进行的工作,并且是确保接受Knative的一项重要的持续挑战。

挑战7.扩展

Kubernetes取得了巨大的成功,原因有很多。特别是,该平台可以通过设计进行扩展。实际上,Knative本身通过添加一系列CRD来使用K8s扩展,它们共同定义了Knative。

但是Knative本身呢?它应该可扩展吗?一个简单的答案是肯定的。例如,Knative Eventing已定义了插入点和模板,用于向系统添加新的源,代理和渠道。这种可扩展性导致了20多种不同的源定义。

Knative可以通过设计扩展的另一方面是客户端CLI。它更进一步,并定义了一个插件模型和接口。使用此扩展点,社区提交了一系列用于诊断,管理,操纵事件源以及迁移Knative集群的插件。肯定会有更多人遵循这个初始设定。

另一个扩展领域是为Knative定义功能即服务层。尽管有很多方法可以定义该层,例如Knative客户端插件,但社区探索了如何添加此功能。尽管这项工作尚未成功,主要是由于对Knative治理的必要改进,但它提出了扩展Knative的官方模型的需求。这些努力的结果推动并包括在2020年初秋社区采用的新治理模式中。

挑战8.易于使用

Knative客户端工作组的成立是为了提供一个Knative简单的用户界面。从一开始,目标就是创建一个CLI,该CLI可以简化用户体验,但不限制用户访问Knative提供的全部功能的能力。

CLI将Knative的核心功能公开为一组命令性命令。但是,在所有情况下,用户都可以为手动创建的对象或一次运行一个命令所产生的对象导出和导入关联的YAML文件。

此外,如Challenge 7中所述,CLI可通过内部和外部插件进行扩展。内部插件可以嵌入(内置)CLI的特殊版本,该版本将插件的命令代码嵌入CLI二进制文件中。外部插件将命令动态添加到CLI。通过将插件可执行文件放置在用户文件系统的已知位置来添加它们。

挑战9. Knative Operator中的升级和回滚支持

Knative运营商提供的功能,安装,管理和配置Knative组件。在0.17发行版之前,一个Knative Operator版本用于支持一个Knative版本。如果您需要升级或回滚Knative,则必须安装Knative Operator的较新或较旧的版本。Knative Operator在其0.17版本中实现了对多个Knative版本的支持,从而取得了突破。

Knative在major.minor.patch版本号方面应用语义版本控制。小数有一个负3原则。Knative运算符支持的最简单版本可以退回到当前的次要版本减负3。例如,0.18的运算符支持从0.15到0.18的Knative。此功能是在Knative Operator 0.16.0中引入的。您可以使用该spec.version字段指定Knative组件的版本。

Knative运算符试图使Knative体验更加轻松。Knative具有自动机制,因此您不必担心清除过时或无用的资源。借助多版本支持,可以通过更改spec.version自定义资源中的字段来顺利进行升级和回滚过程。您需要注意的一条规则是,Knative Operator无法升级或回滚到多个次要版本。您必须在每个步骤中向上或向下移动一个次要版本。补丁程序号可以是任何数字,只要在发行版中可用即可。

挑战10.输入格式

正如我们前面提到的,Knative以前具有一个生成组件,该组件成为Tekton项目。构建组件解决了无服务器平台的可用性问题,即用户倾向于以不同的输入格式带来其应用程序。固有属性以及K8本身都需要容器映像作为输入格式位于容器注册表中。但是,如果我有一个包含源代码和Dockerfile的Git存储库,该怎么办?还是只是一个没有Dockerfile的Git存储库?

将Tekton移至其自己的独立项目的优势在于,它已发展成为一种通用的集群内构建机制。但是,当我们研究IBM Cloud Code Engine时,我们意识到这是必要步骤,但还不够。为了获得诸如“这是我的源代码,为我无服务器运行”之类的用户体验,至少还需要另外两个要素:位于Tekton前面的Orchestrator组件和有助于填补潜在空白的内容库。在构建过程中。

幸运的是,这些缺失的组件可以在开源生态系统中找到。例如,可以通过诸如ShipwrightKPack之类的项目来处理协调器。内容库可以通过解决云本土Buildpacks从云计算原住民基金会(CNCF)和它们的实现,如Paketo

将它们组合到系统中可以使无服务器平台从应用程序的任何输入格式开始:

  • 纯源代码,然后使用构建包对其进行增强,构建,并将构建结果发布到容器注册表中。
  • 源代码和一个Dockerfile,然后将其构建,并将构建结果发布到容器注册表。
  • 一个现成的图像,位于容器注册表中。

将来可能会进行进一步的增强,例如特殊功能的buildpack,其中输入源是功能源代码。

开源治理挑战

毫不奇怪,像Knative这样的项目试图解决云原生应用程序的常见且流行的方法,却遇到了越来越多的麻烦。Knative的早期普及甚至在该项目用于任何产品或服务之前就已经引起了广泛的知名度。

尽管公司尚未发布1.0版本,但随着公司采用并开始使用该项目,这种早期流行度有所提高。围绕治理和对Knative的扩展以及如何保持项目充满活力和热情,出现了一系列挑战。我们在这里特别探讨三个。

挑战11.商标

与所有项目一样,命名也起着重要的作用。在发布Knative时,很难预料该项目和名称会获得如此高的知名度。在许多方面,Kubernetes可能也是如此。不幸的是,名称识别具有缺点。

主要问题是法律问题;这是事实的简要提要,以及对Knative的开发人员和贡献者的影响。简而言之,Google拥有Knative名称的商标。要维护和执行该商标,您必须是法人实体或为法人实体的一部分。由于Knative既不是组织的组成部分,也不是其他法律实体的一部分,因此Google选择保留和保护该商标。当这意味着十几个贡献者中的一家公司对项目的重要部分拥有单方面所有权时,这可能会引起问题。

最初,指导委员会(SC)控制了项目和商标。但是,随着更多的贡献者在该项目中取得长足发展,并且对其他人开放了治理,该商标成为让社区向前发展的黏性点。经过几个月的激烈辩论和整个社区的参与,一个解决方案出现了。

简而言之,解决方案的实质是将项目的控制权与商标的控制权分开。该项目继续由SC和技术监督委员会(TOC)指导和控制,该委员会是从贡献者中选出的,任职时间有限。成立了一个二级委员会来维持对商标的控制。商标委员会的成员基于对该项目的贡献。截至目前,共有三个成员:Google,IBM和Red Hat,以及VMware。他们的目标是定义和保护Knative商标和品牌。

挑战12。官僚作风

随着组织的发展,所有组织都会遭受官僚主义的形式。因此,在公开项目全面开发的第一年,Knative出现官僚主义方面就不足为奇了。我们要提到的具体项目是,许多TOC席位都由非贡献者或由创始组织选定的代表填补,而不是由贡献者以有机方式选举产生的人。

这不一定是一件坏事,因为一开始要引导项目,您需要从经验丰富且经验丰富的开源开发人员中选择领导才能和领导才能,而不是为新生项目贡献力量。但是,项目在初始引导期之后如何发展,以形成一个包容各方且变化多端的技术委员会?

为了缓解这一普遍的缺点,许多开源项目逐渐发展为包括民选领导人,而不是选定的领导人。在有关治理变化的公开辩论中,这个问题多次浮出水面。尽管该问题尚未完全解决,但TOC和SC的明确路径和目标是要支持从直接为守则做出贡献的人员中选拔和晋升的领导人。

挑战13:如何保持亲切热情

毫无疑问,任何开源项目的生命线都是其维持一支活跃的贡献者团队的能力。Knative也不例外。从一开始,Knative项目的领导者就做出了出色的工作,欢迎并扩大了社区的规模,使参与者从大型组织到小型组织。

如今,github.com/knative社区在2021年初拥有495个成员,23个存储库以及10多个积极参与的组织,这些组织的实力很强。而且这些指标不包括存在扩展项目的新兴github.com/knative-sandbox组织。

我们之所以列出如何让Knative欢迎成为挑战的原因,更多的是出于恐惧,而不是当前的现实。围绕商标的问题清楚地表明,随着Knative变得更加成功,可能会给社区施加压力,要求其遵循少数群体的规则。尽管治理更新解决了当前的紧迫问题,但我们不是100%相信基本问题已得到解决。尽管取得了重大进展。

治理中缺少的一个可能减轻我们担忧的组成部分是,Knative(及其商标)是被纺成一个独立的非营利组织,还是更好地加入了接受类似项目的现有开源组织之一,例如CNCF。尽管是一个简单的解决方案,但现实是Knative并未加入独立组织,因为当前的指导和技术委员会成员对此主题存在不同的哲学观点。因此,我们不确定是否会发生这种情况。尽管如此,看来最新的治理更新是所有有关方面进行真诚努力的结果。因此,我们希望当前的“休战”能够保持下去。

结论

Knative是一个成熟的平台,用于在K8之上的无服务器工作负载。它经历了20多个版本,包括扩展机制,并拥有一个不断发展,充满活力的开源社区。

也就是说,这并非没有挑战。有些是技术性的,有些则不是。在此博客文章中,我们重点介绍了三个方面的13个挑战。解决了许多挑战,我们重点介绍了解决方案。并面临着一些挑战,因此我们暗示了正在解决的方案。

我们坚信,虽然Knative社区虽然不完美,但在技术上却很强大,其文化根植于包容性,并且总体上受到欢迎。这些特征应使其能够克服我们列出的挑战以及将来可能出现的挑战。我们对这个社区的美好未来以及整个项目的成功持谨慎乐观的态度。

原创文章,作者:冰封一夏,如若转载,请注明出处:http://www.nncjzx.com/219.html

关注本站公众号获取更多实时内容

本站微信公众号:二线码农