提到FaaS,大家很容易联想到近几年很火的概念Serverless。的确,FaaS跟它确实有个某种关系,或者说,FaaS就是在某种型态下Serverless的体现。本文是结合行业现有FaaS产品的技术调研类总结,包括了当前比较火的FaaS产品以及相关的一些底层技术。

Knative Func

Func命令创建工程

1
func create -l <language> <function-name>

示例:

1
2
3
func create -l rust knative-func-demo-rust
func create -l go knative-func-demo-go
func create -l springboot knative-func-demo-springboot

工程示例

1
2
3
4
5
6
7
8
9
10
❯ tree
knative-func-demo-rust
├── Cargo.lock
├── Cargo.toml
├── func.yaml
├── README.md
└── src
├── config.rs
├── handler.rs
└── main.rs

总结

  • 提供命令工具可以辅助初始化项目工程,涉及多种语言。
  • Func命令提供一键构建部署镜像,以Serving形式提供服务,并没有专门的SDK。
  • Knative Serving 仅仅能运行应用,不能运行函数,还不能称之为 FaaS 平台。

OpenFunction

Function生命周期

img

函数框架(Functions framework)

  • 封装函数入参,即固定函数入参有哪些。

函数构建(Build)

img

提供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 输出到外部。

img

同步运行时

目前支持使用 Knative Serving 作为运行时。

异步运行时

基于 KEDA 和 Dapr 实现的事件驱动运行时。

Function CRD示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
apiVersion: core.openfunction.io/v1beta2
kind: Function
metadata:
name: function-cloudevent-java
spec:
version: "v2.0.0"
image: "openfunctiondev/sample-cloudevent-func:v1"
imageCredentials:
name: push-secret
build:
builder: openfunction/builder-java:v2-18
env:
FUNC_NAME: "dev.openfunction.samples.CloudEventFunctionImpl"
FUNC_CLEAR_SOURCE: "true"
srcRepo:
url: "https://github.com/OpenFunction/samples.git"
sourceSubPath: "functions/knative/java"
revision: "main"
serving:
template:
containers:
- name: function # DO NOT change this
imagePullPolicy: IfNotPresent
triggers:
http:
port: 8080

组件关系

img

特点汇总

模式:Pod:Func为1:1

  1. 多运行时支持:支持不同的函数运行时,包括但不限于 Knative、Keda、Dapr 等,允许开发者根据需求选择最适合的运行时环境。
  2. 多编程语言支持:可以支持多种编程语言,使得开发者可以使用他们熟悉的语言来编写函数。
  3. 事件驱动:与事件驱动架构兼容,可以响应来自不同事件源的事件,如 HTTP 请求、云事件(CloudEvents)、消息队列消息等。
  4. 构建和部署:集成了构建工具,如Buildpacks和Tekton,以自动化函数的构建和部署过程。
  5. 云原生:设计为云原生,充分利用Kubernetes的特性,如自动扩缩容、服务发现和配置管理。

OpenFaaS

通用架构

img

基于Kubernetes的架构

img

开发人员的工作流程

img

KNIX

前面的函数运行时基本等同于容器,这个不一样。

image-20231229145905991

特点汇总

模式:Pod:Func为M:N

  • 函数运行时,运行时Worker池执行函数代码,Java函数代码动态被ClassLoader加载,通过反射执行函数方法。

fission

这个产品的特点是有明显的函数运行时容器。

Fig.1 Function Pod

  1. Fetcher 从 CRD 获取函数信息。
  2. 从 StorageSvc 中提取部署归档文件。
  3. 将存档保存到共享卷。
  4. 调用环境容器上的专用终结点以启动函数专用化。
  5. 环境容器从卷加载用户函数。
  6. 开始处理来自路由器的请求。

国内云厂商

阿里-函数计算3.0

地址:函数计算 3.0-阿里云帮助中心 (aliyun.com)

实现:不同语言对应不同的函数运行时,函数运行时区别于容器运行时,处于更上层。是重要的产品化产物,容器运行时为函数Worker运行提供更底层的支持。

针对Java:

  • 不支持代码编译:仅支持上传已经开发完成、编译打包后的ZIP包或JAR包。函数计算不提供Java的编译能力。

  • 不支持在线编辑:由于不支持上传代码,所以不支持在线编辑代码,仅支持通过上传 JAR 包通过 OSS 上传两种方法提交代码。

  • 基于安全容器模板技术的优化

我们是如何做到基于安全容器模板技术的优化的?每个容器独占一个虚拟机沙箱,这个沙箱相当于是一个独立的虚拟机,有自己独立的 linux 内核,这样一来每个容器都是通过独立的 kernel 来做安全隔离。神龙启动时模板化大量虚拟机用于提升启动速度,通过 virtiofs 延迟挂载用户代码目录,通过虚拟机微内核隔离用户,可以做到单台机上每个微内核 20M 左右的内存,单机至少 2000 个容器,控制它的冷启动时间是在 250 毫秒左右。通过调度算法,我们可以合理地使用资源,承诺用户的资源 quota。

6.png

image-20240102234440948

又研发了容器运行时:RunD

论文阅读 — RunD: Lightweight Secure Container for High-density Deployment && High-concurrency Startup - 知乎 (zhihu.com)

img

用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业务混合部署,例如:离线和在线业务的混合部署。

腾讯-云函数

image-20240103143958165

img

img

基础实现:直接将代码下载至母机,再将代码目录挂载至Docker。

结论:资料有限不能确定容器运行时具体实现与产品选择,不能确定是字眼还是采用的哪款开源实现。能确定的是,同样没有基于原生容器。

华为云

img

arch

基础支撑技术

Wasm

原生Wasm + Container方案1

image-20231228162858981

支撑组件:containerd

截至目前,Wasm众多运行时,如wsamtimewasmerwasmedge已经很好的与容器生态进行了融合。

构建Wasm项目OCI标准镜像:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
FROM --platform=$BUILDPLATFORM rust:1.64 AS buildbase
WORKDIR /src
RUN <<EOT bash
set -ex
apt-get update
apt-get install -y \
git \
clang
rustup target add wasm32-wasi
EOT

FROM buildbase AS build
COPY Cargo.toml .
COPY src ./src
# Build the Wasm binary
RUN cargo build --target wasm32-wasi --release

FROM scratch
ENTRYPOINT [ "/hello.wasm" ]
COPY --link --from=build /src/target/wasm32-wasi/release/hello.wasm /hello.wasm

构建Wasm OCI镜像:

1
docker buildx build --provenance=false --platform wasi/wasm -t secondstate/rust-example-hello .

image-20231228161512385

运行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
2
podman run --rm --annotation module.wasm.image/variant=compat-smart localhost/hello-wasm:latest /hello.w
asm 50000000

构建Wasm+Container方案3

基于Wasm运行时基础镜像构建业务容器,与传统容器构件一致。

Kubernetes-supported

RuntimeClass

诞生已久:

img

生机:运行Wasm的RuntimeClass并没有很多应用案例。

1
2
3
4
5
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
name: wasmedge
handler: wasmedge

使用示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
apiVersion: v1
kind: Pod
metadata:
labels:
run: wasi-demo
name: wasi-demo
spec:
containers:
- args:
- /wasi_example_main.wasm
- "50000000"
image: wasmedge/example-wasi:latest
name: wasi-demo
restartPolicy: Never
nodeSelector:
kwasm.sh/kwasm-provisioned: kind-worker2
runtimeClassName: wasmedge
CRI-O/Containerd + CRUN

Use OCI containers to run WebAssembly workloads | Opensource.com — 使用 OCI 容器运行 WebAssembly 工作负载 |Opensource.com

Kwasm

KWasm/kwasm-operator: This Kubernetes Operators installs WebAssembly support on your Kubernetes Nodes (github.com)

特点:kwasm-Operator自动化安装WASM运行时

Runwasi

采用Runwasi方案原理:

img

img

下载wasm运行时,并配置

添加RuntimeClass

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
kubectl apply -f - <<EOF
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
name: "wasmtime"
scheduling:
nodeSelector:
wasmtime-enabled: "yes"
handler: "wasmtime"
EOF

kubectl apply -f - <<EOF
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
name: spin
scheduling:
nodeSelector:
wasmtime-enabled: "yes"
handler: spin
EOF

kubectl apply -f - <<EOF
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: wasm-spin
spec:
replicas: 1
selector:
matchLabels:
app: wasm-spin
template:
metadata:
labels:
app: wasm-spin
spec:
runtimeClassName: spin
containers:
- name: spin-hello
image: ghcr.io/deislabs/containerd-wasm-shims/examples/spin-rust-hello:latest
command: ["/"]
---
apiVersion: v1
kind: Service
metadata:
name: wasm-spin
spec:
ports:
- protocol: TCP
port: 80
selector:
app: wasm-spin
EOF

Firecracker

containerd architecture diagram

image-20231230225947869

image-20240102152339317

可以在轻量级虚拟机(称为 microVM)中部署工作负载,与传统虚拟机相比,这些虚拟机提供了增强的安全性和工作负载隔离,同时实现了容器的速度和资源效率。是AWS Serverless底层支撑技术。

启动速度这个存疑,未实测,正邮件向在作者求证。PS:个人表示不信。

基于Firecracker的运行时有:lima, colima等。

Kubernetes-supported

支撑组件:containerd + firecreacker shim 或者 containerd + Kata

Kata Containers

image-20231230000525891

Baidu is running Kata Containers in production to support Function Computing, Cloud Container Instances, and Edge Computing.

image-20231230230247362

版本迭代历史:

image-20231230233708025

image-20231230233743355

image-20231230233919309

多类型沙箱支持(WASM etc.)

ff0273c0467789e1c173b38f20fe76c3

gVisor

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 沙箱具备冷启动速度快、资源开销小的有点,但目前的使用约束较多,支持的语言也有限,成熟度不高,目前还有很多尚未解决的隔离、通用性和语言生态问题。

技术对照

img

总结

  • 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 等公司采用。

参考资料