我有一个非常简单的 Python3.6 Lambda 函数,唯一的复杂性是我想包含pyyaml在其中。index.py看起来像这样 -
import yaml
def handler(event, context):
return event
Run Code Online (Sandbox Code Playgroud)
如果我捆绑pyyaml在我的 Lambda 可部署中,一切都会正常工作,如下所示 -
(aws_layer_demo) justin@justin-XPS-13-9360:~/work/aws_demos/aws_layer_demo$ jar -tvf tmp/layer-demo-dev/2019-05-31-06-27-41.zip
59 Fri May 31 06:27:13 BST 2019 index.py
0 Fri May 31 06:19:32 BST 2019 __init__.py
4881 Fri May 31 06:15:37 BST 2019 yaml/composer.py
25554 Fri May 31 06:15:37 BST 2019 yaml/constructor.py
3294 Fri May 31 06:15:37 BST 2019 yaml/cyaml.py
{... etc ...}
Run Code Online (Sandbox Code Playgroud)
我可以 ping Lambda 函数并获得响应,没问题。
现在我想测试包括pyyaml在一个层内。所以我现在有两个可部署的东西,一个用于应用程序 -
(aws_layer_demo) justin@justin-XPS-13-9360:~/work/aws_demos/aws_layer_demo$ jar -tvf tmp/layer-demo-dev/2019-05-31-06-43-42.zip
59 Fri May 31 06:27:13 BST 2019 index.py
0 Fri May 31 06:19:32 BST 2019 __init__.py
Run Code Online (Sandbox Code Playgroud)
和一层 -
(aws_layer_demo) justin@justin-XPS-13-9360:~/work/aws_demos/aws_layer_demo$ jar -tvf tmp/layer-demo-layer-dev/2019-05-31-06-43-42.zip
0 Fri May 31 06:43:42 BST 2019 __init__.py
4881 Fri May 31 06:15:37 BST 2019 yaml/composer.py
25554 Fri May 31 06:15:37 BST 2019 yaml/constructor.py
3294 Fri May 31 06:15:37 BST 2019 yaml/cyaml.py
{... etc ...}
Run Code Online (Sandbox Code Playgroud)
我已经使用 Cloudformation 堆栈(通过 S3)部署了两者,看起来函数和层都已正确部署 -
(aws_layer_demo) justin@justin-XPS-13-9360:~/work/aws_demos/aws_layer_demo$ ./scripts/show_function_config.sh dev
------------------------------------------------------------------------------------------------
| GetFunctionConfiguration |
+--------------+-------------------------------------------------------------------------------+
| CodeSha256 | MImn7X/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX= |
| CodeSize | 372 |
| Description | |
| FunctionArn | arn:aws:lambda:eu-west-1:XXXXXXXXXXXX:function:layer-demo-dev |
| FunctionName| layer-demo-dev |
| Handler | index.handler |
| LastModified| 2019-05-31T05:44:14.089+0000 |
| MemorySize | 512 |
| RevisionId | XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX |
| Role | arn:aws:iam::XXXXXXXXXXXX:role/layer-demo-dev-AppFunctionRole-XXXXXXXXXXXX |
| Runtime | python3.6 |
| Timeout | 5 |
| Version | $LATEST |
+--------------+-------------------------------------------------------------------------------+
|| Layers ||
|+-------------+------------------------------------------------------------------------------+|
|| Arn | arn:aws:lambda:eu-west-1:XXXXXXXXXXXX:layer:layer-demo-dev:2 ||
|| CodeSize | 41184 ||
|+-------------+------------------------------------------------------------------------------+|
|| TracingConfig ||
|+-------------------------------+------------------------------------------------------------+|
|| Mode | PassThrough ||
|+-------------------------------+------------------------------------------------------------+|
|| VpcConfig ||
|+---------------------------------------------------------------+----------------------------+|
|| VpcId | ||
|+---------------------------------------------------------------+----------------------------+|
Run Code Online (Sandbox Code Playgroud)
特别注意上面的“层”,以及 CodeSize > 0 的事实(即我没有意外部署大小为零的 zip 文件)
但是当我 ping 新分层的 Lambda 函数时,我现在得到 -
Unable to import module 'index'
Run Code Online (Sandbox Code Playgroud)
如果我更深入地研究 Cloudwatch 日志,我会得到 -
Unable to import module 'index': No module named 'yaml'
Run Code Online (Sandbox Code Playgroud)
所以。感觉好像我可能以某种方式错误地构造了我的层包(就目录结构而言),以便 Lambdayaml在内部 AWS上看不到PYTHONPATH。或者其他的东西。谁能告诉我哪里可能出错?
非常感谢。
事实证明,这是由于几个因素造成的。
首先,您必须非常小心地构建层包结构。仅压缩依赖项是不够的 - 对于 Python Lambda 函数,它们必须安装在pythonzip 文件内的目录中。该目录会根据您使用的运行时而变化。Lambda 文档中不是特别清楚,但这里有更多详细信息 -
https://medium.com/@adhorn/getting-started-with-aws-lambda-layers-for-python-6e10b1f9a5d
其次,在部署该层时,您需要指定兼容的运行时 - 因此,如果您使用 AWS CLI,则类似于 -
aws lambda publish-layer-version --layer-name $appname --content S3Bucket=$s3bucketname,S3Key=$appname/layer.zip --compatible-runtimes python3.7
Run Code Online (Sandbox Code Playgroud)
按照这两个步骤操作,您的图层应该可以正常工作。