Ruby gem 本机扩展不适用于 AWS Lambda

Ruby gem with native extensions not working on AWS Lambda

我有一个 ruby 脚本,我正尝试在 AWS Lambda 上 运行。我如何才能使用带有本机扩展的 Ruby gem?

我已经通过 bundle install --deployment 安装了我的 Ruby gem 并将它们包含在我的部署中。当我 运行 lambda 上的函数时,出现错误:

Ignoring oj-2.18.5 because its extensions are not built. Try: gem pristine oj --version 2.18.5

Init error when loading handler

{

"errorMessage": "libruby.so.2.5: cannot open shared object file: No such file or directory - /opt/ruby/gems/2.5.0/gems/oj-2.18.5/lib/oj/oj.so",

...

我已经尝试在 lambda 代码本身和 lambda 层中包含依赖项。唯一改变的是错误消息中的路径。

Lambda 能够找到我的 ruby gem。当它们位于错误的位置时,我会收到不同的错误消息。

/opt/ruby/gems/2.5.0/gems/oj-2.18.5/lib/oj/oj.so 确实存在。

我已经在 Ubuntu 和 AWS-linux 上对 bundle install 生成的文件进行了尝试。在这两个系统上,bundle 都告诉我它是“Installing oj 2.18.5 with native extensions”。

如果我将 libruby.so 的副本上传到我的 lambda,并将环境变量 LD_LIBRARY_PATH 设置为其位置,并使用安装在 AWS-linux 上的依赖项集进行修复上面列出的错误,但只是给我一个更不透明的错误:

/lib64/libc.so.6: version `GLIBC_2.25' not found (required by /opt/ruby/lib/libruby.so.2.5)

运行 ldd on gems/oj-2.18.5/lib/oj/oj.so 澄清了第一个错误。问题不是 oj.so 不存在,而是 libruby.so.2.5 不存在。第二个问题是当前的 Ruby lambda 具有 glibc 版本 2.17,其中 AWS-linux 带有 glibc 版本 2.25.

这里的根本问题是,如果您有本机依赖项,​​您需要将 gem 安装在与 运行 相同的系统上。我发现最好的方法是使用 docker。 https://github.com/lambci/docker-lambda 有 docker 个 lambda 安装映像。

对于 ruby,请执行以下操作:

  1. 构建 docker ruby 图像
  2. 将您的 gemfile 复制到原始目录中
  3. 从那个目录,运行:docker run -v "$PWD":/var/task --entrypoint bundle lambci/lambda-base:ruby2.5 install --path=/var/task

这将为您提供一个名为 ruby 的文件夹,其版本依赖项与 lambda 兼容。

如果您打算将此输出与 lambda 层一起使用,请记住 bunlde 生成的文件结构是 ruby/2.5.0/... 并且在上传之前需要 ruby/gems/2.5.0/...

问题正如您所说,总结一下:本机扩展gem需要在与运行[=27]相同的环境中构建=].因此,在将vendor上传到aws之前,我们必须在类似于lambda的环境中安装gems。


要以符合 lambda 的方式构建 vendor/bundle,请使用以下 docker 容器:

docker run --rm -v "$PWD":/var/task lambci/lambda:build-ruby2.7 bundle install --deployment

这会给你一个有效的 vendor/bundle 依赖。

您可以运行另一个容器来检查该功能是否有效:

docker run --rm -v $PWD:/var/task:ro,delegated lambci/lambda:ruby2.7 lambda_handler.lambda_handler

The full list of images is here: https://github.com/lambci/docker-lambda

这个问题已经存在 1 年了,但我不得不搜索大约 2 个小时来解决与 gem nokogiri 完全相同的问题,所以我认为这可能对某些人有用。

希望这能让您免去谷歌搜索的时间!