serverless初探
概述
无服务器是一种云原生开发模型,可使开发人员专注构建和运行应用,而无需管理服务器。
无服务器方案中仍然有服务器,但它们已从应用开发中抽离了出来。云提供商负责置备、维护和扩展服务器基础架构等例行工作。开发人员可以简单地将代码打包到容器中进行部署。
部署之后,无服务器应用即可响应需求,并根据需要自动扩容。公共云提供商的无服务器产品通常通过一种事件驱动执行模型来按需计量。因此,当无服务器功能闲置时,不会产生费用。
-
Serverless(无服务器架构)指的是由开发者实现的业务逻辑运行在无状态的计算容器中,它由事件触发, 完全被第三方管理,其业务层面的状态则被存储在数据库和其他存储资源。
-
Serverless不代表不需要服务器,而是说开发者不用过多考虑服务器的问题,计算资源作为服务而不是服务器的概念出现。
-
Serverless是一种构建和管理基于微服务架构的完整流程,允许开发者在服务级别而不是服务器级别来管理应用部署,这大大降低了软件开发的复杂度,使得开发者可以快速迭代,更快速地开发软件。
Serverless特点有: 无需管理基础设施、按用付费、事件驱动、自动化构建部署。
需要强调的是无服务器架构不仅仅是函数计算,还包含各类后端服务,FaaS是无服务器架构的一种实现,它包含了一个标准化的运行时框架,用于构建执行函数。
无服务器架构概述
无服务器与其他云计算模型的区别在于,它是由云提供商负责管理云基础架构和应用扩展。无服务器应用部署在容器中,这些容器在被调用时会自动按需启动。
在标准的基础架构即服务(IaaS)云计算模型中,用户需要预先购买容量单元;也就是说,您要先向公共云提供商支付始终可用的服务器组件的费用,才能运行您的应用。 用户自行负责在需求高时扩展服务器容量,并在不再需要时缩减容量。即使在应用闲置不用期间,运行该应用所需的云基础架构也要保持就绪。
无服务器架构则与之相反,应用仅在需要时启动。有事件触发应用代码运行时,公共云提供商才会为这一代码分配资源。该代码执行结束后,用户便不再付费。除了成本与效率上的优势外,无服务器也能将开发人员从应用扩展和服务器置备相关的琐碎日常任务中解放出来。
使用无服务器时,管理操作系统和文件系统、安全补丁、负载平衡、容量管理、扩展、日志和监控等例行任务都由云服务提供商分担。
您可以构建完全无服务器化的应用,也可以打造包含部分无服务器、部分传统微服务组件的应用。
云提供商在无服务器计算中有什么作用?
无服务器计算产品通常分为两类,分别是后端即服务(BaaS)和功能即服务(FaaS)。
BaaS 可让开发人员访问各种各样的第三方服务和应用。例如,云提供商可以提供认证服务、额外加密、云访问数据库以及高置信度使用数据。在 BaaS 中,无服务器功能通常通过应用编程接口(API)调用。
在大多数情况下,当开发人员提到无服务器时,他们所指的基本是 FaaS 模型。在 FaaS 下,开发人员仍然要编写自定义服务器端逻辑,但它可以在完全由云服务提供商管理的容器中运行。
主流公共云提供商全都拥有一种或多种 FaaS 产品。比如 Amazon Web Services 的 AWS Lambda、Microsoft Azure 的 Azure Functions、Google Cloud 的多款产品,以及 IBM Cloud 的 IBM Cloud Functions 等。
一些组织选择使用开源服务器平台运行自己的 FaaS 环境,例如基于 Kubernetes 的 Knative 项目构建的 红帽® OpenShift Serverless。
什么是功能即服务 (FaaS)?
功能即服务(FaaS)是一种事件驱动计算执行模型;开发人员编写逻辑,部署到完全由平台管理的容器中,然后按需执行。
与 BaaS 不同,FaaS 可让开发人员拥有更大的掌控权力,他们可以创建自定义应用,而不依赖于包含预编写服务的库。
代码则部署到云提供商管理的容器中。具体而言,这些容器具有以下特点:
使用 FaaS 时,开发人员可以通过 API 调用无服务器应用,FaaS 提供商则通过 API 网关来处理 API。
无服务器用例有哪些?
对于能够瞬时启动的异步、无状态应用,无服务器架构是十分理想的选择。同样,无服务器适合那些有不频繁、无法预知的激增需求的用例。
比如有一个批处理传入图像文件的任务,它的运行频率也许并不高,但时不时就会有大量图像一次性到达。或者例如监控数据库传入的更改,再应用一系列功能,比如对照质量标准检查更改或进行自动转换。
无服务器应用也适合涉及传入数据流、聊天机器人、计划任务或业务逻辑的用例。
其他一些常见的无服务器用例有后端 API 和 Web 应用、业务流程自动化、无服务器网站,以及跨多系统集成。
- 异步,并发,易于并行化成独立工作单元的工作负载
- 低频或有零星请求,但具有较大不可预测扩容变化需求的工作负载
- 无状态,短期运行,对冷启动延迟不敏感的工作负载
- 业务需求变化迅速,要求快速开发实现的场景
什么是 Knative 和无服务器 Kubernetes?
作为一种在自动化基础架构中运行容器化应用的方式,Kubernetes 容器编排平台不出意料地成为了运行无服务器环境的热门选择。然而,Kubernetes 本身并不足以原生运行无服务器应用。
Knative 是一个开源社区项目,可以添加组件,从而在 Kubernetes 上部署、运行和管理无服务器应用。
利用 Knative 无服务器环境,您可以将代码部署到 Kubernetes 平台,如红帽 OpenShift。借助 Knative,您可以将代码打包为容器镜像并交给系统,以此来创建相应的服务。您的代码仅在需要时才会运行,并由 Knative 来自动启动和停止实例。
Knative 主要由 3 个组件构成:
- 构建 - 一种灵活地将源代码构建到容器中的方法。
- 服务 - 通过请求驱动模型实现容器的快速部署和自动扩展,以根据需要为工作负载提供服务。
- 事件 - 用于使用和发起事件以触发应用的基础架构。应用可能由多种源触发,例如您自己应用的事件、来自多个提供商的云服务、软件即服务 (SaaS) 系统,以及红帽 AMQ 流。
与早期的无服务器框架不同,Knative 能够部署任何现代应用工作负载,包括单体应用以及微服务和微小功能等。
作为由单一服务提供商控制的 FaaS 解决方案的替代选择,Knative 可以在运行 Kubernetes 的任何云平台中运行,包括在本地数据中心运行。这让组织在运行无服务器工作负载时拥有了更大的敏捷性和灵活性。
无服务器的发展
随着容器和按需云产品的普及,无服务器架构和 FaaS 也发展起来。根据红帽和 451 Research 携手开展的调研,无服务器的发展可以追溯为三个阶段。
无服务器的"1.0"阶段存在诸多局限,对于常规计算而言不甚理想。无服务器 1.0 具有以下特征:
- HTTP 和少许其他代码
- 仅限功能
- 有限执行时间(5-10 分钟)
- 无编排
- 有限本地开发体验
Kubernetes 在"无服务器 1.5"时代面世,此时许多无服务器框架都开始自动缩放容器。无服务器 1.5 具有以下特征:
- Knative
- 基于 Kubernetes 的自动扩展
- 微服务和功能
- 可在本地轻松调试和测试
- 多语言并可移植
如今,"无服务器 2.0"方兴正艾,增加了集成和状态。提供商已开始逐渐添加缺少的部件,使无服务器适合一般用途的业务工作负载。无服务器 2.0 具有以下特征:
- 基本状态处理
- 采用企业级启程模式
- 高级消息传递功能
- 与企业级 PaaS 混合
- 企业就绪型事件来源
- 状态与集成
无服务器计算的优缺点
优点
- 无服务器计算可以提高开发人员的工作效率,降低运营成本。通过摆脱诸如服务器置备和管理等例行任务,开发人员就会有更多的时间专注于自己的应用。
- 无服务器有助于 DevOps 的采用,可以减少开发人员明确描述基础架构(需要相应的置备操作)的需要。
- 可以通过整合第三方 BaaS 产品的完整组件来进一步简化应用开发。
- 在无服务器模型中,由于您只需为所需的云计算时间付费,而不用全程运行和管理自己的服务器,因此大大降低了运营成本。
缺点
- 不运行自己的服务器或控制自己的服务器端逻辑也有弊端。
- 云提供商可能对其组件的交互方式有着严格的限制,从而影响您系统的灵活性和定制能力。采用 BaaS 环境时,开发人员可能要为代码不受其控制的服务负责。
- 放弃对 IT 堆栈这些方面的控制,也同时意味着您会受制于供应商技术锁定。即便您决定要更换提供商,也可能需要升级系统以符合新供应商的规范,而这无疑会增加成本。
当前各厂商的Serverless标准不统一,软件不能跨厂商迁移,客观上存在厂商锁定问题,这是制约Serverless发展的最主要因素。正因为如此,谷歌发起了Knative项目。
主要缺点
- 厂商绑定
Serverless 只提供了应用本身部署和运行的便利性,但应用依赖的其它服务,比如 API 网关、数据库、消息、缓存管理组件等,会因为选用了某个厂商的 Serverless 平台,而必须使用该厂商提供的配套服务,比如使用 AWS Lambda 就必须配套使用 AWS 的 DB, S3 等产品,这样用户就被该厂商绑定,不能进行随意的迁移或者迁移成本非常高。在 Baas 行业内,一个比较典型的事件是:2016 年 1 月 19 日,Facebook 关闭曾经花巨额资金收购的 Parse,造成用户不得不迁移在这个平台中产生一年多的数据,无疑需要花费比较大的人力和时间成本。
- 没有行业标准
因为对 Serverless 缺乏统一认知以及相应的标准,Serverless 应用无法适应所有的云平台,只适合简单的应用开发,无法推动形成大型成功案例。
knative优点
- 便利性:Knative 以 Kubernetes 和 istio 作为其底层框架,因此无论是线上还是线下,任何 Kubernetes 集群,无论是云上 Kubernetes 服务还是自建 Kubernetes 集群,都能通过安装 istio 和 knative 插件快速的搭建 serverless 平台。
- 标准化:Knative 联合 CNCF,把所有事件标准化,统一为 CloudEvent,提供事件的跨平台,同时让函数和具体的调用方能够解耦。
- 服务间解耦:使用 Knative 使得应用不在与底层依赖服务强绑定,可以跨云实现业务互通
- 成熟的生态:Knative 基于 Kubernetes 体系构建,与 kubernetes 生态结合更紧密;
- 自动伸缩:监控应用的请求,并自动扩缩容,得益于 Istio 能力加持,天生支持蓝绿发布、回滚功能,方便应用发布流程。
- 应用监控:支持日志的收集、查找和分析,并支持 VAmetrics 数据展示、调用关系 tracing
knative地位
Knative与云原生平台的三个最佳实践
- 服务的编排要实现计算资源弹性化
- 服务的构建和部署要实现高度自动化
- 事件驱动基础设施标准化
Knative的三个组件(Serving、Build、Eventing)正是遵循这三个最佳实践的设计实现。
Knative Serving
Serving组件提供的能力有:
- 用户容器的快速部署
- 自动伸缩,支持缩容到零
- 服务路由和流量控制
- 容器和配置的版本管理
Serving组件的主要概念构成:
- Service:负责管理工作负载的整个生命周期
- Route:将HTTP请求路由到一个或多个revision/修订版本
- Configuration:保存应用容器和配置的最新状态,是创建Revision的模板
- Revision:工作负载的代码和配置的时间点快照
用户容器的主要限制:
- 必须是无状态的HTTP服务
- 允许挂载configmap,secret,projected,但不允许挂载持久卷pvc
- 一个Service只能有一个用户容器
Knative Build
Knative build作为Knative的CI/CD基础组件,实现了服务的自动化构建和部署能力。 在v0.8.0后由Tekton Pipelines项目替代,Tekton pipline是google开源的另外一个用于云原生平台的CI/CD的项目,以其灵活扩展的能力、轻量级、白盒化的特点成为Knative build的最佳接替者。
Knative Eventing
Knative Eventing的核心功能是对发布/订阅细节进行抽象处理,帮助开发人员摆脱相关负担。
Eventing组件的特性如下:
- 声明式地绑定event sources, triggers和services
- 从少量事件到实时stream pipelines动态扩展
- 采用CloudeEvents标准
- 抽象的事件来源,解耦具体事件源类型(eg. Kafka,CronJob,Github,kubernetes … )
- Channel处理缓冲和持久性,即使该服务已被关闭时也确保将事件传递到其预期的服务。另外,Channel是我们代码和底层消息传递解决方案之间的一个抽象层。这意味着可以像 Kafka 和 RabbitMQ 一样在某些服务之间进行消息交换,但在这两种情况下我们都不需要编写特定的实现代码。(目前Channel的实现有InMemory, Kafka, Nats, PubSub )
关于CloudEvents
由于Serverless 平台和产品众多,支持的事件来源和事件格式定义也是五花八门,CNCF serveless工作组提出CloudEvnets项目,试图对事件进行标准化。
CloudEvents是以通用格式描述事件数据的规范,以提供跨服务、平台和系统的互操作性。CloudEvents当前已经发布1.0版。
Knative在当当单品API项目中的应用
Knative作为开源仅一年多的项目,各项特性还在快速发展演进过程中,出于稳妥考虑,我们选择了相对成熟的Serving组件,应用到业务形态相对独立的单品API服务进行了实践。
单品API服务是当当网基础平台中核心的基础服务之一,由一系列与商品相关的API服务构成,单品API完成大量后台API的接口聚合并提供接口性能的加速,单品API为所有相关上游服务提供高效可靠的底层服务支持。
我们搭建了一套完整的运行环境,分别如下:
- Knative: v0.8.0
- Istio: v1.3.0
- Kubernetes:v1.14.4
- Docker: v18.06.3
- Centos:v7.5
- Promethues v2.2.1
- Grafana v5.0.3
- Tekton Pipelines: v0.8.0
- Harbor:v1.5.0
首先编写用户容器对应的dockerfile,然后编写对应的Tekton tastk及taskrun文件,构建代码打包运行时容器推送到私有镜像仓库,编写knative的service.yaml 配置文件并完成部署。服务就整体运行起来了。
评估Knative平台对应用的性能影响
为了评估Knative对应用性能的影响,我们分成了三个对照组,分别对平均响应时间,tps进行了比较。
从测试结果来看,对比K8S原生的部署方案,Knative的引入带来了27ms的延迟和10%的TPS损失。
Knative相关的运维工具
Knative直接继承使用了K8S平台上的解决方案,避免了重复建设。
- 日志中心:EFK
- 监控:Promethues & Grafana
- 服务网格可视化工具: Kiali,Jaeger
性能优化
Knative Serving支持缩容到零,这极大提高了低频应用的资源占用,同时也带来了一个问题,那就是冷启动延迟问题,对于容器启动速度较慢或者对请求延迟非常敏感的场景这个问题表现得会更为突出,那么如何解决这个问题呢,在这里我们采用保留服务最小副本数的方法在资源占用和服务响应延迟之间进行平衡。
配置示例:
# 为服务设置最小所需保留副本数,n为1或者估算的最小副本数
autoscaling.knative.dev/minScale: “n”
对于可预见的高并发场景我们可以为服务预设预期最小所需副本数,这样可以避免突发高并发请求导致大量请求积压;为服务预设最大所需副本数可以避免资源过度分配;为服务的每个POD设置最大并发请求数上限保障每个服务的可用性。
配置示例:
#为服务预设预期最小所需副本数
autoscaling.knative.dev/minScale: “200”
#为服务预设最大所需副本数避免资源过度分配
autoscaling.knative.dev/maxScale: “500"
#为服务的每个POD设置最大并发请求数上限保障每个服务的可用性
autoscaling.knative.dev/target: “100”
参考和引用文档:
副本数避免资源过度分配
autoscaling.knative.dev/maxScale: “500"
#为服务的每个POD设置最大并发请求数上限保障每个服务的可用性
autoscaling.knative.dev/target: “100”
------
参考和引用文档:
[Knative 系列(一):基本概念和原理解读]: https://www.infoq.cn/article/PEOIcPk4lZRg-fAwry8H
[what is serverless]: https://www..com/zh/topics/cloud-native-apps/what-is-serverless#