Fission 介绍
7月 1, 2017 tech postFission 是一个 Serverless Framework,基于 Kubernetes ,使用 Golang 编写。目前处于 early alpha 阶段,所以实现还很简单。
fission 目前主要有这样几个概念:
- Function:开发写的代码
- Environment: function 的运行环境,一个 docker image ,目前只支持运行单个文件的 function ( issue#103)
- Pool:它就是 fission 的资源池,实质就是在 kubernetes 之上运行的一批容器,管理它的组件叫做 Pool Manager
- Service:当 pool 中的容器被激活,它就变成了一个可对外提供服务的 service
- Router:将用户的请求转发到 pool 中对应的 service 上
- Controller:对外暴露 API ,存储 function 的代码以及存储其他数据到 Etcd 上。
看看官网的使用示例:
# 准备好运行环境:添加 env
$ fission env create --name nodejs --image fission/node-env
# 上传代码:添加function
$ fission function create --name hello --env nodejs --code hello.js
# 添加路由
$ fission route create --method GET --url /hello --function hello
其中的 hello.js 内容如下:
module.exports = async function(context) {
return {
status: 200,
body: "Hello, world!\n"
};
}
然后我们调用它:
# 调用
$ curl http://$FISSION_ROUTER/hello
Hello, world!
在上述示例中,fission 的执行的流程如下:
1.新建资源池
新建 nodjs 的 env 后,pool manager 会在 kubernetes 中创建与之对应的 Deployment 来做为它的资源池,默认有 3 个 pod 副本,每个 pod 包含两个 container :fetcher container 和 service container。
fetcher 的镜像固定是 fission/fetcher,它的作用是从 controller 获取 function 对应的代码。service container 的镜像即我们在 env 中规定的 fission/node-env,它负责加载 function 并对外提供服务。
这两个容器之间有一个共享的 volume 用来传递代码。
2.存储 Function
Controller 将上传的 hello.js 存储起来(这里是本地)。
3.添加路由
Controller 得到的路由信息提供给 pool manager 和 router 使用。
4.处理请求
Router 会从 controller 和 pool manager 获取 functions 和 triggers 的信息,并会在本地缓存 url 到 function,function 到 service 的映射,在接到用户的请求后,会先判断有无已被缓存的 service:
- 如果没有,会把情况告知 pool manager,同时将用户的请求阻塞住。
- 如果有,则会直接将请求转发到对应的 service。
说说没有的情况,pool manager 在收到 router 的请求后,会从 pool 中选择一个 pod A 并激活它,同时新建一个 pod 来补充 pool 。激活的过程如下:
- pool manager 请求 pod A 中 fetcher 容器的接口, fetcher 容器从 controller 拉取 hello.js 的代码并将其放到与 service 容器的共享 volume 中。
- pool manager 请求 pod A 中 service 容器的接口, service 容器把共享 volume 中的 hello.js 加载到服务中。
激活之后,pod A 就可以对外提供服务了(一个 Service),这时 router 将用户的请求转发到 pod A 的 service 容器上。在用户请求处理完毕后,pod A 会被缓存下来,等到持续几分钟内没有新的请求,pool manager 就会把 pod A 销毁。
到这里,一个请求就算完成了。
开发
Fission 本身也是部署在 Kubernetes 中的,Controller,Router,Pool Manager 这几个组件被打包到 fission-bundle , fission-bundle 又被打包到了 docker 镜像中。所以每次修改代码都得重新打包 fission-bundle 的镜像,然后推送到私有的 Docker 仓库中,非常繁琐。如果是使用 minikube 的 kubernetes ,倒是可以通过
$ minikube docker-env
来避免推送镜像,但还是很繁琐。我想尝试将代码挂载到容器中,然后使用类似 bee、nodemon 这样的工具来自动编译并重启服务。