FaaS及底层技术
提到FaaS,大家很容易联想到近几年很火的概念Serverless
。的确,FaaS跟它确实有个某种关系,或者说,FaaS就是在某种型态下Serverless的体现。本文是结合行业现有FaaS产品的技术调研类总结,包括了当前比较火的FaaS产品以及相关的一些底层技术。
Knative Func
Func命令创建工程
1 | func create -l <language> <function-name> |
示例:
1 | func create -l rust knative-func-demo-rust |
工程示例
1 | ❯ tree |
总结
- 提供命令工具可以辅助初始化项目工程,涉及多种语言。
- Func命令提供一键构建部署镜像,以Serving形式提供服务,并没有专门的SDK。
- Knative Serving 仅仅能运行应用,不能运行函数,还不能称之为 FaaS 平台。
OpenFunction
Function生命周期
函数框架(Functions framework)
- 封装函数入参,即固定函数入参有哪些。
函数构建(Build)
提供OpenFunction Builder CRD,为用户提供了一种可以自由选择 Build 方案的 Build 框架。OpenFunction 选择 Cloud Native Buildpacks(CNB)[1] 作为容器镜像制作的默认选择。v0.3.0后采用shipwright-io/build: Shipwright - a framework for building container images on Kubernetes (github.com)
函数服务(Serving)
提供OpenFunction Serving CRD,并将函数分为同步函数和异步函数。提供运行函数 / 应用,以及赋予函数 / 应用基于事件驱动或流量驱动的自动伸缩的能力(Autoscaling)两大能力。
- Knative Service 负责同步函数的运行与自动伸缩。
- KEDA 会负责异步函数的自动伸缩。
- Dapr 会将外部的输入通过 OpenFunction Context 传递给 Functions framework,进而传递给函数;函数执行完成会通过调用 Functions framework 中相应的函数将输出通过 Dapr 输出到外部。
同步运行时
目前支持使用 Knative Serving 作为运行时。
异步运行时
基于 KEDA 和 Dapr 实现的事件驱动运行时。
Function CRD示例
1 | apiVersion: core.openfunction.io/v1beta2 |
组件关系
特点汇总
模式:Pod:Func为1:1
- 多运行时支持:支持不同的函数运行时,包括但不限于 Knative、Keda、Dapr 等,允许开发者根据需求选择最适合的运行时环境。
- 多编程语言支持:可以支持多种编程语言,使得开发者可以使用他们熟悉的语言来编写函数。
- 事件驱动:与事件驱动架构兼容,可以响应来自不同事件源的事件,如 HTTP 请求、云事件(CloudEvents)、消息队列消息等。
- 构建和部署:集成了构建工具,如Buildpacks和Tekton,以自动化函数的构建和部署过程。
- 云原生:设计为云原生,充分利用Kubernetes的特性,如自动扩缩容、服务发现和配置管理。
OpenFaaS
通用架构
基于Kubernetes的架构
开发人员的工作流程
KNIX
前面的函数运行时基本等同于容器,这个不一样。
特点汇总
模式:Pod:Func为M:N
- 函数运行时,运行时Worker池执行函数代码,Java函数代码动态被ClassLoader加载,通过反射执行函数方法。
fission
这个产品的特点是有明显的函数运行时容器。
- Fetcher 从 CRD 获取函数信息。
- 从 StorageSvc 中提取部署归档文件。
- 将存档保存到共享卷。
- 调用环境容器上的专用终结点以启动函数专用化。
- 环境容器从卷加载用户函数。
- 开始处理来自路由器的请求。
国内云厂商
阿里-函数计算3.0
地址:函数计算 3.0-阿里云帮助中心 (aliyun.com)
实现:不同语言对应不同的函数运行时,函数运行时区别于容器运行时,处于更上层。是重要的产品化产物,容器运行时为函数Worker运行提供更底层的支持。
针对Java:
不支持代码编译:仅支持上传已经开发完成、编译打包后的ZIP包或JAR包。函数计算不提供Java的编译能力。
不支持在线编辑:由于不支持上传代码,所以不支持在线编辑代码,仅支持通过上传 JAR 包或通过 OSS 上传两种方法提交代码。
基于安全容器模板技术的优化
我们是如何做到基于安全容器模板技术的优化的?每个容器独占一个虚拟机沙箱,这个沙箱相当于是一个独立的虚拟机,有自己独立的 linux 内核,这样一来每个容器都是通过独立的 kernel 来做安全隔离。神龙启动时模板化大量虚拟机用于提升启动速度,通过 virtiofs 延迟挂载用户代码目录,通过虚拟机微内核隔离用户,可以做到单台机上每个微内核 20M 左右的内存,单机至少 2000 个容器,控制它的冷启动时间是在 250 毫秒左右。通过调度算法,我们可以合理地使用资源,承诺用户的资源 quota。
又研发了容器运行时:RunD
用Rust实现VMM Dragonball:让原有VMM的内存资源开销从100+MB下降到3MB。即使是128M实例的开销也在可接受范围。同时支持设备直通、设备热插拔、NUMA等特性,让RunD能够适配各种复杂业务场景;多进程融合设计:使RunD在生产环境维护升级更加便捷,提升安全容器稳定性的同时也让进程间通信转换为进程内通信,降低通信开销,优化启动性能;精简操作系统相关组件:有效剥离非容器场景相关特性和组件,降低资源开销,精简组件和接口数量,减小沙箱受攻击风险;VMM 和Guest Kernel的融合设计是安全容器的独特之处。传统虚拟机Guest Kernel由用户提供,VMM要处理各类Guest Kernel,因此大量问题要在宿主机侧解决。但在安全容器场景,Guest Kernel和VMM的统一提供让两者可以深度融合。这一设计进一步提升了安全容器的启动速度,降低了安全容器的开销。 通过上述技术突破,RunD目前已在生产环境部署并支持单节点4000安全容器、200/s并发、200ms启动。
技术应用场景
RunD技术解决了微服务和Serverless场景下细粒度资源安全隔离和按需供给问题,该技术适合以下三类场景:
- 多租户容器场景,例如:公共云对外容器服务场景;
- 可信&不可信容器混合部署,例如:大数据场景里面部分UDF程序的安全隔离;
- 不同SLO业务混合部署,例如:离线和在线业务的混合部署。
腾讯-云函数
基础实现:直接将代码下载至母机,再将代码目录挂载至Docker。
结论:资料有限不能确定容器运行时具体实现与产品选择,不能确定是字眼还是采用的哪款开源实现。能确定的是,同样没有基于原生容器。
华为云
基础支撑技术
Wasm
原生Wasm + Container方案1
支撑组件:containerd
截至目前,Wasm众多运行时,如wsamtime
,wasmer
,wasmedge
已经很好的与容器生态进行了融合。
构建Wasm项目OCI标准镜像:
1 | FROM --platform=$BUILDPLATFORM rust:1.64 AS buildbase |
构建Wasm OCI镜像:
1 | docker buildx build --provenance=false --platform wasi/wasm -t secondstate/rust-example-hello . |
运行Wasm OCI镜像:
1 | docker run --runtime=io.containerd.wasmedge.v1 --platform=wasi/wasm secondstate/rust-example-hello |
原生Wasm + Container方案2
运行组件:podman
+ crun
构建组件:buildah
构建Wasm OCI镜像:
1 | buildah build --annotation "module.wasm.image/variant=compat" -t mywasm-image . |
运行Wasm OCI镜像:
1 | podman run --rm --annotation module.wasm.image/variant=compat-smart localhost/hello-wasm:latest /hello.w |
构建Wasm+Container方案3
基于Wasm运行时基础镜像构建业务容器,与传统容器构件一致。
Kubernetes-supported
RuntimeClass
诞生已久:
生机:运行Wasm的RuntimeClass并没有很多应用案例。
1 | apiVersion: node.k8s.io/v1 |
使用示例:
1 | apiVersion: v1 |
CRI-O/Containerd + CRUN
Kwasm
特点:kwasm-Operator自动化安装WASM运行时
Runwasi
采用Runwasi方案原理:
下载wasm运行时,并配置
添加RuntimeClass
1 | kubectl apply -f - <<EOF |
Firecracker
可以在轻量级虚拟机(称为 microVM)中部署工作负载,与传统虚拟机相比,这些虚拟机提供了增强的安全性和工作负载隔离,同时实现了容器的速度和资源效率。是AWS Serverless底层支撑技术。
启动速度这个存疑,未实测,正邮件向在作者求证。PS:个人表示不信。
基于Firecracker
的运行时有:lima
, colima
等。
Kubernetes-supported
支撑组件:containerd
+ firecreacker shim
或者 containerd
+ Kata
Kata Containers
Baidu is running Kata Containers in production to support Function Computing, Cloud Container Instances, and Edge Computing.
版本迭代历史:
多类型沙箱支持(WASM etc.)
gVisor
Unikernel 技术为代表gVisor 引入了进程虚拟化
的思想,去掉了设备模型,将虚拟化的边界移到了系统调用层面,从而减少传统设备虚拟化的开销。而代价却是有大量的 Linux 系统调用需要沙箱处理,暴露了更多的攻击面(目前已实现了数百个系统调用)。
Unikernel 则源于90年代的操作系统微内核理念,随着近年来容器技术的走红,这项技术也越来越被人关注(例如 Nabla container)。其核心思想是将 Linux 的宏内核拆分成为多个库,只打包应用依赖的库到微内核镜像中。每个应用拥有独立的微内核,从而提升性能,降低开销,减少攻击面。
GraalVM for Java
解决Java传统应用或代码基于容器冷启动慢,性能差的问题。
根据OpenFunction与KNIX的设计提示,FaaS提供基础函数定义规范,那仅仅针对Java的冷启动慢问题可以采用自定义builder+二进制可执行镜像解决。
问题与总结
冷启动问题
- 沙箱预热:通过提前启动一批应用沙箱(比如容器),形成预热资源池,冷启动请求达到时,直接从预热池拉起函数实例,从而消除沙箱创建和初始化的开销。
- 实例保活:请求执行完成后,平台不会即刻将实例回收,而是保活一个固定的时间窗(从几分钟到半小时不等),这样,在该时间窗内有新的请求到来时,可以直接复用保活实例,进行热启动。
- 单实例多并发:用户可以为函数配置一个合理的并发度,这样,平台会为多个并发请求只拉起一个实例进行并发处理,从而减少实例创建的数目,降低冷启动次数。
- 预留实例:企业可以为自己的应用配置一定数目的预留实例,预留实例是一种按照一定策略(如定时、指标)提前创建并常驻在平台上资源,请求到达后,通过热启动响应。值得一提的是,FunctionGraph即将推出的基于AI技术的预留实例智能推荐策略,帮助企业在性能和成本之间取得最佳平衡。
- 快照加速:我们推出的基于快照技术的冷启动解决方案SnapShot,可以显著提升包括Java函数在内的应用冷启动性能。当然还有Oracle GraalVM中Java静态编译技术,可以有效突破Java应用冷启动桎梏,实现启动性能质的飞跃。
容器隔离技术
容器隔离技术是推动容器运行时快速发展的主要动力之一。当前主流的容器隔离技术有以下几种:
Linux 容器隔离技术:Linux 容器主要采用 namespace + cgroups 的方式实现隔离,其主要特点是高性能、低开销。LXC 是比较早期的隔离技术,后来由于其安全性和可移植性的问题,逐渐被 libcontainer 取代,但其隔离性一直较差,例如 runc 容器。
轻量级虚拟化容器隔离技术:MicroVM 是一种基于虚拟化的容器隔离技术,它使用了轻量级的虚拟化技术来实现容器的隔离,具备了传统虚拟机的强隔离性和安全性,但带来的效率问题也颇为明显,比如 QEMU, Stratovirt 等。
用户态内核隔离技术:用户态内核是将原来运行在内核态的大部分内核功能运行在用户态,通过对业务进程系统调用的代理实现系统调用的安全隔离。相比于虚拟化,用户态内核更加轻量化、性能更好,但由于依旧处于早期发展阶段,其稳定性、可靠性和兼容性存在不少问题,比如 gVisor,Quark 等。
语言虚拟机隔离技术:语言虚拟机隔离技术本质上是将底层字节码通过专用的语言虚拟机来加载运行,从而达到隔离的目的。Wasm 虚拟机就是语言虚机的一种。该类型语言虚拟机隔离技术利用与平台无关的系统接口(WASI),使 Wasm 程序能够访问到系统资源。Wasm 沙箱具备冷启动速度快、资源开销小的有点,但目前的使用约束较多,支持的语言也有限,成熟度不高,目前还有很多尚未解决的隔离、通用性和语言生态问题。
技术对照
总结
- FaaS场景中,可以概述为K8s中需要执行由引入了由外部人员参与制作的镜像时,安全为第一考虑要素。参照上述各案例的选择,引入安全容器运行时是必要的选择。
- Func实现有具体规范或框架,也就是限制了用户Func的入参出参的行为。
- FaaS产品可以总结为两类运行时,函数运行时与容器运行时,特殊情况可能合二为一。目前市面上大多数的容器运行时实现还是基于容器技术。由于WASM技术发展的时间段,编程语言等因素,目前未在各类FaaS产品中明显引用(腾讯云有CustomRuntime支持,有文章做了基于此的WebAssembly运行尝试)。依据目前Docker或各类容器运行时的Roadmap中可初见端倪,支持与发展WASM已经是现在进行时。
- 各头部云厂商都在容器运行时方面有更多选择,优化,甚至自研,且起步时间比较早。
- FaaS是个为用户降本增效的轻量级业务实现方案,更多常见在于与后端BaaS的打通(提供公有云业务API调用SDK),辅助绑定用户使用自己的云产品。目前对云舰是否有价值?
标注解释
[1]Cloud Native Buildpacks(CNB)是云原生领域最新涌现出来的新技术,它不依赖于 Dockerfile,而是能自动检测要 build 的代码,并生成符合 OCI 标准的容器镜像,已经被 Google Cloud、IBM Cloud、Heroku、Pivotal 等公司采用。
参考资料
- Wasm的野心:取代K8s,不如结合K8s-51CTO.COM
- AWS Lambda WebAssembly Serverless Functions in AWS Lambda (secondstate.io)
- Netlify WebAssembly Serverless Functions in Netlify (secondstate.io)
- Tencent Cloud 在腾讯云上部署基于 WebAssembly 的高性能 serverless 函数 - WasmEdge的个人空间 - OSCHINA - 中文开源技术交流社区
- Vercel Rust and WebAssembly Serverless functions in Vercel (secondstate.io)
- Wasm and Kubernetes: A New Era of Cloud-Native Application Deployment | by Seifeddine Rajhi | Nov, 2023 | Medium — Wasm 和 Kubernetes:云原生应用部署的新时代 |由 Seifeddine Rajhi |2023年11月 |中等
- Video: https://www.youtube.com/watch?v=pTQ_jVYhAoc
- Video: https://www.youtube.com/watch?v=fEIs-oS9A-4
- A Paper on RunD: A Lightweight Secure Container Runtime for High-density Deployment and High-concurrency Startup in Serverless Computing - Alibaba Cloud Community
- 论文阅读 — RunD: Lightweight Secure Container for High-density Deployment && High-concurrency Startup - 知乎 (zhihu.com)
- 腾讯云Serverless2.0架构精解 - 掘金 (juejin.cn)
- 15年了,我们到底怎样才能用好 Serverless? - 华为云开发者联盟 - 博客园 (cnblogs.com)
- iSulad+Kuasar:管理面资源消耗锐减 99%的新一代统一容器运行时解决方案 (openeuler.org)
- 深度解析 AWS Firecracker 原理篇 – 虚拟化与容器运行时技术 | 亚马逊AWS官方博客 (amazon.com)
- https://blog.csdn.net/com_stu_zhang/article/details/104903920
- Wasm and Kubernetes: A New Era of Cloud-Native Application Deployment | by Seifeddine Rajhi | Nov, 2023 | Medium