Fass及Serverless

Serverless AWS 官方对 Serverless 的介绍:服务器架构是基于互联网的系统,应用开发不使用常规的服务进程,而是依赖于第三方服务,客户端逻辑和服务托管远程过程调用的组合。简单的讲,Serverless 就是指应用的开发不再需要考虑服务器的硬件基础设施,而是依赖于第三提供的后端服务(Baas)和应用逻辑运行容器(FaaS),但是并不是意味着没有服务器,而是服务器以特定功能的第三方服务的形式存在。

Serverless 带来的好处:

  • 降低了硬件基础设施的部署和维护成本
  • 方便应用服务的扩展和监控,因为依赖的第三方运行平台基本都支持动态扩展和服务监控。
  • 降低了由于应用服务访问流量变化而带来的硬件资源的浪费。
  • 方便开发者专注应用的开发,更快速的发布应用,而不需要关注基础架构的问题

Fission 是怎样在 Kubernetes 上实现的

简单的来讲,Fission 是一个构建在 Kubernetes 之上的 FaaS/Serverless 函数框架
最核心的,一个 FaaS 框架必须做好:

  • 将函数转化为服务
  • 管理这些服务的生命周期

有很多种方法可以达到以上目标,每种方法都需要权衡。框架计算是基于源码级别,还是Docker镜像级别,又或者是两者之间(类似buildpacks)?一个函数首次运行时间上限是多少?这些选择都会影响平台的灵活性、易用性、资源的利用率和消耗,当然还有性能。

打包,源码和镜像

Fission为了对新手友好。选择基于源码级别来计算,所以用户能避免处理容器镜像打包、推送镜像到镜像中心、管理镜像中心证书、镜像版本等问题。

然而,容器镜像还是最灵活的打包应用的方式,比如,一个纯粹的代码级别接口是不允许用户打包二进制依赖的。

所以,Fission选择了一种混合的方法—-容器镜像包含函数所需的动态装载器。这种方法允许大多数用户纯粹从源码级别来使用Fission,但需要时也允许他们自定义容器镜像。

在Fission中,这些镜像被称作“环境镜像”,包含了编程语言(比如说 NodeJS 或者 Python) 所需的运行环境,一系列通用的依赖和为函数准备动态加载器。如果这些依赖满足用户所写的函数,镜像无需重新构建,否则,依赖列表需要修改,镜像需要重新构建。

这些环境镜像只是和 Fission 的特定语言相关,它们给框架提供了一个统一的接口。这样的设计可以让 Fission 相对容易地扩展到其他语言。

冷启动性能

Serverless 函数其中一个目标就是函数只在运行时使用 CPU/内存资源。这样优化了函数的资源消耗,但也带来了从空闲到启动的性能损耗(冷启动损耗)。

冷启动损耗在很多场景下非常重要。特别是交互式应用的场景——就像用户等待一个web或移动应用响应——几秒的冷启动延迟是不能接收的。

为了优化冷启动延迟,Fission为每个环境保持着一个运行容器池。当一个函数请求进来之后, Fission 不需要部署一个新容器——它只需要选择一个已经在运行的容器,将函数拷贝到容器当中,将函数动态加载起来,并将请求路由到这个实例即可。对 NodeJS 和 Python 函数来说,这个过程的损耗差不多是 100 毫秒。

Fission 是怎样在 Kuberntes 上工作的

fission-workflow.png
Controller负责追踪函数、HTTP 路由、事件触发器和环境镜像。poolmgr负责管理空闲的环境容器池、将函数加载到这些容器当中、以及杀死空闲的函数实例。Router接收HTTP请求,并将他们路由到函数实例上,如果需要会向 poolmgr请求新的实例。

Controller提供Fission API,所有其他组件通过关注controller来更新。Router被暴露为Kubernetes的服务,可能是LoadBalancer类型或NodePort类型,依赖于Kubernetes集群在哪里托管。

当router获得请求,它会查找缓存,看是否有一个路由过去的服务。如果没有,它会查找匹配请求的函数,并且向poolmgr请求一个新的实例。poolmgr有一个空闲pods池,它会选择一个 pod,将函数加载进去(将请求发送到pod的容器中),并将pod地址返回给router。Router 将请求代理到这个pod。这个pod也会被缓存给随后的请求,如果空闲了好几分钟,那就会被杀掉。

Controller

Accept REST API requests and create Fission resources

Controller是客户端与之交谈的组件。它包含用于功能,触发器,环境,Kubernetes事件监视等的CRUD API,以及用于内部第三方服务的代理API。

所有fission资源都存储在kubernetes CRD中。它需要能够与kubernetes API服务对话。要访问所有命名空间中的CRD,Controller将使用具有群集范围的管理员权限的服务帐户。

controller.png

  1. 客户端将请求发送到Controller上的端点。
  2. (A)控制器根据请求操作CRD。
  3. (B)如果一个请求是对另一个内部服务的,则将该请求代理到该服务。

Executor

Executor是为功能扩展功能容器的组件。当路由器收到对功能的请求时,它将检查功能服务记录是否在其缓存中。如果高速缓存未命中,功能服务记录已找到或已过期,它将要求执行程序提供一个新的记录。执行程序然后从Kubernetes CRD检索功能信息,并调用执行程序类型之一来启动function pod。一旦function pod启动,将返回包含service/pod的地址的功能服务记录。

Fission现在支持两种不同的执行程序类型:

  • poolManager
  • NewDeploy
    这两种executor类型具有不同的策略来启动,专门化和管理Pod。

executor.png

基于PoolManager

poolmanager.png

  1. PoolManager监视环境变化。
  2. 监听到环境有创建/删除变化时,poolmanager也会进行创建/删除操作。
  3. 路由器询问功能的服务地址。
  4. Executor从CRD检索功能信息
  5. 调用PoolManager选择pod提供服务
  6. PoolManager从热池中选择一个通用容器。
  7. 将函数注入进入使其pod提供服务。
  8. 将pod的服务地址返回到路由器。在这种情况下,地址是容器的IP。
  9. 路由器将请求重定向到刚返回的地址。

基于NewDeploy

newdeploy.png

  1. 路由器询问功能的服务地址。
  2. 执行器从CRD检索功能信息
  3. 调用NewDeploy以启动相关服务pod。
  4. NewDeploy创建三个Kubernetes资源:Deployment,Service,HPA。
  5. 服务的地址返回到路由器。
  6. 路由器将请求重定向到刚返回的地址。
  7. 对Pod的服务负载平衡请求。

NewDeploy适用于旨在为大量流量提供服务的功能,并实现功能容器的自动扩展和负载平衡。

Function Pod

Place to load and execute the user function

Function Pod用于处理来自客户端的HTTP请求。它包含两个容器:Fetcher和环境容器。

function-pod.png

  1. Fetcher从CRD获取功能信息。
  2. 从StorageSvc中提取部署存档。
  3. 将存档保存到共享卷。
  4. 调用环境容器上执行相关函数操作。
  5. 环境容器从卷中加载用户功能。
  6. 开始处理来自路由器的请求。

Builder Manager

Compile the source code into a runnable function

builder manager会监视环境CRD和包的更改,并build源代码。创建包含映像的环境后,builder manager将在fission-builder名称空间下创建Kubernetes 的service和deployment,以启动environment builder。一旦创建了包含源归档的软件包,builder manager就会让environment builder对已经打包好的函数代码进一步build变为可部署的包。

构建之后,builder manager要求Builder在构建成功后将部署档案上传到存储服务,并更新构建日志附带的软件包状态

buildermanager.png

  • Builder Manager监视环境变化。
  • 创建/删除带有构建映像的新环境时创建/删除服务并进行部署。
  • Builder Manager监视软件包的更改。
  • 向构建器服务发送构建请求
  • Builder pod从Builder Manager接收构建请求
  • Builder从StorageSvc中提取源归档文件并开始构建过程。
  • Builder将部署归档文件上传到StorageSvc,以function pod使用。
  • Builder Manager使用构建日志更新软件包状态。

Build Pod

Place to load and execute the user function

Builder Pod主要负责将source archive转为deployment archive使pod正常运行通过相关功能服务,它包括两个容器:Fetcher and Builder Container.

builder-pod.png

  • Builder Manager要求Fetcher提取source archive.。
  • Fetcher从StorageSvc中拉出source archive.。
  • 将archive保存到共享卷。
  • Builder Manager将构建请求发送到Builder容器以开始构建过程。
  • Builder容器从卷中读取source archive,然后将其编译为deployment archive。
  • 最后,将结果保存回共享卷。
  • Builder Manager要求Fetcher上传deployment archive

StorageSvc

Home for source and deployment archives

存储服务是存储大于256KB的软件包。Builder从存储服务中拉去source archive,然后将deployment archives上传到其中。fetcher还是会拉取deployment archives相关function pod。

storagesvc.png

  • 客户端(CLI或HTTP请求)连接到Controller上的StorageSvc代理端点。
  • 控制器代理对StorageSvc的请求。
  • StorageSvc将上传的archiber存储到Kubernetes持久卷中。
  • 要将source archive构建成deployment archive,Fetcher将下载source archive并保存到共享卷。构建过程完成后,Fetcher会将deployment archive上传到StorageSvc。
  • Fetcher内部函数pod提取在(中创建的部署归档文件,以供environment container加载。

Fission的Trigger

fission支持三种触发方式:

  • HTTP Trigger
    • fission httptrigger create --url /hello --method GET --function hello
  • Message Queue Trigger
    • fission mqtrigger create --name hello --function node --topic foobar
  • Timer Triggers
    • fission timer create --name halfhourly --function hello --cron "0 */30 * * * *

      参考

      fission官网