亚马逊AWS官方博客

使用 TriggerMesh KLR 在 Amazon EKS 中部署与 AWS Lambda 兼容的函数

自定义 AWS Lambda 运行时已在 re:Invent 2018 大会上推出。Knative 是一个旨在构建、部署和管理无服务器工作负载的开源项目。Sebastien Goasguen 的这篇博文解释道,TriggerMesh 的 Knative Lambda Runtime 是一种自定义运行时环境,可在 Amazon EKS 集群上运行的 Knative 上运行 Lambda 函数。

Arun


knative + TriggerMesh + EKS 徽标。

AWS Lambda 已成为全球领先的无服务器产品。AWS Lambda 能够轻松连接各种 AWS 服务,这为真正的原生云应用程序打开了大门,并让用户能够更快地进行创新。与此同时,Kubernetes 已成为容器编排领域的领导者,并成为本地部署环境中原生云应用程序的领先推动者。Amazon Elastic Container Service for Kubernetes (EKS) 于去年正式推出。

无服务器和容器这两个领域似乎存在矛盾,无服务器消除了所有基础设施负担,并重点关注应用程序架构和服务,而 Kubernetes 仍然会给用户和运营商带来容器和基础设施方面的问题。

然而,这两个领域似乎注定会在几个方面汇合。Knative 就是一个例子,这个开源项目旨在使用 Kubernetes 构建可在任何地方运行、以源为中心、基于容器的应用程序。Knative 由三个部分组成:构建、服务和事件。构建会获取源代码,并尽可能透明地为用户生成容器。服务会获取这些容器,并提供缩放到 0 等功能。最后,事件会提供一种获取任意位置的云事件的方法,并能使用它们来触发函数,这与 AWS 事件源可用于触发 AWS Lambda 函数的方式非常相似。

随着 Knative 的发展,我们不得不考虑是否有可能在 Knative、EKS 集群甚至另一个 Kubernetes 集群(包括本地)中运行 AWS Lambda 函数。您可能希望通过这样的做法来统一 Kubernetes 下的工作负载管理,或者将所有工作负载(包括函数)纳入一个“屋檐”下,或者您可能只是认为 AWS Lambda 函数应成为各无服务器提供商的函数标准。

在本博文中,我们想向您展示这是如何实现的:您确实可以使用 TriggerMesh Knative Lambda Runtimes (KLR) 在 Knative 中运行 AWS Lambda 函数。

KLR 是称为构建模板的 Knative 对象,它使用 AWS Lambda 自定义运行时 API 的自定义实施。[Lambda 自定义运行时] (https://thinkwithwp.com/about-aws/whats-new/2018/11/aws-lambda-now-supports-custom-runtimes-and-layers/) 向开源社区开放了一个超棒的集成点。在 TriggerMesh 中,我们决定实施所谓的函数调用程序来公开 Lambda 自定义运行时 API。然后,我们使用它为 Go、Ruby、Node 和 Python 函数构建 Knative 模板。

这是一项令人激动万分的发展,我们迫不及待地想要与您分享。下文内容提供了分步演练,用以指导您创建 EKS 集群并运行 TriggerMesh KLR 函数。您将:

  • 使用 eksctl 创建 EKS 集群
  • 安装 Knative
  • 安装 TriggerMesh Knative CLI
  • 使用 TriggerMesh KLR 在 EKS 中部署函数

下图展示了我们将要实施的整体设置。

Triggermesh 示意图。

在本文的其余部分中,我们假设您已经配置好 AWS CLI(例如 aws)和 Kubernetes CLI(例如 kubectl)。如果您未进行配置,请访问以下链接:

创建 EKS 集群

您首先需要使用具有集群配置文件机制的 eksctl 来设置 Amazon EKS 集群。首先,必须下载以下工具:

在安装所有必备工具后,您可以启动 EKS 集群。在本例中,我们会将集群部署在 us-east-2(即我们的俄亥俄区域)中,您可将 AWS_REGION 替换为支持 Amazon EKS 的任何区域。

部署集群

export AWS_REGION=us-east-1
export ACCOUNT_ID=$(aws sts get-caller-identity –query “Account” –output text)
在导出区域后,按照如下所示创建 ClusterConfig:

cat >cluster.yaml <<EOF
apiVersion: eksctl.io/v1alpha4
kind: ClusterConfig
metadata:
name: knative
region: ${AWS_REGION}

nodeGroups:

name: knodes
desiredCapacity: 3
instanceType: m5.large
EOF

在创建该文件后,我们使用 eksctl create cluster 命令创建集群并存储凭证以便对其进行访问:

eksctl create cluster --kubeconfig eksknative.yaml -f cluster.yaml

完成此操作大约需要 15 分钟时间,之后,便可获得可供使用的 Amazon EKS 集群。
由于您使用 --kubeconfig 选项运行了 eksctl 命令,因此用于访问 Kubernetes 集群的凭证存储在运行命令时所在目录内的 eksknative.yaml 文件中。这样做的好处是使主要的 kubeconfig 文件保持整洁,但缺点在于,您现在需要在每条 kubectl 命令中指定这个文件。

为方便起见,您可以设置一个别名,用于在使用 kubectl 时指定配置文件:

alias knative='kubectl --kubeconfig=eksknative.yaml'

要验证能否正常访问集群,请发出以下命令(此命令应列出集群中的三个节点):

knative get nodes
NAME                             STATUS    ROLES     AGE       VERSION
ip-192-168-10-163.ec2.internal   Ready     <none>    1m        v1.11.5
ip-192-168-12-106.ec2.internal   Ready     <none>    1m        v1.11.5
ip-192-168-43-220.ec2.internal   Ready     <none>    1m        v1.11.5

在拥有正常工作的 EKS 集群之后,接下来就可以在其中安装 Knative 了。

在您的 EKS 集群中安装 Knative

只需运行几条 kubectl apply 命令即可完成 Knative 的安装。
默认的 Knative 安装将使用 Istio 服务网格。要了解有关服务网格,特别是 AWS 上的服务网格的更多信息,请参阅 App Mesh 服务。

安装 Istio

要安装 Istio,请使用以下两条命令(请注意使用使用我们的别名执行 kubectl --kubeconfig = eksknative.yaml,它使用的是正确的集群配置文件):

knative apply --filename https://github.com/knative/serving/releases/download/v0.4.0/istio-crds.yaml && \
knative apply --filename https://github.com/knative/serving/releases/download/v0.4.0/istio.yaml

安装 Knative Serving 和 Knative Build

完成后,您可以继续安装 Knative 组件:构建和服务。在本文中,我们将跳过事件组件的安装,因为这里没有用到该组件。

knative apply --filename https://github.com/knative/serving/releases/download/v0.4.0/serving.yaml \
--filename https://github.com/knative/build/releases/download/v0.4.0/build.yaml \
--filename https://github.com/knative/serving/releases/download/v0.4.0/monitoring.yaml \
--filename https://raw.githubusercontent.com/knative/serving/v0.4.0/third_party/config/build/clusterrole.yaml

如果以上安装失败,请再次应用清单。Kubernetes 的声明性方面将确保创建所有对象。

几分钟后,您应该能够在以前的命令创建的几个名称空间中列出 pod,它们分别是:

  • istio-system,用于 Istio 组件和将会接收 Internet 流量的 Ingress Gateway
  • knative-serving,用于服务控制器和自动扩展程序
  • knative-build,用于构建控制器
knative get pods -n knative-serving
NAME                          READY     STATUS    RESTARTS   AGE
activator-6f7d494f55-57r9k    2/2       Running   1          2m
autoscaler-5cb4d56d69-mj4lm   2/2       Running   1          2m
controller-6d65444c78-tlpmm   1/1       Running   0          2m
webhook-55f88654fb-ppczx      1/1       Running   0          2m
knative get pods -n knative-build
NAME                                READY     STATUS    RESTARTS   AGE
build-controller-68dfb74954-5d68l   1/1       Running   0          2m
build-webhook-866fd64885-95sq4      1/1       Running   0          2m

如果所有 pod 都处于正在运行状态,那么恭喜您! 您已在 EKS 集群上成功安装 Knative。
现在,我们来使用 Knative!

获取 Ingress Gateway 的公开 DNS 名称

在 Knative 集群中部署函数时,您需要知道如何访问它们。在安装 Knative 过程中,会在 istio-system 命名空间中创建所谓的 Ingress Gateway。此网关将配置 LoadBalancer 类型的服务并获取公开 DNS 名称。
我们来找到此公开 DNS 名称,以便您可以将其作为目标来调用您的函数。可以通过很多方法实现此目标,但如果您知道 jq,您可以轻松编写一条查询来获取此信息。
jq 是一个命令行 JSON 处理程序,可以非常方便地处理 Kubernetes 清单。在 OSX 上,您可以通过 brew install jq 获取 jq 或转到下载页面
DNS 名称位于 Ingress Gateway 清单的状态部分,您可以通过类似如下的查询来获取此信息:

$ knative get svc istio-ingressgateway -o json -n istio-system | jq -r .status.loadBalancer.ingress[0].hostname
af375ca60465511e9911e02b74097eec-2072757389.us-east-1.elb.amazonaws.com

安装 TriggerMesh CLI tm

Knative API 可以直接与 kubectl 配合使用,但为了简化使用,我们为 Knative 集群开发了 CLI。我们称之为 tm,即 TriggerMesh 的简写。

要创建函数并使用与 AWS 兼容的 Lambda 运行时,请先安装 tm。您可以访问 GitHub 发布页面并下载最新版本的 Linux 或 OSX 二进制文件,或者如果您使用的是 Go 环境,也可以通过以下代码获得:

go get github.com/triggermesh/tm

使用以下命令验证它是否在 $PATH 中:

which tm

kubectl 类似,您需要指定一个配置文件来定位您的 EKS 集群。为方便起见,您可以设置如下别名:

alias tmk='tm --config=eksknative.yaml'

使用以下命令验证您是否可以列出 Knative 服务及其内部版本:

tmk get services
NAMESPACE    SERVICE
tmk get builds
NAMESPACE    BUILD

如果上面的命令正确返回,则表示您的 TriggerMesh CLI 已正确配置,并能与运行 Knative 的 EKS 集群正确通信。现在,我们来用它部署一个函数。

使用 Knative Lambda Runtime (KLR) 部署函数

TriggerMesh KLR 徽标。
如简介中所述,TriggerMesh KLR 表示使用 AWS 自定义运行时 API 构建函数的 Knative 方法,这意味着您可以在 Knative 和 AWS Lambda 中部署相同的函数。

Python、Ruby、Node 和 Go 均已实施。为了向您展示如何使用 Knative 创建与 AWS Lambda 兼容的函数,我们将使用 TriggerMesh CLI 部署一个简单的 Python 终端节点 Knative。可以将相同的 Python 函数部署到 AWS Lambda。

安装 KLR 模板

首先,您需要创建一个 Knative 构建模板。构建模板是一个 Knative API 对象,它用于定义如何在 Kubernetes 集群中构建容器。该模板还包含将生成的容器映像推送到容器注册表(例如 ECR、Docker Hub)的信息。函数需要封装在 AWS 自定义运行时调用程序和引导脚本中(与官方文档所述极为相似),然后存储为容器映像。
现在,用 tm 在您的 EKS 集群上创建 Python KLR 模板 – 对于此操作,您只需执行一次:

tmk deploy buildtemplate -f https://raw.githubusercontent.com/triggermesh/knative-lambda-runtime/master/python-3.7/buildtemplate.yaml

您可以加载由文件引用的本地模板,或者如上所示使用远程 URL。以上命令指向直接存储在 KLR GitHub 存储库中的 Python 构建模板的 URL。

创建模板后,您可以列出该模板,还可以删除此模板(使用 tm delete)来清理内容:

tmk get buildtemplates
NAMESPACE    NAME                        READY
default      knative-python37-runtime    True

设置容器注册表凭证

如上所述,构建模板用于将我们的函数打包为容器映像。该映像需要存储在容器注册表中。在这里,我们将使用 Docker Hub。要告知 Knative 在何处存储映像,可以通过 tm 使用 tm set registry-auth 命令设置 Docker Hub 凭证:

tmk set registry-auth dockerhub
Registry: index.docker.io
Username: runseb
Password: **********
Registry credentials set

此命令也只需执行一次。为容器注册表设置好身份验证凭证后,TriggerMesh 即可知晓如何进行推送。

使用 KLR 模板将函数部署为 Knative 服务

现在,要部署简单的 Python HTTP 终端节点函数,我们可以告诉 tm 创建一项服务。Knative 服务与核心 Kubernetes 服务不同:它会创建一个配置和一个路由对象,该对象可以帮助进行流量划分并存储函数的修订。在本文中,我们不会探讨配置和路由,而只是向您展示如何部署服务。

您将需要引用我们刚刚创建的构建模板,以便 Knative 了解如何打包您的函数。您将定义一组构建参数,即您的函数位于哪个目录,以及处理程序是什么。您将根据上面运行的 tm set registry-auth 命令定义要使用的注册表主机,最后您将使用 -f 选项指定函数的位置。最后一个选项可以指向本地目录或远程目录。在下面的示例中,我们将指向无服务器框架示例存储库。所有这一切将得出如下所示的一个命令:

tmk deploy service python-test -f https://github.com/serverless/examples \
                              --build-template knative-python37-runtime \
                              --build-argument DIRECTORY=aws-python-simple-http-endpoint \
                              --build-argument HANDLER=handler.endpoint \
                              --registry-host dockerhub \
                              --wait

访问您的 KLR 函数

现在您已成功部署您的函数,接下来您可以通过 Istio Ingress Gateway DNS 名称调用该函数,但需要传递自定义主机标头:

curl -H 'Host: python-test.default.svc.cluster.local' http://af375ca60465511e9911e02b74097eec-2072757389.us-east-1.elb.amazonaws.com
{"statusCode": 200, "body": "{\"message\": \"Hello, the current time is 15:05:53.694014\"}"}

恭喜,您已在 EKS 集群中的 Knative 上部署了 AWS Lambda 兼容函数!

请注意,此 DNS 名称并不适用于您 – 您需要将上面的命令替换为您自己的命令。

通过为 Knative 服务设置自定义域,可以大大改进此命令。这可以根据自定义域文档完成。

如果要部署 Go、Node 或 Ruby 函数,可以使用其他 KLR 模板
最后,由于 Knative 确实通过 AWS API 网关公开流量,因此可能需要稍微修改该函数的响应主体。我们目前正在研究如何修改 KRL 模板,以发送 API 网关将发送的相同响应。

小结

本文所执行的操作总结如下:

  • 我们使用 eksctl cli 在 EKS 上创建了一个 Kubernetes 集群。
  • 我们通过 kubectl cli 部署了 Knative 组件和 Istio。
  • 然后,我们使用 TriggerMesh CLI tm 创建了 Knative 服务。
  • Knative 服务创建了一个网络路由对象,允许我们通过 Istio 入站网关调用该函数。系统使用提供 AWS Lambda 自定义运行时 API 的 KLR 模板,将该函数透明地封装为容器映像。调用该函数时,Knative 将该函数扩展到至少一个副本,并在集群中显示 Kubernetes Pod。

删除集群

现在,您已经完成了 Knative 和 TriggerMesh Knative Lambda Runtime 的实验,接下来可以通过一个命令来删除集群,以此清理所有内容:

eksctl delete cluster knative

为了安全起见,请确保正确删除 CloudFormation 堆栈。

小结

在这篇内容详实的文章中,我们向您展示了:

  • 如何使用 eksctl 创建 EKS 集群。
  • 如何在您的 EKS 集群中安装 Knative。
  • 安装 TriggerMesh Knative CLI。
  • 使用与 AWS Lambda 兼容的 TriggerMesh Lambda Runtime 在 Knative 中部署函数。

在 re:Invent 2018 大会上公布的 AWS 自定义运行时 API 已经启用 Knative Lambda Runtime。KLR 属于 AWS Lambda 自定义运行时,可在 Kubernetes 上使用。您可以在 GitHub 上找到提供自定义运行时 API 的函数调用程序。如果您转到该存储库,将会看到如何在 Knative 中使用适用于 Rust 和 C++ 的 AWS 自定义运行时的示例。

这是一项非常激动人心的发展,通过 AWS 技术的主动开源工作实现。尽管 AWS Lambda 显然是运行关联 AWS 服务的函数的首选方式,但我们可以设想将 AWS Lambda 函数部署在其他云乃至本地这样一种环境,这会使 Lambda 成为无服务器范式的关键标准,即使在 AWS 云之外也是如此。
请尽管提交问题向我们发送反馈,或者通过 Twitter @triggermesh 与我们联系。

Sebastien Goasguen。

Sebastien Goasguen

Sebastien Goasguen 是一位拥有二十年开源经验的资深人士,曾任 Apache CloudStack 项目的副总裁。2016 年,他创立了一家基于 Kubernetes 的初创公司 Skippbox,在该公司,他领导了 kompose、cab 和 kubeless 的开发工作。他于 2018 年秋与他人共同创建了 TriggerMesh,这是一个基于 Knative 和 Kubernetes 构建的无服务器管理平台。Sebastien 过去撰写过 70 多篇科学论文、《O’Reilly Docker Cookbook》一书,并与人合著了《Kubernetes Cookbook》。

本博文中的内容和意见属于第三方作者,AWS 不对本博文的内容或准确性负责。

Arun Gupta

Arun Gupta

Arun Gupta 是 Amazon Web Services 的首席开源技术专家。在 AWS,他致力于与容器和开源有关的所有工作。他负责 AWS 内的 CNCF 策略,并积极参与 CNCF 董事会和技术会议。他在构建和领导开发人员社区方面拥有超过 12 年的经验,曾在 Sun、Oracle、Red Hat 和 Couchbase 工作过。他在 40 多个国家/地区就无数主题发表过大量演讲,连续四年荣获“JavaOne Rock Star”明星讲师称号。Gupta 还在美国成立了 Devoxx4Kids 分部,继续面向儿童推广技术教育。Gupta 是一位多产的博客作者、编著了多部书籍、热爱跑步、喜欢环球旅行,同时还是 Docker Captain、Java 冠军、JUG 领导者和 NetBeans Dream Team 成员,您可以通过 @arungupta 轻松与他交流。