亚马逊AWS官方博客

使用无服务器框架和 Tekton 部署 AWS Lambda 函数

本文是 TriggerMesh 联合创始人 Sebastien Goasguen 的一篇特约文章。

可以说,使用无服务器框架来部署 AWS Lambda 是部署函数以及配置函数触发方式的最简单方式。如果您向将函数的部署自动化,您将很可能需要选择 CI/CD 工作流。CI/CD 管道可以使用多种工具(例如使用 Jenkins、AWS CodePipeline、Google Cloud Build、CircleCI、Bamboo、Rundeck)以不同的方式实施。2019 年 3 月,Linux 基金会宣布成立持续交付基金会 (CDF)。持续交付基金会以提供中立的协作平台,促进下一代持续交付系统的开发为宗旨。Tekton 是一个开源 Google 项目,由 CDF 托管,提供与 Kubernetes 类似的 API 资源来描述 CI/CD 管道。

在本文中,我们将解释如何借助 Tekton 和无服务器框架实现 AWS Lambda 函数的自动化部署。我们将首先快速回顾一下无服务器框架,然后深入介绍 Tekton 核心 API 对象。

无服务器框架

无服务器框架已经成为开发 AWS Lambda 函数的首选工具,其原因也非常充分:只要拥有一个恰当配置的 AWS 账户,即可以极为快速地开始使用 Lambda。

入门

首先要安装无服务器框架并生成 Python 函数的骨架:

npm install -g serverless
serverless create -t aws-python3

最终写入工作目录的骨架将是:

.
├── handler.py
└── serverless.yml

此函数将存储在 handler.py 文件中,而描述如何部署和调用函数的清单文件为 serverless.yml
为确保能够从互联网访问您的函数,您必须编辑 serverless.yml 清单文件,其中 functions 部分的设置与以下类似:

functions:
  hello:
    handler: handler.hello
    events:
      - http:
          path: /
          method: get

要部署此函数:

serverless deploy

部署完成后,将会在 stdout 上显示描述函数的信息,与以下类似:

...
Service Information
service: foo
stage: dev
region: us-east-1
stack: foo-dev
resources: 9
api keys:
  None
endpoints:
  GET - https://i0vh8byjr9.execute-api.us-east-1.amazonaws.com/dev/
functions:
  hello: foo-dev-hello
layers:
  None
Serverless: Run the "serverless" command to setup monitoring, troubleshooting and testing.

现在您可以调用可公开访问的终端节点并解析输出,从而从无服务器框架收到一条好消息:

curl -s https://i0vh8byjr9.execute-api.us-east-1.amazonaws.com/dev/ | jq .message
"Go Serverless v1.0! Your function executed successfully!"

这十分简单直接,但正如在简介部分所指出,您很可能会通过 CI/CD 管道来部署和更新函数,而这可能是 Jenkins 等传统的 CI/CD 管道,也可能是某个可用的 SaaS 解决方案。如果您希望在 Kubernetes 集群内执行并通过类似于 Kubernetes 的 API 来定义 CI/CD 管道,我们建议您试试 Tekton。

Tekton 的概念简介

Tekton 是一组可以用于描述 CI/CD 管道并且将在 Kubernetes 集群中运行该管道的 API 对象。

Tekton 提供了用来表示 CI/CD 管道的 Kubernetes 原生 API(借助自定义资源功能)。在这个已经以 Kubernetes 为中心的世界里,它本身已经十分值得开发。

Tekton API 由五个关键对象组成:

  1. Task:描述将在容器内执行的步骤集。Task 规范类似于 Kubernetes Pod。
  2. TaskRun:将触发执行 Task 并定义 Task 运行所需输入和输出集的对象。
  3. Pipeline:需要执行的 Tasks 集。
  4. PipelineRun:将触发执行 Pipeline 的对象。
  5. PipelineResource:定义可以作为 Task 的输入和输出的对象。

要了解更多有关 Pipeline 对象的信息,请参阅 GitHub 上的教程

在本文的最后一部分,我们将重点介绍 Task 对象并使用它来部署一个 AWS Lambda 函数。

使用 Tekton 部署 Lambda 函数

在 上一部分我们介绍了如何使用无服务器框架来部署 AWS Lambda 函数,此外还快速介绍了 Tekton 的几个概念,下面我们会将两者结合起来。

我们需要执行的操作包括:

  • 定义一个 GitHub 存储库,其中包含作为 PipelineResource 对象的函数代码。
  • 创建一个将会运行serverless deployTask 对象。
  • 创建一个将 TaskPipelineResource 作为输入引用的 TaskRun 对象,从而执行 Task
  • 检查执行该 Task 的 Pod 的日志,并确认正在部署函数。

显示的 YAML 清单都可在 GitHub 上获取。您可以首先克隆该存储库以方便访问示例文件:

git clone https://github.com/sebgoa/klr-demo
cd klr-demo

您也可以直接通过 curl 命令获取清单文件,与以下类似:

curl https://raw.githubusercontent.com/sebgoa/klr-demo/master/resources.yaml

PipelineResource 的形状如下,这是所有 Kubernetes 用户都熟悉的东西。您将看到 API 版本、种类、在元数据部分定义的对象名称,在规范部分,您还将看到 git 存储库的 URL,其中包含了我们的函数代码。

apiVersion: tekton.dev/v1alpha1
kind: PipelineResource
metadata:
  name: klr-demo
spec:
  type: git
  params:
  - name: revision
    value: master
  - name: url
    value: https://github.com/sebgoa/klr-demo

如果解开部署函数所需的 Task 对象,与 Kubernetes 对象一样,所有我们将看到 apiVersionkindmetadata 以及 spec 部分。spec 首先将引用 inputs 部分中的一个 git 类型的资源,从而让我们可以指向包含函数代码的 git 存储库。

apiVersion: tekton.dev/v1alpha1
kind: Task
metadata:
  name: serverless-deploy
spec:
  inputs:
    resources:
    - name: repository
      type: git
…

然后 Task 将定义 steps。在我们的 Task 中,我们将仅有一个步骤。此步骤应会运行 serverless deploy。为此,我们需要一个包含 serverless 节点包的容器镜像。我们在 Triggermesh 构建了此镜像并且可从 gcr.io/triggermesh/serverless 公开访问它。此步骤与以下类似:

  steps:
  - name: deploy
    workingDir: '/workspace/repository'
    image: gcr.io/triggermesh/serverless
    command: ["serverless"]
    args: ["deploy"]
…

为确保正常运行,运行该步骤的 Kubernetes Pod 将需要使用您的 AWS 凭证。您可以使用 Kubernetes Secrets 将您的凭证作为环境变量传递,也可以使用卷挂载的方式。下面是使用两个环境变量的最简单示例:

    env: 
    - name: AWS_ACCESS_KEY_ID
      valueFrom: 
        secretKeyRef: 
          name: awscreds
          key: aws_access_key_id
    - name: AWS_SECRET_ACCESS_KEY
      valueFrom: 
        secretKeyRef: 
          name: awscreds
          key: aws_secret_access_key

并它将定义您的 TaskPipelineResource。您的简短管道的声明已经完成。要启动此管道的执行(单个 Task),您现在需要编写一个 TaskRun 对象。

您可以通过 curl 获取 TaskRun 清单,与以下类似:

curl -s https://raw.githubusercontent.com/sebgoa/klr-demo/master/deploy.yaml

此对象的形状与所有 Kubernetes 对象同样类似,具有常用的 apiVersionkindmetadata、和 spec 部分:

apiVersion: tekton.dev/v1alpha1
kind: TaskRun
metadata:
  name: deploy
spec:
…

spec 部分,我们将设置指向我们的 PipelineResource(它定义了要使用的 git 存储库)的任务的输入。最后,taskRef 部分将指向执行我们的 serverless deployTask

spec:
  inputs:
    resources:
    - name: repository
      resourceRef:
        name: klr-demo
  taskRef:
    kind: Task
    name: serverless-deploy

恰当配置对象并取得包含您的 AWS 凭证的 Secret 后,您将可以通过 Tekton 和无服务器框架创建对象并启动函数的部署。

如果您已经克隆了示例存储库:

kubectl apply -f resources.yaml
kubectl apply -f deploy.yaml

下图描绘了关键的 Tekton API 对象(TaskResourceTaskRun)并显示了基本的流程。创建 TaskRun 对象将会创建一个 Pod,后者将会运行 serverless deploy 命令以将函数部署到 AWS Lambda。

创建 Pod 的 TaskRun 示例,该 Pod 将会运行 serverless deploy 命令以将函数部署到 AWS Lambda。

Task 将在一个 Pod 中执行并且您将从 Pod Logs 中获得无服务器日志,例如:

kubectl logs serverless-deploy-fgn9x-pod-570cb9 -c build-step-deploy
Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Creating Stack...
Serverless: Checking Stack create progress...
.....
2020-01-28T14:18:24.054347892Z service: aws-python-simple-http-endpoint
2020-01-28T14:18:24.054360411Z stage: dev
2020-01-28T14:18:24.054367679Z region: us-east-1
2020-01-28T14:18:24.054375006Z stack: aws-python-simple-http-endpoint-dev
2020-01-28T14:18:24.05438248Z resources: 10
2020-01-28T14:18:24.054725635Z api keys:
2020-01-28T14:18:24.054763849Z   None
2020-01-28T14:18:24.055481345Z endpoints:
2020-01-28T14:18:24.055540592Z   GET - https://1st3ojbj1d.execute-api.us-east-1.amazonaws.com/dev/ping
2020-01-28T14:18:24.055893183Z functions:
2020-01-28T14:18:24.055951609Z   currentTime: aws-python-simple-http-endpoint-dev-currentTime
2020-01-28T14:18:24.056206865Z layers:
2020-01-28T14:18:24.056266366Z   None</code

小结

AWS Lambda 用户如果使用无服务器框架来部署函数,必须建立自动化的持续部署,从而确保可以自动接受测试和部署函数代码的更改。尽管已经存在大量的 CI/CD 解决方案(包括 Jenkins、CircleCI 和 CodePipeline),作为此领域的新来者,Tekton 提供了一种与 Kubernetes 类似的 API,令 Amazon Elastic Kubernetes Service (Amazon EKS) 等 Kubernetes 用户极感兴趣。这让使用 Amazon EKS 集群来运行容器化工作负载以及 CI/CD 管道(包括推动无服务器架构发展的管道)成为可能。

如果您想更深入试用 Tekton,请参阅 Task 目录。本文中描述的无服务器 Task 将在未来几周贡献到目录中。

此外,如果您希望将 Tekton 与 Knative 结合使用,您可能会对 TriggerMesh Lambda 运行时感兴趣,之前在“使用 TriggerMesh KLR 在 Amazon EKS 中部署与 AWS Lambda 兼容的函数”一文中已经介绍过此运行时。此外,您还可能会对 GitHub 上适用于 AWS 服务的 Knative 事件源感兴趣,借助这些事件源可以将您的 AWS 服务事件与本地应用程序关联。

Sebastien Goasguen

Sebastien Goasguen

Sebastien 是集成平台公司 TriggerMesh 的联合创始人,TriggerMesh 为开发人员管理原生云应用程序提供支持。他从事开源事业已经接近 20 年。Sebastien 是 Apache 软件基金会的一名提交者,也是 Kubernetes 生态系统的早期贡献者。2014 年前后,Docker 的迅猛崛起令他很震惊,决定尽可能学习,并在后来撰写了《O’Reilly Docker 工作手册》一书。这一经历让他认识了 Kubernetes 并一眼就爱上了 Pod。Sebastien 成为 CNCF 领域的早期和活跃参与者 — 积极贡献、构建、教授和创新。他创立了 TriggerMesh 以推动无服务器领域的边界,让所有企业都能受益于这一新的理念,包括那些仍在使用本地应用程序的企业。

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

精选图片来自 Pixabay