Serverless Framework如何基于多requirements.txt打包独立Lambda层
多独立Lambda层打包可行方案
你的项目按功能组拆分目录、每个组维护独立依赖的结构很合理,针对serverless-python-requirements默认不支持多独立层的问题,有三个落地性很强的方案可选:
方案1:调整现有插件配置,无需换工具
serverless-python-requirements不是完全不支持多独立层,只是默认配置只生成单个全局层,改几行配置就能实现需求:
- 在
serverless.yml的layers字段下,为每个功能组单独声明层资源,路径直接指向对应功能组目录:
layers: group1Deps: path: function-group-1 compatibleRuntimes: - python3.9 # 替换成你实际使用的Python版本 group2Deps: path: function-group-2 compatibleRuntimes: - python3.9
- 修改插件配置,关掉默认的全局层自动生成逻辑:
custom: pythonRequirements: layer: false # 关闭插件自动生成单全局层的逻辑 dockerizePip: true # 非Linux环境必开,用Lambda一致的环境装依赖,避免二进制兼容问题 useDownloadCache: true
- 最后给每个Lambda函数绑定对应层即可:
lambda-A绑定group1Deps,lambda-B、lambda-C绑定group2Deps。
这个方案不需要改现有技术栈,配置量很小,缺点是如果后续功能组变多,要手动加对应的层配置。
方案2:写轻量脚本预打包层,完全脱离插件黑盒
这个方案可控性最高,不会被插件的隐式逻辑卡,排查问题也简单:
- Lambda层有固定的目录规范,Python依赖必须放在
python/lib/python<你的版本号>/site-packages/路径下,层加载的时候才能被Python解释器识别。 - 写个不到10行的脚本,遍历所有带
requirements.txt的功能组目录,自动创建符合规范的层目录,用pip把依赖直接装到对应目录里,再给Serverless指定用现成的目录做层源就行。
举个可直接用的bash脚本例子:
#!/bin/bash # 替换成你Lambda实际用的Python版本 RUNTIME=python3.9 for func_dir in */; do if [ -f "${func_dir}requirements.txt" ]; then echo "Start packing layer for ${func_dir}" # 创建Lambda层要求的标准目录结构 BUILD_PATH="${func_dir}layer_temp/python/lib/${RUNTIME}/site-packages" mkdir -p $BUILD_PATH # 直接把依赖装到层目录里 pip install -r "${func_dir}requirements.txt" -t $BUILD_PATH fi done
- 把脚本加到部署流程的前置步骤里,部署前自动执行,之后在
serverless.yml里声明层的时候,把path指向每个功能组下生成的layer_temp目录即可,部署时Serverless会直接上传已经装好依赖的层,不会重复执行安装逻辑。
如果要缩小编包体积,直接在脚本里加逻辑删掉__pycache__、.dist-info这类没用的文件就行,非常灵活。
方案3:换用原生支持多层的部署框架
如果不想自己维护脚本,可以换用对多工作区、多层支持更友好的部署工具:
- 用AWS SAM的话,每个层可以单独指定代码目录和依赖文件路径,执行
sam build的时候会自动给每个层安装对应依赖、打包成符合规范的层包,不需要额外写配置或者脚本。 - 用AWS CDK/CDKTF的话,可以直接写逻辑遍历项目下的功能组目录,批量生成对应的Lambda层资源,不需要手动重复写层配置,功能组多的时候效率很高。
注意:所有带C扩展的Python依赖(比如numpy、pyarrow、pandas),一定要在和Lambda运行环境一致的Amazon Linux环境下打包,不然本地Windows/macOS装出来的二进制文件上传到Lambda会直接报加载错误,要么开Docker装依赖,要么直接在CI的Linux环境里跑打包流程。
内容的提问来源于stack exchange,提问作者Dương Quang Thọ
相关产品推荐
相关产品推荐

