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

Ric*_*ard 7 python-3.x scikit-learn scikit-image aws-lambda

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

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


背景:经过大量谷歌搜索和阅读后,似乎最好的方法是使用 docker 在本地运行 AWS lambda 运行时,然后在那里安装/编译 scikit-image(或您正在寻找的任何模块)。完成后,您可以将其作为自定义层上传/安装到 AWS。

这在概念上非常简单,但我正在努力使用最佳实践方法来做到这一点。我已经完成了这项工作,但不确定我是否以最好/正确/最佳/安全的方式做这件事…… 有数百万篇关于此的完全不同的博客文章,AWS 文档本身也是(恕我直言)详细但略过一些基本问题

我一直试图基本上遵循两个很好的中等职位,这里这里......对这些人的敬意。


我的主要问题是:

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

对于所谓的最新图像,有多个(甚至在亚马逊本身)多个位置/版本等。例如https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.htmlhttps://cdn.amazonlinux.com/os-images/2.0.20190823.1/

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

为了安全性和最新性,我更喜欢使用亚马逊提供的 docker 镜像。

  1. 是AWS的λ运行时这里,可链接到这个AMI,码头工人的形象? 如果是(或不是)你如何下载它以在本地运行它?
  2. 您如何确保知道何时可能需要重建层,因为 AWS lambda 运行时已被亚马逊更改并且使用旧运行时破坏了层?
  3. 在 docker AIM 容器内构建(在 scikit-image 的情况下编译)pip 安装的模块,还是只是告诉 pip 下载预构建的版本并希望/相信它会获得编译的库是更好的选择是您正在运行的 AMI 的最佳选择吗?

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

  1. 下载并使用AWS 的 SAM来完成所有这些工作是否更好?(看起来有点矫枉过正和复杂,但它看起来确实需要确保您始终使用“正确”的 AMI docker 容器)
  2. 是否有任何(好的,可信赖的)预构建 lambda 层的存储库(这可能会使所有这些成为一个有争议的问题)?我看了,但找不到任何。

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

Ric*_*ard 8

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


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

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

所有 AWS lambda 运行时环境的完整列表,不仅仅是 python,在这里


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

迄今为止,我发现的最好方法是将AWS 的 SAM 与我从这里的一个很棒的博客中使用的一些调整结合使用。

需要进行调整是因为(在我撰写本文时)AWS SAM 允许您定义层,但实际上不会为您构建它们。...从 SAM 组的 github 中查看此请求

我不打算在这里详细解释这一点 - 相反,请查看bryson3gps 博客。他解释得很好,所有功劳都归功于他。 *


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

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

意思是,如果您为要安装在层中的一组模块定义了一个 requirements.txt,它实际上不会将它们安装/构建到准备上传到 AWS 的本地目录中(就像您使用它来定义一个 lambda功能)。

但是,如果您在 SAM 中定义一个层,它将为您打包(压缩所有内容并上传到 S3)并部署(在 AWS 云中使用 ARN 等定义它以便可以使用)该层。


让 SAM 也构建层的方法

目前,从这里的 bryson3Gps 博客中“愚弄”SAM 为您构建图层的技巧是

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

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

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

  2. 在层定义的 SAM 规范中,将 ContentUri(即它查找文件/目录压缩并上传到 AWS的位置)设置为您在 (1) 中定义的函数的构建位置

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

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

那么,当您告诉 SAM 为整个模板打包(发送到 S3)和部署(使用 AWS 配置)时,它会上传/创建您定义的层,但它也会使用该层的正确内容为(虚拟)功能构建的。

它运作良好。

一些额外的提示

1

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

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

sys.path.append('/opt')
import <a module in your layer>
Run Code Online (Sandbox Code Playgroud)

而不是这样做,在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
Run Code Online (Sandbox Code Playgroud)

2

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

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

3

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

cd .aws-sam/<wherever you package is>/
rm -r numpy*
rm -f scipy*
Run Code Online (Sandbox Code Playgroud)

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

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


spe*_*hak 3

从 v0.50.0 开始,sam cli直接支持构建层。您AWS::Serverless::LayerVersion可以使用有关要使用的运行时策略的元数据来装饰您的资源。

MyLayer:
 Type: AWS::Serverless::LayerVersion
 Properties:
   Description: Layer description
   ContentUri: 'my_layer/'
   CompatibleRuntimes:
    - python3.8
 Metadata:
   BuildMethod: python3.8
Run Code Online (Sandbox Code Playgroud)