在Kubernetes集群上的OpenFaaS机制

首先

我们来看看在Kubernetes上运行OpenFaaS时,如何创建和执行函数。

在Kubernetes集群上使用OpenFaaS(faas-netes)的组件列表

    • API gateway

FaaS REST API + GUI
K8Sの場合は、faas-netesdへのProxyもしくは、Docker Swarmの場合は、同サーバ上で処理します

faas-netesd

FaaS本体
OpenFaaSに外部プラグインが追加され、K8SのAPIと連携します
functionのCRUD操作や実行をします

Prometheus
AlertManager
nats-queue-worker

FaaSを非同期実行時させる場合に利用します
使わない場合はすべて同期実行となります
本記事では扱いません

Function的管理方式

管理Function的方法

OpenFaaS没有专用的存储,其特点是由K8S的组件管理。

Function被表示为deployment和service。

如果您部署Function而没有特别指定命名空间,它将在默认的命名空间中部署。
可以确认已部署的Function在K8S的Deployment和Service中进行管理。

$ kubectl get deployment
NAME            DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
alertmanager    1         1         1            1           1h
faas-netesd     1         1         1            1           1h
gateway         1         1         1            1           1h
hello-python3   1         1         1            1           43m
nodejs-echo     1         1         1            1           1h
prometheus      1         1         1            1           1h
ruby-echo       1         1         1            1           1h
shrink-image    1         1         1            1           1h
url-ping        1         1         1            1           1h

$ kubectl get po
NAME                             READY     STATUS    RESTARTS   AGE
alertmanager-77b4b476b-qdbl5     1/1       Running   1          1h
faas-netesd-64fb9b4dfb-mqss5     1/1       Running   1          1h
gateway-5cb4f64656-pltpb         1/1       Running   1          1h
hello-python3-5997c5598f-jzh5n   1/1       Running   1          43m
nodejs-echo-5c9699c8b5-4zkht     1/1       Running   1          1h
prometheus-7fbfd8bfb8-kv98c      1/1       Running   1          1h
ruby-echo-8d95f97fb-4wkm7        1/1       Running   1          1h
shrink-image-5dd9c4cc7c-qhmq2    1/1       Running   1          1h
url-ping-5965bc9f4f-2gltw        1/1       Running   1          1h

$ kubectl get svc
NAME            CLUSTER-IP   EXTERNAL-IP   PORT(S)          AGE
alertmanager    10.0.0.79    <nodes>       9093:31113/TCP   6d
faas-netesd     10.0.0.115   <nodes>       8080:31111/TCP   6d
gateway         10.0.0.75    <nodes>       8080:31112/TCP   6d
hello-python3   10.0.0.66    <none>        8080/TCP         44m
kubernetes      10.0.0.1     <none>        443/TCP          6d
nodejs-echo     10.0.0.102   <none>        8080/TCP         1h
prometheus      10.0.0.127   <nodes>       9090:31119/TCP   6d
ruby-echo       10.0.0.64    <none>        8080/TCP         1h
shrink-image    10.0.0.119   <none>        8080/TCP         1h
url-ping        10.0.0.178   <none>        8080/TCP         1h

查看服务时,可以看到每个功能都在8080端口上接收请求。
我们来看一下一个功能的服务。

$ kubectl get svc url-ping -o yaml | grep -a2 selector
    protocol: TCP
    targetPort: 8080
  selector:
    faas_function: url-ping
  sessionAffinity: None

我们可以看到该标签指定了 faas_function: url-ping 的 Pod。
现在,让我们来查看 faas 的 CLI 构建的 Dockerfile。

FROM python:3-alpine

# Alternatively use ADD https:// (which will not be cached by Docker builder)
RUN apk --no-cache add curl \
    && echo "Pulling watchdog binary from Github." \
    && curl -sSL https://github.com/openfaas/faas/releases/download/0.6.9/fwatchdog > /usr/bin/fwatchdog \
    && chmod +x /usr/bin/fwatchdog \
    && apk del curl --no-cache
    …

这个fwatchdog似乎在8080端口接收请求,并启动各种语言的进程。
fwatchdog是一个HTTP服务器,它将标准输入传递给子进程,并接收子进程的标准输出。

68747470733a2f2f63616d6f2e67697468756275736572636f6e74656e742e636f6d2f363163313639616235636430313334366263336463376131316564633164323138663062653362342f363837343734373037333361326632663730363237333265373437373639366436373265363336663664326.jpeg

只需要启动子进程,所以如果进行定制,似乎可以支持语言运行时和Docker内的Docker。

你是如何部署Function(Deployment)的?

在FaaS-netes的部署处理程序中,我们可以看到它访问了K8S API并创建了部署和服务。

部署 := clientset.Extensions().Deployments(functionNamespace)

_, err = deploy.Create(deploymentSpec)
如果 err != nil {
log.Println(err)
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(err.Error()))
return
}

log.Println(“已创建部署 – ” + request.Service)

service := clientset.Core().Services(functionNamespace)
serviceSpec := makeServiceSpec(request)
_, err = service.Create(serviceSpec)

https://github.com/openfaas/faas-netes/blob/0.3.7/handlers/deploy.go#L83

在更新时,我们使用更新处理程序同样访问K8S API,并更新部署。

如果 _, updateErr := clientset.ExtensionsV1beta1().Deployments(functionNamespace).Update(deployment); updateErr != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(updateErr.Error()))
}

因为通过service和deployment进行管理,所以无论容器映像是什么,只需设置标签并将其部署到K8S即可,在GUI界面上将直接反映出来。

我们是如何管理Function的尝试次数的?

根据我们目前了解,OpenFaaS本身不会保存持久存储。然而,即使删除了API Gateway、每个函数以及faas-netes中的Pod,在重新生成时,函数的执行次数等信息仍然保留。这是因为这些信息被保存在Prometheus度量指标中,即使删除了Pod,仍然可以通过引用这些度量指标来保留数据。具体可参考:https://github.com/openfaas/faas/blob/v0.5/gateway/server.go#L38

如何扩大/放大Function功能规模?

当特定功能的API Gateway通过请求数量超过一定数时,函数将进行扩容(增加Pod)。
此时,API Gateway会收集与该功能相关的请求度量,Prometheus会收集这些度量,并通过AlertManager与FaaS进行通信。
这是因为AlertManager可以在Docker Swarm或K8S上运行,可用作组件之间的触发器。
https://github.com/openfaas/faas/blob/v0.5/gateway/handlers/alerthandler.go#L16

处理的流程如下所示。

scaleout.png

最后

在这次介绍中,还存在一些未提及但令人感兴趣的实施方案。

    • Function間を連携させるFunctionチェーンや、wrapper functionを作り、Functionの結果をまとめてからfunctionを実行する方法などもありました。1

Functionを実行する際の非同期処理が、NATS2で実現が可能です。

在未来的Roadmap 3中,特权容器等功能将包括Docker Build和API Gateway的Kafka支持、除NatsQ外的其他Kafka支持。

目前,由于功能太过自由,存在着诸多安全和资源方面的问题,如Authn/Authz、函数间通信、对Kubernetes上其他Pod的影响、资源管理等。但就个人使用而言,这是一个非常有趣的机制。

在Z Lab中,我們主要進行與Kubernetes和CNCF相關的技術調查和開發工作。請繼續享受Z Lab Advent Calendar 2017。

以下是一个选项的汉语本土化释义:
1. 链接函数的指南:https://github.com/openfaas/faas/blob/b32a3f30ea936215ba10628fb202f7dcb2415e96/guide/chaining_functions.md
2. 异步处理指南:https://github.com/openfaas/faas/blob/master/guide/asynchronous.md
3. 路线图:https://github.com/openfaas/faas/blob/master/ROADMAP.md
广告
将在 10 秒后关闭
bannerAds