调试 AWS Lambda:常见的调用错误及解决方法
掌握调试 AWS Lambda 函数的艺术。本综合指南详细介绍了最常见的调用失败,涵盖从 IAM 权限问题、VPC 连接问题到内存不足和函数超时等资源限制。学习如何有效利用 CloudWatch 日志,并应用实用的、可操作的修复方法—包括优化配置、管理依赖项和纠正执行角色—以确保无服务器函数可靠且一致的性能。
调试 AWS Lambda:常见调用错误及修复方法
AWS Lambda 调用错误通常来自以下三种情况之一:调用方无法调用函数、Lambda 无法启动运行时,或者您的代码启动后失败。最快的修复方法是在更改内存、超时、IAM 策略或 VPC 设置之前,先确定哪个阶段失败。
从 CloudWatch 日志开始,然后按顺序确认权限、处理程序设置、依赖项和网络配置。
建立调试基线:CloudWatch 日志
在更改函数之前,请检查日志组 /aws/lambda/YourFunctionName。正常的 Lambda 执行通常包含以下平台日志行:
- START: 表示执行开始。
- END: 表示执行完成。
- REPORT: 提供摘要指标(持续时间、计费持续时间、已用内存、最大已用内存以及 X-Ray 追踪详细信息)。
如果函数从未启动,您可能看不到应用程序日志。在这种情况下,请检查调用服务、Lambda 控制台测试结果、CloudTrail 事件以及函数的基于资源的策略。
解决权限和访问错误
权限错误可以说是 Lambda 调用失败的最常见原因。这些通常分为两类:函数缺少运行权限,或调用实体缺少调用函数的权限。
执行角色(IAM 角色)失败
每个 Lambda 函数都必须承担一个 IAM 执行角色。如果此角色配置错误,函数将无法与必要的 AWS 服务交互。
常见缺失权限:
| 所需服务访问权限 | 所需的 IAM 策略操作 |
|---|---|
| 记录到 CloudWatch | logs:CreateLogGroup、logs:CreateLogStream、logs:PutLogEvents |
| VPC 连接 | ec2:CreateNetworkInterface、ec2:DeleteNetworkInterface、ec2:DescribeNetworkInterfaces |
| 读取 S3/DynamoDB | s3:GetObject、dynamodb:GetItem 等 |
修复方法:
- 导航到 AWS 控制台中的 Lambda 函数配置。
- 检查“权限”选项卡并查看附加的 IAM 角色策略。
- 确保该角色具有基本的 AWS 托管策略
AWSLambdaBasicExecutionRole,或者其自定义策略包含必要的 CloudWatch 操作。 - 仅添加您的代码实际需要的服务权限,例如特定存储桶前缀的
s3:GetObject。
基于资源的策略错误(调用权限)
如果您的 Lambda 由其他服务(如 S3、API Gateway、SNS 或跨账户调用)调用,则该服务需要获得调用您函数的显式权限。
症状: 该服务(例如 S3)尝试触发 Lambda,但 CloudWatch 日志中未显示任何内容,并且该服务报告错误。
修复方法:使用 add-permission CLI 命令或等效的控制台设置来授予调用权限。例如,允许 S3 存储桶调用该函数:
aws lambda add-permission \
--function-name my-processing-function \
--statement-id S3InvokePermission \
--action lambda:InvokeFunction \
--principal s3.amazonaws.com \
--source-arn arn:aws:s3:::my-trigger-bucket
对于跨账户调用,请检查双方:调用方需要具有调用 lambda:InvokeFunction 的 IAM 权限,并且 Lambda 函数需要具有允许该调用方的基于资源的策略。
配置和资源约束错误
这些错误与定义的运行时环境设置以及对函数施加的资源限制有关。
函数超时错误
函数超时是一种常见的失败,表示执行超过了最大允许时间。Lambda 将强制终止执行并记录 Task timed out 错误。
诊断:
- 检查 CloudWatch 日志中的
REPORT行。查看Duration与配置的超时时间。 - 如果函数提前超时(例如,在 30 秒限制内仅 5 秒后),则瓶颈可能是初始化或连接(例如,等待 DNS 查找)。
修复方法:
- 增加超时时间: 如果任务本身是长时间运行的(例如,大型数据处理),请增加超时时间(最多 15 分钟)。
- 优化代码/依赖项: 如果任务缓慢,请分析代码以识别瓶颈。确保任何外部调用在代码内定义了合理的超时时间。
- 处理冷启动: 大型初始化过程可能导致超时。如果冷启动是关键问题,请使用 Lambda 预置并发。
内存耗尽错误
如果您的函数需要的 RAM 多于分配的量,它将崩溃并根据运行时记录 OutOfMemoryError 或类似消息。
诊断: 查看 CloudWatch REPORT 行中的 Max Memory Used 指标。如果此值持续接近或等于配置的 Memory Size,则可能存在内存泄漏或资源不足。
修复方法: 增加内存分配并重新测试。Lambda 会随着您分配更多内存而分配更多 CPU,因此更高的内存有时可以减少持续时间,足以抵消部分成本。测量您自己的函数,而不是假设它会更便宜。
AWS Lambda Power Tuning 可以帮助比较特定工作负载的内存设置。
处理程序配置错误 (Runtime.HandlerNotFound)
当 Lambda 无法找到函数配置中定义的入口点时,会发生此错误。
症状: Error: Runtime.HandlerNotFound 或类似的启动失败。
修复方法: 验证函数设置中的 Handler 字段是否与结构匹配:[file_name].[function_name]。例如,在 my_code.py 中定义的 Python 函数,入口函数为 lambda_handler,必须将处理程序设置为 my_code.lambda_handler。
对于 Node.js,处理程序名称遵循模块和导出的函数,例如 index.handler 用于 index.js 中导出的 handler 函数。
网络和 VPC 连接问题
当 Lambda 函数配置为在虚拟私有云 (VPC) 内运行时,它可以访问私有资源,但默认情况下会失去公共互联网访问权限。
缺少互联网访问权限
如果您的 Lambda 位于 VPC 中并且需要连接到外部服务,则需要通过 NAT 网关或其他批准的出口路径连接到互联网。将函数放在公共子网中不会为其提供公共 IP 地址。
症状: HTTP 连接失败,访问公共端点时超时。
修复方法:
- 验证函数是否附加到专为 Lambda 工作负载设计的私有子网。
- 确保这些私有子网具有将出站互联网流量 (
0.0.0.0/0) 指向 NAT 网关的路由表条目。 - 如果 Lambda 仅需要私下访问 AWS 服务,请考虑使用 VPC 端点,例如用于 S3 和 DynamoDB 的网关端点或用于受支持服务的接口端点。
安全组和 ACL 限制
您的函数可以成功启动,但当其安全组、目标安全组、网络 ACL 或路由表阻止连接时,可能会挂起。
修复方法:允许从 Lambda 安全组到目标端口的出站流量,并允许从 Lambda 安全组到目标安全组的入站流量。例如,连接到 PostgreSQL 的 Lambda 函数需要来自 Lambda 的出站 TCP 5432 以及数据库端的入站 TCP 5432。
如果执行角色缺少 VPC 访问所需的 EC2 网络接口权限,则 Lambda 在准备运行函数所需的 VPC 网络时可能会失败。
部署和运行时配置错误
这些问题与代码包的构建方式或所选的运行时环境有关。
依赖项和包错误
如果您的代码依赖于未正确打包或未针对特定运行时环境安装的外部库,则函数将在初始化期间失败。
症状: 运行时异常,如 module not found、cannot import name 或 No such file or directory(在 Python 或 Node.js 中尤其常见)。
修复方法:
- 本地环境与 Lambda 环境: 确保在与 Lambda 运行时匹配的环境中构建依赖项(例如,使用
pip install -t .为 Python 正确放置依赖项)。 - 使用 Lambda 层: 将较大、稳定的依赖项打包到 Lambda 层中,以减小主部署包的大小并提高部署速度。
- 检查路径: 验证您的运行时配置是否正确指向已安装依赖项的位置。
部署包大小和格式
Lambda 有部署包大小限制,这些限制取决于您是直接上传 .zip 文件、通过 Amazon S3 上传、使用层还是部署容器镜像。在重构大型函数之前,请检查您打包方法的当前 Lambda 配额。
症状: 部署因大小错误而失败,或者大型包导致冷启动变慢。
修复方法:
- 精简: 删除不必要的文件、文档和开发依赖项。
- 层: 将静态资产或大型依赖项移至 Lambda 层。
- 容器镜像: 对于非常大的应用程序,请考虑将函数作为来自 Amazon ECR 的容器镜像进行部署。
事件和负载问题
某些调用失败源于事件本身:
- 格式错误的 JSON: 控制台测试和 CLI 调用需要有效的 JSON 负载。
- 意外的事件形状: S3 事件、API Gateway 事件和 EventBridge 事件不具有相同的字段。
- 异步重试行为: 异步调用可以在失败后重试,并且如果配置了目标或死信队列,则可能将失败的事件发送到该队列。
对于直接的 CLI 测试,捕获响应和日志:
aws lambda invoke \
--function-name my-function \
--payload '{"ping": true}' \
--cli-binary-format raw-in-base64-out \
response.json
在使用 AWS CLI v2 直接在命令行上传递原始 JSON 时,通常需要 --cli-binary-format raw-in-base64-out 选项。
故障排除步骤总结
遇到调用错误时,请遵循以下系统方法:
- 首先检查 CloudWatch: 查找 Lambda 服务在
START行之前记录的即时错误。 - 验证 IAM 角色: 确保函数的执行角色具有所有必需的权限(日志记录、VPC 和服务访问权限)。
- 审查配置: 检查处理程序名称、内存设置和超时限制。
- 分析 VPC 设置: 如果使用 VPC,请验证安全组、子网映射和路由表(特别是 NAT 网关访问)。
- 检查依赖项: 确认所有必需的库都已正确打包并且运行时可以访问。
一旦您知道失败是发生在调用之前、运行时启动期间还是代码内部,修复方法就会变得非常明确。首先检查日志,验证活动的 IAM 身份和资源策略,然后根据您看到的具体错误调整处理程序、包、超时、内存和 VPC 设置。