案例5
题目
某公司搭建了一个文件管理系统,用户上传文件到Amazon S3后,通过AWS Lambda函数将文件元数据(文件名、上传时间、大小)写入Amazon DynamoDB表。近期发现用户上传文件后,DynamoDB表中未新增数据,但S3桶中文件正常存储。请根据以下配置信息排查并解决问题。
相关配置信息
-
S3存储桶配置
- 桶名称:
file - upload - bucket,启用了版本控制。 - 事件通知配置:配置了Lambda触发器,事件类型为“所有对象创建事件”,目标Lambda函数为
file - metadata - processor。 - 桶策略:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "lambda.amazonaws.com" }, "Action": "s3:GetObject", "Resource": "arn:aws:s3:::file - upload - bucket/*" } ] }
- 桶名称:
-
Lambda函数配置
- 函数代码(Python):
import boto3 import json from datetime import datetime dynamodb = boto3.resource('dynamodb') table = dynamodb.Table('file - metadata - table') def lambda_handler(event, context): for record in event['Records']: bucket = record['s3']['bucket']['name'] key = record['s3']['object']['key'] size = record['s3']['object']['size'] upload_time = datetime.now().isoformat() table.put_item( Item={ 'FileName': key, 'UploadTime': upload_time, 'FileSize': size } ) return { 'statusCode': 200, 'body': json.dumps('Metadata processed successfully') } - 执行角色:
lambda - execution - role,策略如下:{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "logs:CreateLogGroup", "Resource": "*" }, { "Effect": "Allow", "Action": "logs:CreateLogStream", "Resource": "*" }, { "Effect": "Allow", "Action": "logs:PutLogEvents", "Resource": "*" } ] }
- 函数代码(Python):
-
DynamoDB表配置
- 表名:
file - metadata - table,主键为FileName(字符串类型),无排序键。 - 表的读写容量模式:按需模式(On - Demand)。
- 表名:
解题思路
1. 明确问题现象
- 核心问题:S3文件上传后,DynamoDB表未写入元数据,但Lambda函数未报错(假设日志中无明显错误)。
- 可能方向:
- S3事件通知未正确触发Lambda函数。
- Lambda函数缺少DynamoDB写入权限。
- 代码逻辑错误导致数据未写入。
- S3桶策略或Lambda角色权限不足。
2. 排查S3事件通知配置
- 检查点:
- 登录AWS控制台,进入S3桶
file - upload - bucket的“事件通知”页面,确认:- 事件类型是否为“所有对象创建事件”。
- 目标Lambda函数是否正确关联(
file - metadata - processor)。 - 是否有错误提示(如Lambda函数ARN无效、权限不足)。
- 登录AWS控制台,进入S3桶
- 发现问题:
事件通知配置正确,但S3桶策略中允许Lambda访问GetObject,但Lambda触发事件通知时,不需要GetObject权限(事件通知仅传递元数据,不读取文件内容),因此桶策略无直接问题,但需确认Lambda能否接收事件。
3. 排查Lambda函数权限
- 关键分析:
Lambda函数需要向DynamoDB表file - metadata - table写入数据,对应操作是dynamodb:PutItem。- 当前
lambda - execution - role的策略仅包含CloudWatch日志权限,完全缺少DynamoDB相关权限,这是核心错误!
- 当前
- 修正角色策略:
为lambda - execution - role添加DynamoDB写入权限:
(替换{ "Effect": "Allow", "Action": "dynamodb:PutItem", "Resource": "arn:aws:dynamodb:your - region:your - account - id:table/file - metadata - table" }your - region和your - account - id为实际值)
4. 检查代码逻辑
- 潜在问题:
- S3事件通知的
event结构中,record['s3']['object']['size']可能不存在?
实际上,S3事件通知的“对象创建事件”中,size字段是可选的,若文件上传时未提供(如分块上传未完成),可能为null或缺失,导致代码报错。 - 但题目中用户反馈“无数据写入”,且假设日志无报错,优先考虑权限问题。
- S3事件通知的
- 代码修正(可选):
为避免size缺失导致错误,可添加默认值:size = record['s3']['object'].get('size', 0) # 使用get()方法避免KeyError
5. 验证S3事件触发和Lambda执行
- 步骤1:重新上传文件
上传一个测试文件到S3桶,观察Lambda函数是否被触发(可在Lambda控制台查看执行历史)。 - 步骤2:检查Lambda日志
进入CloudWatch Logs,查看Lambda函数的日志组,确认是否有权限错误:- 若出现
AccessDeniedException,说明DynamoDB写入权限缺失(即步骤3未修复)。 - 若日志显示正常执行但DynamoDB无数据,可能是代码逻辑问题(如
FileName重复导致主键冲突)。
- 若出现
- 步骤3:检查DynamoDB表
使用DynamoDB控制台查询表file - metadata - table,确认是否有新写入的条目,或是否因主键重复导致写入失败(若文件名为唯一主键,重复上传同文件名会覆盖旧数据,而非新增)。
6. 额外检查:S3桶与Lambda的权限关联
- Lambda函数要接收S3事件通知,需确保S3桶有权限调用Lambda(通过事件通知配置自动授予,一般无需额外策略)。
- 若事件通知配置中提示“无法授权”,需在Lambda函数的“权限”页面,确保存在名为
AWSServiceRoleForS3EventNotifications的权限策略(或手动添加lambda:InvokeFunction权限到S3桶的事件通知角色)。
总结
核心错误:Lambda函数缺少DynamoDB写入权限
- 权限缺失:
lambda - execution - role未包含dynamodb:PutItem权限,导致写入失败。 - 次要改进:代码中对S3事件字段的健壮性处理(如
size可能缺失)。
解决步骤:
- 为Lambda执行角色添加DynamoDB写入权限。
- 验证上传文件后Lambda是否正常执行并写入数据。
AWS排错核心:服务间的权限传递必须明确,每个服务(如Lambda、S3、DynamoDB)交互时,需确保执行角色具备目标服务的必要操作权限(如PutItem、GetObject等),可通过服务控制台的错误日志快速定位权限缺失问题。

浙公网安备 33010602011771号