OpenFaaS接口

翻译自: https://blog.alexellis.io/the-power-of-interfaces-openfaas/ 2019年5月28日
首发于:http://hiknowledge.top/2019/12/27/openfaas%e6%8e%a5%e5%8f%a3/

在这篇文章中,我将探索如何将接口的思想引入OpenFaaS,以使项目适应不断变化的容器环境。您将了解如何通过提供程序模型和faas-provider SDK扩展OpenFaaS。然后,我将向您介绍为什么我们要构建faas-cli generate命令,它的作用,以及如何使用它来为Kubernetes生成CRD。

OpenFaaS架构介绍

一开始有OpenFaaS, OpenFaaS只在Docker Swarm上运行。

四个月后,一个名为Kubernetes的容器编配平台的需求也出现了,该平台的吸引力和业界的接受度都在增长。回顾历史,很难想象 Kubernetes 并不总是容器战争的赢家。

当时,OpenFaaS网关和API接口的集群实现是紧密耦合的。

Provider模型

因此,我将OpenFaaS网关现有的REST API分为三个组件——网关、提供者接口和faas-swarm。 其思想是,提供者可以接入任何容器编制器,并了解如何在不更改接口或工具的情况下执行CRUD、伸缩和调用

这意味着网关组件不需要像Kubernetes的client-go包那样有大量的依赖关系而膨胀起来,这意味着我们可以更紧密地遵循单一责任原则(SRP)。

从现在开始,OpenFaaS网关只作为配置选项(如验证、跟踪和度量)的中间件

faas-provider

今天,有一个Golang SDK允许任何人引导OpenFaaS提供者——你只需填写“http.Handler”函数即可,简化了整个体验。

OpenDNS的Alex Boten领导的团队在不到24小时内创建了他们自己的OpenFaaS provider

faas-memory

这是一个 in-memory provider实现的例子。

import (
	bootstrap "github.com/openfaas/faas-provider"
	bootTypes "github.com/openfaas/faas-provider/types"
)

func main() {

	bootstrapHandlers := bootTypes.FaaSHandlers{
		FunctionProxy:  handlers.MakeProxy(),
		DeleteHandler:  handlers.MakeDeleteHandler(),
		DeployHandler:  handlers.MakeDeployHandler(),
		FunctionReader: handlers.MakeFunctionReader(),
		ReplicaReader:  handlers.MakeReplicaReader(),
		ReplicaUpdater: handlers.MakeReplicaUpdater(),
		UpdateHandler:  handlers.MakeUpdateHandler(),
		HealthHandler:  handlers.MakeHealthHandler(),
		InfoHandler:    handlers.MakeInfoHandler(version.BuildVersion(), version.GitCommitSHA),
	}

	readConfig := types.ReadConfig{}
	osEnv := types.OsEnv{}
	cfg := readConfig.Read(osEnv)

	bootstrapConfig := bootTypes.FaaSConfig{
		ReadTimeout:     cfg.ReadTimeout,
		WriteTimeout:    cfg.WriteTimeout,
		TCPPort:         &cfg.Port,
		EnableHealth:    true,
		EnableBasicAuth: false,
	}

	log.Infof("listening on port %d ...", cfg.Port)
	bootstrap.Serve(&bootstrapHandlers, &bootstrapConfig)
}

您可以看到,我们在 bootTypes.FaaSHandlers 中有效地设置了各Handler结构,然后运行 bootstrap.Serve 用于启动provider。

通过遵循provider模型,任何容器编配器或其他系统(如内存存储)都可以作为接入对象,整个OpenFaaS生态系统仍然可用且兼容。

保持兼容

为了保持提供者的兼容性,我们引入了在构建时为Swarm和Kubernetes提供者运行的certifier项目,以确保它们支持API接口。

当Hashicorp的Nic Jackson启动faas-nomad提供程序时,他使用这个工具进行了一种测试驱动的开发。

规则的一个例外:Operator和CRD

2017年,我和Stefan Prodan在KubeCon讨论了将我们的faas-netes改造成一使用自己的Function CRD的Operator。

在Stefan使用来自faas-netes控制器的代码将一个工作操作符组合在一起后不久,它就工作了,这意味着用户可以进行选择。他们可以使用REST API或CRD,实际上他们可以两者都使用。REST API创建了CRD条目。

我们已经有了一个OpenFaaS provider的生态系统和用于不同的容器编制器的 后端,如:Docker Swarm、Kubernetes、AWS Fargate和Hashicorp Nomad。这意味着我们现在有两种正交的方式来在OpenFaaS中部署函数。

所有现有的提供程序都使用stack.yml文件和REST API,但是OpenFaaS Operator现在有了一个CRD。

进入faas-cli generate

我提出了以下建议:特性:通过CLI生成Kubernetes CRD YAML文件

假设我们有一个名为webhook-responder的函数,它接收HTTP消息,然后在Slack中向传入的webhook URL发送消息。

它看起来是下面这样的,由于我们的faas-provider接口,我们可以将它部署到任何兼容的OpenFaaS Provider。

#stack.yml
provider:
  name: openfaas
  gateway: http://127.0.0.1:8080

functions:
  webhook-responder:
    lang: go
    handler: ./webhook-responder
    image: alexellisuk/webhook-responder:latest
    environment:
      write_debug: true
    secrets:
     - webhook-token
     - slack-incoming-url

我们可以使用faas-cli deployfaas-cli up来部署这个函数。

对于Kubernetes的操作人员和开发人员来说,使用REST API提供了一些价值,但是在本质上,我们更喜欢我们最喜欢的工具kubectlkubectl工具允许本地Kubernetes策略和与RBAC和其他工具的深度集成。

我提出的解决方案是创建一个生成命令,它将用一个stack.yml文件作为输入,然后生成一个CRD。下面是它实际的样子:

$ faas-cli generate
# or
$ faas-cli generate --api=openfaas.com/v1alpha2

注意:您可以运行faas-cli generate --help来获得更多的选项。

#webhook-responder.yaml
---
apiVersion: openfaas.com/v1alpha2
kind: Function
metadata:
  name: webhook-responder
  namespace: openfaas-fn
spec:
  name: webhook-responder
  image: alexellisuk/webhook-responder:latest
  environment:
    write_debug: "true"
  secrets:
  - webhook-token
  - slack-incoming-url

这个函数可以用: kubectl apply -f webhook-responder.yaml 来部署。

如果您想了解faas-cli如何生成,那么请查看这里的命令文件:generate.go。最初的版本是由社区的Vivek Syngh编写的。

为Knative扩展faas-cli generate

在2018年夏天,谷歌宣布了一个新的无服务器项目,名为Knative。我立即着手评估这个已经饱和的市场的新进入者,发现用OpenFaaS构建的任何功能都可以部署,而不需要 到他们的平台上修改。

Portability with Knative (gist)

OpenFaaS函数商店允许社区和最终用户共享、发现和协作函数。

在我的Gist,我展示了来自函数存储的函数可以部署到Knative。这启发了Michael Hausenblas, RedHat的开发者倡导者,在他的第一篇Knative博客文章中展示了着色功能 colorise

就在今年KubeCon Barcelona的无服务器从业者峰会(SPS)之前,我开始更新faas-cli以生成Knative服务定义。

Pull request: Add knative serving v1alpha1 to generate CRD command.

$ faas-cli generate --api=serving.knative.dev/v1alpha1

---
apiVersion: serving.knative.dev/v1alpha1
kind: Service
metadata:
  name: webhook-responder
  namespace: openfaas-fn
spec:
  runLatest:
    configuration:
      revisionTemplate:
        spec:
          container:
            image: alexellisuk/webhook-responder:latest
            env:
            - name: write_debug
              value: "true"
            volumeMounts:
            - name: webhook-token
              mountPath: /var/openfaas/secrets/webhook-token
              readOnly: true
            - name: slack-incoming-url
              mountPath: /var/openfaas/secrets/slack-incoming-url
              readOnly: true
          volumes:
          - name: webhook-token
            secret:
              secretName: webhook-token
          - name: slack-incoming-url
            secret:
              secretName: slack-incoming-url

您甚至可以将这个命令传递到kubectl apply,甚至在stack.yml中也可以使用它包含多个函数。

faas-cli generate --api=serving.knative.dev/v1alpha1 | kubectl apply -f -

你可以这样搜索商店:

$ faas-cli store list --verbose
FUNCTION                    DESCRIPTION
Colorization                Turn black and white photos to color ...
Inception                   This is a forked version of the work ...
Have I Been Pwned           The Have I Been Pwned function lets y...
SSL/TLS cert info           Returns SSL/TLS certificate informati...
Face blur by Endre Simo     Blur out faces detected in JPEGs. Inv...
Figlet                      OpenFaaS Figlet image. This repositor...
...

然后将一个函数从商店部署到Knative,例如figlet(生成ASCII标志):

$ faas-cli generate --api=serving.knative.dev/v1alpha1 --from-store="figlet"

包装

OpenFaaS提供者模型及其REST API意味着该项目可以针对各种容器编制器,甚至是AWS Lambda这样的专有SaaS产品,而无需对接口进行任何额外的更改。

faas-cli生成命令还为我们提供了一种方法,可以在不抛弃原始设计的情况下深入集成Kubernetes当前和未来的生态系统。

您可能想知道OpenFaaS REST API和Kubernetes或Knative上OpenFaaS的CRD是否互相正交?这可能是事实,但是OpenFaaS Operator表明我们可以两全其美。

本设计之所以成功,是因为OpenFaaS的目标是Docker或OCI镜像格式和端口8080上的简单HTTP接口。我称之为“Serverless 2.0运行时契约”或“一个Serverless工作负载”。

Serverless 2.0 Landscape

在Serverless 2.0世界中,您可以在任何列出的模板系统中构建函数,然后在选择的任何服务平台和列出的可安装或托管的基础设施产品上运行它们。

我的 其他相关工作:

未来的工作

OpenFaaS的使命是:简化无服务器函数。因此,在我看来,未来的工作是扩展OpenFaaS提供商和CRD生态系统,以便将开发人员的体验带到所有平台。

在2019年,我们的社区将对Kubernetes生态系统的目标进行双重调整:性能、安全性和企业特性。我们也超越了Kubernetes和faas-lambda。Edward Wilde在SPS活动中谈到了他如何创建一个直接部署到AWS Lambda的faas-provider,而不需要对为OpenFaaS构建的图像进行额外的修改。订阅博客获取更多信息。

在我看来,这是社区未来的一些工作:

  • 一个以Knative Serving CRD为接入目标的OpenFaaS provider,它将被(想象地)称为faas-knative,并将OpenFaaS REST API、CLI、函数存储和UI带给Knative用户,以及在无服务器环境下的最佳开发体验之一。
  • Rancher的首席架构师Darren Shepherd表示有兴趣构建一个OpenFaaS Provider,为名为Rio的新Rancher microPaaS平台带来开发者体验。
  • 一个 faas-cli generate --api=services.rio.cattle.io 命令为Rio生成自己的Service定义,以支持实验和快速反馈。看issue

Get involved

我们拥有强大的核心团队和200多名贡献者,现在是参与项目的最佳时机。欢迎贡献和反馈,以及任何其他问题或意见。

不知道如何贡献?加入Slack,然后跟上我们最新的社区视频简报:如何贡献,2019年

Follow @alexellisuk and @openfaas on Twitter.

发布者

jahentao

挖掘概念,创造工具