为 Scikit-image 构建自定义 AWS Lambda 层

Build custom AWS Lambda layer for Scikit-image

大纲: 我需要在一些 AWS lambda 函数中使用 scikit-image,所以我希望构建一个包含 scikit-image 的自定义 AWS lambda 层.

我的问题通常应该适用于任何 python 模块,特别是 scikit-learn,或者我认为一般的任何自定义层。


背景: 经过大量谷歌搜索和阅读,似乎最好的方法是使用 docker 到 运行 AWS lambda 运行本地时间,然后在里面 install/compile scikit-image(或您要查找的任何模块)。完成后,您可以 upload/install 将其作为自定义层发送到 AWS。

这在概念上非常简单,但我正在努力寻找最佳实践方法来做到这一点。我已经开始工作了,但不确定我是按照 best/right/optimal/secure 的方式来做的…… 有数百万篇关于此的略有不同的博客文章,AWS 文档本身(恕我直言)过于详细但跳过了一些基本问题

我基本上一直在尝试关注两个不错的中型帖子,here and here ...向那些人致敬。


我的主要问题是:

  1. 在哪里可以找到最新的 AWS AMI docker 映像?

有多个(甚至在亚马逊本身)多个 locations/versions 等据称是最新的图像。例如 https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html, or https://cdn.amazonlinux.com/os-images/2.0.20190823.1/.

..这忽略了大量非亚马逊 github 托管的可能性,例如 lambci/lambda:build-python3.6 来自中等帖子 here, or onema/amazonlinux4lambda from here.

我更愿意使用亚马逊提供的 docker 图片,以确保安全性和最新性。

  1. AWS lambda 运行时间here, which links to this AMI是docker图像吗?如果是(或不是)你如何下载它运行 在本地?
  2. 您如何确保知道何时可能需要重建层,因为 AWS lambda 运行time 已被亚马逊更改,这会破坏您使用较旧的 运行time?
  3. 的图层
  4. 在 docker AIM 容器中构建 (在 scikit-image 的情况下编译)pip 安装模块是否更好,或者只是告诉 pip 下载预构建版本 和 hope/trust 它将获得最适合 AMI 的编译库,你 运行ning?

基本上我关心的是稳定性和性能。我想确保在这种情况下为 scikit-image 编译的库尽可能针对 AMI 容器进行了优化。

  1. 下载并使用 AWS's SAM 来完成所有这些是否更好?(看起来有点矫枉过正和复杂,但它确实解决了问题确保您一直在使用 'correct' AMI docker 容器)
  2. 周围是否有任何(良好的、可信赖的)预构建 lambda 层的回购(这可能会使所有这些成为一个有争议的问题)?我找了找也没找到。

...感谢任何建议、想法和评论!

我不是这方面的专家,但我碰巧在同一天遇到了完全相同的一组问题。但是我可以回答问题#1 和#2。将它们打乱:
2) AMI 不是 docker 映像,它用于 EC2 实例。

1) 以下是我如何获得合适的 docker 图片:

我安装了 SAM cli 并执行了以下命令:

sam init --runtime python3.7(设置 hello world 示例)
sam build -u(构建应用程序,-u 表示使用容器)

sam build -u 的输出:

Fetching lambci/lambda:build-python3.7 Docker container image

好了。您可以直接从 dockerhub 获取图像,或者如果您安装了 SAM cli,则可以执行 "sam build -u"。现在您有了图像,如果您不想要开销,则不必遵循完整的 SAM 工作流程。

有趣的几天弄清楚了这一点。 ...希望下面的答案对那些努力弄清楚如何制作自定义层(对于 python 以及其他语言)的人有所帮助。


在哪里可以找到最新的 AWS AMI docker 映像?

正如 Greg 上面指出的那样,答案是 "right" docker 用于构建图层的图像在哪里:lambci/lambda:build-python3.7。这是他们使用的 docker 图像的官方 SAM 存储库。

所有 AWS lambda 运行时间环境的完整列表,而不仅仅是 python,是 here


构建您自己的 AWS lambda 层的最佳方法是什么? ...构建自定义 python 模块层的最佳方法是什么?

迄今为止,我发现的最佳方法是使用 AWS's SAM in combination with some tweaks I used from a great blog here

调整是必要的,因为(在我写这篇文章的时候)AWS SAM 允许您定义层,但实际上不会为您构建它们。 ...请参见 SAM 组的 github 中的 this request

我不打算在这里详细解释 - 请查看 bryson3gps blog。他解释得很好,所有的功劳都归功于他。*


好的,使用过程的快速背景:

目前,AWS SAM 不会为您构建您的层。

意思是,如果你为一组模块定义了一个requirement.txt安装在一个层中,它实际上不会install/build它们进入本地目录准备上传到 AWS(就像你用它来定义 lambda 函数一样)。

但是,如果您在 SAM 中定义一个层,它将打包(压缩所有内容并上传到 S3)并部署(定义它在带有 ARN 等的 AWS Cloud 中,因此可以使用)那个层适合你。


让 SAM 也构建图层的方法

目前,从 bryson3Gps 博客 here 中 "fool" SAM 也为您构建图层的方法是

  1. 在 SAM 中定义虚拟 AWS lambda 函数模板。 然后对于该功能,制作一个 pip requirement.txt,SAM 将在构建期间使用它来将您想要的模块加载到您的层中。您实际上不会将此功能用于任何事情。

这需要制作一个定义基本功能的 SAM template.yaml 文件。查看 SAM 教程,然后查看 bryson3gps 的博客。很简单。

  1. 在同一 template.yaml 文件中定义一个 AWS 层。再次不太难 - 查看博客

  2. 在您的层定义的 SAM 规范中,将 ContentUri(即查找 files/directories 以压缩并上传到 AWS 的位置)设置为 您在 (1).

  3. 中定义的函数的构建位置

因此,当您使用 sam build 时,它会为您构建函数(即为函数处理 requirements.txt)并将生成的函数包放​​在一个目录中,以便稍后压缩并发送到 AWS。

但是(这是关键)您定义的图层 ContentUri 指向相同的目录 sam build 用于为(虚拟)函数创建目录。

那么,当您告诉 SAM 将模板作为一个整体打包(发送到 S3)和部署(使用 AWS 配置)时,它将 upload/create 您定义的层,但它也会使用为(虚拟)函数构建的图层的正确内容。

效果很好。

一些额外的提示

1

在 bryson3gps 的博客中,他指出这种方法没有将图层包放在 lambda AMI 目录中的正确位置,默认情况下无法找到它们(对于 python 即 /opt/python).相反,它们被放置在 /opt.

他的解决方法是在导入之前将 /opt 添加到 lambda 脚本中的 sys.path:

sys.path.append('/opt')
import <a module in your layer>

sam package 上传到 S3 之前(sam build 之后),您可以进入适当的 .aws-sam/<your package subdir> 目录并将所有内容移动到新的 /python 该包目录中的目录。这导致层模块正确放置在 /opt/python 中,而不仅仅是 /opt.

cd .aws-sam/<wherever you package is>/
mkdir .python
mv * .python
mv .python python

2

如果您正在使用编译代码制作 python 图层(例如我正在使用的 scikit-image)确保 你使用 sam build -u (带有 -u 标志)。

这将确保构建(pip'ing requirements.txt)将在与 AWS lambda 运行time 匹配的 docker 容器内发生,DL 也将正确的库) 运行时间。

3

如果您包含任何依赖于 numpy 或 scipy 的模块,则 在 sam build -u 之后,但 在 [=160 之前=]确保进入构建的适当.aws-sam/<your package>目录并删除numpy和scipy模块依赖项将安装

cd .aws-sam/<wherever you package is>/
rm -r numpy*
rm -f scipy*

相反,您应该在 lambda 函数中指定使用 AWS 提供的 numpy/scipy 层。

我找不到告诉 SAM 使用 --no_dep 运行 pip 的方法,所以必须手动执行此操作

从 v0.50.0 开始,sam cli 有 direct support for building layers。您使用有关要使用的运行时策略的元数据来装饰 AWS::Serverless::LayerVersion 资源。

MyLayer:
 Type: AWS::Serverless::LayerVersion
 Properties:
   Description: Layer description
   ContentUri: 'my_layer/'
   CompatibleRuntimes:
    - python3.8
 Metadata:
   BuildMethod: python3.8