serverless
Serverless(无服务器架构)是指服务端逻辑由开发者实现,运行在无状态的计算容器中,由事件触发,完全被第三方管理,其业务层面的状态则存储在数据库或其他介质中。
Serverless 是云原生技术发展的高级阶段,可以使开发者更聚焦在业务逻辑,而减少对基础设施的关注。
进阶定义
Serverless是由事件(event)驱动(例如 HTTP、pub/sub)的全托管计算服务。用户无需管理服务器等基础设施,只需编写代码和选择触发器(trigger),比如 RPC 请求、定时器等并上传,其余的工作(如实例选择、扩缩容、部署、容灾、监控、日志、安全补丁等)全部由 serverless 系统托管。用户只需要为代码实际运行消耗的资源付费——代码未运行则不产生费用。
Serverless 相比 serverful,有以下 3 个改变(来自 Berkeley 的总结):
- 弱化了存储和计算之间的联系。服务的储存和计算被分开部署和收费,存储不再是服务本身的一部分,而是演变成了独立的云服务,这使得计算变得无状态化,更容易调度和扩缩容,同时也降低了数据丢失的风险。
- 代码的执行不再需要手动分配资源。不需要为服务的运行指定需要的资源(比如使用几台机器、多大的带宽、多大的磁盘等),只需要提供一份代码,剩下的交由 serverless 平台去处理就行了。当前阶段的实现平台分配资源时还需要用户方提供一些策略,例如单个实例的规格和最大并发数,单实例的最大 CPU 使用率。理想的情况是通过某些学习算法来进行完全自动的自适应分配。
- 按使用量计费。Serverless按照服务的使用量(调用次数、时长等)计费,而不是像传统的 serverful 服务那样,按照使用的资源(ECS 实例、VM 的规格等)计费。
Serverless 的分类
BaaS
BaaS(Backend as a Service)后端即服务,一般是一个个的 API 调用后端或别人已经实现好的程序逻辑,比如身份验证服务 Auth0,这些 BaaS 通常会用来管理数据,还有很多公有云上提供的我们常用的开源软件的商用服务,比如亚马逊的 RDS 可以替代我们自己部署的 MySQL,还有各种其它数据库和存储服务。
FaaS
FaaS(Functions as a Service)函数即服务,FaaS 是无服务器计算的一种形式,当前使用最广泛的是 AWS 的 Lambada。
现在当大家讨论 Serverless 的时候首先想到的就是 FaaS,有点甚嚣尘上了。FaaS 本质上是一种事件驱动的由消息触发的服务,FaaS 供应商一般会集成各种同步和异步的事件源,通过订阅这些事件源,可以突发或者定期的触发函数运行。
传统的服务器端软件不同是经应用程序部署到拥有操作系统的虚拟机或者容器中,一般需要长时间驻留在操作系统中运行,而 FaaS 是直接将程序部署上到平台上即可,当有事件到来时触发执行,执行完了就可以卸载掉。
使用场景
Serverless 比较适合以下场景:
- 异步的并发,组件可独立部署和扩展
- 应对突发或服务使用量不可预测(主要是为了节约成本,因为 Serverless 应用在不运行时不收费)
- 短暂、无状态的应用,对冷启动时间不敏感
- 需要快速开发迭代的业务(因为无需提前申请资源,因此可以加快业务上线速度)
Serverless 的使用场景示例如:
- ETL
- 机器学习及 AI 模型处理
- 图片处理
- IoT 传感器数据分析
- 流处理
- 聊天机器人
优缺点
优点
-
降低运营成本:
Serverless 是非常简单的外包解决方案。它可以让您委托服务提供商管理服务器、数据库和应用程序甚至逻辑,否则您就不得不自己来维护。由于这个服务使用者的数量会非常庞大,于是就会产生规模经济效应。在降低成本上包含了两个方面,即基础设施的成本和人员(运营/开发)的成本。
-
降低开发成本:
IaaS 和 PaaS 存在的前提是,服务器和操作系统管理可以商品化。Serverless 作为另一种服务的结果是整个应用程序组件被商品化。
-
扩展能力:
Serverless 架构一个显而易见的优点即“横向扩展是完全自动的、有弹性的、且由服务提供者所管理”。从基本的基础设施方面受益最大的好处是,您只需支付您所需要的计算能力。
-
更简单的管理:
Serverless 架构明显比其他架构更简单。更少的组件,就意味着您的管理开销会更少。
-
“绿色”的计算:
随着Serverless架构的出现,让服务提供商提供我们的计算能力最大限度满足实时需求。这将使我们更有效地利用计算资源。
在上面我们提到了使用 IaaS给 我们带来了五点好处,FaaS 当然也包括了这些好处,但是它给我们带来的最大的好处就是多快好省。减少从概念原型到实施的等待时间,比自己维护服务更省钱。
-
降低人力成本
不需要再自己维护服务器,操心服务器的各种性能指标和资源利用率,而是关心应用程序本身的状态和逻辑。而且 serverless 应用本身的部署也十分容易。同时,对于运维来说,也不再需要监控那些更底层的如磁盘使用量、CPU 使用率等底层和长期的指标信息,而是监控应用程序本身的度量,这将更加直观和有效。
在此看来有人可能会提出 “NoOps” 的说法,其实这是不存在的,只要有应用存在的一天就会有 Ops,只是人员的角色会有所转变,部署将变得更加自动化,监控将更加面向应用程序本身,更底层的运维依然需要专业的人员去做。
-
降低风险
对于组件越多越复杂的系统,出故障的风险就越大。我们使用 BaaS 或 FaaS 将它们外包出去,让专业人员来处理这些故障,有时候比我们自己来修复更可靠,利用专业人员的知识来降低停机的风险,缩短故障修复的时间,让我们的系统稳定性更高。
-
减少资源开销
我们在申请主机资源一般会评估一个峰值最大开销来申请资源,往往导致过度的配置。
解决这个问题最好的办法就是,不计划到底需要使用多少资源,而是根据实际需要来请求资源,当然前提必须是整个资源池是充足的(公有云显然更适合)。根据使用时间来付费,根据每次申请的计算资源来付费,让计费的粒度更小,将更有利于降低资源的开销。这是对应用程序本身的优化,例如让每次请求耗时更短,让每次消耗的资源更少将能够显著节省成本。
-
增加缩放的灵活性
以 AWS Lamba 为例,当平台接收到第一个触发函数的事件时,它将启动一个容器来运行你的代码。如果此时收到了新的事件,而第一个容器仍在处理上一个事件,平台将启动第二个代码实例来处理第二个事件。AWS lambad 的这种自动的零管理水平缩放,将持续到有足够的代码实例来处理所有的工作负载。
但是,AWS 仍然只会向您收取代码的执行时间,无论它需要启动多少个容器实例要满足你的负载请求。例如,假设所有事件的总执行时间是相同的,在一个容器中按顺序调用Lambda 100 次与在 100 默认执行 Lambada 函数最大并发数是 1000。
-
缩短创新周期
小团队的开发人员正可以在几天之内从头开始开发应用程序并部署到生产。使用短而简单的函数和事件来粘合强大的驱动数据存储和服务的 API。完成的应用程序具有高度可用性和可扩展性,利用率高,成本低,部署速度快。
以 Docker 为代表的容器技术仅仅是缩短了应用程序的迭代周期,而 serverless 技术是直接缩短了创新周期,从概念到最小可行性部署的时间,让初级开发人员也能在很短的时间内完成以前通常要经验丰富的工程师才能完成的项目。
缺点
-
状态管理
要想实现自由的缩放,无状态是必须的,而对于有状态的服务,使用 serverless 这就丧失了灵活性,有状态服务需要与存储交互就不可避免的增加了延迟和复杂性。
-
延迟
应用程序中不同组件的访问延迟是一个大问题,我们可以通过使用专有的网络协议、RPC 调用、数据格式来优化,或者是将实例放在同一个机架内或同一个主机实例上来优化以减少延迟。
而 serverless 应用程序是高度分布式、低耦合的,这就意味着延迟将始终是一个问题,单纯使用 serverless 的应用程序是不太现实的。
-
本地测试
Serverless 应用的本地测试困难是一个很棘手的问题。虽然可以在测试环境下使用各种数据库和消息队列来模拟生产环境,但是对于无服务应用的集成或者端到端测试尤其困难,很难在本地模拟应用程序的各种连接,并与性能和缩放的特性结合起来测试,并且 serverless 应用本身也是分布式的,简单的将无数的 FaaS 和 BaaS 组件粘合起来也是有挑战性的。
knative
簡單玩 Knative — — 用於 Kubernetes 的 Serverless/FaaS 開源框架
Knative 的目标是在基于 Kubernetes 之上为整个开发生命周期提供帮助。它的具体实现方式是:首先使你作为开发人员能够以你想要的语言和以你想要的方式来编写代码,其次帮助你构建和打包应用程序,最后帮助你运行和伸缩应用程序。
Build(构建)Build 组件是解决如何从源代码到容器的
通过灵活的插件化的构建系统将用户源代码构建成容器。目前已经支持多个构建系统,比如 Google 的 Kaniko,它无需运行 Docker daemon 就可以在 Kubernetes 集群上构建容器镜像。
Serving(服务)解决如何从容器到 URL 的
基于负载自动伸缩,包括在没有负载时缩减到零。允许你为多个修订版本(revision)应用创建流量策略,从而能够通过 URL 轻松路由到目标应用程序。
Event(事件)
使得生产和消费事件变得容易。抽象出事件源,并允许操作人员使用自己选择的消息传递层。
Knative 是以 Kubernetes 的一组自定义资源类型(CRD)的方式来安装的,因此只需使用几个 YAML 文件就可以轻松地开始使用 Knative 了。这也意味着,在本地或者托管云服务上,任何可以运行 Kubernetes 的地方都可以运行 Knative 和你的代码。
build
- Build
驱动构建过程的自定义 Kubernetes 资源。在定义构建时,您需要定义如何获取源代码以及如何创建容器镜像来运行代码。
- Build Template
封装可重复构建步骤集合以及允许对构建进行参数化的模板。
- Service Account
允许对私有资源(如 Git 仓库或容器镜像库)进行身份验证。
[备注] 在撰写本章时,社区正在积极的将 Build 迁移到 Build Pipeline(构建流水线),对 Build 中的流水线进行重构使其更接近 Knative 的 CI/CD 流水线风格。这意味着除了编译和打包代码外,Knative 中的构建还可以轻松地运行测试并发布这些结果。请密切关注 Knative 的未来版本,了解这一变化。
serving
Knative Serving 将一组对象定义为 Kubernetes 自定义资源定义 (CRD)。这些资源用于定义和控制无服务器工作负载在集群上的行为方式。
-
服务:
service.serving.knative.dev
资源自动管理工作负载的整个生命周期。它控制其他对象的创建,以确保您的应用程序具有路由、配置和服务的每次更新的新修订。服务可以定义为始终将流量路由到最新版本或固定版本。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18apiVersion: serving.knative.dev/v1 kind: Service metadata: name: echo namespace: default spec: template: metadata: annotations: autoscaling.knative.dev/class: "kpa.autoscaling.knative.dev" spec: containers: - image: ealen/echo-server:latest ports: - containerPort: 3000 env: - name: TARGET value: "echo"
Service
1
2
3
4
5
6
7kubectl describe ksvc echo NAME URL LATEST AGE echo http://echo.default.127.0.0.1.sslip.io echo-00001 3m23s CONDITIONS READY REASON 3 OK / 3 True
-
路由:
route.serving.knative.dev
资源将网络端点映射到一个或多个修订版。您可以通过多种方式管理流量,包括部分流量和命名路线。Route还有很多用途,比如将流量导向特定的版本容器,甚至在多个版本之间分配流量等。1
2
3
4
5
6
7
8
9
10apiVersion: serving.knative.dev/v1 kind: Route metadata: name: echo-route namespace: default spec: traffic: - configurationName: echo latestRevision: true percent: 100
-
配置:
configuration.serving.knative.dev
资源为您的部署维护所需的状态。它在代码和配置之间提供了清晰的分离,并遵循十二因素应用程序方法。修改配置会创建一个新的修订版。 -
修订:
revision.serving.knative.dev
资源是对工作负载所做的每次修改的代码和配置的时间点快照。修订是不可变的对象,只要有用就可以保留。Knative Serving Revisions 可以根据传入流量自动放大和缩小。
Knative Eventing 是 API 的集合,使您能够在应用程序中使用事件驱动的架构。您可以使用这些 API 创建将事件从事件生成者(称为源)路由到接收事件的事件使用者(称为接收器)的组件。接收器还可以配置为通过发送响应事件来响应 HTTP 请求。
Knative Eventing 是一个独立平台,为各种类型的工作负载提供支持,包括标准 Kubernetes 服务和 Knative Serving Services。
Knative Eventing 使用标准 HTTP POST 请求在事件生成器和接收器之间发送和接收事件。这些事件符合CloudEvents 规范,可以使用任何编程语言创建、解析、发送和接收事件。
Knative Eventing 组件是松散耦合的,可以相互独立开发和部署。任何生产者都可以在有活动的事件消费者正在侦听这些事件之前生成事件。任何事件消费者都可以在创建事件的生产者之前表达对一类事件的兴趣。