【发布时间】:2019-05-25 21:44:08
【问题描述】:
我正在尝试扩展 this guide,通过构建 CodePipeline 来获取 GitHub 中的更改、构建它们并将更改部署到我的 Lambda。 sam build --use-container; sam local start-api 允许我在本地成功调用该函数 - 但是当我将该函数部署到 AWS 时,代码无法导入依赖项。
我的代码依赖于requests。我已将其正式包含在我的 requirements.txt 文件中:
requests==2.20.0
我的 buildspec.yml 包含安装依赖项的说明
version: 0.1
phases:
install:
commands:
- pip install -r hello_world/requirements.txt -t .
- pip install -U pytest
pre_build:
commands:
- python -m pytest tests/
build:
commands:
- aws cloudformation package --template-file template.yaml --s3-bucket <my_bucket>
--output-template-file outputTemplate.yml
artifacts:
type: zip
files:
- '**/*'
当我的包在 CodeBuild 中构建时,即被确认:
[Container] 2018/12/27 23:16:44 Waiting for agent ping
[Container] 2018/12/27 23:16:46 Waiting for DOWNLOAD_SOURCE
[Container] 2018/12/27 23:16:46 Phase is DOWNLOAD_SOURCE
[Container] 2018/12/27 23:16:46 CODEBUILD_SRC_DIR=/codebuild/output/src775882062/src
[Container] 2018/12/27 23:16:46 YAML location is /codebuild/output/src775882062/src/buildspec.yml
[Container] 2018/12/27 23:16:46 Processing environment variables
[Container] 2018/12/27 23:16:46 Moving to directory /codebuild/output/src775882062/src
[Container] 2018/12/27 23:16:46 Registering with agent
[Container] 2018/12/27 23:16:46 Phases found in YAML: 3
[Container] 2018/12/27 23:16:46 PRE_BUILD: 1 commands
[Container] 2018/12/27 23:16:46 BUILD: 1 commands
[Container] 2018/12/27 23:16:46 INSTALL: 2 commands
[Container] 2018/12/27 23:16:46 Phase complete: DOWNLOAD_SOURCE Success: true
[Container] 2018/12/27 23:16:46 Phase context status code: Message:
[Container] 2018/12/27 23:16:46 Entering phase INSTALL
[Container] 2018/12/27 23:16:46 Running command pip install -r hello_world/requirements.txt -t .
Collecting requests==2.20.0 (from -r hello_world/requirements.txt (line 1))
Downloading https://files.pythonhosted.org/packages/f1/ca/10332a30cb25b627192b4ea272c351bce3ca1091e541245cccbace6051d8/requests-2.20.0-py2.py3-none-any.whl (60kB)
...
但是当我调用部署的函数时,我得到一个错误:
Unable to import module 'app': No module named 'requests'
这似乎与this question 非常相似,但我没有在我的 Lambda 大楼中使用PYTHONPATH。
编辑:我在这个包中的文件中添加了一些调试代码,以尝试了解它们的运行时环境。我还向another package 添加了类似的调试,我通过 CodePipeline 部署到 Lambda(尽管这个不使用 SAM)。调试代码如下:
import os, sys
print('Inside ' + __file__)
for path in sys.path:
print(path)
if (os.path.exists(path)):
print(os.listdir(path))
for f in os.listdir(path):
if f.startswith('requests'):
print('Found requests!')
print()
此代码尝试确定 requests 模块是否存在于 Lambda 运行时环境的 sys.path 中,如果存在,则在哪里。
对于这个(支持 SAM 的)包,在任何地方都找不到 requests。在未启用 SAM 的包中,requests(以及包的所有其他 requirements.txt 声明的依赖项)在 /var/task 中找到。
看起来 CodeBuild 没有将函数的依赖项与源捆绑在一起,或者 CloudFormation 没有部署这些依赖项。我怀疑这是因为这是一个 SAM 定义的函数,而不是“普通”的 Cloudformation 函数。
This page 说“您还可以使用与 AWS SAM 集成的其他 AWS 服务来自动化您的部署”,但我看不出如何让 CodePipeline 运行 sam deploy 而不是 aws cloudformation deploy(尽管 @ 987654325@ 声称它们是同义词)。
EDIT2 - 我相信我找到了问题所在。对于上下文,请回想一下,我有两个包正在通过 CodePipeline(或尝试)部署 Lambda - 这个问题中提到的一个,将 Lambda 称为AWS::Serverless::Function,另一个使用AWS::Lambda::Function。第一个函数的代码被定义为相对位置(即,对我的包中的目录的引用:CodeUri: main/),而第二个函数的 Code 是对 S3 位置的引用(在 CodePipeline 中使用 @987654348 获取@或...BucketName"]})
以下是第一个包的 CodeBuild 输出示例:
[Container] 2018/12/30 19:19:48 Running command aws cloudformation package --template-file template.yaml --s3-bucket pop-culture-serverless-bucket --output-template-file outputTemplate.yml
Uploading to 669099ba3d2258eeb7391ad772bf870d 4222 / 4222.0 (100.00%)
Successfully packaged artifacts and wrote output template to file outputTemplate.yml.
Execute the following command to deploy the packaged template
aws cloudformation deploy --template-file /codebuild/output/src110881899/src/outputTemplate.yml --stack-name <YOUR STACK NAME>
与第二个包的 CodeBuild 输出中的相同输出进行比较:
....
[Container] 2018/12/30 16:42:27 Running command aws cloudformation package --template-file template.json --s3-bucket {BUCKET_NAME} --output-template-file outputTemplate.yml
Successfully packaged artifacts and wrote output template to file outputTemplate.yml.
Execute the following command to deploy the packaged template
aws cloudformation deploy --template-file /codebuild/output/src282566886/src/outputTemplate.yml --stack-name <YOUR STACK NAME>
这表明第一个包的 aws cloudformation package 调用会导致将文件 (669099ba3d2258eeb7391ad772bf870d) 上传到 S3,这仅基于 template.yaml 的内容,而“第二个包的 CodePipeline 的 Build 阶段的“输出”是 CodeBuild 一直在运行的目录的zipin - 其中包括依赖项(因为调用了pip install)。 p>
我可以通过简单地将我的 SAM 模板函数的 template.yaml 更改为引用 S3 位置来解决此问题 - 但这意味着我将无法在本地测试对函数的更新(例如,sam local start-api)而不编辑模板,因为它会引用 S3 位置,因此不会受到本地更改的影响。
理想情况下,我想找到一种方法将代码的依赖项包含在打包和上传的 S3 文件中。从本地测试来看,运行sam package/aws cloudformation package 而不首先运行sam build 似乎只包含源代码(无依赖项)。但是,我无法在 CodeBuild 中运行 sam build,因为那里没有安装 SAM。
(这也表明我无意中部署了我的第二个包的测试依赖项 - 因为需要在 CodeBuild 中安装它们(以便运行测试))
【问题讨论】:
-
部署 lambda 函数时,所有不属于 AWS 环境的依赖项都必须添加到部署包中。 https://docs.aws.amazon.com/lambda/latest/dg/current-supported-versions.html。我确实使用像
pip install requests -t这样的命令。在我看来,CodeBuild 依赖于 AWS Serverless,它依赖于带有 lambda 的标准 zip 文件。所以我认为你仍然必须通过本地安装来做到这一点。但是您可以将 setup 命令放在构建脚本中。
标签: amazon-web-services aws-lambda python-packaging