将应用程序分解为由AWS Lambda、谷歌函数和Azure函数推广的小工作单元的概念是现代软件体系架构中最流行的趋势之一。Serverless的主要好处是,您不必管理底层应用程序基础架构,开发人员可以集中精力在交付业务价值方面。
虽然Serverless的开发人员工作流可能非常有吸引力,但是有一些原因说明这种方法可能不适合您的组织:
- 您有不允许在共享环境中运行的监管或公司限制。
- 您已经为现有的微服务提供了一个调度器集群和CI/CD工作流。
- Serverless仍然需要提供和部署函数、数据存储和消息队列等连接器的操作开销。
- 您希望对操作系统和运行时平台有更多的控制。
OpenFaaS(或FaaS)是一个框架,用于构建没有服务器的函数,但是使用了容器。有了OpenFaaS,您可以将任何进程或容器作为Linux或Windows的无服务器函数进行打包—只需使用Nomad集群即可。这个项目通过它的UI和CLI来关注易用性,这两个UI和CLI可以用于测试和监视函数,同Prometheus配合提供了自动缩放功能。
架构
OpenFaaS围绕Docker进行构建;所有功能都打包到Docker镜像中,这是微服务常用的工作流。由gateway、provider和monitoring element这三个核心组件组成。
Gateway是允许管理和执行函数的外部API。它不直接与Nomad交互,而是将此责任委托给一个管理函数生命周期的Provider:部署、扩展和认证管理。Gateway和Provider都发出调用计数和计时数据等指标(metrics),这些数据是使用Prometheus收集的。
Prometheus还能够根据存储的指标来广播警报。该功能允许Gateway侦听警报并对其作出反应。一个典型的例子是根据负载或其他因素自动触发函数缩放。
让我们看看在Nomad上使用OpenFaaS创建和部署函数是多么容易。
在Nomad上运行OpenFaaS
要在Nomad集群上运行OpenFaaS,可以使用Nomad提供者Github存储库中的示例作业文件: https://raw.githubusercontent.com/hashicorp/faas-nomad/master/nomad_job_files/faas.hcl
$ wget https://raw.githubusercontent.com/hashicorp/faas-nomad/master/nomad_job_files/faas.hcl faas.hcl
$ nomad run faas.hcl
或者为什么不从这篇文章开始启动交互式终端呢,交互式终端已经预先安装了Nomad、Consul和OpenFaaS。
启动交互式演示
创建一个新函数
要创建一个新函数,我们可以利用OpenFaaS CLI faas-cli,这对于大多数平台(如Windows、Linux和MacOS)都是可用的。它还支持许多编程语言,如Node、Python和Go。
Languages available as templates:
- csharp
- go
- go-armhf
- node
- node-arm64
- node-armhf
- python
- python-armhf
- python3
- ruby
除了官方模板之外,您还可以使用社区提交的模板。我们将使用绑定的Go模板并创建一个名为bcrypt的函数。
$ faas-cli new -lang go bcrypt
Folder: bcrypt created.
___ _____ ____
/ _ \ _ __ ___ _ __ | ___|_ _ __ _/ ___|
| | | | '_ \ / _ \ '_ \| |_ / _` |/ _` \___ \
| |_| | |_) | __/ | | | _| (_| | (_| |___) |
\___/| .__/ \___|_| |_|_| \__,_|\__,_|____/
|_|
Function created in folder: bcrypt
Stack file written: bcrypt.yml
新命令为bcrypt/handler.go函数和当前文件夹里的函数定义文件 bcrypt.yml创建了入口点。
$ tree -L 2
.
├── bcrypt
│ └── handler.go
├── bcrypt.yml
└── template
├── csharp
├── go
├── go-armhf
├── node
├── node-arm64
├── node-armhf
├── python
├── python-armhf
├── python3
└── ruby
看看handler.go中包含了我们的示例函数代码,我们可以看到它只包含一个带有简单接口的函数。参数以字节码的形式传给函数,输出是一个简单的字符串。
package function
import (
"fmt"
)
// Handle a serverless request
func Handle(req []byte) string {
return fmt.Sprintf("Hello, Go. You said: %s", string(req))
}
让我们将这个函数替换为允许使用bcrypt对字符串进行哈希的东西。编辑文件bcrypt/handler.go并用以下函数替换内容:
$ vim bcrypt/handler.go
package function
import (
"golang.org/x/crypto/bcrypt"
)
// Handle a serverless request
func Handle(req []byte) string {
hash, err := bcrypt.GenerateFromPassword(req, bcrypt.DefaultCost)
if err != nil {
return ""
}
return string(hash)
}
一旦你保存了你的文件,让我们运行gofmt命令来检查有没有语法错误:
gofmt -s -w bcrypt/handler.go
我们使用的是位于golang实验包的bcrypt库,因此我们需要向vendor提供依赖项,我们可以使用dep这个go的依赖管理工具来做到这一点。
$ cd bcrypt
$ dep init
Using master as constraint for direct dep golang.org/x/crypto
Locking in master (b3c9a1d) for direct dep golang.org/x/crypto
$ cd -
下一步是构建我们的函数,并将其部署到Nomad,在此之前,我们需要编辑bcrypt.yml文件,更改image字段来设置一个Docker仓库。
provider:
name: faas
gateway: https://my.gateway.com
functions:
bcrypt:
lang: go
handler: ./bcrypt
image: my.docker.registry.com/bcrypt
我们还更改了gateway字段并指向Nomad集群上运行的网关。
如果使用交互式终端,那么环境变量FAAS_GATEWAY和DOCKER_REGISTRY将包含要添加到bcrypt.yml文件中的正确值。
$ sed -i "s#^\(\s*image\s*:\s*\).*#\1${DOCKER_REGISTRY}/bcrypt#" bcrypt.yml
$ sed -i "s#^\(\s*gateway\s*:\s*\).*#\1${FAAS_GATEWAY}#" bcrypt.yml
现在我们来构建我们的函数:
$ faas-cli build --yaml bcrypt.yml
[0] > Building: bcrypt.
Clearing temporary build folder: ./build/bcrypt/
#...
Removing intermediate container a5e0be2bfdc9
Successfully built 74cbd7f5e103
Successfully tagged bcrypt:latest
Image: bcrypt built.
[0] < Builder done.
构建过程在Docker容器中执行,而不是Docker,并且faas-cli中不需要任何其他依赖项。在部署函数前需要将函数推到Docker仓库,我们可以使用faas-cli push命令来完成此任务。
$ faas-cli push --yaml bcrypt.yml
[0] > Pushing: bcrypt.
The push refers to a repository [2886795314-5000-ollie01.environments.katacoda.com/bcrypt]
974e4f38d961: Layer already exists
8af4da1e470e: Layer already exists
f6a874b4e2c7: Layer already exists
ec8a829eb761: Layer already exists
60273f4e6fd4: Pushed
2aebd096e0e2: Layer already exists
latest: digest: sha256:b253f51abbcc53b69c84eed015cc244871de6049e4410200230c2612408a4075 size: 1574
[0] < Pushing done.
现在将该函数部署到Nomad集群上的OpenFaaS。
$ faas-cli deploy --yaml bcrypt.yml
Deploying: bcrypt.
Removing old function.
Deployed.
URL: https://2886795314-8080-ollie01.environments.katacoda.com/function/bcrypt
200 OK
当我们部署一个函数时,OpenFaaS网关将委托给在集群上创建作业的Nomad provider。您可以使用nomad status命令检查函数是否正在运行。
$ nomad status
ID Type Priority Status Submit Date
OpenFaaS-bcrypt service 1 running 01/10/18 17:37:16 UTC
faas-nomadd system 50 running 01/10/18 17:14:08 UTC
为了测试我们的函数,我们可以使用faas-cli,或者使用它的HTTP接口调用函数。首先,让我们使用faas-cli命令:
$ echo "password" | faas-cli invoke --yaml bcrypt.yml bcrypt
$2a$10$zFYttFRKZorR3zHsoquQ5.qypL0/4vTbzjzM2bWdzOBtMq8XhXSZG
我们还可以使用curl或使用网关URL的其他HTTP客户端调用它:
$ curl -d 'Nic' $FAAS_GATEWAY/function/bcrypt
$2a$10$FddcGwse0z0PlX6o3tr.SuGgUK9poanZLvqdGHAjz.L9Jp.J5qGI6
这就是创建和部署最基本的函数所需的全部内容,以查看更全面的示例,包括如何使用测试驱动的方法创建函数,为什么不查看我的发送tweet的示例:https://github.com/nicholasjackson/openfaas -functions/tree/master/tweet
总结
我们希望你喜欢这篇文章,我们期待听到你用Nomad和OpenFaaS创建的奇妙的东西。
如果您想深入了解,请查看OpenFaaS文档:https://github.com/openfaas/faas/blob/master/guide/README.md
有关Nomad提供程序的更多信息,包括如何使用Prometheus配置监控,请参阅我们的GitHub repo文档:https://github.com/hashicorp/faas-nomad
最后,如果你想从OpenFaaS中获得一些灵感,请关注OpenFaaS的创始人Alex Ellis的博客:https://blog.alexellis.io